aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/nvi/FAQ160
-rw-r--r--contrib/nvi/LAYOUT128
-rw-r--r--contrib/nvi/LICENSE (renamed from usr.bin/vi/ex/script.h)25
-rw-r--r--contrib/nvi/README113
-rw-r--r--contrib/nvi/build/ExtUtils/Embed.pm473
-rw-r--r--contrib/nvi/build/Makefile.in630
-rw-r--r--contrib/nvi/build/README369
-rw-r--r--contrib/nvi/build/README.LynxOS320
-rw-r--r--contrib/nvi/build/acconfig.h82
-rw-r--r--contrib/nvi/build/aclocal.m417
-rwxr-xr-xcontrib/nvi/build/config.guess571
-rw-r--r--contrib/nvi/build/config.h.in179
-rwxr-xr-xcontrib/nvi/build/config.sub872
-rwxr-xr-xcontrib/nvi/build/configure4446
-rw-r--r--contrib/nvi/build/configure.in725
-rw-r--r--contrib/nvi/build/distrib84
-rwxr-xr-xcontrib/nvi/build/install-sh238
-rw-r--r--contrib/nvi/build/pathnames.h.in45
-rw-r--r--contrib/nvi/build/port.h.in185
-rw-r--r--contrib/nvi/build/recover.in49
-rw-r--r--contrib/nvi/build/spell.ok58
-rw-r--r--contrib/nvi/catalog/Makefile84
-rw-r--r--contrib/nvi/catalog/README166
-rw-r--r--contrib/nvi/catalog/dump.c (renamed from usr.bin/vi/ex/ex_undo.c)125
-rw-r--r--contrib/nvi/catalog/dutch317
-rw-r--r--contrib/nvi/catalog/dutch.base307
-rw-r--r--contrib/nvi/catalog/dutch.check37
-rw-r--r--contrib/nvi/catalog/dutch.owner1
-rw-r--r--contrib/nvi/catalog/english317
-rw-r--r--contrib/nvi/catalog/english.base309
-rw-r--r--contrib/nvi/catalog/english.check36
-rw-r--r--contrib/nvi/catalog/english.owner1
-rw-r--r--contrib/nvi/catalog/french317
-rw-r--r--contrib/nvi/catalog/french.base309
-rw-r--r--contrib/nvi/catalog/french.check34
-rw-r--r--contrib/nvi/catalog/german317
-rw-r--r--contrib/nvi/catalog/german.base307
-rw-r--r--contrib/nvi/catalog/german.check36
-rw-r--r--contrib/nvi/catalog/german.owner1
-rw-r--r--contrib/nvi/catalog/ru_RU.KOI8-R267
-rw-r--r--contrib/nvi/catalog/ru_RU.KOI8-R.base219
-rw-r--r--contrib/nvi/catalog/ru_RU.KOI8-R.check169
-rw-r--r--contrib/nvi/catalog/ru_RU.KOI8-R.owner1
-rw-r--r--contrib/nvi/catalog/ru_SU.KOI8-R267
-rw-r--r--contrib/nvi/catalog/ru_SU.KOI8-R.base219
-rw-r--r--contrib/nvi/catalog/ru_SU.KOI8-R.check169
-rw-r--r--contrib/nvi/catalog/ru_SU.KOI8-R.owner1
-rw-r--r--contrib/nvi/catalog/spanish317
-rw-r--r--contrib/nvi/catalog/spanish.base309
-rw-r--r--contrib/nvi/catalog/spanish.check35
-rw-r--r--contrib/nvi/catalog/spell.ok19
-rw-r--r--contrib/nvi/catalog/swedish317
-rw-r--r--contrib/nvi/catalog/swedish.base307
-rw-r--r--contrib/nvi/catalog/swedish.check34
-rw-r--r--contrib/nvi/catalog/swedish.owner1
-rw-r--r--contrib/nvi/cl/README.signal174
-rw-r--r--contrib/nvi/cl/cl.h78
-rw-r--r--contrib/nvi/cl/cl_bsd.c345
-rw-r--r--contrib/nvi/cl/cl_funcs.c704
-rw-r--r--contrib/nvi/cl/cl_main.c471
-rw-r--r--contrib/nvi/cl/cl_read.c334
-rw-r--r--contrib/nvi/cl/cl_screen.c581
-rw-r--r--contrib/nvi/cl/cl_term.c459
-rw-r--r--contrib/nvi/clib/bsearch.c (renamed from usr.bin/vi/ex/ex_abbrev.c)137
-rw-r--r--contrib/nvi/clib/env.c160
-rw-r--r--contrib/nvi/clib/gethostname.c22
-rw-r--r--contrib/nvi/clib/getopt.c130
-rw-r--r--contrib/nvi/clib/memchr.c (renamed from usr.bin/vi/ex/ex_source.c)53
-rw-r--r--contrib/nvi/clib/memmove.c147
-rw-r--r--contrib/nvi/clib/memset.c137
-rw-r--r--contrib/nvi/clib/mkstemp.c (renamed from usr.bin/vi/ex/ex_preserve.c)161
-rw-r--r--contrib/nvi/clib/mmap.c50
-rw-r--r--contrib/nvi/clib/snprintf.c45
-rw-r--r--contrib/nvi/clib/strdup.c (renamed from usr.bin/vi/vi/v_redraw.c)52
-rw-r--r--contrib/nvi/clib/strerror.c (renamed from usr.bin/vi/vi/v_stop.c)69
-rw-r--r--contrib/nvi/clib/strpbrk.c (renamed from usr.bin/vi/ex/ex_set.c)58
-rw-r--r--contrib/nvi/clib/strsep.c (renamed from usr.bin/vi/ex/ex_put.c)79
-rw-r--r--contrib/nvi/clib/strtol.c134
-rw-r--r--contrib/nvi/clib/strtoul.c (renamed from usr.bin/vi/ex/ex_file.c)132
-rw-r--r--contrib/nvi/clib/vsnprintf.c31
-rw-r--r--contrib/nvi/common/api.c525
-rw-r--r--contrib/nvi/common/args.h29
-rw-r--r--contrib/nvi/common/common.h96
-rw-r--r--contrib/nvi/common/cut.c (renamed from usr.bin/vi/common/cut.c)132
-rw-r--r--contrib/nvi/common/cut.h77
-rw-r--r--contrib/nvi/common/delete.c160
-rw-r--r--contrib/nvi/common/exf.c1498
-rw-r--r--contrib/nvi/common/exf.h82
-rw-r--r--contrib/nvi/common/gs.h210
-rw-r--r--contrib/nvi/common/key.c865
-rw-r--r--contrib/nvi/common/key.h222
-rw-r--r--contrib/nvi/common/line.c576
-rw-r--r--contrib/nvi/common/log.c (renamed from usr.bin/vi/common/log.c)179
-rw-r--r--contrib/nvi/common/log.h20
-rw-r--r--contrib/nvi/common/main.c617
-rw-r--r--contrib/nvi/common/mark.c (renamed from usr.bin/vi/common/mark.c)161
-rw-r--r--contrib/nvi/common/mark.h42
-rw-r--r--contrib/nvi/common/mem.h168
-rw-r--r--contrib/nvi/common/msg.c895
-rw-r--r--contrib/nvi/common/msg.h65
-rw-r--r--contrib/nvi/common/options.awk (renamed from usr.bin/vi/common/options.awk)2
-rw-r--r--contrib/nvi/common/options.c1141
-rw-r--r--contrib/nvi/common/options.h101
-rw-r--r--contrib/nvi/common/options_f.c367
-rw-r--r--contrib/nvi/common/put.c (renamed from usr.bin/vi/common/put.c)139
-rw-r--r--contrib/nvi/common/recover.c (renamed from usr.bin/vi/common/recover.c)275
-rw-r--r--contrib/nvi/common/screen.c233
-rw-r--r--contrib/nvi/common/screen.h203
-rw-r--r--contrib/nvi/common/search.c492
-rw-r--r--contrib/nvi/common/seq.c (renamed from usr.bin/vi/common/seq.c)193
-rw-r--r--contrib/nvi/common/seq.h44
-rw-r--r--contrib/nvi/common/util.c230
-rw-r--r--contrib/nvi/common/util.h56
-rw-r--r--contrib/nvi/docs/TODO147
-rw-r--r--contrib/nvi/docs/USD.doc/edit/Makefile11
-rw-r--r--contrib/nvi/docs/USD.doc/edit/edit.vindex (renamed from usr.bin/vi/USD.doc/edit/edit.vindex)0
-rw-r--r--contrib/nvi/docs/USD.doc/edit/edittut.ms (renamed from usr.bin/vi/USD.doc/edit/edittut.ms)68
-rw-r--r--contrib/nvi/docs/USD.doc/exref/Makefile17
-rw-r--r--contrib/nvi/docs/USD.doc/exref/ex.rm (renamed from usr.bin/vi/USD.doc/exref/ex.rm)31
-rw-r--r--contrib/nvi/docs/USD.doc/exref/ex.summary (renamed from usr.bin/vi/USD.doc/exref/ex.summary)30
-rw-r--r--contrib/nvi/docs/USD.doc/vi.man/Makefile16
-rw-r--r--contrib/nvi/docs/USD.doc/vi.man/spell.ok179
-rw-r--r--contrib/nvi/docs/USD.doc/vi.man/vi.1 (renamed from usr.bin/vi/USD.doc/vi.man/vi.1)1794
-rw-r--r--contrib/nvi/docs/USD.doc/vi.ref/Makefile32
-rw-r--r--contrib/nvi/docs/USD.doc/vi.ref/ex.cmd.roff (renamed from usr.bin/vi/USD.doc/vi.ref/ex.cmd.roff)400
-rw-r--r--contrib/nvi/docs/USD.doc/vi.ref/index.so260
-rw-r--r--contrib/nvi/docs/USD.doc/vi.ref/merge.awk (renamed from usr.bin/vi/USD.doc/vi.ref/merge.awk)2
-rw-r--r--contrib/nvi/docs/USD.doc/vi.ref/ref.so103
-rw-r--r--contrib/nvi/docs/USD.doc/vi.ref/set.opt.roff (renamed from usr.bin/vi/USD.doc/vi.ref/set.opt.roff)500
-rw-r--r--contrib/nvi/docs/USD.doc/vi.ref/spell.ok (renamed from usr.bin/vi/USD.doc/vi.ref/spell.ok)146
-rw-r--r--contrib/nvi/docs/USD.doc/vi.ref/vi.cmd.roff (renamed from usr.bin/vi/USD.doc/vi.ref/vi.cmd.roff)483
-rw-r--r--contrib/nvi/docs/USD.doc/vi.ref/vi.ref (renamed from usr.bin/vi/USD.doc/vi.ref/vi.ref)1016
-rw-r--r--contrib/nvi/docs/USD.doc/vitut/Makefile22
-rw-r--r--contrib/nvi/docs/USD.doc/vitut/vi.apwh.ms (renamed from usr.bin/vi/USD.doc/vitut/vi.apwh.ms)4
-rw-r--r--contrib/nvi/docs/USD.doc/vitut/vi.chars (renamed from usr.bin/vi/USD.doc/vitut/vi.chars)5
-rw-r--r--contrib/nvi/docs/USD.doc/vitut/vi.in (renamed from usr.bin/vi/USD.doc/vitut/vi.in)46
-rw-r--r--contrib/nvi/docs/USD.doc/vitut/vi.summary (renamed from usr.bin/vi/USD.doc/vitut/vi.summary)12
-rw-r--r--contrib/nvi/docs/changelog1102
-rw-r--r--contrib/nvi/docs/ev (renamed from usr.bin/vi/docs/ev)0
-rw-r--r--contrib/nvi/docs/features (renamed from usr.bin/vi/docs/features)51
-rw-r--r--contrib/nvi/docs/help229
-rw-r--r--contrib/nvi/docs/internals/autowrite (renamed from usr.bin/vi/docs/internals/autowrite)8
-rw-r--r--contrib/nvi/docs/internals/context (renamed from usr.bin/vi/docs/internals/context)4
-rw-r--r--contrib/nvi/docs/internals/cscope.NOTES142
-rw-r--r--contrib/nvi/docs/internals/gdb.script (renamed from usr.bin/vi/docs/internals/gdb.script)32
-rw-r--r--contrib/nvi/docs/internals/input (renamed from usr.bin/vi/docs/internals/input)0
-rw-r--r--contrib/nvi/docs/internals/openmode36
-rw-r--r--contrib/nvi/docs/internals/quoting208
-rw-r--r--contrib/nvi/docs/internals/structures68
-rw-r--r--contrib/nvi/docs/interp/interp190
-rw-r--r--contrib/nvi/docs/interp/spell.ok46
-rw-r--r--contrib/nvi/docs/spell.ok173
-rw-r--r--contrib/nvi/docs/tutorial/vi.advanced (renamed from usr.bin/vi/docs/tutorial/vi.advanced)0
-rw-r--r--contrib/nvi/docs/tutorial/vi.beginner (renamed from usr.bin/vi/docs/tutorial/vi.beginner)0
-rwxr-xr-xcontrib/nvi/docs/tutorial/vi.tut.csh (renamed from usr.bin/vi/docs/tutorial/vi.tut.csh)0
-rw-r--r--contrib/nvi/ex/ex.awk (renamed from usr.bin/vi/ex/excmd.awk)2
-rw-r--r--contrib/nvi/ex/ex.c2370
-rw-r--r--contrib/nvi/ex/ex.h228
-rw-r--r--contrib/nvi/ex/ex_abbrev.c117
-rw-r--r--contrib/nvi/ex/ex_append.c277
-rw-r--r--contrib/nvi/ex/ex_args.c327
-rw-r--r--contrib/nvi/ex/ex_argv.c (renamed from usr.bin/vi/ex/ex_argv.c)433
-rw-r--r--contrib/nvi/ex/ex_at.c126
-rw-r--r--contrib/nvi/ex/ex_bang.c186
-rw-r--r--contrib/nvi/ex/ex_cd.c129
-rw-r--r--contrib/nvi/ex/ex_cmd.c (renamed from usr.bin/vi/ex/excmd.c)265
-rw-r--r--contrib/nvi/ex/ex_cscope.c1057
-rw-r--r--contrib/nvi/ex/ex_delete.c65
-rw-r--r--contrib/nvi/ex/ex_display.c145
-rw-r--r--contrib/nvi/ex/ex_edit.c153
-rw-r--r--contrib/nvi/ex/ex_equal.c59
-rw-r--r--contrib/nvi/ex/ex_file.c80
-rw-r--r--contrib/nvi/ex/ex_filter.c316
-rw-r--r--contrib/nvi/ex/ex_global.c328
-rw-r--r--contrib/nvi/ex/ex_init.c417
-rw-r--r--contrib/nvi/ex/ex_join.c (renamed from usr.bin/vi/ex/ex_join.c)75
-rw-r--r--contrib/nvi/ex/ex_map.c121
-rw-r--r--contrib/nvi/ex/ex_mark.c45
-rw-r--r--contrib/nvi/ex/ex_mkexrc.c101
-rw-r--r--contrib/nvi/ex/ex_move.c (renamed from usr.bin/vi/ex/ex_move.c)96
-rw-r--r--contrib/nvi/ex/ex_open.c46
-rw-r--r--contrib/nvi/ex/ex_perl.c69
-rw-r--r--contrib/nvi/ex/ex_preserve.c103
-rw-r--r--contrib/nvi/ex/ex_print.c352
-rw-r--r--contrib/nvi/ex/ex_put.c51
-rw-r--r--contrib/nvi/ex/ex_quit.c46
-rw-r--r--contrib/nvi/ex/ex_read.c360
-rw-r--r--contrib/nvi/ex/ex_screen.c138
-rw-r--r--contrib/nvi/ex/ex_script.c (renamed from usr.bin/vi/ex/ex_script.c)452
-rw-r--r--contrib/nvi/ex/ex_set.c46
-rw-r--r--contrib/nvi/ex/ex_shell.c378
-rw-r--r--contrib/nvi/ex/ex_shift.c (renamed from usr.bin/vi/ex/ex_shift.c)99
-rw-r--r--contrib/nvi/ex/ex_source.c85
-rw-r--r--contrib/nvi/ex/ex_stop.c51
-rw-r--r--contrib/nvi/ex/ex_subst.c (renamed from usr.bin/vi/ex/ex_subst.c)876
-rw-r--r--contrib/nvi/ex/ex_tag.c1324
-rw-r--r--contrib/nvi/ex/ex_tcl.c80
-rw-r--r--contrib/nvi/ex/ex_txt.c430
-rw-r--r--contrib/nvi/ex/ex_undo.c77
-rw-r--r--contrib/nvi/ex/ex_usage.c196
-rw-r--r--contrib/nvi/ex/ex_util.c234
-rw-r--r--contrib/nvi/ex/ex_version.c39
-rw-r--r--contrib/nvi/ex/ex_visual.c161
-rw-r--r--contrib/nvi/ex/ex_write.c375
-rw-r--r--contrib/nvi/ex/ex_yank.c46
-rw-r--r--contrib/nvi/ex/ex_z.c (renamed from usr.bin/vi/ex/ex_z.c)88
-rw-r--r--contrib/nvi/ex/script.h23
-rw-r--r--contrib/nvi/ex/tag.h107
-rw-r--r--contrib/nvi/ex/version.h2
-rw-r--r--contrib/nvi/include/bitstring.h143
-rw-r--r--contrib/nvi/include/cl_extern.h56
-rw-r--r--contrib/nvi/include/com_extern.h199
-rw-r--r--contrib/nvi/include/ex_def.h78
-rw-r--r--contrib/nvi/include/ex_extern.h127
-rw-r--r--contrib/nvi/include/ip_extern.h23
-rw-r--r--contrib/nvi/include/options_def.h79
-rw-r--r--contrib/nvi/include/perl_extern.h8
-rw-r--r--contrib/nvi/include/sys/queue.h259
-rw-r--r--contrib/nvi/include/tcl_extern.h1
-rw-r--r--contrib/nvi/include/tk_extern.h29
-rw-r--r--contrib/nvi/include/vi_extern.h142
-rw-r--r--contrib/nvi/ip/IP_INSTRUCTIONS41
-rw-r--r--contrib/nvi/ip/ip.h92
-rw-r--r--contrib/nvi/ip/ip_funcs.c443
-rw-r--r--contrib/nvi/ip/ip_main.c165
-rw-r--r--contrib/nvi/ip/ip_read.c307
-rw-r--r--contrib/nvi/ip/ip_screen.c87
-rw-r--r--contrib/nvi/ip/ip_term.c108
-rw-r--r--contrib/nvi/ip_cl/Makefile20
-rw-r--r--contrib/nvi/ip_cl/ip_cl.c742
-rw-r--r--contrib/nvi/perl_api/VI.pod218
-rw-r--r--contrib/nvi/perl_api/nviperl.pod43
-rw-r--r--contrib/nvi/perl_api/perl.xs1115
-rw-r--r--contrib/nvi/perl_api/perlsfio.c85
-rw-r--r--contrib/nvi/perl_api/typemap42
-rw-r--r--contrib/nvi/perl_scripts/forall.pl10
-rw-r--r--contrib/nvi/perl_scripts/make.pl27
-rw-r--r--contrib/nvi/perl_scripts/tk.pl20
-rw-r--r--contrib/nvi/perl_scripts/wc.pl11
-rw-r--r--contrib/nvi/tcl_api/tcl.c852
-rw-r--r--contrib/nvi/tcl_scripts/errors.tcl44
-rw-r--r--contrib/nvi/tcl_scripts/gnats.tcl95
-rw-r--r--contrib/nvi/tcl_scripts/mailprocs.tcl115
-rw-r--r--contrib/nvi/tcl_scripts/wc.tcl16
-rw-r--r--contrib/nvi/tk/init.tcl1096
-rw-r--r--contrib/nvi/tk/tk_funcs.c346
-rw-r--r--contrib/nvi/tk/tk_main.c423
-rw-r--r--contrib/nvi/tk/tk_read.c207
-rw-r--r--contrib/nvi/tk/tk_screen.c86
-rw-r--r--contrib/nvi/tk/tk_term.c169
-rw-r--r--contrib/nvi/tk/tk_util.c250
-rw-r--r--contrib/nvi/tk/tki.h64
-rw-r--r--contrib/nvi/vi/getc.c (renamed from usr.bin/vi/vi/getc.c)132
-rw-r--r--contrib/nvi/vi/v_at.c109
-rw-r--r--contrib/nvi/vi/v_ch.c (renamed from usr.bin/vi/vi/v_ch.c)167
-rw-r--r--contrib/nvi/vi/v_cmd.c (renamed from usr.bin/vi/vi/vcmd.c)84
-rw-r--r--contrib/nvi/vi/v_delete.c107
-rw-r--r--contrib/nvi/vi/v_ex.c696
-rw-r--r--contrib/nvi/vi/v_increment.c267
-rw-r--r--contrib/nvi/vi/v_init.c126
-rw-r--r--contrib/nvi/vi/v_itxt.c537
-rw-r--r--contrib/nvi/vi/v_left.c293
-rw-r--r--contrib/nvi/vi/v_mark.c234
-rw-r--r--contrib/nvi/vi/v_match.c170
-rw-r--r--contrib/nvi/vi/v_paragraph.c (renamed from usr.bin/vi/vi/v_paragraph.c)104
-rw-r--r--contrib/nvi/vi/v_put.c (renamed from usr.bin/vi/vi/v_put.c)68
-rw-r--r--contrib/nvi/vi/v_redraw.c39
-rw-r--r--contrib/nvi/vi/v_replace.c203
-rw-r--r--contrib/nvi/vi/v_right.c145
-rw-r--r--contrib/nvi/vi/v_screen.c65
-rw-r--r--contrib/nvi/vi/v_scroll.c (renamed from usr.bin/vi/vi/v_scroll.c)230
-rw-r--r--contrib/nvi/vi/v_search.c515
-rw-r--r--contrib/nvi/vi/v_section.c (renamed from usr.bin/vi/vi/v_section.c)76
-rw-r--r--contrib/nvi/vi/v_sentence.c (renamed from usr.bin/vi/vi/v_sentence.c)121
-rw-r--r--contrib/nvi/vi/v_status.c41
-rw-r--r--contrib/nvi/vi/v_txt.c2950
-rw-r--r--contrib/nvi/vi/v_ulcase.c179
-rw-r--r--contrib/nvi/vi/v_undo.c (renamed from usr.bin/vi/vi/v_undo.c)69
-rw-r--r--contrib/nvi/vi/v_util.c180
-rw-r--r--contrib/nvi/vi/v_word.c (renamed from usr.bin/vi/vi/v_word.c)195
-rw-r--r--contrib/nvi/vi/v_xchar.c107
-rw-r--r--contrib/nvi/vi/v_yank.c82
-rw-r--r--contrib/nvi/vi/v_z.c149
-rw-r--r--contrib/nvi/vi/v_zexit.c54
-rw-r--r--contrib/nvi/vi/vi.c1251
-rw-r--r--contrib/nvi/vi/vi.h377
-rw-r--r--contrib/nvi/vi/vs_line.c514
-rw-r--r--contrib/nvi/vi/vs_msg.c927
-rw-r--r--contrib/nvi/vi/vs_refresh.c885
-rw-r--r--contrib/nvi/vi/vs_relative.c305
-rw-r--r--contrib/nvi/vi/vs_smap.c (renamed from usr.bin/vi/svi/svi_smap.c)718
-rw-r--r--contrib/nvi/vi/vs_split.c607
-rw-r--r--usr.bin/vi/Makefile3
-rw-r--r--usr.bin/vi/USD.doc/edit/Makefile18
-rw-r--r--usr.bin/vi/USD.doc/exref/Makefile14
-rw-r--r--usr.bin/vi/USD.doc/vi.man/Makefile14
-rw-r--r--usr.bin/vi/USD.doc/vi.man/vi.0798
-rw-r--r--usr.bin/vi/USD.doc/vi.man/vi.0.ps1063
-rw-r--r--usr.bin/vi/USD.doc/vi.ref/Makefile25
-rw-r--r--usr.bin/vi/USD.doc/vi.ref/paper.ps30924
-rw-r--r--usr.bin/vi/USD.doc/vi.ref/vi.ref.txt5544
-rw-r--r--usr.bin/vi/USD.doc/vitut/Makefile17
-rw-r--r--usr.bin/vi/common/Makefile108
-rw-r--r--usr.bin/vi/common/args.h53
-rw-r--r--usr.bin/vi/common/cut.h96
-rw-r--r--usr.bin/vi/common/delete.c193
-rw-r--r--usr.bin/vi/common/exf.c830
-rw-r--r--usr.bin/vi/common/exf.h128
-rw-r--r--usr.bin/vi/common/gs.h107
-rw-r--r--usr.bin/vi/common/line.c492
-rw-r--r--usr.bin/vi/common/log.h53
-rw-r--r--usr.bin/vi/common/main.c711
-rw-r--r--usr.bin/vi/common/mark.h73
-rw-r--r--usr.bin/vi/common/mem.h178
-rw-r--r--usr.bin/vi/common/msg.c427
-rw-r--r--usr.bin/vi/common/msg.h82
-rw-r--r--usr.bin/vi/common/options.c890
-rw-r--r--usr.bin/vi/common/options.h.stub108
-rw-r--r--usr.bin/vi/common/options_f.c518
-rw-r--r--usr.bin/vi/common/pathnames.h45
-rw-r--r--usr.bin/vi/common/screen.c309
-rw-r--r--usr.bin/vi/common/screen.h342
-rw-r--r--usr.bin/vi/common/search.c833
-rw-r--r--usr.bin/vi/common/search.h54
-rw-r--r--usr.bin/vi/common/seq.h79
-rw-r--r--usr.bin/vi/common/signal.c569
-rw-r--r--usr.bin/vi/common/term.c732
-rw-r--r--usr.bin/vi/common/term.h205
-rw-r--r--usr.bin/vi/common/trace.c84
-rw-r--r--usr.bin/vi/common/util.c215
-rw-r--r--usr.bin/vi/common/vi.h124
-rw-r--r--usr.bin/vi/docs/README200
-rw-r--r--usr.bin/vi/docs/bugs.current47
-rw-r--r--usr.bin/vi/docs/changelog519
-rw-r--r--usr.bin/vi/docs/internals/quoting219
-rw-r--r--usr.bin/vi/docs/internals/structures61
-rw-r--r--usr.bin/vi/ex/ex.c1866
-rw-r--r--usr.bin/vi/ex/ex_append.c220
-rw-r--r--usr.bin/vi/ex/ex_args.c263
-rw-r--r--usr.bin/vi/ex/ex_at.c118
-rw-r--r--usr.bin/vi/ex/ex_bang.c242
-rw-r--r--usr.bin/vi/ex/ex_cd.c223
-rw-r--r--usr.bin/vi/ex/ex_delete.c92
-rw-r--r--usr.bin/vi/ex/ex_digraph.c324
-rw-r--r--usr.bin/vi/ex/ex_display.c169
-rw-r--r--usr.bin/vi/ex/ex_edit.c122
-rw-r--r--usr.bin/vi/ex/ex_equal.c86
-rw-r--r--usr.bin/vi/ex/ex_exit.c79
-rw-r--r--usr.bin/vi/ex/ex_global.c400
-rw-r--r--usr.bin/vi/ex/ex_init.c202
-rw-r--r--usr.bin/vi/ex/ex_map.c160
-rw-r--r--usr.bin/vi/ex/ex_mark.c66
-rw-r--r--usr.bin/vi/ex/ex_mkexrc.c130
-rw-r--r--usr.bin/vi/ex/ex_open.c75
-rw-r--r--usr.bin/vi/ex/ex_print.c212
-rw-r--r--usr.bin/vi/ex/ex_read.c300
-rw-r--r--usr.bin/vi/ex/ex_screen.c155
-rw-r--r--usr.bin/vi/ex/ex_shell.c150
-rw-r--r--usr.bin/vi/ex/ex_stop.c76
-rw-r--r--usr.bin/vi/ex/ex_tag.c905
-rw-r--r--usr.bin/vi/ex/ex_usage.c197
-rw-r--r--usr.bin/vi/ex/ex_util.c189
-rw-r--r--usr.bin/vi/ex/ex_version.c71
-rw-r--r--usr.bin/vi/ex/ex_visual.c137
-rw-r--r--usr.bin/vi/ex/ex_write.c327
-rw-r--r--usr.bin/vi/ex/ex_yank.c69
-rw-r--r--usr.bin/vi/ex/excmd.h.stub285
-rw-r--r--usr.bin/vi/ex/filter.c414
-rw-r--r--usr.bin/vi/ex/tag.h58
-rw-r--r--usr.bin/vi/install/recover.script32
-rw-r--r--usr.bin/vi/sex/sex_confirm.c86
-rw-r--r--usr.bin/vi/sex/sex_get.c514
-rw-r--r--usr.bin/vi/sex/sex_refresh.c140
-rw-r--r--usr.bin/vi/sex/sex_screen.c340
-rw-r--r--usr.bin/vi/sex/sex_screen.h79
-rw-r--r--usr.bin/vi/sex/sex_term.c217
-rw-r--r--usr.bin/vi/sex/sex_util.c148
-rw-r--r--usr.bin/vi/sex/sex_window.c196
-rw-r--r--usr.bin/vi/svi/svi_confirm.c95
-rw-r--r--usr.bin/vi/svi/svi_curses.c252
-rw-r--r--usr.bin/vi/svi/svi_ex.c650
-rw-r--r--usr.bin/vi/svi/svi_get.c161
-rw-r--r--usr.bin/vi/svi/svi_line.c441
-rw-r--r--usr.bin/vi/svi/svi_refresh.c818
-rw-r--r--usr.bin/vi/svi/svi_relative.c334
-rw-r--r--usr.bin/vi/svi/svi_screen.c332
-rw-r--r--usr.bin/vi/svi/svi_screen.h262
-rw-r--r--usr.bin/vi/svi/svi_split.c627
-rw-r--r--usr.bin/vi/svi/svi_term.c310
-rw-r--r--usr.bin/vi/svi/svi_util.c347
-rw-r--r--usr.bin/vi/vi/v_delete.c160
-rw-r--r--usr.bin/vi/vi/v_ex.c352
-rw-r--r--usr.bin/vi/vi/v_increment.c163
-rw-r--r--usr.bin/vi/vi/v_init.c256
-rw-r--r--usr.bin/vi/vi/v_left.c287
-rw-r--r--usr.bin/vi/vi/v_mark.c210
-rw-r--r--usr.bin/vi/vi/v_match.c198
-rw-r--r--usr.bin/vi/vi/v_ntext.c1899
-rw-r--r--usr.bin/vi/vi/v_replace.c194
-rw-r--r--usr.bin/vi/vi/v_right.c162
-rw-r--r--usr.bin/vi/vi/v_screen.c90
-rw-r--r--usr.bin/vi/vi/v_search.c414
-rw-r--r--usr.bin/vi/vi/v_status.c73
-rw-r--r--usr.bin/vi/vi/v_text.c883
-rw-r--r--usr.bin/vi/vi/v_ulcase.c212
-rw-r--r--usr.bin/vi/vi/v_util.c159
-rw-r--r--usr.bin/vi/vi/v_xchar.c136
-rw-r--r--usr.bin/vi/vi/v_yank.c94
-rw-r--r--usr.bin/vi/vi/v_z.c159
-rw-r--r--usr.bin/vi/vi/v_zexit.c82
-rw-r--r--usr.bin/vi/vi/vcmd.h346
-rw-r--r--usr.bin/vi/vi/vi.c937
-rw-r--r--usr.bin/vi/xaw/xaw_screen.c98
413 files changed, 69887 insertions, 74849 deletions
diff --git a/contrib/nvi/FAQ b/contrib/nvi/FAQ
new file mode 100644
index 000000000000..357650a589bd
--- /dev/null
+++ b/contrib/nvi/FAQ
@@ -0,0 +1,160 @@
+@(#)FAQ 8.13 (Berkeley) 10/14/96
+
+Q: How can I get vi to display my character set?
+A: Vi uses the C library routine isprint(3) to determine if a character
+ is printable, or should be displayed as an octal or hexadecimal value
+ on the screen. Generally, if vi is displaying printable characters
+ in octal/hexadecimal forms, your environment is not configured correctly.
+ Try looking at the man pages that allow you to configure your locale.
+ For example, to configure an ISO 8859-1 locale under Solaris using csh,
+ you would do:
+
+ setenv LANG C
+ setenv LC_CTYPE iso_8859_1
+
+ Other LC_CTYPE systems/values that I'm told work:
+
+ System Value
+ ====== =====
+ FreeBSD lt_LN.ISO_8859-1
+ HP-UX 9.X american.iso88591
+ HP-UX 10.X en_US.iso88591
+ SunOS 4.X iso_8859_1
+ SunOS 5.X iso_8859_1
+
+ If there's no other solution, you can use the print and noprint edit
+ options of vi to specify that a specific character is printable or not
+ printable.
+
+Q: My map won't work!
+A: One thing that you should immediately check if a vi map doesn't work
+ is if depends on the final cursor position after a P or p command.
+ Historic vi's were inconsistent as to the final position of the cursor,
+ and, to make matter worse, the final cursor position also depended on
+ whether the put text came from a named or unnamed buffer! Vi follows
+ the POSIX 1003.2 standard on this one, and makes this consistent, always
+ placing the cursor on the first character.
+
+Q: I'm using ksh or csh as my vi edit option shell value, and file
+ expansions don't work right!
+A: The problem may be in your ksh or csh startup files, e.g., .cshrc. Vi
+ executes the shell to do name expansion, and the shell generally reads
+ its startup files. If the startup files are not correctly configured
+ for non-interactive use, e.g., they always echo a prompt to the screen,
+ vi will be unable to parse the output and things will not work
+ correctly.
+
+Q: How does the iclower edit option differ from the ignorecase (i.e. ic)
+ edit option?
+A: The difference is that the ignorecase edit option always ignores the
+ case of letters in the Regular Expression (RE), and the iclower edit
+ option only ignores the case if there are no upper-case letters in the
+ RE. If any upper-case letters appear in the Regular Expression, then
+ it will be treated case-sensitively, as if the ignorecase edit option
+ was not set.
+
+Q: When I edit binary files, vi appends a <newline> to the last line!
+A: This is historic practice for vi, and further, it's required by the
+ POSIX 1003.2 standard. My intent is to provide a command line and/or
+ edit option to turn this behavior off when I switch to version 2.0 of
+ the Berkeley DB package.
+
+Q: My cursor keys don't work when I'm in text input mode!
+A: A common problem over slow links is that the set of characters sent by
+ the cursor keys don't arrive close enough together for vi to understand
+ that they are a single keystroke, and not separate keystrokes. Try
+ increasing the value of the escapetime edit option, which will cause
+ vi to wait longer before deciding that the <escape> character that
+ starts cursor key sequences doesn't have any characters following it.
+
+Q: When I edit some files, vi seems to hang forever, and I have to kill it.
+A: Vi uses flock(2) and fcntl(2) to do file locking. When it attempts to
+ acquired a lock for a file on an NFS mounted filesystem, it can hang
+ for a very long (perhaps infinite) period of time. Turning off the
+ "lock" edit option will keep vi from attempting to acquire any locks
+ on the files you edit.
+
+Q: When I compile vi I get lots of warnings about pointer assignments
+ being incompatible!
+A: Vi is partially written to support wide characters. When this code
+ interfaces with the code that doesn't yet support wide characters,
+ the pointer types clash. This will hopefully be fixed in the near
+ future, but I've been saying that for awhile, now.
+
+Q: I get jumpy scrolling behavior in the screen!
+A: This is almost certainly a problem with the system's terminfo or
+ termcap information for your terminal. If the terminfo/termcap entry
+ doesn't have the settable scrolling region capabilities, or the more
+ powerful scrolling commands, these behaviors can result. Historic
+ implementations of vi, and some of the vi clones, don't suffer from
+ this problem because they wrote their own screen support instead of
+ using the curses library.
+
+ The solution is to find a good terminfo or termcap entry for your
+ terminal, which will fix the problem for all of the applications on
+ your system, not just vi. Eric Raymond maintains the freely
+ redistributable termcap/terminfo entries. They can be downloaded
+ from http://www.ccil.org/~esr/ncurses.html, or you can contact him
+ at esr@snark.thyrsus.com.
+
+Q: The entire screen repaints on every keystroke!
+A: Your system's curses implementation is broken. You should use the
+ curses implementation provided with vi or a curses replacement such
+ as ncurses. Eric Raymond is one of the maintainers of the freely
+ redistributable ncurses package. You can download ncurses from
+ http://www.ccil.org/~esr/ncurses.html, or you can contact him at
+ esr@snark.thyrsus.com.
+
+Q: When I use vi on a Sun console (terminal type sun-34) the screen
+ is occasionally trashed, usually when exiting vi!
+A: The Sun console can't handle the 'al' capability of the termcap
+ entry (the il1 capability of terminfo entries). If you delete that
+ entry from your terminfo/termcap information everything should work
+ correctly.
+
+Q: I don't have a version of ctags (or I have ctags, but it doesn't tag
+ nearly enough things)!
+A: There's a version of ctags available on the 4.4BSD-Lite distributions,
+ as well as the FreeBSD, NetBSD, Linux and GNU distributions. Or, you
+ might want to try Exuberant Ctags:
+
+ Title: Exuberant Ctags
+ Version: 1.3
+ Entered-date: 16JUN96
+ Description:
+ A better ctags which generates tags for all possible tag types:
+ macro definitions, enumerated values (values inside enum{...}),
+ function and method definitions, enum/struct/union tags, external
+ function prototypes (optional), typedefs, and variable
+ declarations. It is far less easily fooled by code containing #if
+ preprocessor conditional constructs, using a conditional path
+ selection algorithm to resolve complicated choices, and a
+ fall-back algorithm when this one fails. Can also be used to print
+ out a list of selected objects found in source files.
+ Keywords: ctags, tags, exuberant
+ Author: darren@sirsi.com (Darren Hiebert)
+ darren@hiwaay.net (Darren Hiebert)
+ Maintained-by: darren@sirsi.com (Darren Hiebert)
+ darren@hiwaay.net (Darren Hiebert)
+ Primary-site: sunsite.unc.edu /pub/Linux/devel/lang/c
+ 27kB ctags-1.3.tar.gz
+ Alternate-site: ftp.halcyon.com /local/gvr
+ 27kB ctags-1.3.tar.gz
+ Original-site:
+ Platforms: UNIX, MSDOS, WindowsNT, Windows95, OS/2, Amiga
+ Copying-policy: Public domain
+
+Q: When I update a file I already have open, and use :e to reread it, I
+ get nul's for the rest of the file!
+A: Your system's implementation of mmap(2) has a bug; you will have to
+ exit vi and re-execute it.
+
+Q: Where can I get cscope?
+A: Cscope is available on UNIXWare System V Release 4.0 variants such as
+ Sun Solaris 2.x (/opt/SUNWspro/bin) and UNIXWare System V Release 4.1.
+
+ You can buy version 13.3 source with an unrestricted license for $400
+ from AT&T Software Solutions by calling +1-800-462-8146. Binary
+ redistribution of cscope is an additional $1500, one-time flat fee.
+
+ For more information, see http://www.unipress.com/att/new/cscope.html.
diff --git a/contrib/nvi/LAYOUT b/contrib/nvi/LAYOUT
new file mode 100644
index 000000000000..e3a55ebb5778
--- /dev/null
+++ b/contrib/nvi/LAYOUT
@@ -0,0 +1,128 @@
+# @(#)LAYOUT 8.12 (Berkeley) 10/10/96
+
+LAYOUT
+ This file: the layout of the nvi sources.
+
+LICENSE
+ Nvi's copyright notice and conditions for redistribution.
+
+README
+ Welcome message and basic information.
+
+build/
+ The build/configuration directory for nvi. See build/README for
+ more information.
+
+catalog/
+ Support for message catalogs for nvi. See catalog/README for more
+ information.
+
+cl/
+ Source files for nvi's curses screen support.
+
+clib/
+ Replacement source files for C library functions.
+
+common/
+ Source files for pieces of code that are shared by ex and vi,
+ e.g., searching and logging code or code translating line numbers
+ into requests to the dbopen(3) database code. It also has the
+ interface code for modifying "records" in the underlying database.
+
+curses/
+ A stripped-down replacement curses library. Do not try and use
+ this library outside of nvi, many standard curses functions have
+ been removed because nvi doesn't use them. See build/README for
+ more information.
+
+db/
+ A stripped-down replacement DB library. Do not try and use this
+ library outside of nvi, many standard DB functions have been
+ removed because nvi doesn't use them. See db/README for more
+ information.
+
+docs/
+ Ex/vi documentation, both current and historic.
+
+ USD.doc/
+ [USD stands for "User's Supplementary Documents".]
+
+ edit/ Roff source for "Edit: A tutorial". This document
+ was USD:14 in the 4.3BSD manuals, but was not
+ distributed with 4.4BSD.
+
+ exref/ Roff source for "Ex Reference Manual -- Version
+ 3.7". This document was USD:16 in the 4.3BSD
+ manuals, and USD tabbed 12 in the 4.4BSD manuals.
+
+ vi.man/ Roff source for a UNIX manual page for nex/nvi.
+ An updated version of the 4.4BSD manual page.
+
+ vi.ref/ Roff source for the nex/nvi reference document.
+ An updated version of the 4.4BSD document, USD
+ tabbed 13.
+
+ vitut/ Roff source for "An Introduction to Display
+ Editing with Vi". This document was USD:15 in
+ the 4.3BSD manuals, but was not distributed with
+ 4.4BSD. It includes the historic "Vi Quick
+ Reference" card.
+
+
+ PostScript preformatted versions of the nex/nvi reference
+ manual and manual page are in the files named with a ".ps"
+ suffix, in their respective source directories. Flat text
+ preformatted versions of the nex/nvi reference manual and
+ manual page are in the files named with a ".txt" suffix,
+ in their respective source directories.
+
+ changelog -- Log of changes from version to version.
+ features -- Todo list, suggested features list.
+ internals/
+ autowrite -- Vi autowrite option discussion.
+ context -- Previous context marks discussion.
+ gdb.script -- GDB debugging scripts.
+ input -- Vi maps, executable buffers, and input discussion.
+ openmode -- Open mode behaviors.
+ quoting -- Vi quoting discussion.
+ structures -- Out-of-date nvi internal structure description.
+ tutorial/ -- Historic vi tutorial(s), of unknown quality.
+
+ex/
+ The ex source code. Because vi has the colon command, lots of
+ this code is used by vi. Generally, if functionality is shared
+ by both ex and vi, it's in the ex directory. If it's vi only,
+ it's in the vi directory. Files are generally named by the
+ command(s) they support, but occasionally with a name that
+ describes their functionality.
+
+ version.h -- Version information.
+
+include/
+ Replacement include files:
+
+ bitstring.h -- The 4.4BSD bitstring operations.
+ sys/queue.h -- The 4.4BSD queue operations.
+
+perl_api/
+ Source code supporting the Perl scripting language for nvi.
+
+perl_scripts/
+ Scripts for Perl included with nvi.
+
+regex/
+ Henry Spencer's POSIX 1003.2 regular expression (RE) library.
+
+tcl_api/
+ Source code supporting the Tcl scripting language for nvi.
+
+tcl_scripts/
+ Scripts for Tcl included with nvi.
+
+tk/
+ Source files for nvi's Tk screen support.
+
+ init.tcl -- Vi startup tcl script.
+
+vi/
+ The vi source code.
diff --git a/usr.bin/vi/ex/script.h b/contrib/nvi/LICENSE
index b21c63a2071c..78e8f4a40e19 100644
--- a/usr.bin/vi/ex/script.h
+++ b/contrib/nvi/LICENSE
@@ -1,6 +1,14 @@
+The vi program is freely redistributable. You are welcome to copy, modify
+and share it with others under the conditions listed in this file. If any
+company (not any individual!) finds vi sufficiently useful that you would
+have purchased it, or if any company wishes to redistribute it, contributions
+to the authors would be appreciated.
+
/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1991, 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,17 +37,4 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * @(#)script.h 8.2 (Berkeley) 4/17/94
*/
-
-struct _script {
- pid_t sh_pid; /* Shell pid. */
- int sh_master; /* Master pty fd. */
- int sh_slave; /* Slave pty fd. */
- char *sh_prompt; /* Prompt. */
- size_t sh_prompt_len; /* Prompt length. */
- char sh_name[64]; /* Pty name */
- struct winsize sh_win; /* Window size. */
- struct termios sh_term; /* Terminal information. */
-};
diff --git a/contrib/nvi/README b/contrib/nvi/README
new file mode 100644
index 000000000000..33db36a5c862
--- /dev/null
+++ b/contrib/nvi/README
@@ -0,0 +1,113 @@
+# @(#)README 8.147 (Berkeley) 10/19/96
+
+This is the README for nex/nvi, a freely redistributable implementation
+of the ex/vi text editors originally distributed as part of the Fourth
+Berkeley Software Distribution (4BSD), by the University of California,
+Berkeley.
+
+The source code for nex/nvi can be retrieved by using anonymous ftp to
+ftp.cs.berkeley.edu. The file ucb/4bsd/nvi.tar.gz is the gzip'd archive,
+of version 1.71 of nex/nvi. This version is believed to be stable and
+problem free. The file ucb/4bsd/nvi-###.ALPHA.tar.gz is a gzip'd archive
+of the current alpha-test release of nex/nvi. This version reflects the
+current development tree, and will be more likely to have problems.
+
+See the file:
+ build/README for information on building nvi.
+ LAYOUT for a description of where everything is.
+ LICENSE for the copyright and redistribution terms.
+
+If you have any questions about nex/nvi, problems with it, or concerns
+about the conditions for redistribution, please contact me:
+
+ Keith Bostic +1-508-287-4781
+ 394 E. Riding Dr. bostic@bostic.com
+ Carlisle, MA 01741
+ USA
+
+Keith Bostic
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+o This software is several years old and is the product of many folks' work.
+
+ This software was originally derived from software contributed to
+ the University of California, Berkeley by Steve Kirkendall, the
+ author of the vi clone elvis. Without his work, this work would
+ have been far more difficult.
+
+ IEEE POSIX 1003.2 style regular expression support is courtesy of
+ Henry Spencer, for which I am *very* grateful.
+
+ Elan Amir did the original 4BSD curses work that made it possible
+ to support a full-screen editor using curses.
+
+ George Neville-Neil added the Tcl interpreter, and the initial
+ interpreter design was his.
+
+ Sven Verdoolaege added the Perl interpreter.
+
+ Rob Mayoff provided the original Cscope support.
+
+o Many, many people suggested enhancements, and provided bug reports and
+ testing, far too many to individually thank.
+
+o From the original vi acknowledgements, by William Joy and Mark Horton:
+
+ Bruce Englar encouraged the early development of this display
+ editor. Peter Kessler helped bring sanity to version 2's
+ command layout. Bill Joy wrote versions 1 and 2.0 through 2.7,
+ and created the framework that users see in the present editor.
+ Mark Horton added macros and other features and made the editor
+ work on a large number of terminals and Unix systems.
+
+o And...
+ The financial support of UUNET Communications Services is gratefully
+ acknowledged.
+
+=-=-=-=-=-=-=-=-=-=-=
+o Status:
+
+This software is in beta test, and it's pretty stable. Almost all of the
+historic functionality in ex/vi is there, the only major missing pieces
+are open mode and the lisp edit option.
+
+Nvi is largely 8-bit clean. This isn't difficult to fix, and was left in
+during initial development to keep things simple. Wide character support
+will be integrated at the same time that it is made fully 8-bit clean.
+
+There aren't a lot of new features in nex/nvi, but there are a few things
+you might like. The "Additional Features" section of the reference work
+(docs/USD.doc/vi.ref/vi.ref.txt, docs/USD.doc/vi.ref/vi.ref.ps) has more
+information.
+
+=-=-=-=-=-=-=-=-=-=-=
+o Debugging:
+
+Code fixes are greatly appreciated, of course, but if you can't provide
+them, please email me as much information as you can as to how I might
+reproduce the bug, and I'll try to fix it locally. Stack traces of core
+dumps are only rarely helpful -- an example file with a set of keystrokes
+that causes the problem is almost invariably necessary. I know it's
+annoying, but simply playing with the bug until you can reproduce it at
+will, with minimal keystrokes, is immensely helpful to me.
+
+Please include the following in the bug report;
+
+ o The version of nvi you're running (use :version to get it).
+ o The row/column dimensions of the screen (80 x 32).
+ o Unless you're confident that they're not part of the problem,
+ your startup files (.exrc, .nexrc) and the environment variable
+ (EXINIT, NEXINIT) values. (Cutting and pasting the output
+ of ":set all" is usually sufficient.)
+
+If you want to do your own debugging, recompile the program with DEBUG
+defined. (Configuring with --enable-debug will do this for you.) This
+turns on the additional command-line option -D, that takes either s or w
+as an argument. The option -Ds causes nvi to ignore the EXINIT and
+.exrc files on startup, and -Dw causes nvi to print out the process id
+and wait for you to enter a <carriage-return> to continue.
+
+If you're running a memory checker (e.g. Purify) on nvi, you will first
+want to recompile everything with "-DPURIFY" set in the CFLAGS. This
+initializes allocated pages in the DB code, and free's allocated memory
+at the end of the nvi execution.
diff --git a/contrib/nvi/build/ExtUtils/Embed.pm b/contrib/nvi/build/ExtUtils/Embed.pm
new file mode 100644
index 000000000000..04525c18c908
--- /dev/null
+++ b/contrib/nvi/build/ExtUtils/Embed.pm
@@ -0,0 +1,473 @@
+# $Id: Embed.pm,v 1.17 1996/07/02 13:48:17 dougm Exp $
+require 5.002;
+
+package ExtUtils::Embed;
+require Exporter;
+require FileHandle;
+use Config;
+use Getopt::Std;
+
+#Only when we need them
+#require ExtUtils::MakeMaker;
+#require ExtUtils::Liblist;
+
+use vars qw(@ISA @EXPORT $VERSION
+ @Extensions $Verbose $lib_ext
+ $opt_o $opt_s
+ );
+use strict;
+
+$VERSION = sprintf("%d.%02d", q$Revision: 1.17 $ =~ /(\d+)\.(\d+)/);
+#for the namespace change
+$Devel::embed::VERSION = "99.99";
+
+sub Version { $VERSION; }
+
+@ISA = qw(Exporter);
+@EXPORT = qw(&xsinit &ldopts
+ &ccopts &ccflags &ccdlflags &perl_inc
+ &xsi_header &xsi_protos &xsi_body);
+
+#let's have Miniperl borrow from us instead
+#require ExtUtils::Miniperl;
+#*canon = \&ExtUtils::Miniperl::canon;
+
+$Verbose = 0;
+$lib_ext = $Config{lib_ext} || '.a';
+
+sub xsinit {
+ my($file, $std, $mods) = @_;
+ my($fh,@mods,%seen);
+ $file ||= "perlxsi.c";
+
+ if (@_) {
+ @mods = @$mods if $mods;
+ }
+ else {
+ getopts('o:s:');
+ $file = $opt_o if defined $opt_o;
+ $std = $opt_s if defined $opt_s;
+ @mods = @ARGV;
+ }
+ $std = 1 unless scalar @mods;
+
+ if ($file eq "STDOUT") {
+ $fh = \*STDOUT;
+ }
+ else {
+ $fh = new FileHandle "> $file";
+ }
+
+ push(@mods, static_ext()) if defined $std;
+ @mods = grep(!$seen{$_}++, @mods);
+
+ print $fh &xsi_header();
+ print $fh "EXTERN_C void xs_init _((void));\n\n";
+ print $fh &xsi_protos(@mods);
+
+ print $fh "\nEXTERN_C void\nxs_init()\n{\n";
+ print $fh &xsi_body(@mods);
+ print $fh "}\n";
+
+}
+
+sub xsi_header {
+ return <<EOF;
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <EXTERN.h>
+#include <perl.h>
+
+#ifdef __cplusplus
+}
+# ifndef EXTERN_C
+# define EXTERN_C extern "C"
+# endif
+#else
+# ifndef EXTERN_C
+# define EXTERN_C extern
+# endif
+#endif
+
+EOF
+}
+
+sub xsi_protos {
+ my(@exts) = @_;
+ my(@retval,%seen);
+
+ foreach $_ (@exts){
+ my($pname) = canon('/', $_);
+ my($mname, $cname);
+ ($mname = $pname) =~ s!/!::!g;
+ ($cname = $pname) =~ s!/!__!g;
+ my($ccode) = "EXTERN_C void boot_${cname} _((CV* cv));\n";
+ next if $seen{$ccode}++;
+ push(@retval, $ccode);
+ }
+ return join '', @retval;
+}
+
+sub xsi_body {
+ my(@exts) = @_;
+ my($pname,@retval,%seen);
+ my($dl) = canon('/','DynaLoader');
+ push(@retval, "\tdXSUB_SYS;\n") if $] > 5.002;
+ push(@retval, "\tchar *file = __FILE__;\n\n");
+
+ foreach $_ (@exts){
+ my($pname) = canon('/', $_);
+ my($mname, $cname, $ccode);
+ ($mname = $pname) =~ s!/!::!g;
+ ($cname = $pname) =~ s!/!__!g;
+ if ($pname eq $dl){
+ # Must NOT install 'DynaLoader::boot_DynaLoader' as 'bootstrap'!
+ # boot_DynaLoader is called directly in DynaLoader.pm
+ $ccode = "\t/* DynaLoader is a special case */\n\tnewXS(\"${mname}::boot_${cname}\", boot_${cname}, file);\n";
+ push(@retval, $ccode) unless $seen{$ccode}++;
+ } else {
+ $ccode = "\tnewXS(\"${mname}::bootstrap\", boot_${cname}, file);\n";
+ push(@retval, $ccode) unless $seen{$ccode}++;
+ }
+ }
+ return join '', @retval;
+}
+
+sub static_ext {
+ unless (scalar @Extensions) {
+ @Extensions = sort split /\s+/, $Config{static_ext};
+ unshift @Extensions, qw(DynaLoader);
+ }
+ @Extensions;
+}
+
+sub ldopts {
+ require ExtUtils::MakeMaker;
+ require ExtUtils::Liblist;
+ my($std,$mods,$link_args,$path) = @_;
+ my(@mods,@link_args,@argv);
+ my($dllib,$config_libs,@potential_libs,@path);
+ local($") = ' ' unless $" eq ' ';
+ my $MM = bless {} => 'MY';
+ if (scalar @_) {
+ @link_args = @$link_args if $link_args;
+ @mods = @$mods if $mods;
+ }
+ else {
+ @argv = @ARGV;
+ #hmm
+ while($_ = shift @argv) {
+ /^-std$/ && do { $std = 1; next; };
+ /^--$/ && do { @link_args = @argv; last; };
+ /^-I(.*)/ && do { $path = $1 || shift @argv; next; };
+ push(@mods, $_);
+ }
+ }
+ $std = 1 unless scalar @link_args;
+ @path = $path ? split(/:/, $path) : @INC;
+
+ push(@potential_libs, @link_args) if scalar @link_args;
+ push(@potential_libs, $Config{libs}) if defined $std;
+
+ push(@mods, static_ext()) if $std;
+
+ my($mod,@ns,$root,$sub,$extra,$archive,@archives);
+ print STDERR "Searching (@path) for archives\n" if $Verbose;
+ foreach $mod (@mods) {
+ @ns = split('::', $mod);
+ $sub = $ns[-1];
+ $root = $MM->catdir(@ns);
+
+ print STDERR "searching for '$sub${lib_ext}'\n" if $Verbose;
+ foreach (@path) {
+ next unless -e ($archive = $MM->catdir($_,"auto",$root,"$sub$lib_ext"));
+ push @archives, $archive;
+ if(-e ($extra = $MM->catdir($_,"auto",$root,"extralibs.ld"))) {
+ local(*FH);
+ if(open(FH, $extra)) {
+ my($libs) = <FH>; chomp $libs;
+ push @potential_libs, split /\s+/, $libs;
+ }
+ else {
+ warn "Couldn't open '$extra'";
+ }
+ }
+ last;
+ }
+ }
+ #print STDERR "\@potential_libs = @potential_libs\n";
+
+ my($extralibs, $bsloadlibs, $ldloadlibs, $ld_run_path) =
+ $MM->ext(join ' ',
+ $MM->catdir("-L$Config{archlib}", "CORE"), " -lperl",
+ @potential_libs);
+
+ my $ld_or_bs = $bsloadlibs || $ldloadlibs;
+ print STDERR "bs: $bsloadlibs ** ld: $ldloadlibs" if $Verbose;
+ my $linkage = "$Config{ldflags} @archives $ld_or_bs";
+ print STDERR "ldopts: '$linkage'\n" if $Verbose;
+
+ return $linkage if scalar @_;
+ print "$linkage\n";
+}
+
+sub ccflags {
+ print " $Config{ccflags} ";
+}
+
+sub ccdlflags {
+ print " $Config{ccdlflags} ";
+}
+
+sub perl_inc {
+ print " -I$Config{archlib}/CORE ";
+}
+
+sub ccopts {
+ ccflags;
+ ccdlflags;
+ perl_inc;
+}
+
+sub canon {
+ my($as, @ext) = @_;
+ foreach(@ext) {
+ # might be X::Y or lib/auto/X/Y/Y.a
+ next if s!::!/!g;
+ s:^(lib|ext)/(auto/)?::;
+ s:/\w+\.\w+$::;
+ }
+ grep(s:/:$as:, @ext) if ($as ne '/');
+ @ext;
+}
+
+__END__
+
+=head1 NAME
+
+ExtUtils::Embed - Utilities for embedding Perl in C/C++ applications
+
+=head1 SYNOPSIS
+
+
+ perl -MExtUtils::Embed -e xsinit
+ perl -MExtUtils::Embed -e ldopts
+
+=head1 DESCRIPTION
+
+ExtUtils::Embed provides utility functions for embedding a Perl interpreter
+and extensions in your C/C++ applications.
+Typically, an application B<Makefile> will invoke ExtUtils::Embed
+functions while building your application.
+
+=head1 @EXPORT
+
+ExtUtils::Embed exports the following functions:
+
+L<xsinit()>, L<ldopts()>, L<ccopts()>, L<perl_inc()>, L<ccflags()>,
+L<ccdlflags()>, L<xsi_header()>, L<xsi_protos()>, L<xsi_body()>
+
+=head1 FUNCTIONS
+
+=item xsinit()
+
+Generate C/C++ code for the XS intializer function.
+
+When invoked as C<`perl -MExtUtils::Embed -e xsinit --`>
+the following options are recognized:
+
+B<-o> <output filename> (Defaults to B<perlxsi.c>)
+
+B<-o STDOUT> will print to STDOUT.
+
+B<-std> (Write code for extensions that are linked with the current Perl.)
+
+Any additional arguments are expected to be names of modules
+to generate code for.
+
+When invoked with parameters the following are accepted and optional:
+
+C<xsinit($filename,$std,[@modules])>
+
+Where,
+
+B<$filename> is equivalent to the B<-o> option.
+
+B<$std> is boolean, equivalent to the B<-std> option.
+
+B<[@modules]> is an array ref, same as additional arguments mentioned above.
+
+=item Examples
+
+
+ perl -MExtUtils::Embed -e xsinit -- -o xsinit.c Socket
+
+
+This will generate code with an B<xs_init> function that glues the perl B<Socket::bootstrap> function
+to the C B<boot_Socket> function and writes it to a file named "xsinit.c".
+
+Note that B<DynaLoader> is a special case where it must call B<boot_DynaLoader> directly.
+
+ perl -MExtUtils::Embed -e xsinit
+
+
+This will generate code for linking with B<DynaLoader> and
+each static extension found in B<$Config{static_ext}>.
+The code is written to the default file name B<perlxsi.c>.
+
+
+ perl -MExtUtils::Embed -e xsinit -- -o xsinit.c -std DBI DBD::Oracle
+
+
+Here, code is written for all the currently linked extensions along with code
+for B<DBI> and B<DBD::Oracle>.
+
+If you have a working B<DynaLoader> then there is rarely any need to statically link in any
+other extensions.
+
+=item ldopts()
+
+Output arguments for linking the Perl library and extensions to your
+application.
+
+When invoked as C<`perl -MExtUtils::Embed -e ldopts --`>
+the following options are recognized:
+
+B<-std>
+
+Output arguments for linking the Perl library and any extensions linked
+with the current Perl.
+
+B<-I> <path1:path2>
+
+Search path for ModuleName.a archives.
+Default path is B<@INC>.
+Library archives are expected to be found as
+B</some/path/auto/ModuleName/ModuleName.a>
+For example, when looking for B<Socket.a> relative to a search path,
+we should find B<auto/Socket/Socket.a>
+
+When looking for B<DBD::Oracle> relative to a search path,
+we should find B<auto/DBD/Oracle/Oracle.a>
+
+Keep in mind, you can always supply B</my/own/path/ModuleName.a>
+as an additional linker argument.
+
+B<--> <list of linker args>
+
+Additional linker arguments to be considered.
+
+Any additional arguments found before the B<--> token
+are expected to be names of modules to generate code for.
+
+When invoked with parameters the following are accepted and optional:
+
+C<ldopts($std,[@modules],[@link_args],$path)>
+
+Where,
+
+B<$std> is boolean, equivalent to the B<-std> option.
+
+B<[@modules]> is equivalent to additional arguments found before the B<--> token.
+
+B<[@link_args]> is equivalent to arguments found after the B<--> token.
+
+B<$path> is equivalent to the B<-I> option.
+
+In addition, when ldopts is called with parameters, it will return the argument string
+rather than print it to STDOUT.
+
+=item Examples
+
+
+ perl -MExtUtils::Embed -e ldopts
+
+
+This will print arguments for linking with B<libperl.a>, B<DynaLoader> and
+extensions found in B<$Config{static_ext}>. This includes libraries
+found in B<$Config{libs}> and the first ModuleName.a library
+for each extension that is found by searching B<@INC> or the path
+specifed by the B<-I> option.
+In addition, when ModuleName.a is found, additional linker arguments
+are picked up from the B<extralibs.ld> file in the same directory.
+
+
+ perl -MExtUtils::Embed -e ldopts -- -std Socket
+
+
+This will do the same as the above example, along with printing additional arguments for linking with the B<Socket> extension.
+
+
+ perl -MExtUtils::Embed -e ldopts -- DynaLoader
+
+
+This will print arguments for linking with just the B<DynaLoader> extension
+and B<libperl.a>.
+
+
+ perl -MExtUtils::Embed -e ldopts -- -std Msql -- -L/usr/msql/lib -lmsql
+
+
+Any arguments after the second '--' token are additional linker
+arguments that will be examined for potential conflict. If there is no
+conflict, the additional arguments will be part of the output.
+
+
+=item perl_inc()
+
+For including perl header files this function simply prints:
+
+ -I $Config{archlib}/CORE
+
+So, rather than having to say:
+
+ perl -MConfig -e 'print "-I $Config{archlib}/CORE"'
+
+Just say:
+
+ perl -MExtUtils::Embed -e perl_inc
+
+=item ccflags(), ccdlflags()
+
+These functions simply print $Config{ccflags} and $Config{ccdlflags}
+
+=item ccopts()
+
+This function combines perl_inc(), ccflags() and ccdlflags() into one.
+
+=item xsi_header()
+
+This function simply returns a string defining the same B<EXTERN_C> macro as
+B<perlmain.c> along with #including B<perl.h> and B<EXTERN.h>.
+
+=item xsi_protos(@modules)
+
+This function returns a string of B<boot_$ModuleName> prototypes for each @modules.
+
+=item xsi_body(@modules)
+
+This function returns a string of calls to B<newXS()> that glue the module B<bootstrap>
+function to B<boot_ModuleName> for each @modules.
+
+B<xsinit()> uses the xsi_* functions to generate most of it's code.
+
+=head1 EXAMPLES
+
+For examples on how to use B<ExtUtils::Embed> for building C/C++ applications
+with embedded perl, see the eg/ directory and the I<perlembed> man page.
+
+=head1 SEE ALSO
+
+the I<perlembed> man page
+
+=head1 AUTHOR
+
+Doug MacEachern <dougm@osf.org>
+
+Based on ideas from Tim Bunce <Tim.Bunce@ig.co.uk> and
+B<minimod.pl> by Andreas Koenig <k@anna.in-berlin.de> and Tim Bunce.
+
+=cut
+
diff --git a/contrib/nvi/build/Makefile.in b/contrib/nvi/build/Makefile.in
new file mode 100644
index 000000000000..54025e7d3b9d
--- /dev/null
+++ b/contrib/nvi/build/Makefile.in
@@ -0,0 +1,630 @@
+# @(#)Makefile.in 8.75 (Berkeley) 10/23/96
+
+srcdir= @srcdir@/..
+CC= @CC@
+OPTFLAG=@OPTFLAG@
+CFLAGS= -c $(OPTFLAG) @CFLAGS@ -I. -I$(srcdir)/include @CPPFLAGS@
+LDFLAGS=@LDFLAGS@
+PERL= @vi_cv_path_perl@
+PERLLIB=@vi_cv_perllib@
+SHRPENV=@shrpenv@
+
+# Objects
+COBJS= addbytes.o addch.o box.o clear.o clrtobot.o clrtoeol.o \
+ cr_put.o ctrace.o cur_hash.o curses.o delch.o deleteln.o delwin.o \
+ erase.o fullname.o getch.o getstr.o id_subwins.o idlok.o initscr.o \
+ insch.o insertln.o longname.o move.o mvwin.o newwin.o overlay.o \
+ overwrite.o putchar.o refresh.o scroll.o setterm.o standout.o \
+ toucholap.o touchwin.o tscroll.o tstp.o tty.o unctrl.o waddnstr.o
+CLOBJS= cl_bsd.o cl_funcs.o cl_main.o cl_read.o cl_screen.o cl_term.o
+DBOBJS= db.o mpool.o \
+ bt_close.o bt_conv.o bt_debug.o bt_delete.o bt_get.o bt_open.o \
+ bt_overflow.o bt_page.o bt_put.o bt_search.o bt_seq.o \
+ bt_split.o bt_utils.o \
+ rec_close.o rec_delete.o rec_get.o rec_open.o rec_put.o \
+ rec_search.o rec_seq.o rec_utils.o
+REOBJS= regcomp.o regerror.o regexec.o regfree.o
+TKOBJS= tk_funcs.o tk_main.o tk_read.o tk_screen.o tk_term.o tk_util.o
+VIOBJS= cut.o delete.o ex.o ex_abbrev.o ex_append.o ex_args.o ex_argv.o \
+ ex_at.o ex_bang.o ex_cd.o ex_cmd.o ex_cscope.o ex_delete.o \
+ ex_display.o ex_edit.o ex_equal.o ex_file.o ex_filter.o \
+ ex_global.o ex_init.o ex_join.o ex_map.o ex_mark.o ex_mkexrc.o \
+ ex_move.o ex_open.o ex_perl.o ex_preserve.o ex_print.o ex_put.o \
+ ex_quit.o ex_read.o ex_screen.o ex_script.o ex_set.o ex_shell.o \
+ ex_shift.o ex_source.o ex_stop.o ex_subst.o ex_tag.o ex_tcl.o \
+ ex_txt.o ex_undo.o ex_usage.o ex_util.o ex_version.o ex_visual.o \
+ ex_write.o ex_yank.o ex_z.o exf.o getc.o key.o line.o log.o main.o \
+ mark.o msg.o options.o options_f.o put.o recover.o screen.o \
+ search.o seq.o util.o v_at.o v_ch.o v_cmd.o v_delete.o v_ex.o \
+ v_increment.o v_init.o v_itxt.o v_left.o v_mark.o v_match.o \
+ v_paragraph.o v_put.o v_redraw.o v_replace.o v_right.o v_screen.o \
+ v_scroll.o v_search.o v_section.o v_sentence.o v_status.o v_txt.o \
+ v_ulcase.o v_undo.o v_util.o v_word.o v_xchar.o v_yank.o v_z.o \
+ v_zexit.o vi.o vs_line.o vs_msg.o vs_refresh.o vs_relative.o \
+ vs_smap.o vs_split.o
+
+all: nvi @tknvi@
+
+NVIALL= $(CLOBJS) $(VIOBJS) @cobjs@ @LIBOBJS@
+nvi nex: $(NVIALL)
+ $(SHRPENV) $(CC) $(LDFLAGS) -o $@ $(NVIALL) @LIBS@
+ -rm -f nex
+ ln $@ nex
+
+TKALL= $(TKOBJS) $(VIOBJS) @LIBOBJS@
+tknvi: $(TKALL)
+ $(SHRPENV) $(CC) $(LDFLAGS) -o $@ $(TKALL) @TKLIBS@
+
+chmod= @vi_cv_path_chmod@
+cp= @vi_cv_path_cp@
+ln= @vi_cv_path_ln@
+mkdir= @vi_cv_path_mkdir@
+rm= @vi_cv_path_rm@
+strip= @vi_cv_path_strip@
+
+prefix= @prefix@
+bindir= @bindir@
+datadir=@datadir@
+mandir= @mandir@
+exec_prefix=@exec_prefix@
+
+dmode= 755
+emode= 555
+fmode= 444
+
+transform=@program_transform_name@
+
+install: all install_common
+ @echo "Installing vi, ex, view: $(bindir) ..."
+ [ -d $(bindir) ] || \
+ ($(mkdir) $(bindir) && $(chmod) $(dmode) $(bindir))
+ cd $(bindir) && $(rm) -f `echo vi | sed '$(transform)'`
+ $(cp) nvi $(bindir)/`echo vi | sed '$(transform)'`
+ cd $(bindir) && [ -f $(strip) ] && \
+ $(strip) `echo vi | sed '$(transform)'`
+ cd $(bindir) && $(chmod) $(emode) `echo vi | sed '$(transform)'`
+ cd $(bindir) && $(rm) -f `echo ex | sed '$(transform)'`
+ cd $(bindir) && $(rm) -f `echo view | sed '$(transform)'`
+ cd $(bindir) && $(ln) \
+ `echo vi | sed '$(transform)'` `echo ex | sed '$(transform)'`
+ cd $(bindir) && $(ln) \
+ `echo vi | sed '$(transform)'` `echo view | sed '$(transform)'`
+ [ -d $(mandir) ] || \
+ ($(mkdir) $(mandir) && $(chmod) $(dmode) $(mandir))
+ [ -d $(mandir)/cat1 ] || \
+ ($(mkdir) $(mandir)/cat1 && $(chmod) $(dmode) $(mandir)/cat1)
+ @echo "Installing man pages: $(mandir) ..."
+ cd $(mandir)/cat1 && $(rm) -f `echo vi.0 | sed '$(transform)'`
+ $(cp) $(srcdir)/docs/USD.doc/vi.man/vi.0 \
+ $(mandir)/cat1/`echo vi.0 | sed '$(transform)'`
+ cd $(mandir)/cat1 && $(chmod) $(fmode) `echo vi.0 | sed '$(transform)'`
+ cd $(mandir)/cat1 && $(rm) -f `echo ex.0 | sed '$(transform)'`
+ cd $(mandir)/cat1 && $(rm) -f `echo view.0 | sed '$(transform)'`
+ cd $(mandir)/cat1 && $(ln) \
+ `echo vi.0 | sed '$(transform)'` `echo ex.0 | sed '$(transform)'`
+ cd $(mandir)/cat1 && $(ln) \
+ `echo vi.0 | sed '$(transform)'` `echo view.0 | sed '$(transform)'`
+ [ -d $(mandir)/man1 ] || \
+ ($(mkdir) $(mandir)/man1 && $(chmod) $(dmode) $(mandir)/man1)
+ cd $(mandir)/man1 && $(rm) -f `echo vi.1 | sed '$(transform)'`
+ $(cp) $(srcdir)/docs/USD.doc/vi.man/vi.1 \
+ $(mandir)/man1/`echo vi.1 | sed '$(transform)'`
+ cd $(mandir)/man1 && $(chmod) $(fmode) `echo vi.1 | sed '$(transform)'`
+ cd $(mandir)/man1 && $(rm) -f `echo ex.1 | sed '$(transform)'`
+ cd $(mandir)/man1 && $(rm) -f `echo view.1 | sed '$(transform)'`
+ cd $(mandir)/man1 && $(ln) \
+ `echo vi.1 | sed '$(transform)'` `echo ex.1 | sed '$(transform)'`
+ cd $(mandir)/man1 && $(ln) \
+ `echo vi.1 | sed '$(transform)'` `echo view.1 | sed '$(transform)'`
+
+cat= dutch english french german ru_SU.KOI8-R spanish swedish
+install_common:
+ [ -f $(chmod) ]
+ [ -f $(cp) ]
+ [ -f $(ln) ]
+ [ -f $(mkdir) ]
+ [ -f $(rm) ]
+ [ -d $(prefix) ] || \
+ ($(mkdir) $(prefix) && $(chmod) $(dmode) $(prefix))
+ [ -d $(exec_prefix) ] || \
+ ($(mkdir) $(exec_prefix) && $(chmod) $(dmode) $(exec_prefix))
+ [ -d $(datadir) ] || \
+ ($(mkdir) $(datadir) && $(chmod) $(dmode) $(datadir))
+ $(rm) -rf $(datadir)/vi
+ $(mkdir) $(datadir)/vi && $(chmod) $(dmode) $(datadir)/vi
+ @echo "Installing message catalogs: $(datadir)/vi/catalog ..."
+ $(mkdir) $(datadir)/vi/catalog && \
+ $(chmod) $(dmode) $(datadir)/vi/catalog
+ (cd $(srcdir)/catalog && $(cp) $(cat) $(datadir)/vi/catalog && \
+ cd $(datadir)/vi/catalog && $(chmod) $(fmode) *)
+ @echo "Installing Perl scripts: $(datadir)/vi/perl ..."
+ $(mkdir) $(datadir)/vi/perl && $(chmod) $(dmode) $(datadir)/vi/perl
+ [ -f VI.pm ] && $(cp) VI.pm $(datadir)/vi/perl && \
+ cd $(datadir)/vi/perl && $(chmod) $(fmode) VI.pm)
+ (cd $(srcdir)/perl_scripts && $(cp) *.pl $(datadir)/vi/perl && \
+ cd $(datadir)/vi/perl && $(chmod) $(fmode) *.pl)
+ @echo "Installing Tcl scripts: $(datadir)/vi/tcl ..."
+ $(mkdir) $(datadir)/vi/tcl && $(chmod) $(dmode) $(datadir)/vi/tcl
+ (cd $(srcdir)/tcl_scripts && $(cp) *.tcl $(datadir)/vi/tcl && \
+ cd $(datadir)/vi/tcl && $(chmod) $(fmode) *.tcl)
+ @echo "Installing recover script: $(datadir)/vi/recover ..."
+ ($(cp) recover $(datadir)/vi/recover && \
+ $(chmod) $(emode) $(datadir)/vi/recover)
+
+uninstall:
+ $(rm) -rf $(datadir)/vi
+ cd $(bindir) && $(rm) -f `echo ex | sed '$(transform)'`
+ cd $(bindir) && $(rm) -f `echo vi | sed '$(transform)'`
+ cd $(bindir) && $(rm) -f `echo view | sed '$(transform)'`
+ cd $(mandir)/cat1 && $(rm) -f `echo ex.0 | sed '$(transform)'`
+ cd $(mandir)/cat1 && $(rm) -f `echo vi.0 | sed '$(transform)'`
+ cd $(mandir)/cat1 && $(rm) -f `echo view.0 | sed '$(transform)'`
+ cd $(mandir)/man1 && $(rm) -f `echo ex.1 | sed '$(transform)'`
+ cd $(mandir)/man1 && $(rm) -f `echo vi.1 | sed '$(transform)'`
+ cd $(mandir)/man1 && $(rm) -f `echo view.1 | sed '$(transform)'`
+
+docs:
+ cd $(srcdir)/docs/USD.doc/vi.ref && $(MAKE)
+ cd $(srcdir)/docs/USD.doc/vi.man && $(MAKE)
+ cd $(srcdir)/docs/USD.doc/edit && $(MAKE)
+ cd $(srcdir)/docs/USD.doc/exref && $(MAKE)
+ cd $(srcdir)/docs/USD.doc/vitut && $(MAKE)
+
+clean:
+ -rm -f *.core *.o memcpy.c perl.c
+ -rm -f nex nvi tknvi core
+ -rm -f $(COBJS) $(CLOBJS) $(DBOBJS) $(REOBJS)
+ -rm -f $(TKOBJS) $(VIOBJS)
+
+cleandocs:
+ cd $(srcdir)/docs/USD.doc/vi.ref && $(MAKE) clean
+ cd $(srcdir)/docs/USD.doc/vi.man && $(MAKE) clean
+ cd $(srcdir)/docs/USD.doc/edit && $(MAKE) clean
+ cd $(srcdir)/docs/USD.doc/exref && $(MAKE) clean
+ cd $(srcdir)/docs/USD.doc/vitut && $(MAKE) clean
+
+distclean maintainer-clean realclean: clean cleandocs
+ -rm -f Makefile config.cache config.h config.log config.status
+ -rm -f pathnames.h port.h
+
+# Vi curses sources.
+cl_bsd.o: $(srcdir)/cl/cl_bsd.c
+ $(CC) $(CFLAGS) $?
+cl_funcs.o: $(srcdir)/cl/cl_funcs.c
+ $(CC) $(CFLAGS) $?
+cl_main.o: $(srcdir)/cl/cl_main.c
+ $(CC) $(CFLAGS) $?
+cl_read.o: $(srcdir)/cl/cl_read.c
+ $(CC) $(CFLAGS) $?
+cl_screen.o: $(srcdir)/cl/cl_screen.c
+ $(CC) $(CFLAGS) $?
+cl_term.o: $(srcdir)/cl/cl_term.c
+ $(CC) $(CFLAGS) $?
+
+# Vi Tk sources.
+tk_funcs.o: $(srcdir)/tk/tk_funcs.c
+ $(CC) $(CFLAGS) @XINCS@ $?
+tk_main.o: $(srcdir)/tk/tk_main.c
+ $(CC) $(CFLAGS) @XINCS@ $?
+tk_read.o: $(srcdir)/tk/tk_read.c
+ $(CC) $(CFLAGS) @XINCS@ $?
+tk_screen.o: $(srcdir)/tk/tk_screen.c
+ $(CC) $(CFLAGS) @XINCS@ $?
+tk_term.o: $(srcdir)/tk/tk_term.c
+ $(CC) $(CFLAGS) @XINCS@ $?
+tk_util.o: $(srcdir)/tk/tk_util.c
+ $(CC) $(CFLAGS) @XINCS@ $?
+
+# Vi Tcl/Perl interpreter sources.
+api.o: $(srcdir)/common/api.c
+ $(CC) $(CFLAGS) $?
+perl.c: $(srcdir)/perl_api/perl.xs $(srcdir)/perl_api/typemap
+ echo "#define _PATH_PERLSCRIPTS \"$(datadir)/vi/perl\"" > $@
+ $(PERL) $(PERLLIB)/ExtUtils/xsubpp -typemap \
+ $(PERLLIB)/ExtUtils/typemap $(srcdir)/perl_api/perl.xs >> $@
+ ($(PERL) -ne 'print "sub $$1 {\$$curscr->$$1(\@_)}\n" \
+ if /newXS\("VI::([^":]*)"/;' $@ ; echo "1;") > VI.pm
+perl.o: perl.c
+ $(CC) $(CFLAGS) $?
+perlsfio.o: $(srcdir)/perl_api/perlsfio.c
+ $(CC) $(CFLAGS) $?
+tcl.o: $(srcdir)/tcl_api/tcl.c
+ $(CC) $(CFLAGS) $?
+
+# Vi sources.
+cut.o: $(srcdir)/common/cut.c
+ $(CC) $(CFLAGS) $?
+delete.o: $(srcdir)/common/delete.c
+ $(CC) $(CFLAGS) $?
+exf.o: $(srcdir)/common/exf.c
+ $(CC) $(CFLAGS) $?
+key.o: $(srcdir)/common/key.c
+ $(CC) $(CFLAGS) $?
+line.o: $(srcdir)/common/line.c
+ $(CC) $(CFLAGS) $?
+log.o: $(srcdir)/common/log.c
+ $(CC) $(CFLAGS) $?
+main.o: $(srcdir)/common/main.c
+ $(CC) $(CFLAGS) $?
+mark.o: $(srcdir)/common/mark.c
+ $(CC) $(CFLAGS) $?
+msg.o: $(srcdir)/common/msg.c
+ $(CC) $(CFLAGS) $?
+options.o: $(srcdir)/common/options.c
+ $(CC) $(CFLAGS) $?
+options_f.o: $(srcdir)/common/options_f.c
+ $(CC) $(CFLAGS) $?
+put.o: $(srcdir)/common/put.c
+ $(CC) $(CFLAGS) $?
+screen.o: $(srcdir)/common/screen.c
+ $(CC) $(CFLAGS) $?
+search.o: $(srcdir)/common/search.c
+ $(CC) $(CFLAGS) $?
+seq.o: $(srcdir)/common/seq.c
+ $(CC) $(CFLAGS) $?
+recover.o: $(srcdir)/common/recover.c
+ $(CC) $(CFLAGS) $?
+util.o: $(srcdir)/common/util.c
+ $(CC) $(CFLAGS) $?
+ex.o: $(srcdir)/ex/ex.c
+ $(CC) $(CFLAGS) $?
+ex_abbrev.o: $(srcdir)/ex/ex_abbrev.c
+ $(CC) $(CFLAGS) $?
+ex_append.o: $(srcdir)/ex/ex_append.c
+ $(CC) $(CFLAGS) $?
+ex_args.o: $(srcdir)/ex/ex_args.c
+ $(CC) $(CFLAGS) $?
+ex_argv.o: $(srcdir)/ex/ex_argv.c
+ $(CC) $(CFLAGS) $?
+ex_at.o: $(srcdir)/ex/ex_at.c
+ $(CC) $(CFLAGS) $?
+ex_bang.o: $(srcdir)/ex/ex_bang.c
+ $(CC) $(CFLAGS) $?
+ex_cd.o: $(srcdir)/ex/ex_cd.c
+ $(CC) $(CFLAGS) $?
+ex_cmd.o: $(srcdir)/ex/ex_cmd.c
+ $(CC) $(CFLAGS) $?
+ex_cscope.o: $(srcdir)/ex/ex_cscope.c
+ $(CC) $(CFLAGS) $?
+ex_delete.o: $(srcdir)/ex/ex_delete.c
+ $(CC) $(CFLAGS) $?
+ex_digraph.o: $(srcdir)/ex/ex_digraph.c
+ $(CC) $(CFLAGS) $?
+ex_display.o: $(srcdir)/ex/ex_display.c
+ $(CC) $(CFLAGS) $?
+ex_edit.o: $(srcdir)/ex/ex_edit.c
+ $(CC) $(CFLAGS) $?
+ex_equal.o: $(srcdir)/ex/ex_equal.c
+ $(CC) $(CFLAGS) $?
+ex_file.o: $(srcdir)/ex/ex_file.c
+ $(CC) $(CFLAGS) $?
+ex_filter.o: $(srcdir)/ex/ex_filter.c
+ $(CC) $(CFLAGS) $?
+ex_global.o: $(srcdir)/ex/ex_global.c
+ $(CC) $(CFLAGS) $?
+ex_init.o: $(srcdir)/ex/ex_init.c
+ $(CC) $(CFLAGS) $?
+ex_join.o: $(srcdir)/ex/ex_join.c
+ $(CC) $(CFLAGS) $?
+ex_map.o: $(srcdir)/ex/ex_map.c
+ $(CC) $(CFLAGS) $?
+ex_mark.o: $(srcdir)/ex/ex_mark.c
+ $(CC) $(CFLAGS) $?
+ex_mkexrc.o: $(srcdir)/ex/ex_mkexrc.c
+ $(CC) $(CFLAGS) $?
+ex_move.o: $(srcdir)/ex/ex_move.c
+ $(CC) $(CFLAGS) $?
+ex_open.o: $(srcdir)/ex/ex_open.c
+ $(CC) $(CFLAGS) $?
+ex_perl.o: $(srcdir)/ex/ex_perl.c
+ $(CC) $(CFLAGS) $?
+ex_preserve.o: $(srcdir)/ex/ex_preserve.c
+ $(CC) $(CFLAGS) $?
+ex_print.o: $(srcdir)/ex/ex_print.c
+ $(CC) $(CFLAGS) $?
+ex_put.o: $(srcdir)/ex/ex_put.c
+ $(CC) $(CFLAGS) $?
+ex_quit.o: $(srcdir)/ex/ex_quit.c
+ $(CC) $(CFLAGS) $?
+ex_read.o: $(srcdir)/ex/ex_read.c
+ $(CC) $(CFLAGS) $?
+ex_screen.o: $(srcdir)/ex/ex_screen.c
+ $(CC) $(CFLAGS) $?
+ex_script.o: $(srcdir)/ex/ex_script.c
+ $(CC) $(CFLAGS) $?
+ex_set.o: $(srcdir)/ex/ex_set.c
+ $(CC) $(CFLAGS) $?
+ex_shell.o: $(srcdir)/ex/ex_shell.c
+ $(CC) $(CFLAGS) $?
+ex_shift.o: $(srcdir)/ex/ex_shift.c
+ $(CC) $(CFLAGS) $?
+ex_source.o: $(srcdir)/ex/ex_source.c
+ $(CC) $(CFLAGS) $?
+ex_stop.o: $(srcdir)/ex/ex_stop.c
+ $(CC) $(CFLAGS) $?
+ex_subst.o: $(srcdir)/ex/ex_subst.c
+ $(CC) $(CFLAGS) $?
+ex_tag.o: $(srcdir)/ex/ex_tag.c
+ $(CC) $(CFLAGS) $?
+ex_tcl.o: $(srcdir)/ex/ex_tcl.c
+ $(CC) $(CFLAGS) $?
+ex_txt.o: $(srcdir)/ex/ex_txt.c
+ $(CC) $(CFLAGS) $?
+ex_undo.o: $(srcdir)/ex/ex_undo.c
+ $(CC) $(CFLAGS) $?
+ex_usage.o: $(srcdir)/ex/ex_usage.c
+ $(CC) $(CFLAGS) $?
+ex_util.o: $(srcdir)/ex/ex_util.c
+ $(CC) $(CFLAGS) $?
+ex_version.o: $(srcdir)/ex/ex_version.c
+ $(CC) $(CFLAGS) $?
+ex_visual.o: $(srcdir)/ex/ex_visual.c
+ $(CC) $(CFLAGS) $?
+ex_write.o: $(srcdir)/ex/ex_write.c
+ $(CC) $(CFLAGS) $?
+ex_yank.o: $(srcdir)/ex/ex_yank.c
+ $(CC) $(CFLAGS) $?
+ex_z.o: $(srcdir)/ex/ex_z.c
+ $(CC) $(CFLAGS) $?
+getc.o: $(srcdir)/vi/getc.c
+ $(CC) $(CFLAGS) $?
+v_at.o: $(srcdir)/vi/v_at.c
+ $(CC) $(CFLAGS) $?
+v_ch.o: $(srcdir)/vi/v_ch.c
+ $(CC) $(CFLAGS) $?
+v_cmd.o: $(srcdir)/vi/v_cmd.c
+ $(CC) $(CFLAGS) $?
+v_delete.o: $(srcdir)/vi/v_delete.c
+ $(CC) $(CFLAGS) $?
+v_ex.o: $(srcdir)/vi/v_ex.c
+ $(CC) $(CFLAGS) $?
+v_increment.o: $(srcdir)/vi/v_increment.c
+ $(CC) $(CFLAGS) $?
+v_init.o: $(srcdir)/vi/v_init.c
+ $(CC) $(CFLAGS) $?
+v_itxt.o: $(srcdir)/vi/v_itxt.c
+ $(CC) $(CFLAGS) $?
+v_left.o: $(srcdir)/vi/v_left.c
+ $(CC) $(CFLAGS) $?
+v_mark.o: $(srcdir)/vi/v_mark.c
+ $(CC) $(CFLAGS) $?
+v_match.o: $(srcdir)/vi/v_match.c
+ $(CC) $(CFLAGS) $?
+v_paragraph.o: $(srcdir)/vi/v_paragraph.c
+ $(CC) $(CFLAGS) $?
+v_put.o: $(srcdir)/vi/v_put.c
+ $(CC) $(CFLAGS) $?
+v_redraw.o: $(srcdir)/vi/v_redraw.c
+ $(CC) $(CFLAGS) $?
+v_replace.o: $(srcdir)/vi/v_replace.c
+ $(CC) $(CFLAGS) $?
+v_right.o: $(srcdir)/vi/v_right.c
+ $(CC) $(CFLAGS) $?
+v_screen.o: $(srcdir)/vi/v_screen.c
+ $(CC) $(CFLAGS) $?
+v_scroll.o: $(srcdir)/vi/v_scroll.c
+ $(CC) $(CFLAGS) $?
+v_search.o: $(srcdir)/vi/v_search.c
+ $(CC) $(CFLAGS) $?
+v_section.o: $(srcdir)/vi/v_section.c
+ $(CC) $(CFLAGS) $?
+v_sentence.o: $(srcdir)/vi/v_sentence.c
+ $(CC) $(CFLAGS) $?
+v_status.o: $(srcdir)/vi/v_status.c
+ $(CC) $(CFLAGS) $?
+v_txt.o: $(srcdir)/vi/v_txt.c
+ $(CC) -c @no_op_OPTFLAG@ @CFLAGS@ -I. -I$(srcdir)/include @CPPFLAGS@ $?
+v_ulcase.o: $(srcdir)/vi/v_ulcase.c
+ $(CC) $(CFLAGS) $?
+v_undo.o: $(srcdir)/vi/v_undo.c
+ $(CC) $(CFLAGS) $?
+v_util.o: $(srcdir)/vi/v_util.c
+ $(CC) $(CFLAGS) $?
+v_word.o: $(srcdir)/vi/v_word.c
+ $(CC) $(CFLAGS) $?
+v_xchar.o: $(srcdir)/vi/v_xchar.c
+ $(CC) $(CFLAGS) $?
+v_yank.o: $(srcdir)/vi/v_yank.c
+ $(CC) $(CFLAGS) $?
+v_z.o: $(srcdir)/vi/v_z.c
+ $(CC) $(CFLAGS) $?
+v_zexit.o: $(srcdir)/vi/v_zexit.c
+ $(CC) $(CFLAGS) $?
+vi.o: $(srcdir)/vi/vi.c
+ $(CC) $(CFLAGS) $?
+vs_line.o: $(srcdir)/vi/vs_line.c
+ $(CC) $(CFLAGS) $?
+vs_msg.o: $(srcdir)/vi/vs_msg.c
+ $(CC) $(CFLAGS) $?
+vs_refresh.o: $(srcdir)/vi/vs_refresh.c
+ $(CC) $(CFLAGS) $?
+vs_relative.o: $(srcdir)/vi/vs_relative.c
+ $(CC) $(CFLAGS) $?
+vs_smap.o: $(srcdir)/vi/vs_smap.c
+ $(CC) $(CFLAGS) $?
+vs_split.o: $(srcdir)/vi/vs_split.c
+ $(CC) $(CFLAGS) $?
+
+addbytes.o: $(srcdir)/curses/addbytes.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+addch.o: $(srcdir)/curses/addch.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+box.o: $(srcdir)/curses/box.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+clear.o: $(srcdir)/curses/clear.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+clrtobot.o: $(srcdir)/curses/clrtobot.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+clrtoeol.o: $(srcdir)/curses/clrtoeol.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+cr_put.o: $(srcdir)/curses/cr_put.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+ctrace.o: $(srcdir)/curses/ctrace.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+cur_hash.o: $(srcdir)/curses/cur_hash.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+curses.o: $(srcdir)/curses/curses.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+delch.o: $(srcdir)/curses/delch.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+deleteln.o: $(srcdir)/curses/deleteln.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+delwin.o: $(srcdir)/curses/delwin.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+erase.o: $(srcdir)/curses/erase.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+fullname.o: $(srcdir)/curses/fullname.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+getch.o: $(srcdir)/curses/getch.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+getstr.o: $(srcdir)/curses/getstr.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+id_subwins.o: $(srcdir)/curses/id_subwins.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+idlok.o: $(srcdir)/curses/idlok.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+initscr.o: $(srcdir)/curses/initscr.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+insch.o: $(srcdir)/curses/insch.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+insertln.o: $(srcdir)/curses/insertln.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+longname.o: $(srcdir)/curses/longname.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+move.o: $(srcdir)/curses/move.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+mvwin.o: $(srcdir)/curses/mvwin.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+newwin.o: $(srcdir)/curses/newwin.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+overlay.o: $(srcdir)/curses/overlay.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+overwrite.o: $(srcdir)/curses/overwrite.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+putchar.o: $(srcdir)/curses/putchar.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+refresh.o: $(srcdir)/curses/refresh.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+scroll.o: $(srcdir)/curses/scroll.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+setterm.o: $(srcdir)/curses/setterm.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+standout.o: $(srcdir)/curses/standout.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+toucholap.o: $(srcdir)/curses/toucholap.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+touchwin.o: $(srcdir)/curses/touchwin.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+tscroll.o: $(srcdir)/curses/tscroll.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+tstp.o: $(srcdir)/curses/tstp.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+tty.o: $(srcdir)/curses/tty.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+unctrl.o: $(srcdir)/curses/unctrl.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+waddnstr.o: $(srcdir)/curses/waddnstr.c
+ $(CC) -D_CURSES_PRIVATE $(CFLAGS) $?
+
+# DB sources.
+db.o: $(srcdir)/db/db/db.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) $?
+mpool.o: $(srcdir)/db/mpool/mpool.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/mpool $?
+bt_close.o: $(srcdir)/db/btree/bt_close.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/btree $?
+bt_conv.o: $(srcdir)/db/btree/bt_conv.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/btree $?
+bt_debug.o: $(srcdir)/db/btree/bt_debug.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/btree $?
+bt_delete.o: $(srcdir)/db/btree/bt_delete.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/btree $?
+bt_get.o: $(srcdir)/db/btree/bt_get.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/btree $?
+bt_open.o: $(srcdir)/db/btree/bt_open.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/btree $?
+bt_overflow.o: $(srcdir)/db/btree/bt_overflow.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/btree $?
+bt_page.o: $(srcdir)/db/btree/bt_page.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/btree $?
+bt_put.o: $(srcdir)/db/btree/bt_put.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/btree $?
+bt_search.o: $(srcdir)/db/btree/bt_search.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/btree $?
+bt_seq.o: $(srcdir)/db/btree/bt_seq.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/btree $?
+bt_split.o: $(srcdir)/db/btree/bt_split.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/btree $?
+bt_utils.o: $(srcdir)/db/btree/bt_utils.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/btree $?
+rec_close.o: $(srcdir)/db/recno/rec_close.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/recno $?
+rec_delete.o: $(srcdir)/db/recno/rec_delete.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/recno $?
+rec_get.o: $(srcdir)/db/recno/rec_get.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/recno $?
+rec_open.o: $(srcdir)/db/recno/rec_open.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/recno $?
+rec_put.o: $(srcdir)/db/recno/rec_put.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/recno $?
+rec_search.o: $(srcdir)/db/recno/rec_search.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/recno $?
+rec_seq.o: $(srcdir)/db/recno/rec_seq.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/recno $?
+rec_utils.o: $(srcdir)/db/recno/rec_utils.c
+ $(CC) -D__DBINTERFACE_PRIVATE $(CFLAGS) -I$(srcdir)/db/recno $?
+
+# Regular Expressions sources.
+regcomp.o: $(srcdir)/regex/regcomp.c
+ $(CC) -D__REGEX_PRIVATE $(CFLAGS) $?
+regerror.o: $(srcdir)/regex/regerror.c
+ $(CC) -D__REGEX_PRIVATE $(CFLAGS) $?
+regexec.o: $(srcdir)/regex/regexec.c
+ $(CC) -D__REGEX_PRIVATE $(CFLAGS) $?
+regfree.o: $(srcdir)/regex/regfree.c
+ $(CC) -D__REGEX_PRIVATE $(CFLAGS) $?
+
+# Random replacement and workaround sources.
+addnstr.o: $(srcdir)/clib/addnstr.c
+ $(CC) $(CFLAGS) $?
+bsearch.o: $(srcdir)/clib/bsearch.c
+ $(CC) $(CFLAGS) $?
+env.o: $(srcdir)/clib/env.c
+ $(CC) $(CFLAGS) $?
+fchmod.o: $(srcdir)/clib/fchmod.c
+ $(CC) $(CFLAGS) $(INC) $?
+gethostname.o: $(srcdir)/clib/gethostname.c
+ $(CC) $(CFLAGS) $(INC) $?
+getopt.o: $(srcdir)/clib/getopt.c
+ $(CC) $(CFLAGS) $(INC) $?
+memchr.o: $(srcdir)/clib/memchr.c
+ $(CC) $(CFLAGS) $?
+memcpy.o: $(srcdir)/clib/memmove.c
+ $(cp) $? memcpy.c
+ $(CC) $(CFLAGS) -DMEMCOPY memcpy.c
+memmove.o: $(srcdir)/clib/memmove.c
+ $(CC) $(CFLAGS) -DMEMMOVE $?
+memset.o: $(srcdir)/clib/memset.c
+ $(CC) $(CFLAGS) $?
+mkstemp.o: $(srcdir)/clib/mkstemp.c
+ $(CC) $(CFLAGS) $?
+mmap.o: $(srcdir)/clib/mmap.c
+ $(CC) $(CFLAGS) $?
+realloc.o: $(srcdir)/clib/realloc.c
+ $(CC) $(CFLAGS) $?
+snprintf.o: $(srcdir)/clib/snprintf.c
+ $(CC) $(CFLAGS) $?
+strdup.o: $(srcdir)/clib/strdup.c
+ $(CC) $(CFLAGS) $?
+strerror.o: $(srcdir)/clib/strerror.c
+ $(CC) $(CFLAGS) $?
+strpbrk.o: $(srcdir)/clib/strpbrk.c
+ $(CC) $(CFLAGS) $?
+strsep.o: $(srcdir)/clib/strsep.c
+ $(CC) $(CFLAGS) $?
+strtol.o: $(srcdir)/clib/strtol.c
+ $(CC) $(CFLAGS) $?
+strtoul.o: $(srcdir)/clib/strtoul.c
+ $(CC) $(CFLAGS) $?
+vsnprintf.o: $(srcdir)/clib/vsnprintf.c
+ $(CC) $(CFLAGS) $?
diff --git a/contrib/nvi/build/README b/contrib/nvi/build/README
new file mode 100644
index 000000000000..efbce2b9dfbb
--- /dev/null
+++ b/contrib/nvi/build/README
@@ -0,0 +1,369 @@
+# @(#)README 8.26 (Berkeley) 10/19/96
+
+Nvi uses the GNU autoconf program for configuration and compilation. You
+should enter:
+
+ configure
+ make
+
+and nvi will configure the system and build one or two binaries: nvi and
+tknvi. You can use any path to the configure script, e.g., to build for
+an x86 architecture, I suggest that you do:
+
+ mkdir build.x86
+ cd build.x86
+ ../build/configure
+ make
+
+There are options that you can specify to the configure command. See
+the next section for a description of these options.
+
+If you want to rebuild or reconfigure nvi, for example, because you change
+your mind as to the curses library that you want to use, create a new
+directory and reconfigure it using "configure" and whatever options you
+choose, don't try to selectively edit the files.
+
+By default, nvi is installed as "vi", with hard links to "ex" and "view".
+To install them using different names, use the configure program options.
+For example, to install them as "nvi", "nex" and "nview", use:
+
+ configure --program-prefix=n
+
+See the section below on installation for details.
+
+Note, if you're building nvi on a LynxOS system, you should read the
+README.LynxOS file in this directory for additional build instructions
+that are specific to that operating system.
+
+If you have trouble with this procedure, send email to the addresses
+listed in ../README. In that email, please provide a complete script
+of the output for all of the above commands that you entered.
+
+=-=-=-=-=-=-=
+NVI'S OPTIONS TO THE CONFIGURE PROGRAM
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+There are many options that you can enter to the configuration program.
+To see a complete list of the options, enter "configure --help". Only
+a few of them are nvi specific. These options are as follows:
+
+ --disable-curses DON'T use the nvi-provided curses routines.
+ --disable-db DON'T use the nvi-provided DB routines.
+ --disable-re DON'T use the nvi-provided RE routines.
+ --enable-debug Build a debugging version.
+ --enable-perlinterp Include a Perl interpreter in vi.
+ --enable-tclinterp Include a Tk/Tcl interpreter in vi.
+ --enable-tknvi Build a Tk/Tcl front-end for vi.
+
+disable-curses:
+ By default, nvi loads its own implementation of the curses
+ routines (which are a stripped-down version of the 4.4BSD curses
+ library). If you have your own curses library implementation and
+ you want to use it instead, enter:
+
+ --disable-curses
+
+ as an argument to configure, and the curses routines will be taken
+ from whatever libraries you load. Note: System V based curses
+ implementations are usually broken. See the last section of this
+ README for further information about nvi and the curses library.
+
+disable-db:
+ By default, nvi loads its own versions of the Berkeley DB routines
+ (which are a stripped-down version of DB 1.85). If you have your
+ own version of the Berkeley DB routines and you want to use them
+ instead, enter:
+
+ --disable-db
+
+ as an argument to configure, and the DB routines will be taken
+ from whatever libraries you load. Make sure that the DB routines
+ you use are at least version 1.85 or later.
+
+disable-re:
+ By default, nvi loads its own versions of the POSIX 1003.2 Regular
+ Expression routines (which are Henry Spencer's implementation).
+ If your C library contains an implementation of the POSIX 1003.2
+ RE routines (note, this is NOT the same as the historic UNIX RE
+ routines), and you want to use them instead, enter:
+
+ --disable-re
+
+ as an argument to configure, and the RE routines will be taken
+ from whatever libraries you load. Please ensure that your RE
+ routines implement Henry Spencer's extensions for doing vi-style
+ "word" searches.
+
+enable-debug:
+ If you want to build nvi with no optimization (i.e. without -O
+ as a compiler flag), with -g as a compiler flag, and with DEBUG
+ defined during compilation, enter:
+
+ --enable-debug
+
+ as an argument to configure.
+
+enable-perlinterp:
+ If you have the Perl 5 libraries and you want to compile in the
+ Perl interpreter, enter:
+
+ --enable-perlinterp
+
+ as an argument to configure. (Note: this is NOT possible with
+ Perl 4, or even with Perl 5 versions earlier than 5.002.)
+
+enable-tclinterp:
+ If you have the Tk/Tcl libraries and you want to compile in the
+ Tcl/Tk interpreter, enter:
+
+ --enable-tclinterp
+
+ as an argument to configure. If your Tk/Tcl include files and
+ libraries aren't in the standard library and include locations,
+ see the next section of this README file for more information.
+
+enable-tknvi:
+ If you have the Tk/Tcl libraries and you want to build the Tcl/Tk
+ nvi front-end, enter:
+
+ --enable-tknvi
+
+ as an argument to configure. If your Tk/Tcl include files and
+ libraries aren't in the standard library and include locations,
+ see the next section of this README file for more information.
+
+=-=-=-=-=-=-=
+ADDING OR CHANGING COMPILERS, OR COMPILE OR LOAD LINE FLAGS
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+If you want to use a specific compiler, specify the CC environment
+variable before running configure. For example:
+
+ env CC=gcc configure
+
+Using anything other than the native compiler will almost certainly
+mean that you'll want to check the compile and load line flags, too.
+
+If you want to specify additional load line flags, specify the ADDLDFLAGS
+environment variable before running configure. For example:
+
+ env ADDLDFLAGS="-Q" configure
+
+would specify the -Q flag in the load line when the nvi programs are
+loaded.
+
+If you don't want configure to use the default load line flags for the
+system, specify the LDFLAGS environment variable before running configure.
+For example:
+
+ env LDFLAGS="-32" configure
+
+will cause configure to set the load line flags to "-32", and not set
+them based on the current system.
+
+If you want to specify additional compile line flags, specify the
+ADDCPPFLAGS environment variable before running configure. For example:
+
+ env ADDCPPFLAGS="-I../foo" configure
+
+would cause the compiler to be passed the -I../foo flag when compiling
+test programs during configuration as well as when building nvi object
+files.
+
+If you don't want configure to use the default compile line flags for the
+system, specify the CPPFLAGS environment variable before running configure.
+For example:
+
+ env CPPFLAGS="-I.." configure
+
+will cause configure to use "-I.." as the compile line flags instead of
+the default values.
+
+=-=-=-=-=-=-=
+ADDING LIBRARIES AND INCLUDE FILES
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+If the Tk/Tcl or any other include files or libraries are in non-standard
+places on your system, you will need to specify the directory path where
+they can be found.
+
+If you want to specify additional library paths, set the ADDLIBS environment
+variable before running configure. For example:
+
+ env ADDLIBS="-L/a/b -L/e/f -ldb" configure
+
+would specify two additional directories to search for libraries, /a/b
+and /e/f, and one additional library to load, "db".
+
+If you want to specify additional include paths, specify the ADDCPPFLAGS
+environment variable before running configure. For example:
+
+ env ADDCPPFLAGS="-I/usr/local/include" LIBS="-ldb" configure
+
+would search /usr/local/include for include files, as well as load the db
+library as described above.
+
+As a final example, let's say that you've downloaded ncurses from the net
+and you've built it in a directory named ncurses which is at the same
+level in the filesystem hierarchy as nvi. You would enter something like:
+
+ env ADDCPPFLAGS="-I../../ncurses/include" \
+ ADDLIBS="-L../../ncurses/libraries" configure
+
+to cause nvi to look for the curses include files and the curses library
+in the ncurses environment.
+
+Notes:
+ Make sure that you prepend -L to any library directory names, and
+ that you prepend -I to any include file directory names! Also,
+ make sure that you quote the paths as shown above, i.e. with
+ single or double quotes around the values you're specifying for
+ ADDCPPFLAGS and ADDLIBS.
+
+ =-=-=-=-=-=
+ You should NOT need to add any libraries or include files to load
+ the Perl5 interpreter. The configure script will obtain that
+ information directly from the Perl5 program. This means that the
+ configure script must be able to find perl in its path. It looks
+ for "perl5" first, and then "perl". If you're building a Perl
+ interpreter and neither is found, it's a fatal error.
+
+ =-=-=-=-=-=
+ You do not need to specify additional libraries to load Tk/Tcl,
+ Perl or curses, as the nvi configuration script adds the
+ appropriate libraries to the load line whenever you specify
+ --enable-tknvi or other Perl or Tk/Tcl related option, or build
+ the Tk/Tcl or curses version of nvi. The library names that are
+ automatically loaded are as follows:
+
+ for Perl: -lperl
+ for Tk/Tcl: -ltk -ltcl -lm
+ for curses: -lcurses
+
+ In addition, the configure script loads:
+
+ ... the X libraries when loading the Tk/Tcl libraries,
+ if they exist.
+
+ ... the -ltermcap or -ltermlib libraries when loading
+ any curses library, if they exist.
+
+ =-=-=-=-=-=
+ The env command is available on most systems, and simply sets one
+ or more environment variables before running a command. If the
+ env command is not available to you, you can set the environment
+ variables in your shell before running configure. For example,
+ in sh or ksh, you could do:
+
+ ADDLIBS="-L/a/b -L/e/f -ldb" configure
+
+ and in csh or tcsh, you could do:
+
+ setenv ADDLIBS "-L/a/b -L/e/f -ldb"
+ configure
+
+ See your shell manual page for further information.
+
+=-=-=-=-=-=-=
+INSTALLING NVI
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Nvi installs the following files into the following locations, with
+the following default values:
+
+Variables: Default value:
+prefix /usr/local
+exec_prefix $(prefix)
+bindir $(prefix)/bin
+datadir $(prefix)/share
+mandir $(prefix)/man
+
+File(s): Default location
+----------------------------------------
+vi $(bindir)/vi
+vi.1 $(mandir)/man1/vi.1
+vi.0 $(mandir)/cat1/vi.0
+Perl scripts $(datadir)/vi/perl/
+Tcl scripts $(datadir)/vi/tcl/
+Message Catalogs $(datadir)/vi/catalog/
+
+Notes:
+ There are two hard links to the vi program, named ex and view.
+ Similarly, there are two hard links to the unformatted vi manual
+ page, named ex.1 and view.1, and two hard links to the formatted
+ manual page, named ex.0 and view.0. These links are created when
+ the program and man pages are installed.
+
+ If you want to install vi, ex, view and the man pages as nvi, nex,
+ nview, use the configure option --program-prefix=n. Other, more
+ complex transformations are possible -- use configure --help to
+ see more options.
+
+ To move the entire installation tree somewhere besides /usr/local,
+ change the value of both "exec_prefix" and "prefix". To move the
+ binaries to a different place, change the value of "bindir".
+ Similarly, to put the datafiles (the message catalogs, Perl and
+ Tcl scripts) or the man pages in a different place, change the
+ value of "datadir" or "mandir". These values can be changed as
+ part of configuration:
+
+ configure --exec_prefix=/usr/contrib --prefix=/usr/share
+
+ or when doing the install itself:
+
+ make exec_prefix=/usr/contrib prefix=/usr/contrib install
+
+ The datafile directory (e.g., /usr/local/share/vi by default) is
+ completely removed and then recreated as part of the installation
+ process.
+
+=-=-=-=-=-=-=
+NVI AND THE CURSES LIBRARY
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+The major portability problem for nvi is selecting a curses library.
+Unfortunately, it is common to find broken versions of curses -- the
+original System V curses was broken, resulting in all vendors whose
+implementations are derived from System V having broken implementations
+in turn.
+
+For this reason, BY DEFAULT, nvi uses the stripped-down curses library
+that's included in its distribution. Of course, it would be preferable
+to use the vendor's curses library, or one of the newer implementations
+of curses, e.g., ncurses.
+
+To use the vendor's curses library, specify the:
+
+ --disable-curses
+
+argument to the configure command. If you use the vendor's or other
+curses library, and you see any of the following symptoms:
+
+ + Core dumps in curses routines.
+ + Missing routines when compiling.
+ + Repainting the wrong characters on the screen.
+ + Displaying inverse video in the wrong places.
+ + Failure to reset your terminal to the correct modes on exit.
+
+you have a broken curses implementation, and you should reconfigure nvi
+to use another curses library or the curses library provided with nvi.
+
+There are two alternative sources for curses libraries:
+
+#1: Compile the 4BSD curses library from any of the recent BSD
+ releases: FreeBSD, NetBSD or 4.4BSD-Lite release 2. These
+ libraries should be able to support nvi.
+
+#2: Retrieve and build the ncurses library. This library is not
+ recommended unreservedly, at least for now, for two reasons.
+ First, it can't be built on any system where the compiler
+ doesn't support function prototypes. Second, it currently has
+ a few bugs in its support for nvi. It mostly works, but it's
+ still not quite right.
+
+One final note. If you see the following symptoms:
+
+ + Line-by-line screen repainting instead of scrolling.
+
+it usually means that your termcap or terminfo information is insufficient
+for the terminal.
diff --git a/contrib/nvi/build/README.LynxOS b/contrib/nvi/build/README.LynxOS
new file mode 100644
index 000000000000..2cc68dafc861
--- /dev/null
+++ b/contrib/nvi/build/README.LynxOS
@@ -0,0 +1,320 @@
+README.LynxOS
+=============
+
+Written by Ronald F. Guilmette <rfg@monkeys.com>
+
+Last modified Wed Aug 14 23:10:07 PDT 1996
+------------------------------------------
+
+0. Introduction
+---------------
+
+This file describes how to build and install the Berkeley nvi editor for
+the LynxOS 2.4.0 operating system.
+
+LynxOS 2.4.0 is available for a variety of different hardware platforms, in
+particular, x86, m680x0, Sparc, and PowerPC. I have successfully built nvi
+on all four of these flavors of LynxOS by following the procedures given in
+this file.
+
+Note that these procedures may not work on versions of LynxOS prior to 2.4.0.
+(As I understand it, a good deal of work went into making the 2.4.0 release
+more POSIX-compliant, and I have no idea what build glitches, if any, you
+might encounter if you try to build nvi on a pre-2.4.0 version of LynxOS.)
+
+There are basically four steps to configuring, building, and installing nvi
+on LynxOS, namely:
+
+ 1. Get setup to use the proper C compiler.
+ 2. Replace your installed `tr' program.
+ 3. Fix your system include files.
+ 4. Do a normal configure, build, and install of nvi.
+
+These steps are described in separate sections below.
+
+1. Get Setup to Use the Proper C Compiler
+------------------------------------------
+
+The first step when building nvi on LynxOS is to set your $PATH environment
+variable properly so that the gcc 2.x compiler appears first on your path,
+prior to the older (and less robust) gcc 1.xx compiler (typically installed
+as /bin/gcc) and/or the old Lynx proprietary C compiler (typically installed
+as /bin/cc), both of which may also be present on your system.
+
+Note that for most operating systems, the configure script for nvi tries
+to use whatever compiler you have installed (and in your $PATH) as "cc",
+however in the special case of LynxOS, the configure script will auto-
+matically try to find a "gcc" program on your $PATH in preference to a
+compiler called "cc". If the nvi configure script only find a compiler
+called "cc", that's OK. It will still try to see if that is really just
+the GNU C compiler installed under the name "cc".
+
+Regardless of the name however (be it "gcc" or "cc") the first C compiler
+in your $PATH should be some _recent_ (i.e. 2.0 or later) version of the
+GNU C compiler... and the nvi configure script now checks that this is the
+case, and fails if it isn't.
+
+Oddly enough, LynxOS 2.4.0 (and some prior versions) shipped with as many
+as three different C compilers installed, so it is important to set your
+$PATH environment variable carfully in order to get the proper C compiler
+to appear first in your $PATH. You want to avoid having either the /bin/gcc
+compiler or the /bin/cc compiler be the first C compiler in your $PATH.
+
+To make sure that the GNU C version 2.x compiler which was shipped with your
+LynxOS system appears first on your path, you will need to either set your
+$PATH variable (for sh/bash/ksh users) or your $path variable (for csh/tcsh
+users). You can, of course, just do this at the shell command prompt, but
+it is probably better to actually edit this change into your .profile file
+(for sh/bash/ksh users) or into your .cshrc file (for csh/tcsh users).
+
+The pathname of the directory that contains the GNU C version 2.x compiler
+is (unfortunately) dependent upon the exact type of LynxOS system you have.
+
+For LynxOS 2.4.0 on x86 systems, gcc 2.x is located in:
+
+ /cygnus/94q4-lynxos-x86/bin
+
+For LynxOS 2.4.0 on m680x0 systems, gcc 2.x is located in:
+
+ /cygnus/94q4-lynxos-68k/bin
+
+For LynxOS 2.4.0 on Sparc systems, gcc 2.x is located in:
+
+ /cygnus/94q4-lynxos-usparc/bin
+
+For LynxOS 2.4.0 on PowerPC systems, gcc 2.x is located in:
+
+ /cygnus/95q2-lynxos-ppc/bin
+
+(Note also that these locations may change in LynxOS 2.5.x and beyond.)
+
+Anyway, it is imperative that you setup your $PATH environment variable
+(*before* you do the configure step for nvi) so that the GNU C version 2.x
+compiler appears in your $PATH before either the /bin/cc or /bin/gcc
+compilers (if present). If you fail to do this, the configure step for
+nvi will fail, because the compiler script actually checks (now) that the
+compiler you are using (if your are on a LynxOS system) is gcc 2.0 or
+later.
+
+To make absolutely sure that you will be configuring and building nvi with
+the proper C compiler (i.e. the GNU C version 2.x compiler on your system)
+you should add the directory name listed above for your specific system type
+to your $PATH setting in your $HOME/.profile file. (For csh/tcsh users, you
+will instead want to add the relevant directory name to the setting of your
+$path variable in your ~/.cshrc file.) Once you have added the proper direc-
+tory name (from the list given above) to your $HOME/.profile file (or to your
+~/.cshrc file, if you are using csh or tcsh) you should log out completely
+and then log back into the system just to make sure your new $PATH/$path
+setting takes effect properly.
+
+When you finish making this adjustment to your $PATH (or $path), the most
+up-to-date version of gcc on your system should be available to you as the
+first `gcc' program on your $PATH. You should verify that this is indeed the
+case simply by typing `gcc -v' and then checking the version number reported
+by the compiler. It should say either "2.6-94q4" or (on PowerPC systems) it
+should say "2.6-95q2". If you don't get these results, try again to set your
+$PATH (or $path) until you do. You won't be able to build nvi until you are
+properly setup to use gcc version 2.0 or later.
+
+Performing the steps shown above will insure that your subsequent configura-
+tion and build steps for nvi will make use of the most up-to-date version of
+gcc that was shipped with your Lynx operating system. (Note that the versions
+of gcc which are currently shipping with LynxOS 2.4.0 are also somewhat out-
+of-date themselves, but they are still quite a bit newer and more bug-free
+and ANSI conformant that those other two C compilers, /bin/cc and /bin/gcc,
+which also ship with LynxOS 2.4.0.)
+
+(Note: At present, LynxOS version 2.4.0 is the latest officially released
+version of LynxOS, and all of the above information is accurate and correct
+for LynxOS 2.4.0 as of the time of this writing. However it is rumored that
+future releases of LynxOS may provide a still newer version of gcc, and that
+it may be located in the /usr/bin directory. Thus, if you are building nvi
+for some LynxOS version later than 2.4.0, you may wish to check and see if
+your system has a program called /usr/bin/gcc, and use that version of gcc,
+if available, rather than the one suggested above.)
+
+2. Replace Your Installed `tr' Program
+---------------------------------------
+
+The `tr' program which comes bundled with LynxOS 2.4.0 (as /bin/tr) has a
+somewhat obscure bug which just happens to be tickled by almost all GNU
+`autoconf' generated `configure' scripts (including the one that nowadays
+comes bundled with nvi). Using the stock /bin/tr program on LynxOS when
+executing such `configure' scripts _will_ cause these scripts to malfunction
+in various ways. It is therefore imperative that you replace your LynxOS
+/bin/tr program with a properly working version of the `tr' command _before_
+you even try to configure nvi. (You can tell if your `tr' program has the
+bug by executng the command "echo ab- | tr ab- ABC". If this yields the
+string "Ab-" then you have the bug. If it yields "ABC" then you don't.)
+
+You can obtain sources for a working version of the `tr' command as part of
+the GNU `textutils' package (the latest version of which, at the time of this
+writing, is 1.19). The GNU textutils package is available for downloading
+from prep.ai.mit.edu in the pub/gnu directory. Look for the file named
+textutils-1.19.tar.gz, or an even more recent version of textutils, if one
+is available. Fetch it, gunzip it, untar it, and follow the directions in
+the INSTALL file included in the tar file to build and install the entire
+textutils set of utility programs (which includes a working `tr' program).
+Then just make sure that the GNU version of `tr' appears on your $PATH
+_before_ the LynxOS version of `tr' (i.e. /bin/tr). Be sure to do this
+step _before_ you start to configure nvi.
+
+When building the textutils set of programs, I suggest that you use the most
+up-to-date C compiler available on your system (as described above). Also,
+note that it will be important for you to AVOID using the -O (optimize)
+compiler option when building the GNU textutils package, even if you are
+using the most up-to-date version of gcc which shipped with your system.
+If you try to use -O when building the textutils package on an x86 with
+the Cygnus 94q4 C compiler, you will end up with a `tr' program which will
+malfunction even worse than the one you are trying to replace! If you use
+-O when building the textutils package on LynxOS on the PowerPC (using the
+Cygnus 95q2 C compiler) you will just get yourself a compiler crash. So
+just don't use -O when building textutils. You can avoid using -O by in-
+voking make in the textutils directory as follows:
+
+ make CFLAGS="-g"
+
+(Note: At present, LynxOS version 2.4.0 is the latest officially released
+version of LynxOS, and all of the above information is accurate and correct
+for LynxOS 2.4.0 as of the time of this writing. However it is rumored that
+the bug in the /bin/tr program will be fixed in future releases of LynxOS,
+so if you have a version of LynxOS later than 2.4.0, you may wish to check
+and see if your /bin/tr program even has the problematic bug before bothering
+with all of this.)
+
+
+3. Fix Your System Include Files
+---------------------------------
+
+If you are building nvi on a PowerPC system, it is also important that you
+apply the patches given at the end of this file to your /usr/include files.
+(Note that you will have to be root in order to do this.) Two of the patches
+included below fix a pair of serious bugs in the /usr/include/stdarg.h file
+on the PowerPC, and you really _do_ want to have these bugs fixed anyway,
+because without these fixes, anything that you compile which uses <stdarg.h>
+will very likely malfunction at run-time.
+
+Regardless of which LynxOS platform you are using (i.e. x86, PowerPC, Sparc,
+or m680x0) you may want to apply all of the system include files patches that
+are included below anyway. Doing so will clean up a few minor problems with
+the relevant system include files (i.e. <stdarg.h>, <ioctl.h>, and <wait.h>)
+and this step will also prevent a few warnings which you would otherwise get
+during the build of nvi.
+
+You can apply all of the patches given at the end of this file simply by
+doing the following:
+
+ su root
+ cd /usr/include
+ /bin/patch < this-file
+
+Where `this-file' is the actual full pathname of the file you are now reading,
+wherever it may reside on your own system.
+
+(Note: At present, LynxOS version 2.4.0 is the latest officially released
+version of LynxOS, and all of the above information is accurate and correct
+for LynxOS 2.4.0 as of the time of this writing. However it is rumored that
+future releases of LynxOS may incorporate some or all of the important system
+include file fixes provided below. Thus, if you are building nvi for some
+LynxOS version later than 2.4.0, you should probably go ahead and try to
+apply the patches given below to your system include files, and then just
+don't worry about it if these patches seem to have already been applied.)
+
+
+4. A Brief Note about Sendmail
+-------------------------------
+
+I should mention also that LynxOS does not normally ship with the `sendmail'
+mail transfer program installed, either under /usr/lib/ or anywhere else for
+that matter. This isn't really a big problem, but nvi normally wants and
+expects to have a sendmail program available so that it can send users notifi-
+cations (by mail) whenever a partially edited file is preserved by the editor
+in response to a sudden system crash, a sudden system shutdown, or an unexpect-
+ed serial-line hangup. You can configure and build nvi without any sendmail
+program installed on your system, but you will get warnings about its absence
+when you are doing the initial configure step prior to actually building nvi.
+If you want to have a fully-functional nvi which does send out notification
+messages (by mail) whenever partially edited files are preserved during a
+serial line hangup or system crash, then you should get the BSD sendmail
+sources (via ftp from ftp.cs.berkeley.edu), build and install sendmail, and
+then reconfigure, rebuild, and reinstall nvi.
+
+Please contact me at the E-mail address below if you experience any problems in
+building or using nvi on LynxOS. I make no guarrantees, but I may be willing
+to try to help.
+
+Ron Guilmette
+Roseville, California
+<rfg@monkeys.com>
+August 14, 1996
+
+
+cut here for LynxOS 2.4.0 system include files patches
+-----------------------------------------------------------------------------
+*** wait.h Fri Apr 26 10:02:45 1996
+--- wait.h Sun May 19 05:36:50 1996
+***************
+*** 94,104 ****
+ /* Function prototypes */
+ #ifndef __LYNXOS
+- #ifdef _POSIX_SOURCE
+ extern pid_t wait _AP((int *));
+ extern pid_t waitpid _AP((pid_t, int *, int));
+! #else
+! extern int wait _AP((union wait *));
+! extern int waitpid _AP((int, union wait *, int));
+! extern int wait3 _AP((union wait *, int, struct rusage *));
+ #endif
+ #endif /* !__LYNXOS */
+--- 94,101 ----
+ /* Function prototypes */
+ #ifndef __LYNXOS
+ extern pid_t wait _AP((int *));
+ extern pid_t waitpid _AP((pid_t, int *, int));
+! #ifndef _POSIX_SOURCE
+! extern int wait3 _AP((int *, int, struct rusage *));
+ #endif
+ #endif /* !__LYNXOS */
+*** ioctl.h Fri Apr 26 16:50:51 1996
+--- ioctl.h Sat May 18 17:55:16 1996
+***************
+*** 572,576 ****
+
+ #ifndef __LYNXOS
+! extern int ioctl _AP((int, int, char *));
+ #endif
+
+--- 572,576 ----
+
+ #ifndef __LYNXOS
+! extern int ioctl _AP((int, int, ...));
+ #endif
+
+*** stdarg.h Fri Apr 26 16:51:02 1996
+--- stdarg.h Sat May 18 19:34:13 1996
+***************
+*** 88,92 ****
+ (((sizeof(TYPE) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+
+! #define va_start(AP, LASTARG) (AP = ((char *) __builtin_next_arg ()))
+
+ void va_end(va_list); /* Defined in libgcc.a */
+--- 88,92 ----
+ (((sizeof(TYPE) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+
+! #define va_start(AP, LASTARG) (AP = ((char *) __builtin_next_arg (LASTARG)))
+
+ void va_end(va_list); /* Defined in libgcc.a */
+***************
+*** 162,166 ****
+ (((sizeof(TYPE) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+
+! #define va_start(AP, LASTARG) (AP = ((char *) __builtin_next_arg ()))
+
+ void va_end(va_list); /* Defined in libgcc.a */
+--- 162,166 ----
+ (((sizeof(TYPE) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+
+! #define va_start(AP, LASTARG) (AP = ((char *) __builtin_next_arg (LASTARG)))
+
+ void va_end(va_list); /* Defined in libgcc.a */
diff --git a/contrib/nvi/build/acconfig.h b/contrib/nvi/build/acconfig.h
new file mode 100644
index 000000000000..567f9ee60070
--- /dev/null
+++ b/contrib/nvi/build/acconfig.h
@@ -0,0 +1,82 @@
+/* @(#)acconfig.h 8.18 (Berkeley) 7/2/96 */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef ssize_t
+
+/* Define if you want a debugging version. */
+#undef DEBUG
+
+/* Define if you have a System V-style (broken) gettimeofday. */
+#undef HAVE_BROKEN_GETTIMEOFDAY
+
+/* Define if you have a Ultrix-style (broken) vdisable. */
+#undef HAVE_BROKEN_VDISABLE
+
+/* Define if you have a BSD version of curses. */
+#undef HAVE_BSD_CURSES
+
+/* Define if you have the curses(3) addnstr function. */
+#undef HAVE_CURSES_ADDNSTR
+
+/* Define if you have the curses(3) beep function. */
+#undef HAVE_CURSES_BEEP
+
+/* Define if you have the curses(3) flash function. */
+#undef HAVE_CURSES_FLASH
+
+/* Define if you have the curses(3) idlok function. */
+#undef HAVE_CURSES_IDLOK
+
+/* Define if you have the curses(3) keypad function. */
+#undef HAVE_CURSES_KEYPAD
+
+/* Define if you have the curses(3) newterm function. */
+#undef HAVE_CURSES_NEWTERM
+
+/* Define if you have the curses(3) setupterm function. */
+#undef HAVE_CURSES_SETUPTERM
+
+/* Define if you have the curses(3) tigetstr/tigetnum functions. */
+#undef HAVE_CURSES_TIGETSTR
+
+/* Define if you have the DB __hash_open call in the C library. */
+#undef HAVE_DB_HASH_OPEN
+
+/* Define if you have the chsize(2) system call. */
+#undef HAVE_FTRUNCATE_CHSIZE
+
+/* Define if you have the ftruncate(2) system call. */
+#undef HAVE_FTRUNCATE_FTRUNCATE
+
+/* Define if you have fcntl(2) style locking. */
+#undef HAVE_LOCK_FCNTL
+
+/* Define if you have flock(2) style locking. */
+#undef HAVE_LOCK_FLOCK
+
+/* Define if you want to compile in the Perl interpreter. */
+#undef HAVE_PERL_INTERP
+
+/* Define if your Perl is at least 5.003_01. */
+#undef HAVE_PERL_5_003_01
+
+/* Define if you have the Berkeley style revoke(2) system call. */
+#undef HAVE_REVOKE
+
+/* Define if you have the Berkeley style strsep(3) function. */
+#undef HAVE_STRSEP
+
+/* Define if you have <sys/mman.h> */
+#undef HAVE_SYS_MMAN_H
+
+/* Define if you have <sys/select.h> */
+#undef HAVE_SYS_SELECT_H
+
+/* Define if you have the System V style pty calls. */
+#undef HAVE_SYS5_PTY
+
+/* Define if you want to compile in the Tcl interpreter. */
+#undef HAVE_TCL_INTERP
+
+/* Define if your sprintf returns a pointer, not a length. */
+#undef SPRINTF_RET_CHARPNT
diff --git a/contrib/nvi/build/aclocal.m4 b/contrib/nvi/build/aclocal.m4
new file mode 100644
index 000000000000..de7e57ed3aac
--- /dev/null
+++ b/contrib/nvi/build/aclocal.m4
@@ -0,0 +1,17 @@
+AC_DEFUN(AM_SANITY_CHECK_CC,
+[dnl Derived from macros from Bruno Haible and from Cygnus.
+AC_MSG_CHECKING([whether the compiler ($CC $CFLAGS $LDFLAGS) actually works])
+AC_LANG_SAVE
+ AC_LANG_C
+ AC_TRY_RUN([main() { exit(0); }],
+ am_cv_prog_cc_works=yes, am_cv_prog_cc_works=no,
+ dnl When crosscompiling, just try linking.
+ AC_TRY_LINK([], [], am_cv_prog_cc_works=yes,
+ am_cv_prog_cc_works=no))
+AC_LANG_RESTORE
+case "$am_cv_prog_cc_works" in
+ *no) AC_MSG_ERROR([Installation or configuration problem: C compiler cannot create executables.]) ;;
+ *yes) ;;
+esac
+AC_MSG_RESULT(yes)
+])dnl
diff --git a/contrib/nvi/build/config.guess b/contrib/nvi/build/config.guess
new file mode 100755
index 000000000000..4c314d97aacb
--- /dev/null
+++ b/contrib/nvi/build/config.guess
@@ -0,0 +1,571 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+#
+# 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 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.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# The master version of this file is at the FSF in /home/gd/gnu/lib.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit system type (host/target name).
+#
+# Only a few systems have been added to this list; please add others
+# (but try to keep the structure clean).
+#
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 8/24/94.)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ alpha:OSF1:V*:*)
+ # After 1.2, OSF1 uses "V1.3" for uname -r.
+ echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^V//'`
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ # 1.2 uses "1.2" for uname -r.
+ echo alpha-dec-osf${UNAME_RELEASE}
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ amiga:NetBSD:*:*)
+ echo m68k-cbm-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ Pyramid*:OSx*:*:*)
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ sun4*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:NetBSD:*:*)
+ echo m68k-atari-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:NetBSD:*:*)
+ echo m68k-sun-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:NetBSD:*:*)
+ echo m68k-apple-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:4*:UMIPS)
+ echo mips-mips-riscos4sysv
+ exit 0 ;;
+ mips:*:5*:RISCos)
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
+ -o ${TARGET_BINARY_INTERFACE}x = x ] ; then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i?86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ sed 's/^ //' << EOF >dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:4)
+ if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=4.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[3478]??:HP-UX:*:*)
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/7?? | 9000/8?[79] ) HP_ARCH=hppa1.1 ;;
+ 9000/8?? ) HP_ARCH=hppa1.0 ;;
+ esac
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ sed 's/^ //' << EOF >dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*X-MP:*:*:*)
+ echo xmp-cray-unicos
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY*C90:*:*:*)
+ echo c90-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY-2:*:*:*)
+ echo cray2-cray-unicos
+ exit 0 ;;
+ hp3[0-9][05]:NetBSD:*:*)
+ echo m68k-hp-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ i?86:BSD/386:*:* | *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:NetBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us.
+ ld_help_string=`ld --help 2>&1`
+ if echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: elf_i?86"; then
+ echo "${UNAME_MACHINE}-unknown-linux" ; exit 0
+ elif echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: i?86linux"; then
+ echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0
+ elif echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: i?86coff"; then
+ echo "${UNAME_MACHINE}-unknown-linuxcoff" ; exit 0
+ elif test "${UNAME_MACHINE}" = "alpha" ; then
+ echo alpha-unknown-linux ; exit 0
+ else
+ # Either a pre-BFD a.out linker (linuxoldld) or one that does not give us
+ # useful --help. Gcc wants to distinguish between linuxoldld and linuxaout.
+ test ! -d /usr/lib/ldscripts/. \
+ && echo "${UNAME_MACHINE}-unknown-linuxoldld" && exit 0
+ # Determine whether the default compiler is a.out or elf
+ cat >dummy.c <<EOF
+main(argc, argv)
+int argc;
+char *argv[];
+{
+#ifdef __ELF__
+ printf ("%s-unknown-linux\n", argv[1]);
+#else
+ printf ("%s-unknown-linuxaout\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ fi ;;
+# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
+# are messed up and put the nodename in both sysname and nodename.
+ i?86:DYNIX/ptx:4*:*)
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
+ else
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ i?86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-unknown-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ echo ${UNAME_MACHINE}-unknown-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-unknown-sysv32
+ fi
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-unknown-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ M680?0:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0)
+ uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3 && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68*:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ i?86:LynxOS:2.*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:* | uSPARC2:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ PowerPC:LynxOS:2.*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *FTX*)
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ printf ("%s-next-nextstep%s\n", __ARCHITECTURE__, version==2 ? "2" : "3");
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-unknown-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+ printf ("vax-dec-bsd\n"); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
+rm -f dummy.c dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+#echo '(Unable to guess system type)' 1>&2
+
+exit 1
diff --git a/contrib/nvi/build/config.h.in b/contrib/nvi/build/config.h.in
new file mode 100644
index 000000000000..c87fcdd7f214
--- /dev/null
+++ b/contrib/nvi/build/config.h.in
@@ -0,0 +1,179 @@
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define if your struct stat has st_blksize. */
+#undef HAVE_ST_BLKSIZE
+
+/* Define if you have <vfork.h>. */
+#undef HAVE_VFORK_H
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef mode_t
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+#undef off_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef pid_t
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+#undef size_t
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if your <sys/time.h> declares struct tm. */
+#undef TM_IN_SYS_TIME
+
+/* Define vfork as fork if vfork does not work. */
+#undef vfork
+
+/* Define if your processor stores words with the most significant
+ byte first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef ssize_t
+
+/* Define if you want a debugging version. */
+#undef DEBUG
+
+/* Define if you have a System V-style (broken) gettimeofday. */
+#undef HAVE_BROKEN_GETTIMEOFDAY
+
+/* Define if you have a Ultrix-style (broken) vdisable. */
+#undef HAVE_BROKEN_VDISABLE
+
+/* Define if you have a BSD version of curses. */
+#undef HAVE_BSD_CURSES
+
+/* Define if you have the curses(3) addnstr function. */
+#undef HAVE_CURSES_ADDNSTR
+
+/* Define if you have the curses(3) beep function. */
+#undef HAVE_CURSES_BEEP
+
+/* Define if you have the curses(3) flash function. */
+#undef HAVE_CURSES_FLASH
+
+/* Define if you have the curses(3) idlok function. */
+#undef HAVE_CURSES_IDLOK
+
+/* Define if you have the curses(3) keypad function. */
+#undef HAVE_CURSES_KEYPAD
+
+/* Define if you have the curses(3) newterm function. */
+#undef HAVE_CURSES_NEWTERM
+
+/* Define if you have the curses(3) setupterm function. */
+#undef HAVE_CURSES_SETUPTERM
+
+/* Define if you have the curses(3) tigetstr/tigetnum functions. */
+#undef HAVE_CURSES_TIGETSTR
+
+/* Define if you have the chsize(2) system call. */
+#undef HAVE_FTRUNCATE_CHSIZE
+
+/* Define if you have the ftruncate(2) system call. */
+#undef HAVE_FTRUNCATE_FTRUNCATE
+
+/* Define if you have fcntl(2) style locking. */
+#undef HAVE_LOCK_FCNTL
+
+/* Define if you have flock(2) style locking. */
+#undef HAVE_LOCK_FLOCK
+
+/* Define if you want to compile in the Perl interpreter. */
+#undef HAVE_PERL_INTERP
+
+/* Define if your Perl is at least 5.003_01. */
+#undef HAVE_PERL_5_003_01
+
+/* Define if you have the Berkeley style revoke(2) system call. */
+#undef HAVE_REVOKE
+
+/* Define if you have <sys/mman.h> */
+#undef HAVE_SYS_MMAN_H
+
+/* Define if you have <sys/select.h> */
+#undef HAVE_SYS_SELECT_H
+
+/* Define if you have the System V style pty calls. */
+#undef HAVE_SYS5_PTY
+
+/* Define if you want to compile in the Tcl interpreter. */
+#undef HAVE_TCL_INTERP
+
+/* Define if your sprintf returns a pointer, not a length. */
+#undef SPRINTF_RET_CHARPNT
+
+/* Define if you have the bsearch function. */
+#undef HAVE_BSEARCH
+
+/* Define if you have the gethostname function. */
+#undef HAVE_GETHOSTNAME
+
+/* Define if you have the getopt function. */
+#undef HAVE_GETOPT
+
+/* Define if you have the getpagesize function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the memchr function. */
+#undef HAVE_MEMCHR
+
+/* Define if you have the memcpy function. */
+#undef HAVE_MEMCPY
+
+/* Define if you have the memmove function. */
+#undef HAVE_MEMMOVE
+
+/* Define if you have the memset function. */
+#undef HAVE_MEMSET
+
+/* Define if you have the mkstemp function. */
+#undef HAVE_MKSTEMP
+
+/* Define if you have the mmap function. */
+#undef HAVE_MMAP
+
+/* Define if you have the select function. */
+#undef HAVE_SELECT
+
+/* Define if you have the setenv function. */
+#undef HAVE_SETENV
+
+/* Define if you have the snprintf function. */
+#undef HAVE_SNPRINTF
+
+/* Define if you have the strdup function. */
+#undef HAVE_STRDUP
+
+/* Define if you have the strerror function. */
+#undef HAVE_STRERROR
+
+/* Define if you have the strpbrk function. */
+#undef HAVE_STRPBRK
+
+/* Define if you have the strsep function. */
+#undef HAVE_STRSEP
+
+/* Define if you have the strtol function. */
+#undef HAVE_STRTOL
+
+/* Define if you have the strtoul function. */
+#undef HAVE_STRTOUL
+
+/* Define if you have the unsetenv function. */
+#undef HAVE_UNSETENV
+
+/* Define if you have the valloc function. */
+#undef HAVE_VALLOC
+
+/* Define if you have the vsnprintf function. */
+#undef HAVE_VSNPRINTF
diff --git a/contrib/nvi/build/config.sub b/contrib/nvi/build/config.sub
new file mode 100755
index 000000000000..43f086781962
--- /dev/null
+++ b/contrib/nvi/build/config.sub
@@ -0,0 +1,872 @@
+#! /bin/sh
+# Configuration validation subroutine script, version 1.1.
+# Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# 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 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.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+if [ x$1 = x ]
+then
+ echo Configuration name missing. 1>&2
+ echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
+ echo "or $0 ALIAS" 1>&2
+ echo where ALIAS is a recognized configuration type. 1>&2
+ exit 1
+fi
+
+# First pass through any local machine types.
+case $1 in
+ *local*)
+ echo $1
+ exit 0
+ ;;
+ *)
+ ;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS (if any).
+basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+if [ $basic_machine != $1 ]
+then os=`echo $1 | sed 's/.*-/-/'`
+else os=; fi
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp )
+ os=
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ tahoe | i[345]86 | i860 | m68k | m68000 | m88k | ns32k | arm \
+ | arme[lb] | pyramid \
+ | tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 \
+ | alpha | we32k | ns16k | clipper | sparclite | i370 | sh \
+ | powerpc | powerpcle | sparc64 | 1750a | dsp16xx | mips64 | mipsel \
+ | pdp11 | mips64el | mips64orion | mips64orionel \
+ | sparc)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ vax-* | tahoe-* | i[345]86-* | i860-* | m68k-* | m68000-* | m88k-* \
+ | sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \
+ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \
+ | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \
+ | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \
+ | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \
+ | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \
+ | mips64el-* | mips64orion-* | mips64orionel-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-cbm
+ ;;
+ amigados)
+ basic_machine=m68k-cbm
+ os=-amigados
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-cbm
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ cray2)
+ basic_machine=cray2-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i[345]86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+ os=-sysv32
+ ;;
+ i[345]86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+ os=-sysv4
+ ;;
+ i[345]86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+ os=-sysv
+ ;;
+ i[345]86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
+ os=-solaris2
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ mac | macintosh)
+ basic_machine=m68k-apple
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | p6)
+ # We don't have specific support for the Intel Pentium (p6) followon yet, so just call it a Pentium
+ basic_machine=i586-intel
+ ;;
+ pentium-* | p5-* | p6-*)
+ # We don't have specific support for the Intel Pentium (p6) followon yet, so just call it a Pentium
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ k5)
+ # We don't have specific support for AMD's K5 yet, so just call it a Pentium
+ basic_machine=i586-amd
+ ;;
+ nexen)
+ # We don't have specific support for Nexgen yet, so just call it a Pentium
+ basic_machine=i586-nexgen
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=rs6000-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ xmp)
+ basic_machine=xmp-cray
+ os=-unicos
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ mips)
+ basic_machine=mips-mips
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sparc)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -unixware* | svr4*)
+ os=-sysv4
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[345]* \
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigados* | -msdos* | -newsos* | -unicos* | -aos* \
+ | -nindy* | -vxworks* | -ebmon* | -hms* | -mvs* | -clix* \
+ | -riscos* | -linux* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* )
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -aux*)
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigados
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxworks*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
diff --git a/contrib/nvi/build/configure b/contrib/nvi/build/configure
new file mode 100755
index 000000000000..e2055d113ca8
--- /dev/null
+++ b/contrib/nvi/build/configure
@@ -0,0 +1,4446 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.7
+# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --enable-debug Build a debugging version."
+ac_help="$ac_help
+ --with-x use the X Window System"
+ac_help="$ac_help
+ --enable-perlinterp Include a Perl interpreter in vi."
+ac_help="$ac_help
+ --enable-tknvi Build a Tk/Tcl front-end for vi."
+ac_help="$ac_help
+ --enable-tclinterp Include a Tk/Tcl interpreter in vi."
+ac_help="$ac_help
+ --disable-curses DON'T use the nvi-provided curses routines."
+ac_help="$ac_help
+ --disable-db DON'T use the nvi-provided DB routines."
+ac_help="$ac_help
+ --disable-re DON'T use the nvi-provided RE routines."
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.7"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=../common/main.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='echo $CPP $CPPFLAGS 1>&5;
+$CPP $CPPFLAGS'
+ac_compile='echo ${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5;
+${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5 2>&5'
+ac_link='echo ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5;
+${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5 2>&5'
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ for ac_prog in ginstall installbsd scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ # OSF/1 installbsd also uses dspmsg, but is usable.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_ifs"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+# Make sure we can run config.sub.
+if $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`$ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`$ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+if test "$program_transform_name" = s,x,x,; then
+ program_transform_name=
+else
+ # Double any \ or $. echo might interpret backslashes.
+ cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+ program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+ rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+
+echo $ac_n "checking if --enable-debug option specified""... $ac_c" 1>&6
+# Check whether --enable-debug or --disable-debug was given.
+if test "${enable_debug+set}" = set; then
+ enableval="$enable_debug"
+ vi_cv_debug="yes"
+else
+ vi_cv_debug="no"
+fi
+
+if test "$vi_cv_debug" = yes; then
+ cat >> confdefs.h <<\EOF
+#define DEBUG 1
+EOF
+
+ OPTFLAG=${OPTFLAG-"-g"}
+ no_op_OPTFLAG=${no_op_OPTFLAG-"-g"}
+fi
+echo "$ac_t""$vi_cv_debug" 1>&6
+
+
+
+case "$host_os" in
+aix3.2.5) OPTFLAG=${OPTFLAG-"-O"};;
+aix4.1*) CFLAGS=${CFLAGS-"-qstrict"}
+ OPTFLAG=${OPTFLAG-"-O3"};;
+aux*) CPPFLAGS=${CPPFLAGS-"-ZP -D_BSD_SOURCE -D_SYSV_SOURCE -D_AUX_SOURCE"}
+ LDFLAGS=${LDFLAGS-"-ZP"}
+ OPTFLAG=${OPTFLAG-"-O"};;
+bsd4.4) OPTFLAG=${OPTFLAG-"-O2"};;
+bsdi*) CC=${CC-"shlicc"}
+ OPTFLAG=${OPTFLAG-"-O2"};;
+irix6*) OPTFLAG=${OPTFLAG-"-O2"};;
+irix*) OPTFLAG=${OPTFLAG-"-O2"};;
+lynxos*) # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_CC" && ac_cv_prog_CC="cc"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if ${CC-cc} -E conftest.c 2>&5 | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+ if test "${CFLAGS+set}" != set; then
+ echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_gcc_g=yes
+else
+ ac_cv_prog_gcc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6
+ if test $ac_cv_prog_gcc_g = yes; then
+ CFLAGS="-g -O"
+ else
+ CFLAGS="-O"
+ fi
+ fi
+else
+ GCC=
+ test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+
+ echo $ac_n "checking for GNU C (gcc) version 2.x""... $ac_c" 1>&6
+ ac_cv_gcc_vers=`${CC-cc} -v 2>&1 | \
+ grep "gcc version " | sed 's/.*version //'`
+ ac_cv_gcc_major=`echo "$ac_cv_gcc_vers" | sed 's/\..*//'`
+ if test "$ac_cv_gcc_major" = "2" ; then
+ echo "$ac_t""yes" 1>&6
+ else
+ echo "$ac_t""no" 1>&6
+ echo "Fatal error: Nvi requires gcc 2.x to build on LynxOS."
+ echo "See build/README.LynxOS for more information."
+ exit 1
+ fi;;
+nextstep3) CPPFLAGS=${CPPFLAGS-"-w -pipe -posix"}
+ LDFLAGS=${LDFLAGS-"-posix"}
+ OPTFLAG=${OPTFLAG-"-O9"};;
+osf*) CFLAGS=${CFLAGS-"-Olimit 1000"};;
+solaris*) no_op_OPTFLAG=${no_op_OPTFLAG-""};;
+sunos*) no_op_OPTFLAG=${no_op_OPTFLAG-""};;
+esac
+
+
+CC=${CC-cc}
+
+
+OPTFLAG=${OPTFLAG-"-O"}
+
+
+no_op_OPTFLAG=${no_op_OPTFLAG-"$OPTFLAG"}
+
+case "$host_os" in
+bsdi2.1) LIBS=${LIBS-"-lipc"};;
+dgux*) LIBS=${LIBS-"-ldgc"};;
+irix6*) LIBS=${LIBS-"-lbsd"};;
+irix*) LIBS=${LIBS-"-lc_s -lbsd"};;
+isc*) LIBS=${LIBS-"-lcposix -linet"};;
+netbsd1*) LIBS=${LIBS-"-lcrypt"};;
+ptx*) LIBS=${LIBS-"-lseq -linet -lsocket"};;
+sco3.2*) LIBS=${LIBS-"-lsocket"};;
+sinix*) LIBS=${LIBS-"-lelf -lc"};;
+solaris*) LIBS=${LIBS-"-lsocket -lnsl -ldl"}
+ RLIBS=yes;;
+wgs*) LIBS=${LIBS-"-lnsl"};;
+esac
+
+case "$host_os" in
+aux*) LIBOBJS="getopt.o strpbrk.o $LIBOBJS";;
+esac
+
+case "$host_os" in
+ultrix*) cat >> confdefs.h <<\EOF
+#define HAVE_BROKEN_VDISABLE 1
+EOF
+;;
+esac
+
+CPPFLAGS="$ADDCPPFLAGS $CPPFLAGS"
+
+LDFLAGS="$ADDLDFLAGS $LDFLAGS"
+
+LIBS="$ADDLIBS $LIBS"
+
+# If we cannot run a trivial program, we must be cross compiling.
+echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_cross=yes
+else
+cat > conftest.$ac_ext <<EOF
+#line 839 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ ac_cv_c_cross=no
+else
+ ac_cv_c_cross=yes
+fi
+fi
+rm -fr conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_cross" 1>&6
+cross_compiling=$ac_cv_c_cross
+
+echo $ac_n "checking whether the compiler ($CC $CFLAGS $LDFLAGS) actually works""... $ac_c" 1>&6
+
+ ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='echo $CPP $CPPFLAGS 1>&5;
+$CPP $CPPFLAGS'
+ac_compile='echo ${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5;
+${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5 2>&5'
+ac_link='echo ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5;
+${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5 2>&5'
+
+ if test "$cross_compiling" = yes; then
+ cat > conftest.$ac_ext <<EOF
+#line 869 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ am_cv_prog_cc_works=yes
+else
+ rm -rf conftest*
+ am_cv_prog_cc_works=no
+fi
+rm -f conftest*
+
+else
+cat > conftest.$ac_ext <<EOF
+#line 888 "configure"
+#include "confdefs.h"
+main() { exit(0); }
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ am_cv_prog_cc_works=yes
+else
+ am_cv_prog_cc_works=no
+fi
+fi
+rm -fr conftest*
+
+case "$am_cv_prog_cc_works" in
+ *no) { echo "configure: error: Installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } ;;
+ *yes) ;;
+esac
+echo "$ac_t""yes" 1>&6
+
+
+PATH="$PATH:/usr/bin:/usr/sbin:/sbin:/etc:/usr/etc:/usr/lib:/usr/ucblib:"
+
+# Extract the first word of "sh", so it can be a program name with args.
+set dummy sh; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_vi_cv_path_shell'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$vi_cv_path_shell" in
+ /*)
+ ac_cv_path_vi_cv_path_shell="$vi_cv_path_shell" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_vi_cv_path_shell="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_vi_cv_path_shell" && ac_cv_path_vi_cv_path_shell="no"
+ ;;
+esac
+fi
+vi_cv_path_shell="$ac_cv_path_vi_cv_path_shell"
+if test -n "$vi_cv_path_shell"; then
+ echo "$ac_t""$vi_cv_path_shell" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test "$vi_cv_path_shell" = no; then
+ echo "Fatal error: the shell utility not found."
+ exit 1
+fi
+
+# Extract the first word of "sendmail", so it can be a program name with args.
+set dummy sendmail; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_vi_cv_path_sendmail'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$vi_cv_path_sendmail" in
+ /*)
+ ac_cv_path_vi_cv_path_sendmail="$vi_cv_path_sendmail" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_vi_cv_path_sendmail="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_vi_cv_path_sendmail" && ac_cv_path_vi_cv_path_sendmail="no"
+ ;;
+esac
+fi
+vi_cv_path_sendmail="$ac_cv_path_vi_cv_path_sendmail"
+if test -n "$vi_cv_path_sendmail"; then
+ echo "$ac_t""$vi_cv_path_sendmail" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test "$vi_cv_path_sendmail" = no; then
+ echo "WARNING: The sendmail utility was not found!"
+ echo "WARNING: Users will not be told of saved files."
+fi
+
+
+for ac_prog in perl5 perl
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_vi_cv_path_perl'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$vi_cv_path_perl" in
+ /*)
+ ac_cv_path_vi_cv_path_perl="$vi_cv_path_perl" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_vi_cv_path_perl="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+vi_cv_path_perl="$ac_cv_path_vi_cv_path_perl"
+if test -n "$vi_cv_path_perl"; then
+ echo "$ac_t""$vi_cv_path_perl" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$vi_cv_path_perl" && break
+done
+test -n "$vi_cv_path_perl" || vi_cv_path_perl="no"
+
+
+
+echo $ac_n "checking for preserve directory""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_path_preserve'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ dirlist="/var/preserve /var/tmp /usr/tmp"
+ vi_cv_path_preserve=no
+ for i in $dirlist; do
+ if test -d $i/vi.recover; then
+ vi_cv_path_preserve=$i/vi.recover
+ break;
+ fi
+ done
+ if test "$vi_cv_path_preserve" = no; then
+ for i in $dirlist; do
+ if test -d $i -a -w $i; then
+ vi_cv_path_preserve=$i/vi.recover
+ break;
+ fi
+ done
+
+ fi
+fi
+
+if test "$vi_cv_path_preserve" = no; then
+ echo "Fatal error: no writeable preserve directory found."
+ exit 1
+fi
+echo "$ac_t""$vi_cv_path_preserve" 1>&6
+
+# Extract the first word of "chmod", so it can be a program name with args.
+set dummy chmod; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_vi_cv_path_chmod'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$vi_cv_path_chmod" in
+ /*)
+ ac_cv_path_vi_cv_path_chmod="$vi_cv_path_chmod" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_vi_cv_path_chmod="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_vi_cv_path_chmod" && ac_cv_path_vi_cv_path_chmod="missing_chmod"
+ ;;
+esac
+fi
+vi_cv_path_chmod="$ac_cv_path_vi_cv_path_chmod"
+if test -n "$vi_cv_path_chmod"; then
+ echo "$ac_t""$vi_cv_path_chmod" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "cp", so it can be a program name with args.
+set dummy cp; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_vi_cv_path_cp'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$vi_cv_path_cp" in
+ /*)
+ ac_cv_path_vi_cv_path_cp="$vi_cv_path_cp" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_vi_cv_path_cp="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_vi_cv_path_cp" && ac_cv_path_vi_cv_path_cp="missing_cp"
+ ;;
+esac
+fi
+vi_cv_path_cp="$ac_cv_path_vi_cv_path_cp"
+if test -n "$vi_cv_path_cp"; then
+ echo "$ac_t""$vi_cv_path_cp" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "ln", so it can be a program name with args.
+set dummy ln; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_vi_cv_path_ln'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$vi_cv_path_ln" in
+ /*)
+ ac_cv_path_vi_cv_path_ln="$vi_cv_path_ln" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_vi_cv_path_ln="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_vi_cv_path_ln" && ac_cv_path_vi_cv_path_ln="missing_ln"
+ ;;
+esac
+fi
+vi_cv_path_ln="$ac_cv_path_vi_cv_path_ln"
+if test -n "$vi_cv_path_ln"; then
+ echo "$ac_t""$vi_cv_path_ln" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "mkdir", so it can be a program name with args.
+set dummy mkdir; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_vi_cv_path_mkdir'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$vi_cv_path_mkdir" in
+ /*)
+ ac_cv_path_vi_cv_path_mkdir="$vi_cv_path_mkdir" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_vi_cv_path_mkdir="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_vi_cv_path_mkdir" && ac_cv_path_vi_cv_path_mkdir="missing_mkdir"
+ ;;
+esac
+fi
+vi_cv_path_mkdir="$ac_cv_path_vi_cv_path_mkdir"
+if test -n "$vi_cv_path_mkdir"; then
+ echo "$ac_t""$vi_cv_path_mkdir" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "rm", so it can be a program name with args.
+set dummy rm; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_vi_cv_path_rm'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$vi_cv_path_rm" in
+ /*)
+ ac_cv_path_vi_cv_path_rm="$vi_cv_path_rm" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_vi_cv_path_rm="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_vi_cv_path_rm" && ac_cv_path_vi_cv_path_rm="missing_rm"
+ ;;
+esac
+fi
+vi_cv_path_rm="$ac_cv_path_vi_cv_path_rm"
+if test -n "$vi_cv_path_rm"; then
+ echo "$ac_t""$vi_cv_path_rm" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_path_vi_cv_path_strip'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$vi_cv_path_strip" in
+ /*)
+ ac_cv_path_vi_cv_path_strip="$vi_cv_path_strip" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_vi_cv_path_strip="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_vi_cv_path_strip" && ac_cv_path_vi_cv_path_strip="missing_strip"
+ ;;
+esac
+fi
+vi_cv_path_strip="$ac_cv_path_vi_cv_path_strip"
+if test -n "$vi_cv_path_strip"; then
+ echo "$ac_t""$vi_cv_path_strip" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 1252 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 1266 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+# If we find X, set shell vars x_includes and x_libraries to the
+# paths, otherwise set no_x=yes.
+# Uses ac_ vars as temps to allow command line to override cache and checks.
+# --without-x overrides everything else, but does not touch the cache.
+echo $ac_n "checking for X""... $ac_c" 1>&6
+
+# Check whether --with-x or --without-x was given.
+if test "${with_x+set}" = set; then
+ withval="$with_x"
+ :
+fi
+
+if test "x$with_x" = xno; then
+ no_x=yes
+else
+ if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then
+ no_x=
+ else
+if eval "test \"`echo '$''{'ac_cv_path_x'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # One or both of the vars are not set, and there is no cached value.
+no_x=yes
+rm -fr conftestdir
+if mkdir conftestdir; then
+ cd conftestdir
+ # Make sure to not put "make" in the Imakefile rules, since we grep it out.
+ cat > Imakefile <<'EOF'
+acfindx:
+ @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"'
+EOF
+ if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then
+ no_x=
+ # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+ eval `${MAKE-make} acfindx 2>/dev/null | grep -v make`
+ # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
+ for ac_extension in a so sl; do
+ if test ! -f $ac_im_usrlibdir/libX11.$ac_extension &&
+ test -f $ac_im_libdir/libX11.$ac_extension; then
+ ac_im_usrlibdir=$ac_im_libdir; break
+ fi
+ done
+ # Screen out bogus values from the imake configuration.
+ case "$ac_im_incroot" in
+ /usr/include) ;;
+ *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;;
+ esac
+ case "$ac_im_usrlibdir" in
+ /usr/lib | /lib) ;;
+ *) test -d "$ac_im_usrlibdir" && ac_x_libraries="$ac_im_usrlibdir" ;;
+ esac
+ fi
+ cd ..
+ rm -fr conftestdir
+fi
+
+if test "$no_x" = yes; then
+test -z "$x_direct_test_library" && x_direct_test_library=Xt
+test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc
+test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h
+cat > conftest.$ac_ext <<EOF
+#line 1352 "configure"
+#include "confdefs.h"
+#include <$x_direct_test_include>
+EOF
+eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ no_x= ac_x_includes=
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ for ac_dir in \
+ /usr/X11R6/include \
+ /usr/X11R5/include \
+ /usr/X11R4/include \
+ \
+ /usr/include/X11R6 \
+ /usr/include/X11R5 \
+ /usr/include/X11R4 \
+ \
+ /usr/local/X11R6/include \
+ /usr/local/X11R5/include \
+ /usr/local/X11R4/include \
+ \
+ /usr/local/include/X11R6 \
+ /usr/local/include/X11R5 \
+ /usr/local/include/X11R4 \
+ \
+ /usr/X11/include \
+ /usr/include/X11 \
+ /usr/local/X11/include \
+ /usr/local/include/X11 \
+ \
+ /usr/X386/include \
+ /usr/x386/include \
+ /usr/XFree86/include/X11 \
+ \
+ /usr/include \
+ /usr/local/include \
+ /usr/unsupported/include \
+ /usr/athena/include \
+ /usr/local/x11r5/include \
+ /usr/lpp/Xamples/include \
+ \
+ /usr/openwin/include \
+ /usr/openwin/share/include \
+ ; \
+ do
+ if test -r "$ac_dir/$x_direct_test_include"; then
+ no_x= ac_x_includes=$ac_dir
+ break
+ fi
+ done
+fi
+rm -f conftest*
+
+# Check for the libraries.
+# See if we find them without any special options.
+# Don't add to $LIBS permanently.
+ac_save_LIBS="$LIBS"
+LIBS="-l$x_direct_test_library $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1415 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+${x_direct_test_function}()
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ LIBS="$ac_save_LIBS" no_x= ac_x_libraries=
+else
+ rm -rf conftest*
+ LIBS="$ac_save_LIBS"
+# First see if replacing the include by lib works.
+for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \
+ /usr/X11R6/lib \
+ /usr/X11R5/lib \
+ /usr/X11R4/lib \
+ \
+ /usr/lib/X11R6 \
+ /usr/lib/X11R5 \
+ /usr/lib/X11R4 \
+ \
+ /usr/local/X11R6/lib \
+ /usr/local/X11R5/lib \
+ /usr/local/X11R4/lib \
+ \
+ /usr/local/lib/X11R6 \
+ /usr/local/lib/X11R5 \
+ /usr/local/lib/X11R4 \
+ \
+ /usr/X11/lib \
+ /usr/lib/X11 \
+ /usr/local/X11/lib \
+ /usr/local/lib/X11 \
+ \
+ /usr/X386/lib \
+ /usr/x386/lib \
+ /usr/XFree86/lib/X11 \
+ \
+ /usr/lib \
+ /usr/local/lib \
+ /usr/unsupported/lib \
+ /usr/athena/lib \
+ /usr/local/x11r5/lib \
+ /usr/lpp/Xamples/lib \
+ \
+ /usr/openwin/lib \
+ /usr/openwin/share/lib \
+ ; \
+do
+ for ac_extension in a so sl; do
+ if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then
+ no_x= ac_x_libraries=$ac_dir
+ break 2
+ fi
+ done
+done
+fi
+rm -f conftest*
+
+fi
+if test "$no_x" = yes; then
+ ac_cv_path_x="no_x=yes"
+else
+ ac_cv_path_x="no_x= ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries"
+fi
+fi
+ fi
+ eval "$ac_cv_path_x"
+fi # $with_x != no
+
+if test "$no_x" = yes; then
+ echo "$ac_t""no" 1>&6
+else
+ test "x$x_includes" = xNONE && x_includes=$ac_x_includes
+ test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
+ ac_cv_path_x="no_x= ac_x_includes=$x_includes ac_x_libraries=$x_libraries"
+ echo "$ac_t""libraries $x_libraries, headers $x_includes" 1>&6
+fi
+
+
+if test "$no_x" != yes; then
+ if test "X$x_libraries" != "X"; then
+ if test "X$RLIBS" = "Xyes"; then
+ XLIBS="-R$x_libraries -L$x_libraries $XLIBS"
+ else
+ XLIBS="-L$x_libraries $XLIBS"
+ fi
+ fi
+ XLIBS="$XLIBS -lX11"
+ if test "X$x_includes" != "X"; then
+ XINCS="-I$x_includes"
+ fi
+fi
+
+
+
+echo $ac_n "checking if --enable-perlinterp option specified""... $ac_c" 1>&6
+# Check whether --enable-perlinterp or --disable-perlinterp was given.
+if test "${enable_perlinterp+set}" = set; then
+ enableval="$enable_perlinterp"
+ vi_cv_perlinterp="yes"
+else
+ vi_cv_perlinterp="no"
+fi
+
+echo "$ac_t""$vi_cv_perlinterp" 1>&6
+if test "$vi_cv_perlinterp" = "yes"; then
+ if test "$vi_cv_path_perl" = no; then
+ echo "Fatal error: no perl5 utility found."
+ exit 1
+ fi
+ $vi_cv_path_perl -e 'require 5.002' || {
+ echo "Fatal error: perl5 must be version 5.002 or later."
+ exit 1
+ }
+ $vi_cv_path_perl -e 'close(STDERR);require 5.003_01' &&
+ cat >> confdefs.h <<\EOF
+#define HAVE_PERL_5_003_01 1
+EOF
+
+
+ eval `$vi_cv_path_perl -V:shrpenv`
+ if test "X$shrpenv" = "XUNKNOWN"; then # pre 5.003_04
+ shrpenv=""
+ fi
+ vi_cv_perllib=`$vi_cv_path_perl -MConfig -e 'print $Config{privlib}'`
+ perlcppflags=`$vi_cv_path_perl -Mlib=$srcdir -MExtUtils::Embed \
+ -e 'ccflags;perl_inc'`
+ if test "X$perlcppflags" != "X"; then
+ CPPFLAGS="$perlcppflags $CPPFLAGS"
+ fi
+ perllibs=`cd $srcdir;$vi_cv_path_perl -MExtUtils::Embed \
+ -e 'ldopts'`
+ if test "X$perllibs" != "X"; then
+ LIBS="$perllibs $LIBS"
+ fi
+ perlldflags=`cd $srcdir;$vi_cv_path_perl -MExtUtils::Embed \
+ -e 'ccdlflags'`
+ if test "X$perlldflags" != "X"; then
+ LDFLAGS="$perlldflags $LDFLAGS"
+ fi
+ LIBOBJS="perl.o perlsfio.o $LIBOBJS"
+ cat >> confdefs.h <<\EOF
+#define HAVE_PERL_INTERP 1
+EOF
+
+fi
+
+
+
+echo $ac_n "checking if --enable-tknvi option specified""... $ac_c" 1>&6
+# Check whether --enable-tknvi or --disable-tknvi was given.
+if test "${enable_tknvi+set}" = set; then
+ enableval="$enable_tknvi"
+ vi_cv_tknvi="yes"
+else
+ vi_cv_tknvi="no"
+fi
+
+echo "$ac_t""$vi_cv_tknvi" 1>&6
+if test "$vi_cv_tknvi" = "yes"; then
+ tknvi=tknvi
+ TKLIBS="-ltk -ltcl -lm $XLIBS $LIBS"
+fi
+
+echo $ac_n "checking if --enable-tclinterp option specified""... $ac_c" 1>&6
+# Check whether --enable-tclinterp or --disable-tclinterp was given.
+if test "${enable_tclinterp+set}" = set; then
+ enableval="$enable_tclinterp"
+ vi_cv_tclinterp="yes"
+else
+ vi_cv_tclinterp="no"
+fi
+
+echo "$ac_t""$vi_cv_tclinterp" 1>&6
+if test "$vi_cv_tclinterp" = "yes"; then
+ LIBOBJS="tcl.o $LIBOBJS"
+ LIBS="-ltk -ltcl -lm $XLIBS $LIBS"
+ cat >> confdefs.h <<\EOF
+#define HAVE_TCL_INTERP 1
+EOF
+
+fi
+
+if test "$vi_cv_tknvi" = "yes" || test "$vi_cv_tclinterp" = "yes"; then
+ echo $ac_n "checking for -ltcl""... $ac_c" 1>&6
+ac_lib_var=`echo tcl | tr '.-/+' '___p'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ltcl -ltk -lm $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1611 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+main()
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ vi_cv_tkfatal="no"
+else
+ echo "$ac_t""no" 1>&6
+vi_cv_tkfatal="yes"
+fi
+
+ if test "$vi_cv_tkfatal" = "yes"; then
+ echo "Fatal error: no Tk/Tcl library; see the section"
+ echo "ADDING LIBRARIES AND INCLUDE FILES in the README file."
+ exit 1
+ fi
+fi
+
+if test "$vi_cv_tclinterp" = yes || test "$vi_cv_perlinterp" = yes; then
+ LIBOBJS="api.o $LIBOBJS"
+fi
+
+echo $ac_n "checking for -ltermlib""... $ac_c" 1>&6
+ac_lib_var=`echo termlib | tr '.-/+' '___p'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ltermlib $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1657 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+tgetent()
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ vi_cv_termlib=-ltermlib
+else
+ echo "$ac_t""no" 1>&6
+vi_cv_termlib=no
+fi
+
+if test "$vi_cv_termlib" = no; then
+ echo $ac_n "checking for -ltermcap""... $ac_c" 1>&6
+ac_lib_var=`echo termcap | tr '.-/+' '___p'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ltermcap $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1693 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+tgetent()
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ vi_cv_termlib=-ltermcap
+else
+ echo "$ac_t""no" 1>&6
+vi_cv_termlib=no
+fi
+
+fi
+if test "$vi_cv_termlib" != no; then
+ LIBS="$vi_cv_termlib $LIBS"
+fi
+
+echo $ac_n "checking if --disable-curses option specified""... $ac_c" 1>&6
+# Check whether --enable-curses or --disable-curses was given.
+if test "${enable_curses+set}" = set; then
+ enableval="$enable_curses"
+ vi_cv_curses="other curses"
+else
+ vi_cv_curses="bundled curses"
+fi
+
+echo "$ac_t""$vi_cv_curses" 1>&6
+case "$vi_cv_curses" in
+"bundled curses")
+ CPPFLAGS="-I\$(srcdir)/curses $CPPFLAGS"
+ cobjs="\$(COBJS)";;
+"other curses")
+ LIBS="-lcurses $LIBS";;
+esac
+
+echo $ac_n "checking for sys/mman.h""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_include_sys_mman'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1748 "configure"
+#include "confdefs.h"
+#include <sys/mman.h>
+EOF
+eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ vi_cv_include_sys_mman=yes
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ vi_cv_include_sys_mman=no
+fi
+rm -f conftest*
+fi
+
+if test "$vi_cv_include_sys_mman" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SYS_MMAN_H 1
+EOF
+
+fi
+echo "$ac_t""$vi_cv_include_sys_mman" 1>&6
+
+echo $ac_n "checking for sys/select.h""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_include_sys_select'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1778 "configure"
+#include "confdefs.h"
+#include <sys/select.h>
+EOF
+eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ vi_cv_include_sys_select=yes
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ vi_cv_include_sys_select=no
+fi
+rm -f conftest*
+fi
+
+if test "$vi_cv_include_sys_select" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SYS_SELECT_H 1
+EOF
+
+fi
+echo "$ac_t""$vi_cv_include_sys_select" 1>&6
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1808 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1830 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1848 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+cat > conftest.$ac_ext <<EOF
+#line 1869 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+fi
+rm -fr conftest*
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for ssize_t""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_type_ssize_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1904 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "ssize_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_ssize_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_ssize_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_ssize_t" 1>&6
+if test $ac_cv_type_ssize_t = no; then
+ cat >> confdefs.h <<\EOF
+#define ssize_t int
+EOF
+
+fi
+
+echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_c_bigendian=unknown
+# See if sys/param.h defines the BYTE_ORDER macro.
+cat > conftest.$ac_ext <<EOF
+#line 1937 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+int main() { return 0; }
+int t() {
+
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif
+; return 0; }
+EOF
+if eval $ac_compile; then
+ rm -rf conftest*
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+cat > conftest.$ac_ext <<EOF
+#line 1953 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+int main() { return 0; }
+int t() {
+
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+; return 0; }
+EOF
+if eval $ac_compile; then
+ rm -rf conftest*
+ ac_cv_c_bigendian=yes
+else
+ rm -rf conftest*
+ ac_cv_c_bigendian=no
+fi
+rm -f conftest*
+
+fi
+rm -f conftest*
+
+if test $ac_cv_c_bigendian = unknown; then
+if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+cat > conftest.$ac_ext <<EOF
+#line 1982 "configure"
+#include "confdefs.h"
+main () {
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long l;
+ char c[sizeof (long)];
+ } u;
+ u.l = 1;
+ exit (u.c[sizeof (long) - 1] == 1);
+}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ ac_cv_c_bigendian=no
+else
+ ac_cv_c_bigendian=yes
+fi
+fi
+rm -fr conftest*
+fi
+fi
+
+echo "$ac_t""$ac_cv_c_bigendian" 1>&6
+if test $ac_cv_c_bigendian = yes; then
+ cat >> confdefs.h <<\EOF
+#define WORDS_BIGENDIAN 1
+EOF
+
+fi
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2019 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if eval $ac_compile; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking for st_blksize in struct stat""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_struct_st_blksize'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2093 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+int main() { return 0; }
+int t() {
+struct stat s; s.st_blksize;
+; return 0; }
+EOF
+if eval $ac_compile; then
+ rm -rf conftest*
+ ac_cv_struct_st_blksize=yes
+else
+ rm -rf conftest*
+ ac_cv_struct_st_blksize=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_struct_st_blksize" 1>&6
+if test $ac_cv_struct_st_blksize = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ST_BLKSIZE 1
+EOF
+
+fi
+
+echo $ac_n "checking for mode_t""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2126 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "mode_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_mode_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_mode_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_mode_t" 1>&6
+if test $ac_cv_type_mode_t = no; then
+ cat >> confdefs.h <<\EOF
+#define mode_t int
+EOF
+
+fi
+
+echo $ac_n "checking for off_t""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2157 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "off_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_off_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_off_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_off_t" 1>&6
+if test $ac_cv_type_off_t = no; then
+ cat >> confdefs.h <<\EOF
+#define off_t long
+EOF
+
+fi
+
+echo $ac_n "checking for pid_t""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2188 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "pid_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_pid_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_pid_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_pid_t" 1>&6
+if test $ac_cv_type_pid_t = no; then
+ cat >> confdefs.h <<\EOF
+#define pid_t int
+EOF
+
+fi
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2219 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "size_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_size_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+ cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2250 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <time.h>
+int main() { return 0; }
+int t() {
+struct tm *tp; tp->tm_sec;
+; return 0; }
+EOF
+if eval $ac_compile; then
+ rm -rf conftest*
+ ac_cv_struct_tm=time.h
+else
+ rm -rf conftest*
+ ac_cv_struct_tm=sys/time.h
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_struct_tm" 1>&6
+if test $ac_cv_struct_tm = sys/time.h; then
+ cat >> confdefs.h <<\EOF
+#define TM_IN_SYS_TIME 1
+EOF
+
+fi
+
+
+ for ac_func in bsearch gethostname getopt memchr memcpy memmove memset
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2286 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in bsearch gethostname getopt memchr memcpy memmove memset
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2337 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+LIBOBJS="$LIBOBJS ${ac_func}.o"
+fi
+
+done
+
+ for ac_func in mkstemp mmap snprintf strdup strerror strpbrk strtol
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2386 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in mkstemp mmap snprintf strdup strerror strpbrk strtol
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2437 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+LIBOBJS="$LIBOBJS ${ac_func}.o"
+fi
+
+done
+
+ for ac_func in strtoul vsnprintf
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2486 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in strtoul vsnprintf
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2537 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+LIBOBJS="$LIBOBJS ${ac_func}.o"
+fi
+
+done
+
+
+for ac_func in select
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2587 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in setenv
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2638 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+ need_env=no
+else
+ echo "$ac_t""no" 1>&6
+need_env=yes
+fi
+done
+
+for ac_func in strsep
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2690 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+ need_strsep=no
+else
+ echo "$ac_t""no" 1>&6
+need_strsep=yes
+fi
+done
+
+for ac_func in unsetenv
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2742 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+need_env=yes
+fi
+done
+
+
+for ac_func in valloc getpagesize
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2795 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for working mmap""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_mmap'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_mmap=no
+else
+cat > conftest.$ac_ext <<EOF
+#line 2847 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Haertel and Jim Avera for this test. */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#ifndef HAVE_GETPAGESIZE
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif
+# else
+# ifdef NBPC
+# define getpagesize() NBPC
+# else
+# define getpagesize() PAGESIZE /* SVR4 */
+# endif
+# endif
+# endif
+#endif
+
+#ifndef HAVE_VALLOC
+# define valloc malloc
+#endif
+
+#ifdef __cplusplus
+extern "C" { void *valloc(unsigned), *malloc(unsigned); }
+#else
+char *valloc(), *malloc();
+#endif
+
+int
+main()
+{
+ char *buf1, *buf2, *buf3;
+ int i = getpagesize(), j;
+ int i2 = i * 2;
+ int fd;
+
+ buf1 = (char *)valloc(i2);
+ buf2 = (char *)valloc(i);
+ buf3 = (char *)malloc(i2);
+ for (j = 0; j < i2; ++j)
+ *(buf1 + j) = rand();
+ fd = open("conftestmmap", O_CREAT | O_RDWR, 0666);
+ write(fd, buf1, i2);
+ mmap(buf2, i, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, fd, 0);
+ for (j = 0; j < i; ++j)
+ if (*(buf1 + j) != *(buf2 + j))
+ exit(1);
+ lseek(fd, (long)i, 0);
+ read(fd, buf2, i); /* read into mapped memory -- file should not change */
+ /* (it does in i386 SVR4.0 - Jim Avera, jima@netcom.com) */
+ lseek(fd, (long)0, 0);
+ read(fd, buf3, i2);
+ for (j = 0; j < i2; ++j)
+ if (*(buf1 + j) != *(buf3 + j))
+ exit(1);
+ exit(0);
+}
+
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ ac_cv_func_mmap=yes
+else
+ ac_cv_func_mmap=no
+fi
+fi
+rm -fr conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_mmap" 1>&6
+if test $ac_cv_func_mmap = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MMAP 1
+EOF
+
+fi
+
+ac_safe=`echo "vfork.h" | tr './\055' '___'`
+echo $ac_n "checking for vfork.h""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2940 "configure"
+#include "confdefs.h"
+#include <vfork.h>
+EOF
+eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_VFORK_H 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for working vfork""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_vfork'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ echo $ac_n "checking for vfork""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_vfork'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2976 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char vfork(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char vfork();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_vfork) || defined (__stub___vfork)
+choke me
+#else
+vfork();
+#endif
+
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ eval "ac_cv_func_vfork=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_vfork=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'vfork`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+cat > conftest.$ac_ext <<EOF
+#line 3017 "configure"
+#include "confdefs.h"
+/* Thanks to Paul Eggert for this test. */
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_VFORK_H
+#include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+ argument registers are propagated back to the parent.
+ The compiler is told about this with #include <vfork.h>,
+ but some compilers (e.g. gcc -O) don't grok <vfork.h>.
+ Test for this by using a static variable whose address
+ is put into a register that is clobbered by the vfork. */
+static
+#ifdef __cplusplus
+sparc_address_test (int arg)
+#else
+sparc_address_test (arg) int arg;
+#endif
+{
+ static pid_t child;
+ if (!child) {
+ child = vfork ();
+ if (child < 0)
+ perror ("vfork");
+ if (!child) {
+ arg = getpid();
+ write(-1, "", 0);
+ _exit (arg);
+ }
+ }
+}
+main() {
+ pid_t parent = getpid ();
+ pid_t child;
+
+ sparc_address_test ();
+
+ child = vfork ();
+
+ if (child == 0) {
+ /* Here is another test for sparc vfork register problems.
+ This test uses lots of local variables, at least
+ as many local variables as main has allocated so far
+ including compiler temporaries. 4 locals are enough for
+ gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe.
+ A buggy compiler should reuse the register of parent
+ for one of the local variables, since it will think that
+ parent can't possibly be used any more in this routine.
+ Assigning to the local variable will thus munge parent
+ in the parent process. */
+ pid_t
+ p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+ p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+ /* Convince the compiler that p..p7 are live; otherwise, it might
+ use the same hardware register for all 8 local variables. */
+ if (p != p1 || p != p2 || p != p3 || p != p4
+ || p != p5 || p != p6 || p != p7)
+ _exit(1);
+
+ /* On some systems (e.g. IRIX 3.3),
+ vfork doesn't separate parent from child file descriptors.
+ If the child closes a descriptor before it execs or exits,
+ this munges the parent's descriptor as well.
+ Test for this by closing stdout in the child. */
+ _exit(close(fileno(stdout)) != 0);
+ } else {
+ int status;
+ struct stat st;
+
+ while (wait(&status) != child)
+ ;
+ exit(
+ /* Was there some problem with vforking? */
+ child < 0
+
+ /* Did the child fail? (This shouldn't happen.) */
+ || status
+
+ /* Did the vfork/compiler bug occur? */
+ || parent != getpid()
+
+ /* Did the file descriptor bug occur? */
+ || fstat(fileno(stdout), &st) != 0
+ );
+ }
+}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ ac_cv_func_vfork=yes
+else
+ ac_cv_func_vfork=no
+fi
+fi
+rm -fr conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_vfork" 1>&6
+if test $ac_cv_func_vfork = no; then
+ cat >> confdefs.h <<\EOF
+#define vfork fork
+EOF
+
+fi
+
+
+if test "$need_env" = yes; then
+ LIBOBJS="env.o $LIBOBJS"
+fi
+
+if test "$need_strsep" = yes; then
+ LIBOBJS="strsep.o $LIBOBJS"
+fi
+
+echo $ac_n "checking for fcntl/flock""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_lock'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ vi_cv_lock=none
+ case "$host_os" in
+ dgux*);;
+ irix*);;
+ *)
+ cat > conftest.$ac_ext <<EOF
+#line 3147 "configure"
+#include "confdefs.h"
+#include <fcntl.h>
+int main() { return 0; }
+int t() {
+flock(0, 0);
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ vi_cv_lock=flock
+fi
+rm -f conftest*
+;;
+ esac
+ if test "$vi_cv_lock" = none; then
+ cat > conftest.$ac_ext <<EOF
+#line 3164 "configure"
+#include "confdefs.h"
+#include <fcntl.h>
+int main() { return 0; }
+int t() {
+fcntl(0, F_SETLK, 0);
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ vi_cv_lock=fcntl
+fi
+rm -f conftest*
+
+ fi
+fi
+
+
+if test "$vi_cv_lock" = flock; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_LOCK_FLOCK 1
+EOF
+
+fi
+if test "$vi_cv_lock" = fcntl; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_LOCK_FCNTL 1
+EOF
+
+fi
+echo "$ac_t""$vi_cv_lock" 1>&6
+
+echo $ac_n "checking for ftruncate/chsize""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_ftruncate'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3201 "configure"
+#include "confdefs.h"
+#include <unistd.h>
+int main() { return 0; }
+int t() {
+ftruncate(0, 0);
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ vi_cv_ftruncate=ftruncate
+else
+ rm -rf conftest*
+ cat > conftest.$ac_ext <<EOF
+#line 3215 "configure"
+#include "confdefs.h"
+#include <unistd.h>
+int main() { return 0; }
+int t() {
+chsize(0, 0);
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ vi_cv_ftruncate=chsize
+else
+ rm -rf conftest*
+ vi_cv_ftruncate=no
+fi
+rm -f conftest*
+
+fi
+rm -f conftest*
+
+fi
+
+if test "$vi_cv_ftruncate" = ftruncate; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_FTRUNCATE_FTRUNCATE 1
+EOF
+
+fi
+if test "$vi_cv_ftruncate" = chsize; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_FTRUNCATE_CHSIZE 1
+EOF
+
+fi
+if test "$vi_cv_ftruncate" = no; then
+ echo
+ echo "Fatal error: no file truncation system call."
+ exit 1
+fi
+echo "$ac_t""$vi_cv_ftruncate" 1>&6
+
+echo $ac_n "checking for tigetstr/tigetnum""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_have_curses_tigetstr'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3261 "configure"
+#include "confdefs.h"
+#include <curses.h>
+int main() { return 0; }
+int t() {
+tigetstr(0);
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ vi_cv_have_curses_tigetstr=yes
+else
+ rm -rf conftest*
+ vi_cv_have_curses_tigetstr=no
+fi
+rm -f conftest*
+
+fi
+
+if test "$vi_cv_have_curses_tigetstr" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_CURSES_TIGETSTR 1
+EOF
+
+fi
+echo "$ac_t""$vi_cv_have_curses_tigetstr" 1>&6
+
+if test "$vi_cv_curses" = "bundled curses"; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_BSD_CURSES 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_CURSES_ADDNSTR 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_CURSES_IDLOK 1
+EOF
+
+else
+ echo $ac_n "checking for addnstr""... $ac_c" 1>&6
+ if eval "test \"`echo '$''{'vi_cv_have_curses_addnstr'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3307 "configure"
+#include "confdefs.h"
+#include <curses.h>
+int main() { return 0; }
+int t() {
+addnstr(0, 0);
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ vi_cv_have_curses_addnstr=yes
+else
+ rm -rf conftest*
+ vi_cv_have_curses_addnstr=no
+fi
+rm -f conftest*
+
+fi
+
+ if test "$vi_cv_have_curses_addnstr" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_CURSES_ADDNSTR 1
+EOF
+
+ fi
+ echo "$ac_t""$vi_cv_have_curses_addnstr" 1>&6
+
+ echo $ac_n "checking for beep""... $ac_c" 1>&6
+ if eval "test \"`echo '$''{'vi_cv_have_curses_beep'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3339 "configure"
+#include "confdefs.h"
+#include <curses.h>
+int main() { return 0; }
+int t() {
+beep();
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ vi_cv_have_curses_beep=yes
+else
+ rm -rf conftest*
+ vi_cv_have_curses_beep=no
+fi
+rm -f conftest*
+
+fi
+
+ if test "$vi_cv_have_curses_beep" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_CURSES_BEEP 1
+EOF
+
+ fi
+ echo "$ac_t""$vi_cv_have_curses_beep" 1>&6
+
+ echo $ac_n "checking for flash""... $ac_c" 1>&6
+ if eval "test \"`echo '$''{'vi_cv_have_curses_flash'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3371 "configure"
+#include "confdefs.h"
+#include <curses.h>
+int main() { return 0; }
+int t() {
+flash();
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ vi_cv_have_curses_flash=yes
+else
+ rm -rf conftest*
+ vi_cv_have_curses_flash=no
+fi
+rm -f conftest*
+
+fi
+
+ if test "$vi_cv_have_curses_flash" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_CURSES_FLASH 1
+EOF
+
+ fi
+ echo "$ac_t""$vi_cv_have_curses_flash" 1>&6
+
+ echo $ac_n "checking for idlok""... $ac_c" 1>&6
+ if eval "test \"`echo '$''{'vi_cv_have_curses_idlok'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3403 "configure"
+#include "confdefs.h"
+#include <curses.h>
+int main() { return 0; }
+int t() {
+idlok(0, 0);
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ vi_cv_have_curses_idlok=yes
+else
+ rm -rf conftest*
+ vi_cv_have_curses_idlok=no
+fi
+rm -f conftest*
+
+fi
+
+ if test "$vi_cv_have_curses_idlok" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_CURSES_IDLOK 1
+EOF
+
+ fi
+ echo "$ac_t""$vi_cv_have_curses_idlok" 1>&6
+
+ echo $ac_n "checking for keypad""... $ac_c" 1>&6
+ if eval "test \"`echo '$''{'vi_cv_have_curses_keypad'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3435 "configure"
+#include "confdefs.h"
+#include <curses.h>
+int main() { return 0; }
+int t() {
+keypad(0, 0);
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ vi_cv_have_curses_keypad=yes
+else
+ rm -rf conftest*
+ vi_cv_have_curses_keypad=no
+fi
+rm -f conftest*
+
+fi
+
+ if test "$vi_cv_have_curses_keypad" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_CURSES_KEYPAD 1
+EOF
+
+ fi
+ echo "$ac_t""$vi_cv_have_curses_keypad" 1>&6
+
+ echo $ac_n "checking for newterm""... $ac_c" 1>&6
+ if eval "test \"`echo '$''{'vi_cv_have_curses_newterm'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3467 "configure"
+#include "confdefs.h"
+#include <curses.h>
+int main() { return 0; }
+int t() {
+newterm(0, 0, 0);
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ vi_cv_have_curses_newterm=yes
+else
+ rm -rf conftest*
+ vi_cv_have_curses_newterm=no
+fi
+rm -f conftest*
+
+fi
+
+ if test "$vi_cv_have_curses_newterm" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_CURSES_NEWTERM 1
+EOF
+
+ fi
+ echo "$ac_t""$vi_cv_have_curses_newterm" 1>&6
+
+ if test "$vi_cv_have_curses_newterm" = no; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_BSD_CURSES 1
+EOF
+
+ fi
+fi
+
+echo $ac_n "checking for setupterm""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_have_curses_setupterm'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3507 "configure"
+#include "confdefs.h"
+#include <curses.h>
+int main() { return 0; }
+int t() {
+setupterm(0, 0, 0);
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ vi_cv_have_curses_setupterm=yes
+else
+ rm -rf conftest*
+ vi_cv_have_curses_setupterm=no
+fi
+rm -f conftest*
+
+fi
+
+if test "$vi_cv_have_curses_setupterm" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_CURSES_SETUPTERM 1
+EOF
+
+fi
+echo "$ac_t""$vi_cv_have_curses_setupterm" 1>&6
+
+echo $ac_n "checking for broken gettimeofday system call""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_gettimeofday'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3539 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+int main() { return 0; }
+int t() {
+gettimeofday(0, 0);
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ vi_cv_gettimeofday=okay
+else
+ rm -rf conftest*
+ vi_cv_gettimeofday=broken
+fi
+rm -f conftest*
+
+fi
+
+if test "$vi_cv_gettimeofday" = broken; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_BROKEN_GETTIMEOFDAY 1
+EOF
+
+fi
+echo "$ac_t""$vi_cv_gettimeofday" 1>&6
+
+echo $ac_n "checking for System V pty calls""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_sys5_pty'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3572 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+grantpt(0);
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ vi_cv_sys5_pty=yes
+else
+ rm -rf conftest*
+ vi_cv_sys5_pty=no
+fi
+rm -f conftest*
+
+fi
+
+if test "$vi_cv_sys5_pty" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SYS5_PTY 1
+EOF
+
+fi
+echo "$ac_t""$vi_cv_sys5_pty" 1>&6
+
+echo $ac_n "checking for revoke system call""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_revoke'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3604 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+revoke("a");
+; return 0; }
+EOF
+if eval $ac_link; then
+ rm -rf conftest*
+ vi_cv_revoke=yes
+else
+ rm -rf conftest*
+ vi_cv_revoke=no
+fi
+rm -f conftest*
+
+fi
+
+if test "$vi_cv_revoke" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_REVOKE 1
+EOF
+
+fi
+echo "$ac_t""$vi_cv_revoke" 1>&6
+
+echo $ac_n "checking for int type sprintf return value""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_sprintf_count'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+cat > conftest.$ac_ext <<EOF
+#line 3639 "configure"
+#include "confdefs.h"
+main(){char buf[20]; exit(sprintf(buf, "XXX") != 3);}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ vi_cv_sprintf_count=yes
+else
+ vi_cv_sprintf_count=no
+fi
+fi
+rm -fr conftest*
+fi
+
+if test "$vi_cv_sprintf_count" = no; then
+ cat >> confdefs.h <<\EOF
+#define SPRINTF_RET_CHARPNT 1
+EOF
+
+fi
+echo "$ac_t""$vi_cv_sprintf_count" 1>&6
+
+echo $ac_n "checking if --disable-db option specified""... $ac_c" 1>&6
+# Check whether --enable-db or --disable-db was given.
+if test "${enable_db+set}" = set; then
+ enableval="$enable_db"
+ vi_cv_db_lib="other DB"
+else
+ vi_cv_db_lib="bundled DB"
+fi
+
+echo "$ac_t""$vi_cv_db_lib" 1>&6
+case "$vi_cv_db_lib" in
+"bundled DB")
+ CPPFLAGS="-I\$(srcdir)/db/include $CPPFLAGS"
+ LIBOBJS="\$(DBOBJS) $LIBOBJS";;
+"other DB")
+ ;;
+esac
+
+echo $ac_n "checking if --disable-re option specified""... $ac_c" 1>&6
+# Check whether --enable-re or --disable-re was given.
+if test "${enable_re+set}" = set; then
+ enableval="$enable_re"
+ vi_cv_re_lib="other RE"
+else
+ vi_cv_re_lib="bundled RE"
+fi
+
+echo "$ac_t""$vi_cv_re_lib" 1>&6
+case "$vi_cv_re_lib" in
+"bundled RE")
+ CPPFLAGS="-I\$(srcdir)/regex $CPPFLAGS"
+ LIBOBJS="\$(REOBJS) $LIBOBJS";;
+"other RE")
+ ;;
+esac
+
+
+echo $ac_n "checking for u_char""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_uchar'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3703 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() { return 0; }
+int t() {
+u_char foo;
+; return 0; }
+EOF
+if eval $ac_compile; then
+ rm -rf conftest*
+ vi_cv_uchar=yes
+else
+ rm -rf conftest*
+ vi_cv_uchar=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$vi_cv_uchar" 1>&6
+if test "$vi_cv_uchar" = no; then
+ u_char_decl="typedef unsigned char u_char;"
+fi
+
+
+echo $ac_n "checking for u_short""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_ushort'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3733 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() { return 0; }
+int t() {
+u_short foo;
+; return 0; }
+EOF
+if eval $ac_compile; then
+ rm -rf conftest*
+ vi_cv_ushort=yes
+else
+ rm -rf conftest*
+ vi_cv_ushort=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$vi_cv_ushort" 1>&6
+if test "$vi_cv_ushort" = no; then
+ u_short_decl="typedef unsigned short u_short;"
+fi
+
+
+echo $ac_n "checking for u_int""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_uint'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3763 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() { return 0; }
+int t() {
+u_int foo;
+; return 0; }
+EOF
+if eval $ac_compile; then
+ rm -rf conftest*
+ vi_cv_uint=yes
+else
+ rm -rf conftest*
+ vi_cv_uint=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$vi_cv_uint" 1>&6
+if test "$vi_cv_uint" = no; then
+ u_int_decl="typedef unsigned int u_int;"
+fi
+
+
+echo $ac_n "checking for u_long""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_ulong'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3793 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() { return 0; }
+int t() {
+u_long foo;
+; return 0; }
+EOF
+if eval $ac_compile; then
+ rm -rf conftest*
+ vi_cv_ulong=yes
+else
+ rm -rf conftest*
+ vi_cv_ulong=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$vi_cv_ulong" 1>&6
+if test "$vi_cv_ulong" = no; then
+ u_long_decl="typedef unsigned long u_long;"
+fi
+
+
+echo $ac_n "checking for u_int8_t""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_uint8'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3823 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() { return 0; }
+int t() {
+u_int8_t foo;
+; return 0; }
+EOF
+if eval $ac_compile; then
+ rm -rf conftest*
+ vi_cv_uint8=yes
+else
+ rm -rf conftest*
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+cat > conftest.$ac_ext <<EOF
+#line 3840 "configure"
+#include "confdefs.h"
+main(){exit(sizeof(unsigned char) != 1);}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ vi_cv_uint8="unsigned char"
+else
+ vi_cv_uint8=no
+fi
+fi
+rm -fr conftest*
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$vi_cv_uint8" 1>&6
+if test "$vi_cv_uint8" = no; then
+ echo
+ echo "Fatal error: no unsigned, 8-bit integral type."
+ exit 1
+fi
+if test "$vi_cv_uint8" != yes; then
+ u_int8_decl="typedef $vi_cv_uint8 u_int8_t;"
+fi
+
+
+echo $ac_n "checking for u_int16_t""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_uint16'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3873 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() { return 0; }
+int t() {
+u_int16_t foo;
+; return 0; }
+EOF
+if eval $ac_compile; then
+ rm -rf conftest*
+ vi_cv_uint16=yes
+else
+ rm -rf conftest*
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+cat > conftest.$ac_ext <<EOF
+#line 3890 "configure"
+#include "confdefs.h"
+main(){exit(sizeof(unsigned short) != 2);}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ vi_cv_uint16="unsigned short"
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+cat > conftest.$ac_ext <<EOF
+#line 3902 "configure"
+#include "confdefs.h"
+main(){exit(sizeof(unsigned int) != 2);}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ vi_cv_uint16="unsigned int"
+else
+ vi_cv_uint16=no
+fi
+fi
+rm -fr conftest*
+fi
+fi
+rm -fr conftest*
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$vi_cv_uint16" 1>&6
+if test "$vi_cv_uint16" = no; then
+ echo
+ echo "Fatal error: no unsigned, 16-bit integral type."
+ exit 1
+fi
+if test "$vi_cv_uint16" != yes; then
+ u_int16_decl="typedef $vi_cv_uint16 u_int16_t;"
+fi
+
+
+echo $ac_n "checking for int16_t""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_int16'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3938 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() { return 0; }
+int t() {
+int16_t foo;
+; return 0; }
+EOF
+if eval $ac_compile; then
+ rm -rf conftest*
+ vi_cv_int16=yes
+else
+ rm -rf conftest*
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+cat > conftest.$ac_ext <<EOF
+#line 3955 "configure"
+#include "confdefs.h"
+main(){exit(sizeof(short) != 2);}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ vi_cv_int16="short"
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+cat > conftest.$ac_ext <<EOF
+#line 3967 "configure"
+#include "confdefs.h"
+main(){exit(sizeof(int) != 2);}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ vi_cv_int16="int"
+else
+ vi_cv_int16=no
+fi
+fi
+rm -fr conftest*
+fi
+fi
+rm -fr conftest*
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$vi_cv_int16" 1>&6
+if test "$vi_cv_int16" = no; then
+ echo
+ echo "Fatal error: no signed, 16-bit integral type."
+ exit 1
+fi
+if test "$vi_cv_int16" != yes; then
+ int16_decl="typedef $vi_cv_int16 int16_t;"
+fi
+
+
+echo $ac_n "checking for u_int32_t""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_uint32'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4003 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() { return 0; }
+int t() {
+u_int32_t foo;
+; return 0; }
+EOF
+if eval $ac_compile; then
+ rm -rf conftest*
+ vi_cv_uint32=yes
+else
+ rm -rf conftest*
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+cat > conftest.$ac_ext <<EOF
+#line 4020 "configure"
+#include "confdefs.h"
+main(){exit(sizeof(unsigned int) != 4);}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ vi_cv_uint32="unsigned int"
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+cat > conftest.$ac_ext <<EOF
+#line 4032 "configure"
+#include "confdefs.h"
+main(){exit(sizeof(unsigned long) != 4);}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ vi_cv_uint32="unsigned long"
+else
+ vi_cv_uint32=no
+fi
+fi
+rm -fr conftest*
+fi
+fi
+rm -fr conftest*
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$vi_cv_uint32" 1>&6
+if test "$vi_cv_uint32" = no; then
+ echo
+ echo "Fatal error: no unsigned, 32-bit integral type."
+ exit 1
+fi
+if test "$vi_cv_uint32" != yes; then
+ u_int32_decl="typedef $vi_cv_uint32 u_int32_t;"
+fi
+
+
+echo $ac_n "checking for int32_t""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'vi_cv_int32'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4068 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() { return 0; }
+int t() {
+int32_t foo;
+; return 0; }
+EOF
+if eval $ac_compile; then
+ rm -rf conftest*
+ vi_cv_int32=yes
+else
+ rm -rf conftest*
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+cat > conftest.$ac_ext <<EOF
+#line 4085 "configure"
+#include "confdefs.h"
+main(){exit(sizeof(int) != 4);}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ vi_cv_int32="int"
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+cat > conftest.$ac_ext <<EOF
+#line 4097 "configure"
+#include "confdefs.h"
+main(){exit(sizeof(long) != 4);}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ vi_cv_int32="long"
+else
+ vi_cv_int32=no
+fi
+fi
+rm -fr conftest*
+fi
+fi
+rm -fr conftest*
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$vi_cv_int32" 1>&6
+if test "$vi_cv_int32" = no; then
+ echo
+ echo "Fatal error: no signed, 32-bit integral type."
+ exit 1
+fi
+if test "$vi_cv_int32" != yes; then
+ int32_decl="typedef $vi_cv_int32 int32_t;"
+fi
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \
+ >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.7"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile port.h:port.h.in
+ pathnames.h:pathnames.h.in recover:recover.in config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@CC@%$CC%g
+s%@OPTFLAG@%$OPTFLAG%g
+s%@no_op_OPTFLAG@%$no_op_OPTFLAG%g
+s%@vi_cv_path_shell@%$vi_cv_path_shell%g
+s%@vi_cv_path_sendmail@%$vi_cv_path_sendmail%g
+s%@vi_cv_path_perl@%$vi_cv_path_perl%g
+s%@vi_cv_path_preserve@%$vi_cv_path_preserve%g
+s%@vi_cv_path_chmod@%$vi_cv_path_chmod%g
+s%@vi_cv_path_cp@%$vi_cv_path_cp%g
+s%@vi_cv_path_ln@%$vi_cv_path_ln%g
+s%@vi_cv_path_mkdir@%$vi_cv_path_mkdir%g
+s%@vi_cv_path_rm@%$vi_cv_path_rm%g
+s%@vi_cv_path_strip@%$vi_cv_path_strip%g
+s%@CPP@%$CPP%g
+s%@XINCS@%$XINCS%g
+s%@shrpenv@%$shrpenv%g
+s%@vi_cv_perllib@%$vi_cv_perllib%g
+s%@tknvi@%$tknvi%g
+s%@TKLIBS@%$TKLIBS%g
+s%@cobjs@%$cobjs%g
+s%@LIBOBJS@%$LIBOBJS%g
+s%@u_char_decl@%$u_char_decl%g
+s%@u_short_decl@%$u_short_decl%g
+s%@u_int_decl@%$u_int_decl%g
+s%@u_long_decl@%$u_long_decl%g
+s%@u_int8_decl@%$u_int8_decl%g
+s%@u_int16_decl@%$u_int16_decl%g
+s%@int16_decl@%$int16_decl%g
+s%@u_int32_decl@%$u_int32_decl%g
+s%@int32_decl@%$int32_decl%g
+
+CEOF
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile port.h:port.h.in
+ pathnames.h:pathnames.h.in recover:recover.in"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust relative srcdir, etc. for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file
+fi; done
+rm -f conftest.subs
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+CONFIG_HEADERS=${CONFIG_HEADERS-"config.h"}
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ cp $ac_given_srcdir/$ac_file_in conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) \(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+# Maximum number of lines to put in a single here document.
+ac_max_here_lines=12
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/contrib/nvi/build/configure.in b/contrib/nvi/build/configure.in
new file mode 100644
index 000000000000..cb8e4637d957
--- /dev/null
+++ b/contrib/nvi/build/configure.in
@@ -0,0 +1,725 @@
+dnl @(#)configure.in 8.134 (Berkeley) 10/15/96
+
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(../common/main.c)
+AC_CONFIG_HEADER(config.h)
+
+dnl Configure setup.
+AC_PROG_INSTALL()
+AC_CANONICAL_HOST
+AC_ARG_PROGRAM()
+
+dnl If the user wants a debugging environment, set OPTFLAG now. (Some
+dnl compilers won't mix optimizing and debug flags.)
+AC_MSG_CHECKING(if --enable-debug option specified)
+AC_ARG_ENABLE(debug,
+ [ --enable-debug Build a debugging version.],
+ [vi_cv_debug="yes"], [vi_cv_debug="no"])
+if test "$vi_cv_debug" = yes; then
+ AC_DEFINE(DEBUG)
+ OPTFLAG=${OPTFLAG-"-g"}
+ no_op_OPTFLAG=${no_op_OPTFLAG-"-g"}
+fi
+AC_MSG_RESULT($vi_cv_debug)
+
+dnl This is where we handle stuff that autoconf can't handle.
+dnl XXX
+dnl Don't override anything if it's already set from the environment.
+
+dnl Compiler, preprocessor and load flags.
+dnl AUX: -ZP disables _BSD_SOURCE et al, but enables POSIX at link time.
+dnl LynxOS: We check for gcc 2.x or better, the gcc 1 that was shipped with
+dnl LynxOS historically wasn't good enough.
+AC_SUBST(CPPFLAGS)
+case "$host_os" in
+aix3.2.5) OPTFLAG=${OPTFLAG-"-O"};;
+aix4.1*) CFLAGS=${CFLAGS-"-qstrict"}
+ OPTFLAG=${OPTFLAG-"-O3"};;
+aux*) CPPFLAGS=${CPPFLAGS-"-ZP -D_BSD_SOURCE -D_SYSV_SOURCE -D_AUX_SOURCE"}
+ LDFLAGS=${LDFLAGS-"-ZP"}
+ OPTFLAG=${OPTFLAG-"-O"};;
+bsd4.4) OPTFLAG=${OPTFLAG-"-O2"};;
+bsdi*) CC=${CC-"shlicc"}
+ OPTFLAG=${OPTFLAG-"-O2"};;
+irix6*) OPTFLAG=${OPTFLAG-"-O2"};;
+irix*) OPTFLAG=${OPTFLAG-"-O2"};;
+lynxos*) AC_PROG_CC()
+ AC_MSG_CHECKING([for GNU C (gcc) version 2.x])
+ ac_cv_gcc_vers=`${CC-cc} -v 2>&1 | \
+ grep "gcc version " | sed 's/.*version //'`
+ ac_cv_gcc_major=`echo "$ac_cv_gcc_vers" | sed 's/\..*//'`
+ if test "$ac_cv_gcc_major" = "2" ; then
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ echo "Fatal error: Nvi requires gcc 2.x to build on LynxOS."
+ echo "See build/README.LynxOS for more information."
+ exit 1
+ fi;;
+nextstep3) CPPFLAGS=${CPPFLAGS-"-w -pipe -posix"}
+ LDFLAGS=${LDFLAGS-"-posix"}
+ OPTFLAG=${OPTFLAG-"-O9"};;
+osf*) CFLAGS=${CFLAGS-"-Olimit 1000"};;
+solaris*) no_op_OPTFLAG=${no_op_OPTFLAG-""};;
+sunos*) no_op_OPTFLAG=${no_op_OPTFLAG-""};;
+esac
+
+dnl The default compiler is cc.
+AC_SUBST(CC)
+CC=${CC-cc}
+
+dnl The default OPTFLAG is -O
+AC_SUBST(OPTFLAG)
+OPTFLAG=${OPTFLAG-"-O"}
+
+dnl The SunOS/Solaris compiler can't optimize vi/v_txt.c; the symptom is
+dnl that the command 35i==<esc> turns into an infinite loop.
+AC_SUBST(no_op_OPTFLAG)
+no_op_OPTFLAG=${no_op_OPTFLAG-"$OPTFLAG"}
+
+dnl Libraries.
+case "$host_os" in
+bsdi2.1) LIBS=${LIBS-"-lipc"};;
+dgux*) LIBS=${LIBS-"-ldgc"};;
+irix6*) LIBS=${LIBS-"-lbsd"};;
+irix*) LIBS=${LIBS-"-lc_s -lbsd"};;
+isc*) LIBS=${LIBS-"-lcposix -linet"};;
+netbsd1*) LIBS=${LIBS-"-lcrypt"};;
+ptx*) LIBS=${LIBS-"-lseq -linet -lsocket"};;
+sco3.2*) LIBS=${LIBS-"-lsocket"};;
+sinix*) LIBS=${LIBS-"-lelf -lc"};;
+solaris*) LIBS=${LIBS-"-lsocket -lnsl -ldl"}
+ RLIBS=yes;;
+wgs*) LIBS=${LIBS-"-lnsl"};;
+esac
+
+dnl A/UX has a broken getopt(3), strpbrk(3).
+case "$host_os" in
+aux*) LIBOBJS="getopt.o strpbrk.o $LIBOBJS";;
+esac
+
+dnl Ultrix has a broken POSIX.1 VDISABLE value.
+case "$host_os" in
+ultrix*) AC_DEFINE(HAVE_BROKEN_VDISABLE);;
+esac
+
+dnl The user may have additional CPP information.
+CPPFLAGS="$ADDCPPFLAGS $CPPFLAGS"
+
+dnl The user may have additional load line information.
+LDFLAGS="$ADDLDFLAGS $LDFLAGS"
+
+dnl The user may have additional library information.
+LIBS="$ADDLIBS $LIBS"
+
+dnl Check to see if it's going to work.
+AM_SANITY_CHECK_CC
+
+dnl Checks for programs.
+PATH="$PATH:/usr/bin:/usr/sbin:/sbin:/etc:/usr/etc:/usr/lib:/usr/ucblib:"
+
+dnl Check for the shell path.
+AC_PATH_PROG(vi_cv_path_shell, sh, no)
+if test "$vi_cv_path_shell" = no; then
+ echo "Fatal error: the shell utility not found."
+ exit 1
+fi
+
+dnl Check for the sendmail path.
+AC_PATH_PROG(vi_cv_path_sendmail, sendmail, no)
+if test "$vi_cv_path_sendmail" = no; then
+ echo "WARNING: The sendmail utility was not found!"
+ echo "WARNING: Users will not be told of saved files."
+fi
+
+dnl Check for the perl5/perl path.
+AC_SUBST(vi_cv_path_perl)
+AC_PATH_PROGS(vi_cv_path_perl, perl5 perl, no)
+
+dnl Check for the "preserve" path.
+dnl Historically, nvi has used /var/tmp/vi.recover. The Linux filesystem
+dnl standard (FSSTND) uses /var/preserve; we add the vi.recover directory
+dnl beneath it so that we don't have name collisions with other editors.
+dnl Other systems have /var/preserve as well, so we test first for an already
+dnl existing name, and then use the first one that's writeable.
+AC_SUBST(vi_cv_path_preserve)
+AC_MSG_CHECKING(for preserve directory)
+AC_CACHE_VAL(vi_cv_path_preserve, [dnl
+ dirlist="/var/preserve /var/tmp /usr/tmp"
+ vi_cv_path_preserve=no
+ for i in $dirlist; do
+ if test -d $i/vi.recover; then
+ vi_cv_path_preserve=$i/vi.recover
+ break;
+ fi
+ done
+ if test "$vi_cv_path_preserve" = no; then
+ for i in $dirlist; do
+ if test -d $i -a -w $i; then
+ vi_cv_path_preserve=$i/vi.recover
+ break;
+ fi
+ done
+
+ fi])
+if test "$vi_cv_path_preserve" = no; then
+ echo "Fatal error: no writeable preserve directory found."
+ exit 1
+fi
+AC_MSG_RESULT($vi_cv_path_preserve)
+
+dnl Check for programs used for installation
+AC_PATH_PROG(vi_cv_path_chmod, chmod, missing_chmod)
+AC_PATH_PROG(vi_cv_path_cp, cp, missing_cp)
+AC_PATH_PROG(vi_cv_path_ln, ln, missing_ln)
+AC_PATH_PROG(vi_cv_path_mkdir, mkdir, missing_mkdir)
+AC_PATH_PROG(vi_cv_path_rm, rm, missing_rm)
+AC_PATH_PROG(vi_cv_path_strip, strip, missing_strip)
+
+dnl Checks for libraries.
+dnl Find the X libraries and includes.
+AC_PATH_X
+AC_SUBST(XINCS)
+if test "$no_x" != yes; then
+ if test "X$x_libraries" != "X"; then
+ if test "X$RLIBS" = "Xyes"; then
+ XLIBS="-R$x_libraries -L$x_libraries $XLIBS"
+ else
+ XLIBS="-L$x_libraries $XLIBS"
+ fi
+ fi
+ XLIBS="$XLIBS -lX11"
+ if test "X$x_includes" != "X"; then
+ XINCS="-I$x_includes"
+ fi
+fi
+
+dnl If the user wants a Perl interpreter in nvi, load it.
+AC_SUBST(shrpenv)
+AC_SUBST(vi_cv_perllib)
+AC_MSG_CHECKING(if --enable-perlinterp option specified)
+AC_ARG_ENABLE(perlinterp,
+ [ --enable-perlinterp Include a Perl interpreter in vi.],
+ [vi_cv_perlinterp="yes"], [vi_cv_perlinterp="no"])
+AC_MSG_RESULT($vi_cv_perlinterp)
+if test "$vi_cv_perlinterp" = "yes"; then
+ if test "$vi_cv_path_perl" = no; then
+ echo "Fatal error: no perl5 utility found."
+ exit 1
+ fi
+ $vi_cv_path_perl -e 'require 5.002' || {
+ echo "Fatal error: perl5 must be version 5.002 or later."
+ exit 1
+ }
+ $vi_cv_path_perl -e 'close(STDERR);require 5.003_01' &&
+ AC_DEFINE(HAVE_PERL_5_003_01)
+
+ eval `$vi_cv_path_perl -V:shrpenv`
+ if test "X$shrpenv" = "XUNKNOWN"; then # pre 5.003_04
+ shrpenv=""
+ fi
+ vi_cv_perllib=`$vi_cv_path_perl -MConfig -e 'print $Config{privlib}'`
+ perlcppflags=`$vi_cv_path_perl -Mlib=$srcdir -MExtUtils::Embed \
+ -e 'ccflags;perl_inc'`
+ if test "X$perlcppflags" != "X"; then
+ CPPFLAGS="$perlcppflags $CPPFLAGS"
+ fi
+ perllibs=`cd $srcdir;$vi_cv_path_perl -MExtUtils::Embed \
+ -e 'ldopts'`
+ if test "X$perllibs" != "X"; then
+ LIBS="$perllibs $LIBS"
+ fi
+ perlldflags=`cd $srcdir;$vi_cv_path_perl -MExtUtils::Embed \
+ -e 'ccdlflags'`
+ if test "X$perlldflags" != "X"; then
+ LDFLAGS="$perlldflags $LDFLAGS"
+ fi
+ LIBOBJS="perl.o perlsfio.o $LIBOBJS"
+ AC_DEFINE(HAVE_PERL_INTERP)
+fi
+
+dnl If the user wants a Tk/Tcl front-end for nvi, build it.
+AC_SUBST(tknvi)
+AC_SUBST(TKLIBS)
+AC_MSG_CHECKING(if --enable-tknvi option specified)
+AC_ARG_ENABLE(tknvi,
+ [ --enable-tknvi Build a Tk/Tcl front-end for vi.],
+ [vi_cv_tknvi="yes"], [vi_cv_tknvi="no"])
+AC_MSG_RESULT($vi_cv_tknvi)
+if test "$vi_cv_tknvi" = "yes"; then
+ tknvi=tknvi
+ TKLIBS="-ltk -ltcl -lm $XLIBS $LIBS"
+fi
+
+dnl If the user wants a Tk/Tcl interpreter in nvi, load it.
+AC_MSG_CHECKING(if --enable-tclinterp option specified)
+AC_ARG_ENABLE(tclinterp,
+ [ --enable-tclinterp Include a Tk/Tcl interpreter in vi.],
+ [vi_cv_tclinterp="yes"], [vi_cv_tclinterp="no"])
+AC_MSG_RESULT($vi_cv_tclinterp)
+if test "$vi_cv_tclinterp" = "yes"; then
+ LIBOBJS="tcl.o $LIBOBJS"
+ LIBS="-ltk -ltcl -lm $XLIBS $LIBS"
+ AC_DEFINE(HAVE_TCL_INTERP)
+fi
+
+dnl Make sure that we can find a Tk/Tcl library.
+if test "$vi_cv_tknvi" = "yes" || test "$vi_cv_tclinterp" = "yes"; then
+ AC_CHECK_LIB(tcl, main,
+ [vi_cv_tkfatal="no"], [vi_cv_tkfatal="yes"], -ltk -lm)
+ if test "$vi_cv_tkfatal" = "yes"; then
+ echo "Fatal error: no Tk/Tcl library; see the section"
+ echo "ADDING LIBRARIES AND INCLUDE FILES in the README file."
+ exit 1
+ fi
+fi
+
+dnl Both Tcl/Tk and Perl interpreters need the vi api code.
+if test "$vi_cv_tclinterp" = yes || test "$vi_cv_perlinterp" = yes; then
+ LIBOBJS="api.o $LIBOBJS"
+fi
+
+dnl Check for the termcap/termlib library. Compile in nvi's curses routines
+dnl unless the user specifies otherwise. These two checks must occur in the
+dnl current order, and -lcurses must be loaded before -ltermcap/-ltermlib.
+AC_CHECK_LIB(termlib, tgetent,
+ [vi_cv_termlib=-ltermlib], [vi_cv_termlib=no])
+if test "$vi_cv_termlib" = no; then
+ AC_CHECK_LIB(termcap, tgetent,
+ [vi_cv_termlib=-ltermcap], [vi_cv_termlib=no])
+fi
+if test "$vi_cv_termlib" != no; then
+ LIBS="$vi_cv_termlib $LIBS"
+fi
+AC_SUBST(cobjs)
+AC_MSG_CHECKING(if --disable-curses option specified)
+AC_ARG_ENABLE(curses,
+ [ --disable-curses DON'T use the nvi-provided curses routines.],
+ [vi_cv_curses="other curses"], [vi_cv_curses="bundled curses"])
+AC_MSG_RESULT($vi_cv_curses)
+case "$vi_cv_curses" in
+"bundled curses")
+ CPPFLAGS="-I\$(srcdir)/curses $CPPFLAGS"
+ cobjs="\$(COBJS)";;
+"other curses")
+ LIBS="-lcurses $LIBS";;
+esac
+
+dnl Checks for header files.
+AC_MSG_CHECKING(for sys/mman.h)
+AC_CACHE_VAL(vi_cv_include_sys_mman, [dnl
+AC_TRY_CPP([#include <sys/mman.h>],
+ [vi_cv_include_sys_mman=yes], [vi_cv_include_sys_mman=no])])
+if test "$vi_cv_include_sys_mman" = yes; then
+ AC_DEFINE(HAVE_SYS_MMAN_H)
+fi
+AC_MSG_RESULT($vi_cv_include_sys_mman)
+
+AC_MSG_CHECKING(for sys/select.h)
+AC_CACHE_VAL(vi_cv_include_sys_select, [dnl
+AC_TRY_CPP([#include <sys/select.h>],
+ [vi_cv_include_sys_select=yes], [vi_cv_include_sys_select=no])])
+if test "$vi_cv_include_sys_select" = yes; then
+ AC_DEFINE(HAVE_SYS_SELECT_H)
+fi
+AC_MSG_RESULT($vi_cv_include_sys_select)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_CHECK_TYPE(ssize_t, int)
+AC_C_BIGENDIAN
+AC_C_CONST
+AC_STRUCT_ST_BLKSIZE
+AC_TYPE_MODE_T
+AC_TYPE_OFF_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_STRUCT_TM
+
+dnl Checks for library functions.
+ AC_CHECK_FUNCS(bsearch gethostname getopt memchr memcpy memmove memset)
+AC_REPLACE_FUNCS(bsearch gethostname getopt memchr memcpy memmove memset)
+ AC_CHECK_FUNCS(mkstemp mmap snprintf strdup strerror strpbrk strtol)
+AC_REPLACE_FUNCS(mkstemp mmap snprintf strdup strerror strpbrk strtol)
+ AC_CHECK_FUNCS(strtoul vsnprintf)
+AC_REPLACE_FUNCS(strtoul vsnprintf)
+
+AC_CHECK_FUNCS(select)
+AC_CHECK_FUNCS(setenv, [need_env=no], [need_env=yes])
+AC_CHECK_FUNCS(strsep, [need_strsep=no], [need_strsep=yes])
+AC_CHECK_FUNCS(unsetenv,, [need_env=yes])
+
+AC_FUNC_MMAP
+AC_FUNC_VFORK
+
+dnl If we needed setenv or unsetenv, add in the clib/env.c replacement file.
+if test "$need_env" = yes; then
+ LIBOBJS="env.o $LIBOBJS"
+fi
+
+dnl If we need strsep, add it and define it so we get a prototype.
+if test "$need_strsep" = yes; then
+ LIBOBJS="strsep.o $LIBOBJS"
+fi
+
+dnl Check for fcntl/flock
+dnl Use flock preferentially, since it has cleaner semantics and won't
+dnl hang up the editor.
+dnl XXX
+dnl Ultrix has a broken fcntl, but a working flock.
+dnl IRIX and DGUX have a broken flock, but working fcntl.
+AC_MSG_CHECKING(for fcntl/flock)
+AC_CACHE_VAL(vi_cv_lock, [dnl
+ vi_cv_lock=none
+ case "$host_os" in
+ dgux*);;
+ irix*);;
+ *)
+ AC_TRY_LINK([#include <fcntl.h>], [flock(0, 0);],
+ [vi_cv_lock=flock]);;
+ esac
+ if test "$vi_cv_lock" = none; then
+ AC_TRY_LINK([#include <fcntl.h>], [fcntl(0, F_SETLK, 0);],
+ [vi_cv_lock=fcntl])
+ fi])
+
+if test "$vi_cv_lock" = flock; then
+ AC_DEFINE(HAVE_LOCK_FLOCK)
+fi
+if test "$vi_cv_lock" = fcntl; then
+ AC_DEFINE(HAVE_LOCK_FCNTL)
+fi
+AC_MSG_RESULT($vi_cv_lock)
+
+dnl Check for ftruncate/chsize
+AC_MSG_CHECKING(for ftruncate/chsize)
+AC_CACHE_VAL(vi_cv_ftruncate, [dnl
+AC_TRY_LINK([#include <unistd.h>], [ftruncate(0, 0);],
+ [vi_cv_ftruncate=ftruncate],
+AC_TRY_LINK([#include <unistd.h>], [chsize(0, 0);],
+ [vi_cv_ftruncate=chsize], [vi_cv_ftruncate=no]))])
+if test "$vi_cv_ftruncate" = ftruncate; then
+ AC_DEFINE(HAVE_FTRUNCATE_FTRUNCATE)
+fi
+if test "$vi_cv_ftruncate" = chsize; then
+ AC_DEFINE(HAVE_FTRUNCATE_CHSIZE)
+fi
+if test "$vi_cv_ftruncate" = no; then
+ echo
+ echo "Fatal error: no file truncation system call."
+ exit 1
+fi
+AC_MSG_RESULT($vi_cv_ftruncate)
+
+dnl Check for the tigetstr/tigetnum functions.
+AC_MSG_CHECKING(for tigetstr/tigetnum)
+AC_CACHE_VAL(vi_cv_have_curses_tigetstr, [dnl
+AC_TRY_LINK([#include <curses.h>], [tigetstr(0);],
+ [vi_cv_have_curses_tigetstr=yes],
+ [vi_cv_have_curses_tigetstr=no])])
+if test "$vi_cv_have_curses_tigetstr" = yes; then
+ AC_DEFINE(HAVE_CURSES_TIGETSTR)
+fi
+AC_MSG_RESULT($vi_cv_have_curses_tigetstr)
+
+dnl Check for potentially missing curses functions in system or user-specified
+dnl libraries. We also have to guess at whether the specified library is a
+dnl BSD or System V style curses. Use the newterm function, all System V
+dnl curses implementations have it, none, as far as I know, of the BSD ones do.
+if test "$vi_cv_curses" = "bundled curses"; then
+ AC_DEFINE(HAVE_BSD_CURSES)
+ AC_DEFINE(HAVE_CURSES_ADDNSTR)
+ AC_DEFINE(HAVE_CURSES_IDLOK)
+else
+ dnl Check for the addnstr function.
+ AC_MSG_CHECKING(for addnstr)
+ AC_CACHE_VAL(vi_cv_have_curses_addnstr, [dnl
+ AC_TRY_LINK([#include <curses.h>], [addnstr(0, 0);],
+ [vi_cv_have_curses_addnstr=yes],
+ [vi_cv_have_curses_addnstr=no])])
+ if test "$vi_cv_have_curses_addnstr" = yes; then
+ AC_DEFINE(HAVE_CURSES_ADDNSTR)
+ fi
+ AC_MSG_RESULT($vi_cv_have_curses_addnstr)
+
+ dnl Check for the beep function.
+ AC_MSG_CHECKING(for beep)
+ AC_CACHE_VAL(vi_cv_have_curses_beep, [dnl
+ AC_TRY_LINK([#include <curses.h>], [beep();],
+ [vi_cv_have_curses_beep=yes],
+ [vi_cv_have_curses_beep=no])])
+ if test "$vi_cv_have_curses_beep" = yes; then
+ AC_DEFINE(HAVE_CURSES_BEEP)
+ fi
+ AC_MSG_RESULT($vi_cv_have_curses_beep)
+
+ dnl Check for the flash function.
+ AC_MSG_CHECKING(for flash)
+ AC_CACHE_VAL(vi_cv_have_curses_flash, [dnl
+ AC_TRY_LINK([#include <curses.h>], [flash();],
+ [vi_cv_have_curses_flash=yes],
+ [vi_cv_have_curses_flash=no])])
+ if test "$vi_cv_have_curses_flash" = yes; then
+ AC_DEFINE(HAVE_CURSES_FLASH)
+ fi
+ AC_MSG_RESULT($vi_cv_have_curses_flash)
+
+ dnl Check for the idlok function.
+ AC_MSG_CHECKING(for idlok)
+ AC_CACHE_VAL(vi_cv_have_curses_idlok, [dnl
+ AC_TRY_LINK([#include <curses.h>], [idlok(0, 0);],
+ [vi_cv_have_curses_idlok=yes],
+ [vi_cv_have_curses_idlok=no])])
+ if test "$vi_cv_have_curses_idlok" = yes; then
+ AC_DEFINE(HAVE_CURSES_IDLOK)
+ fi
+ AC_MSG_RESULT($vi_cv_have_curses_idlok)
+
+ dnl Check for the keypad function.
+ AC_MSG_CHECKING(for keypad)
+ AC_CACHE_VAL(vi_cv_have_curses_keypad, [dnl
+ AC_TRY_LINK([#include <curses.h>], [keypad(0, 0);],
+ [vi_cv_have_curses_keypad=yes],
+ [vi_cv_have_curses_keypad=no])])
+ if test "$vi_cv_have_curses_keypad" = yes; then
+ AC_DEFINE(HAVE_CURSES_KEYPAD)
+ fi
+ AC_MSG_RESULT($vi_cv_have_curses_keypad)
+
+ dnl Check for the newterm function.
+ AC_MSG_CHECKING(for newterm)
+ AC_CACHE_VAL(vi_cv_have_curses_newterm, [dnl
+ AC_TRY_LINK([#include <curses.h>], [newterm(0, 0, 0);],
+ [vi_cv_have_curses_newterm=yes],
+ [vi_cv_have_curses_newterm=no])])
+ if test "$vi_cv_have_curses_newterm" = yes; then
+ AC_DEFINE(HAVE_CURSES_NEWTERM)
+ fi
+ AC_MSG_RESULT($vi_cv_have_curses_newterm)
+
+ if test "$vi_cv_have_curses_newterm" = no; then
+ AC_DEFINE(HAVE_BSD_CURSES)
+ fi
+fi
+
+dnl Check for the setupterm function. We make this check regardless of
+dnl using the system library, because it may be part of the underlying
+dnl termcap/termlib support, and we want to use the local one.
+AC_MSG_CHECKING(for setupterm)
+AC_CACHE_VAL(vi_cv_have_curses_setupterm, [dnl
+AC_TRY_LINK([#include <curses.h>], [setupterm(0, 0, 0);],
+ [vi_cv_have_curses_setupterm=yes],
+ [vi_cv_have_curses_setupterm=no])])
+if test "$vi_cv_have_curses_setupterm" = yes; then
+ AC_DEFINE(HAVE_CURSES_SETUPTERM)
+fi
+AC_MSG_RESULT($vi_cv_have_curses_setupterm)
+
+dnl Some moron decided to drop off an argument from the gettimeofday call,
+dnl without changing the name.
+AC_MSG_CHECKING(for broken gettimeofday system call)
+AC_CACHE_VAL(vi_cv_gettimeofday, [dnl
+AC_TRY_LINK([#include <sys/types.h>
+#include <sys/time.h>], [gettimeofday(0, 0);],
+ [vi_cv_gettimeofday=okay], [vi_cv_gettimeofday=broken])])
+if test "$vi_cv_gettimeofday" = broken; then
+ AC_DEFINE(HAVE_BROKEN_GETTIMEOFDAY)
+fi
+AC_MSG_RESULT($vi_cv_gettimeofday)
+
+dnl Check for which version of openpty to use, System V or Berkeley.
+AC_MSG_CHECKING(for System V pty calls)
+AC_CACHE_VAL(vi_cv_sys5_pty, [dnl
+AC_TRY_LINK(, [grantpt(0);],
+ [vi_cv_sys5_pty=yes], [vi_cv_sys5_pty=no])])
+if test "$vi_cv_sys5_pty" = yes; then
+ AC_DEFINE(HAVE_SYS5_PTY)
+fi
+AC_MSG_RESULT($vi_cv_sys5_pty)
+
+dnl Check for the revoke system call.
+AC_MSG_CHECKING(for revoke system call)
+AC_CACHE_VAL(vi_cv_revoke, [dnl
+AC_TRY_LINK(, [revoke("a");],
+ [vi_cv_revoke=yes], [vi_cv_revoke=no])])
+if test "$vi_cv_revoke" = yes; then
+ AC_DEFINE(HAVE_REVOKE)
+fi
+AC_MSG_RESULT($vi_cv_revoke)
+
+dnl Some versions of sprintf return a pointer to the first argument instead
+dnl of a character count. We assume that the return value of snprintf and
+dnl vsprintf etc. will be the same as sprintf, and check the easy one.
+AC_MSG_CHECKING(for int type sprintf return value)
+AC_CACHE_VAL(vi_cv_sprintf_count, [dnl
+AC_TRY_RUN([main(){char buf[20]; exit(sprintf(buf, "XXX") != 3);}],
+ [vi_cv_sprintf_count=yes], [vi_cv_sprintf_count=no])])
+if test "$vi_cv_sprintf_count" = no; then
+ AC_DEFINE(SPRINTF_RET_CHARPNT)
+fi
+AC_MSG_RESULT($vi_cv_sprintf_count)
+
+dnl We compile in nvi's DB routines unless the user specifies otherwise.
+AC_MSG_CHECKING(if --disable-db option specified)
+AC_ARG_ENABLE(db,
+ [ --disable-db DON'T use the nvi-provided DB routines.],
+ [vi_cv_db_lib="other DB"], [vi_cv_db_lib="bundled DB"])
+AC_MSG_RESULT($vi_cv_db_lib)
+case "$vi_cv_db_lib" in
+"bundled DB")
+ CPPFLAGS="-I\$(srcdir)/db/include $CPPFLAGS"
+ LIBOBJS="\$(DBOBJS) $LIBOBJS";;
+"other DB")
+ ;;
+esac
+
+dnl We compile in nvi's RE routines unless the user specifies otherwise.
+AC_MSG_CHECKING(if --disable-re option specified)
+AC_ARG_ENABLE(re,
+ [ --disable-re DON'T use the nvi-provided RE routines.],
+ [vi_cv_re_lib="other RE"], [vi_cv_re_lib="bundled RE"])
+AC_MSG_RESULT($vi_cv_re_lib)
+case "$vi_cv_re_lib" in
+"bundled RE")
+ CPPFLAGS="-I\$(srcdir)/regex $CPPFLAGS"
+ LIBOBJS="\$(REOBJS) $LIBOBJS";;
+"other RE")
+ ;;
+esac
+
+dnl Check for the standard shorthand types.
+AC_SUBST(u_char_decl)
+AC_MSG_CHECKING(for u_char)
+AC_CACHE_VAL(vi_cv_uchar, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], u_char foo;,
+ [vi_cv_uchar=yes], [vi_cv_uchar=no])])
+AC_MSG_RESULT($vi_cv_uchar)
+if test "$vi_cv_uchar" = no; then
+ u_char_decl="typedef unsigned char u_char;"
+fi
+
+AC_SUBST(u_short_decl)
+AC_MSG_CHECKING(for u_short)
+AC_CACHE_VAL(vi_cv_ushort, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], u_short foo;,
+ [vi_cv_ushort=yes], [vi_cv_ushort=no])])
+AC_MSG_RESULT($vi_cv_ushort)
+if test "$vi_cv_ushort" = no; then
+ u_short_decl="typedef unsigned short u_short;"
+fi
+
+AC_SUBST(u_int_decl)
+AC_MSG_CHECKING(for u_int)
+AC_CACHE_VAL(vi_cv_uint, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], u_int foo;,
+ [vi_cv_uint=yes], [vi_cv_uint=no])])
+AC_MSG_RESULT($vi_cv_uint)
+if test "$vi_cv_uint" = no; then
+ u_int_decl="typedef unsigned int u_int;"
+fi
+
+AC_SUBST(u_long_decl)
+AC_MSG_CHECKING(for u_long)
+AC_CACHE_VAL(vi_cv_ulong, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], u_long foo;,
+ [vi_cv_ulong=yes], [vi_cv_ulong=no])])
+AC_MSG_RESULT($vi_cv_ulong)
+if test "$vi_cv_ulong" = no; then
+ u_long_decl="typedef unsigned long u_long;"
+fi
+
+dnl DB/Vi use specific integer sizes.
+AC_SUBST(u_int8_decl)
+AC_MSG_CHECKING(for u_int8_t)
+AC_CACHE_VAL(vi_cv_uint8, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], u_int8_t foo;,
+ [vi_cv_uint8=yes],
+AC_TRY_RUN([main(){exit(sizeof(unsigned char) != 1);}],
+ [vi_cv_uint8="unsigned char"], [vi_cv_uint8=no]))])
+AC_MSG_RESULT($vi_cv_uint8)
+if test "$vi_cv_uint8" = no; then
+ echo
+ echo "Fatal error: no unsigned, 8-bit integral type."
+ exit 1
+fi
+if test "$vi_cv_uint8" != yes; then
+ u_int8_decl="typedef $vi_cv_uint8 u_int8_t;"
+fi
+
+AC_SUBST(u_int16_decl)
+AC_MSG_CHECKING(for u_int16_t)
+AC_CACHE_VAL(vi_cv_uint16, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], u_int16_t foo;,
+ [vi_cv_uint16=yes],
+AC_TRY_RUN([main(){exit(sizeof(unsigned short) != 2);}],
+ [vi_cv_uint16="unsigned short"],
+AC_TRY_RUN([main(){exit(sizeof(unsigned int) != 2);}],
+ [vi_cv_uint16="unsigned int"], [vi_cv_uint16=no])))])
+AC_MSG_RESULT($vi_cv_uint16)
+if test "$vi_cv_uint16" = no; then
+ echo
+ echo "Fatal error: no unsigned, 16-bit integral type."
+ exit 1
+fi
+if test "$vi_cv_uint16" != yes; then
+ u_int16_decl="typedef $vi_cv_uint16 u_int16_t;"
+fi
+
+AC_SUBST(int16_decl)
+AC_MSG_CHECKING(for int16_t)
+AC_CACHE_VAL(vi_cv_int16, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], int16_t foo;,
+ [vi_cv_int16=yes],
+AC_TRY_RUN([main(){exit(sizeof(short) != 2);}],
+ [vi_cv_int16="short"],
+AC_TRY_RUN([main(){exit(sizeof(int) != 2);}],
+ [vi_cv_int16="int"], [vi_cv_int16=no])))])
+AC_MSG_RESULT($vi_cv_int16)
+if test "$vi_cv_int16" = no; then
+ echo
+ echo "Fatal error: no signed, 16-bit integral type."
+ exit 1
+fi
+if test "$vi_cv_int16" != yes; then
+ int16_decl="typedef $vi_cv_int16 int16_t;"
+fi
+
+AC_SUBST(u_int32_decl)
+AC_MSG_CHECKING(for u_int32_t)
+AC_CACHE_VAL(vi_cv_uint32, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], u_int32_t foo;,
+ [vi_cv_uint32=yes],
+AC_TRY_RUN([main(){exit(sizeof(unsigned int) != 4);}],
+ [vi_cv_uint32="unsigned int"],
+AC_TRY_RUN([main(){exit(sizeof(unsigned long) != 4);}],
+ [vi_cv_uint32="unsigned long"], [vi_cv_uint32=no])))])
+AC_MSG_RESULT($vi_cv_uint32)
+if test "$vi_cv_uint32" = no; then
+ echo
+ echo "Fatal error: no unsigned, 32-bit integral type."
+ exit 1
+fi
+if test "$vi_cv_uint32" != yes; then
+ u_int32_decl="typedef $vi_cv_uint32 u_int32_t;"
+fi
+
+AC_SUBST(int32_decl)
+AC_MSG_CHECKING(for int32_t)
+AC_CACHE_VAL(vi_cv_int32, [dnl
+AC_TRY_COMPILE([#include <sys/types.h>], int32_t foo;,
+ [vi_cv_int32=yes],
+AC_TRY_RUN([main(){exit(sizeof(int) != 4);}],
+ [vi_cv_int32="int"],
+AC_TRY_RUN([main(){exit(sizeof(long) != 4);}],
+ [vi_cv_int32="long"], [vi_cv_int32=no])))])
+AC_MSG_RESULT($vi_cv_int32)
+if test "$vi_cv_int32" = no; then
+ echo
+ echo "Fatal error: no signed, 32-bit integral type."
+ exit 1
+fi
+if test "$vi_cv_int32" != yes; then
+ int32_decl="typedef $vi_cv_int32 int32_t;"
+fi
+
+AC_OUTPUT(Makefile port.h:port.h.in
+ pathnames.h:pathnames.h.in recover:recover.in)
diff --git a/contrib/nvi/build/distrib b/contrib/nvi/build/distrib
new file mode 100644
index 000000000000..45dbe52f4049
--- /dev/null
+++ b/contrib/nvi/build/distrib
@@ -0,0 +1,84 @@
+#! /bin/sh
+# @(#)distrib 8.11 (Berkeley) 10/23/96
+
+# Clean
+#make -f Makefile.in clean
+#rm -f configure config.h.in
+
+# Build autoconf structure.
+echo "Running autoheader"
+autoheader 2>&1 | sed '/warning: AC_TRY_RUN called without default/d'
+chmod 444 config.h.in
+echo "Running autoconf"
+autoconf 2>&1 | sed '/warning: AC_TRY_RUN called without default/d'
+chmod 555 configure config.guess config.sub install-sh
+
+# Build include files.
+f=../include/cl_extern.h
+echo "Building $f"
+rm -f $f
+sed -n "s/^ \* PUBLIC: \(.*\)/\1/p" ../cl/*.c > $f
+chmod 444 $f
+
+f=../include/com_extern.h
+echo "Building $f"
+rm -f $f
+sed -n "s/^ \* PUBLIC: \(.*\)/\1/p" ../clib/*.c ../common/*.c > $f
+chmod 444 $f
+
+f=../include/ex_def.h
+echo "Building $f"
+rm -f $f
+awk -f ../ex/ex.awk ../ex/ex_cmd.c > $f
+chmod 444 $f
+
+f=../include/ex_extern.h
+echo "Building $f"
+rm -f $f
+sed -n "s/^ \* PUBLIC: \(.*\)/\1/p" ../ex/*.c > $f
+chmod 444 $f
+
+if [ -d ../ip ]; then
+ f=../include/ip_extern.h
+ echo "Building $f"
+ rm -f $f
+ sed -n "s/^ \* PUBLIC: \(.*\)/\1/p" ../ip/*.c > $f
+ chmod 444 $f
+fi
+
+f=../include/options_def.h
+echo "Building $f"
+rm -f $f
+awk -f ../common/options.awk ../common/options.c > $f
+chmod 444 $f
+
+f=../include/perl_extern.h
+echo "Building $f"
+rm -f $f
+sed -n "s/^ \* PUBLIC: \(.*\)/\1/p" ../perl_api/*.xs ../perl_api/*.c > $f
+chmod 444 $f
+
+f=../include/tcl_extern.h
+echo "Building $f"
+rm -f $f
+sed -n "s/^ \* PUBLIC: \(.*\)/\1/p" ../tcl_api/*.c > $f
+chmod 444 $f
+
+f=../include/tk_extern.h
+echo "Building $f"
+rm -f $f
+sed -n "s/^ \* PUBLIC: \(.*\)/\1/p" ../tk/*.c > $f
+chmod 444 $f
+
+f=../include/vi_extern.h
+echo "Building $f"
+rm -f $f
+sed -n "s/^ \* PUBLIC: \(.*\)/\1/p" ../vi/*.c > $f
+chmod 444 $f
+
+# Build tags files.
+echo "Building tags files"
+rm -f tags
+ctags -w -d ../cl/*.[ch] ../common/*.[ch] ../ex/*.[ch] ../perl_api/*.[ch] \
+ ../tcl_api/*.[ch] ../tk/*.[ch] ../vi/*.[ch]
+chmod 444 tags
diff --git a/contrib/nvi/build/install-sh b/contrib/nvi/build/install-sh
new file mode 100755
index 000000000000..ab74c882e923
--- /dev/null
+++ b/contrib/nvi/build/install-sh
@@ -0,0 +1,238 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/contrib/nvi/build/pathnames.h.in b/contrib/nvi/build/pathnames.h.in
new file mode 100644
index 000000000000..09cf97460ae8
--- /dev/null
+++ b/contrib/nvi/build/pathnames.h.in
@@ -0,0 +1,45 @@
+/* @(#)pathnames.h.in 8.4 (Berkeley) 6/26/96 */
+
+#ifndef _PATH_BSHELL
+#define _PATH_BSHELL "@vi_cv_path_shell@"
+#endif
+
+#ifndef _PATH_EXRC
+#define _PATH_EXRC ".exrc"
+#endif
+
+#ifndef _PATH_MSGCAT
+#define _PATH_MSGCAT "./"
+#endif
+
+#ifndef _PATH_NEXRC
+#define _PATH_NEXRC ".nexrc"
+#endif
+
+#ifndef _PATH_PRESERVE
+#define _PATH_PRESERVE "@vi_cv_path_preserve@"
+#endif
+
+#ifndef _PATH_SYSV_PTY
+#define _PATH_SYSV_PTY "/dev/ptmx"
+#endif
+
+#ifndef _PATH_SENDMAIL
+#define _PATH_SENDMAIL "@vi_cv_path_sendmail@"
+#endif
+
+#ifndef _PATH_SYSEXRC
+#define _PATH_SYSEXRC "/etc/vi.exrc"
+#endif
+
+#ifndef _PATH_TAGS
+#define _PATH_TAGS "tags"
+#endif
+
+#ifndef _PATH_TMP
+#define _PATH_TMP "/tmp"
+#endif
+
+#ifndef _PATH_TTY
+#define _PATH_TTY "/dev/tty"
+#endif
diff --git a/contrib/nvi/build/port.h.in b/contrib/nvi/build/port.h.in
new file mode 100644
index 000000000000..6696848ecc7d
--- /dev/null
+++ b/contrib/nvi/build/port.h.in
@@ -0,0 +1,185 @@
+/* @(#)port.h.in 8.13 (Berkeley) 6/12/96 */
+
+/*
+ * Declare the basic types, if they aren't already declared. Named and
+ * some system's db.h files protect them with __BIT_TYPES_DEFINED__.
+ */
+#ifndef __BIT_TYPES_DEFINED__
+#define __BIT_TYPES_DEFINED__
+@u_int8_decl@
+@int16_decl@
+@u_int16_decl@
+@int32_decl@
+@u_int32_decl@
+#endif
+
+@u_char_decl@
+@u_short_decl@
+@u_int_decl@
+@u_long_decl@
+
+/*
+ * XXX
+ * Handle function prototypes. This steps on name space that vi doesn't
+ * control, but all of the other solutions are worse.
+ */
+#undef __P
+#if defined(__STDC__) || defined(__cplusplus)
+#define __P(protos) protos /* ANSI C prototypes */
+#else
+#define __P(protos) () /* K&R C preprocessor */
+#endif
+
+/*
+ * XXX
+ * Some versions of System V changed the number of arguments to gettimeofday
+ * without changing the name.
+ */
+#ifdef HAVE_BROKEN_GETTIMEOFDAY
+#define gettimeofday(tv, tz) gettimeofday(tv)
+#endif
+
+/*
+ * XXX
+ * If we don't have mmap, we fake it with read and write, but we'll
+ * still need the header information.
+ */
+#ifndef HAVE_SYS_MMAN_H
+#define MAP_SHARED 1 /* share changes */
+#define MAP_PRIVATE 2 /* changes are private */
+#define PROT_READ 0x1 /* pages can be read */
+#define PROT_WRITE 0x2 /* pages can be written */
+#define PROT_EXEC 0x4 /* pages can be executed */
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.1 names for file descriptors.
+ */
+#ifndef STDERR_FILENO
+#define STDIN_FILENO 0 /* ANSI C #defines */
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.1 names for seek settings.
+ */
+#ifndef SEEK_END
+#define SEEK_SET 0 /* POSIX 1003.1 seek values */
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+
+/*
+ * Hack _POSIX_VDISABLE to \377 since Ultrix doesn't honor _POSIX_VDISABLE
+ * (treats it as ^@). The symptom is that the ^@ keystroke immediately
+ * drops core.
+ */
+#ifdef HAVE_BROKEN_VDISABLE
+#undef _POSIX_VDISABLE
+#define _POSIX_VDISABLE ((unsigned char)'\377')
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.1 tty disabling character.
+ */
+#ifndef _POSIX_VDISABLE
+#define _POSIX_VDISABLE 0 /* Some systems used 0. */
+#endif
+
+/*
+ * XXX
+ * 4.4BSD extension to only set the software termios bits.
+ */
+#ifndef TCSASOFT /* 4.4BSD extension. */
+#define TCSASOFT 0
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.1 maximum path length.
+ */
+#ifndef MAXPATHLEN
+#ifdef PATH_MAX
+#define MAXPATHLEN PATH_MAX
+#else
+#define MAXPATHLEN 1024
+#endif
+#endif
+
+/*
+ * XXX
+ * MIN, MAX, historically in <sys/param.h>
+ */
+#ifndef MAX
+#define MAX(_a,_b) ((_a)<(_b)?(_b):(_a))
+#endif
+#ifndef MIN
+#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b))
+#endif
+
+/*
+ * XXX
+ * "DB" isn't always portable, and we want the private information.
+ */
+#define DB L__DB
+#undef pgno_t /* IRIX has its own version. */
+#define pgno_t L__db_pgno_t
+
+/*
+ * XXX
+ * 4.4BSD extension to provide lock values in the open(2) call.
+ */
+#ifndef O_EXLOCK
+#define O_EXLOCK 0
+#endif
+
+#ifndef O_SHLOCK
+#define O_SHLOCK 0
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.1 bad file format errno.
+ */
+#ifndef EFTYPE
+#define EFTYPE EINVAL
+#endif
+
+/*
+ * XXX
+ * POSIX 1003.2 RE length limit.
+ */
+#ifndef _POSIX2_RE_DUP_MAX
+#define _POSIX2_RE_DUP_MAX 255
+#endif
+
+/*
+ * XXX
+ * 4.4BSD extension to determine if a program dropped core from the exit
+ * status.
+ */
+#ifndef WCOREDUMP
+#define WCOREDUMP(a) 0
+#endif
+
+/*
+ * XXX
+ * Endian-ness of the machine.
+ */
+#if !defined(LITTLE_ENDIAN)
+#define LITTLE_ENDIAN 1234
+#endif
+#if !defined(BIG_ENDIAN)
+#define BIG_ENDIAN 4321
+#endif
+#if !defined(BYTE_ORDER)
+#if WORDS_BIGENDIAN == 1
+#define BYTE_ORDER BIG_ENDIAN
+#else
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+#endif
diff --git a/contrib/nvi/build/recover.in b/contrib/nvi/build/recover.in
new file mode 100644
index 000000000000..cfaf75f2c287
--- /dev/null
+++ b/contrib/nvi/build/recover.in
@@ -0,0 +1,49 @@
+#!/bin/sh -
+#
+# @(#)recover.in 8.8 (Berkeley) 10/10/96
+#
+# Script to recover nvi edit sessions.
+
+RECDIR="@vi_cv_path_preserve@"
+SENDMAIL="@vi_cv_path_sendmail@"
+
+echo 'Recovering nvi editor sessions.'
+
+# Check editor backup files.
+vibackup=`echo $RECDIR/vi.*`
+if [ "$vibackup" != "$RECDIR/vi.*" ]; then
+ for i in $vibackup; do
+ # Only test files that are readable.
+ if test ! -r $i; then
+ continue
+ fi
+
+ # Unmodified nvi editor backup files either have the
+ # execute bit set or are zero length. Delete them.
+ if test -x $i -o ! -s $i; then
+ rm $i
+ fi
+ done
+fi
+
+# It is possible to get incomplete recovery files, if the editor crashes
+# at the right time.
+virecovery=`echo $RECDIR/recover.*`
+if [ "$virecovery" != "$RECDIR/recover.*" ]; then
+ for i in $virecovery; do
+ # Only test files that are readable.
+ if test ! -r $i; then
+ continue
+ fi
+
+ # Delete any recovery files that are zero length, corrupted,
+ # or that have no corresponding backup file. Else send mail
+ # to the user.
+ recfile=`awk '/^X-vi-recover-path:/{print $2}' < $i`
+ if test -n "$recfile" -a -s "$recfile"; then
+ $SENDMAIL -t < $i
+ else
+ rm $i
+ fi
+ done
+fi
diff --git a/contrib/nvi/build/spell.ok b/contrib/nvi/build/spell.ok
new file mode 100644
index 000000000000..fc103f43602d
--- /dev/null
+++ b/contrib/nvi/build/spell.ok
@@ -0,0 +1,58 @@
+ADDCPPFLAGS
+ADDLDFLAGS
+ADDLIBS
+CPPFLAGS
+FreeBSD
+LDFLAGS
+LIBS
+Lite
+NVI
+NVI'S
+NetBSD
+Nvi
+POSIX
+Perl
+README
+Tcl
+Tk
+asnvi
+asvi
+autoconf
+bindir
+cd
+contrib
+csh
+datadir
+datafiles
+db
+distclean
+env
+filesystem
+foo
+gcc
+ksh
+lcurses
+ldb
+lm
+lperl
+ltcl
+ltermcap
+ltermlib
+ltk
+mandir
+mkdir
+ncurses
+nex
+nvi
+nview
+perl
+perlinterp
+setenv
+sh
+tcl
+tclinterp
+tcsh
+terminfo
+tknvi
+usr
+vi
diff --git a/contrib/nvi/catalog/Makefile b/contrib/nvi/catalog/Makefile
new file mode 100644
index 000000000000..1044051ff389
--- /dev/null
+++ b/contrib/nvi/catalog/Makefile
@@ -0,0 +1,84 @@
+# @(#)Makefile 8.29 (Berkeley) 10/19/96
+
+CAT= dutch english french german ru_SU.KOI8-R spanish swedish
+FILES= ../cl/*.c ../common/*.c ../ex/*.c ../tk/*.c ../vi/*.c
+
+all: dump ${CAT}
+
+${CAT}: english.base
+ @echo "... $@"; \
+ rm -f $@; \
+ sort -u $@.base | \
+ awk '{ \
+ if ($$1 == 1) { \
+ print "\nMESSAGE NUMBER 1 IS NOT LEGAL"; \
+ exit 1; \
+ } \
+ if (++nline > $$1) { \
+ print "DUPLICATE MESSAGE NUMBER " $$1; \
+ exit 1; \
+ } \
+ for (; nline < $$1; ++nline) \
+ print ""; \
+ print $0; \
+ }' | \
+ sed -e '1s/^/VI_MESSAGE_CATALOG/' \
+ -e '/"/s/^[^"]*"//' \
+ -e '1!s/"$$/X/' > $@; \
+ chmod 444 $@; \
+ if grep DUPLICATE $@ > /dev/null; then \
+ grep DUPLICATE $@; \
+ fi; \
+ if grep 'NOT LEGAL' $@ > /dev/null; then \
+ grep 'NOT LEGAL' $@; \
+ fi
+
+CHK= dutch.check english.check french.check german.check \
+ ru_SU.KOI8-R.check spanish.check swedish.check
+check: ${CHK}
+${CHK}: ${CAT}
+ @echo "... $@"; \
+ f=`basename $@ .check`; \
+ (echo "Unused message id's (this is okay):"; \
+ awk '{ \
+ while (++nline < $$1) \
+ printf "%03d\n", nline; \
+ }' < $$f.base; \
+ echo =========================; \
+ echo "MISSING ERROR MESSAGES (Please add!):"; \
+ awk '{print $$1}' < $$f.base | sort -u > __ck1; \
+ awk '{print $$1}' < english.base | sort -u > __ck2; \
+ comm -13 __ck1 __ck2; \
+ echo =========================; \
+ echo "Extra error messages (just delete them):"; \
+ comm -23 __ck1 __ck2; \
+ echo =========================; \
+ echo "MESSAGES WITH THE SAME MESSAGE ID's (FIX!):"; \
+ for j in \
+ `sed '/^$$/d' < $$f.base | sort -u | \
+ awk '{print $$1}' | uniq -d`; do \
+ egrep $$j $$f.base; \
+ done; \
+ echo =========================; \
+ echo "Duplicate messages, both id and message (this is okay):"; \
+ sed '/^$$/d' < $$f.base | sort | uniq -c | \
+ awk '$$1 != 1 { print $$0 }' | sort -n; \
+ echo =========================; \
+ echo "Duplicate messages, just message (this is okay):"; \
+ sed '/^$$/d' < $$f | sort | uniq -c | \
+ awk '$$1 != 1 { print $$0 }' | sort -n; \
+ echo =========================) > $@
+
+english.base: dump ${FILES} #Makefile
+ ./dump ${FILES} |\
+ sed -e '/|/!d' \
+ -e 's/|/ "/' \
+ -e 's/^"//' \
+ -e 's/\\"/"/g' |\
+ sort -n > $@
+
+dump: dump.c
+ ${CC} -O -o dump dump.c
+
+clean:
+ rm -f dump dump.o ${CAT} english.base *.check __ck1 __ck2
diff --git a/contrib/nvi/catalog/README b/contrib/nvi/catalog/README
new file mode 100644
index 000000000000..15a706358869
--- /dev/null
+++ b/contrib/nvi/catalog/README
@@ -0,0 +1,166 @@
+# @(#)README 8.4 (Berkeley) 11/22/94
+
+Generally, all non-system error and informational messages in nvi are
+catalog messages, i.e. they can be tailored to a specific langauge.
+Command strings, usage strings, system errors and other "known text"
+are not. It would certainly be possible to internationalize all the
+text strings in nvi, but it's unclear that it's the right thing to do.
+
+First, there's no portable way to do message catalogs. The System V
+scheme is a reasonable choice, but none of the 4BSD derived systems
+support it. So, catalogs are completely implemented within nvi, and
+don't require any library support.
+
+Message catalogs in nvi are fairly simple. Every catalog message
+consists of two parts -- an initial number followed by a pipe (`|')
+character, followed by the English text for the message. For example:
+
+ msgq(sp, M_ERR, "001|This is an error message");
+
+would be a typical message.
+
+When the msgq() routine is called, if the user has specified a message
+catalog and the format string (the third argument) has a leading number,
+then it is converted to a record number, and that record is retrieved
+from the message catalog and used as a replacement format string. If
+the record can't be retrieved for any reason, the English text is displayed
+instead.
+
+Each message format string MUST map into the English format string, i.e.
+it can't display more or different arguments than the English one.
+
+For example:
+
+ msgq(sp, M_ERR, "002|Error: %d %x", arg1, arg2);
+
+is a format string that displays two arguments. It is possible, however,
+to reorder the arguments or to not display all of them. The convention
+nvi uses is the System V printf(3) convention, i.e. "%[0-9]*$" is the name
+of a specific, numbered argument. For example:
+
+ msgq(sp, M_ERR, "002|Error: %2$d %1$x", arg1, arg2);
+
+displays the arguments in reverse order.
+
+If the system supports this convention in its library printf routines
+(as specified by the test #define NL_ARGMAX), nvi uses those routines.
+Otherwise, there is some serious magic going on in common/msg.c to make
+this all work.
+
+Arguments to the msgq function are required to contain ONLY printable
+characters. No further translation is done by the msgq routine before
+displaying the message on the screen. For example, in the msgq call:
+
+ msgq(sp, M_ERR, "003|File: %s", file_name);
+
+"file_name" must contain only printable characters. The routine
+msg_print() returns a printable version of a string in allocated
+memory. For example:
+
+ char *p;
+
+ p = msg_print(sp, file_name);
+ msgq(sp, M_ERR, M("003", "File: %s"), p);
+ FREE_SPACE(sp, p, 0);
+
+makes sure that "file_name" is printable before calling the msgq
+routine.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+The message catalogs themselves are maintained in two files. The first
+is the "base file" which contains two fields, a record number and the
+message itself. All base files are named using the convention
+"vi_<language>.base", e.g. the English one is "vi_english.base". For
+example:
+
+ 002 "Unable to create temporary file"
+ 003 "Warning: %s is not a regular file"
+ 004 "%s already locked, session is read-only"
+ 005 "%s: remove"
+ 006 "%s: close"
+ 007 "%s: remove"
+ 008 "%s: remove"
+ 009 "Read-only file, not written; use ! to override"
+ 010 "Read-only file, not written"
+
+are the first few lines of the current vi_english.base file. Note that
+message #1 is missing -- the first message of each catalog is a special
+one, so that nvi can recognize message catalog files. It's added by the
+Makefile script that creates the second version of the message catalog.
+
+The second file is the file used by nvi to access messages, and is a list
+of the messages, one per line:
+
+ VI_MESSAGE_CATALOG
+ Unable to create temporary fileX
+ Warning: %s is not a regular fileX
+ %s already locked, session is read-onlyX
+ %s: removeX
+ %s: closeX
+ %s: removeX
+ %s: removeX
+ Read-only file, not written; use ! to overrideX
+ Read-only file, not writtenX
+
+Note that all messages have had a trailing 'X' character appended. This
+is to provide nvi a place to store a trailing nul for the message so that
+C library routines that expect one won't be disappointed.
+
+These files are named for their language, e.g. "vi_english". The second
+files are automatically created from the first files.
+
+To create a new catalog for nvi:
+
+Copy the file vi_english.base to a file that you can modify , e.g. "cp
+vi_english.base vi_german.base". For each of the messages in the file,
+replace the message with the string that you want to use. To find out
+what the arguments to a message are, I'm afraid you'll have to search
+the source code for the message number. You can find them fairly quickly
+by doing:
+
+ cd ..; egrep '123\|' */*.[chys]
+
+I'm sorry that there's not an easier way, but I couldn't think of
+anything that wasn't a lot of work.
+
+If, for some reason, you don't have the file vi_english.base, or you
+have new sources for which you want to create a new base catalog, you
+can create it by running the command "make english" in the catalog
+directory.
+
+Once you've translated all of the strings, then add your catalog to the
+"CAT=" line of the Makefile, and run the command "make catalog". This
+will create the second (and corresponding) file for each file named
+<language>.base.
+
+Don't worry about missing line numbers, i.e. base files that look like:
+
+ 005 Message number 5.
+ 007 Message number 7.
+
+This simply means that a message was deleted during the course of nvi's
+development. It will be taken care of automatically when you create
+the second form of the file.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+If you add new messages to the nvi sources, you can check your work by
+doing "make english; make check". The "make check" target lists unused
+message numbers, duplicate message numbers, and duplicate messages.
+Unused message numbers are only useful if you are condensing messages.
+Duplicate message numbers are a serious problem and have to be fixed.
+Duplicate messages are only interesting if a message appears often enough
+that it's worth creating a routine so that the string is only need in
+a single place.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+To select a catalog when running nvi, set the "msgcat" option. If the
+value of this option ends with a '/', it is treated as the name of a
+directory that contains a message catalog "vi_XXXX", where XXXX is the
+value of the LANG environmental variable, if it's set, or the value of
+the LC_MESSAGES environmental variable if it's not. If neither of those
+environmental variables are set, or if the option doesn't end in a '/',
+the option is treated as the full path name of the message catalog to use.
+
+If any messages are missing from the catalog, the backup text (English)
+is used instead.
diff --git a/usr.bin/vi/ex/ex_undo.c b/contrib/nvi/catalog/dump.c
index 433169670509..0b3cd26520d5 100644
--- a/usr.bin/vi/ex/ex_undo.c
+++ b/contrib/nvi/catalog/dump.c
@@ -32,72 +32,83 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)ex_undo.c 8.7 (Berkeley) 8/9/94";
+static char copyright[] =
+"@(#) Copyright (c) 1992, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
+#ifndef lint
+static char sccsid[] = "@(#)dump.c 8.1 (Berkeley) 8/31/94";
+#endif /* not lint */
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
+#include <ctype.h>
#include <stdio.h>
-#include <termios.h>
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
+static void
+parse(fp)
+ FILE *fp;
+{
+ int ch, s1, s2, s3;
-#include "vi.h"
-#include "excmd.h"
+#define TESTD(s) { \
+ if ((s = getc(fp)) == EOF) \
+ return; \
+ if (!isdigit(s)) \
+ continue; \
+}
+#define TESTP { \
+ if ((ch = getc(fp)) == EOF) \
+ return; \
+ if (ch != '|') \
+ continue; \
+}
+#define MOVEC(t) { \
+ do { \
+ if ((ch = getc(fp)) == EOF) \
+ return; \
+ } while (ch != (t)); \
+}
+ for (;;) {
+ MOVEC('"');
+ TESTD(s1);
+ TESTD(s2);
+ TESTD(s3);
+ TESTP;
+ putchar('"');
+ putchar(s1);
+ putchar(s2);
+ putchar(s3);
+ putchar('|');
+ for (;;) { /* dump to end quote. */
+ if ((ch = getc(fp)) == EOF)
+ return;
+ putchar(ch);
+ if (ch == '"')
+ break;
+ if (ch == '\\') {
+ if ((ch = getc(fp)) == EOF)
+ return;
+ putchar(ch);
+ }
+ }
+ putchar('\n');
+ }
+}
-/*
- * ex_undo -- u
- * Undo the last change.
- */
int
-ex_undo(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+main(argc, argv)
+ int argc;
+ char *argv[];
{
- MARK m;
+ FILE *fp;
- /*
- * !!!
- * Historic undo always set the previous context mark.
- */
- m.lno = sp->lno;
- m.cno = sp->cno;
- if (mark_set(sp, ep, ABSMARK1, &m, 1))
- return (1);
-
- /*
- * !!!
- * Multiple undo isn't available in ex, as there's no '.' command.
- * Whether 'u' is undo or redo is toggled each time, unless there
- * was a change since the last undo, in which case it's an undo.
- */
- if (!F_ISSET(ep, F_UNDO)) {
- F_SET(ep, F_UNDO);
- ep->lundo = FORWARD;
- }
- switch (ep->lundo) {
- case BACKWARD:
- if (log_forward(sp, ep, &m))
- return (1);
- ep->lundo = FORWARD;
- break;
- case FORWARD:
- if (log_backward(sp, ep, &m))
- return (1);
- ep->lundo = BACKWARD;
- break;
- case NOTSET:
- abort();
+ for (; *argv != NULL; ++argv) {
+ if ((fp = fopen(*argv, "r")) == NULL) {
+ perror(*argv);
+ exit (1);
+ }
+ parse(fp);
+ (void)fclose(fp);
}
- sp->lno = m.lno;
- sp->cno = m.cno;
- return (0);
+ exit (0);
}
diff --git a/contrib/nvi/catalog/dutch b/contrib/nvi/catalog/dutch
new file mode 100644
index 000000000000..de9fb603bf8e
--- /dev/null
+++ b/contrib/nvi/catalog/dutch
@@ -0,0 +1,317 @@
+VI_MESSAGE_CATALOG
+regel te langX
+kan regel %lu niet verwijderenX
+kan niet toevoegen aan regel %luX
+kan niet invoegen vooraan regel %luX
+kan regel %lu niet opslaanX
+kan laatste regel niet lezenX
+Fout: kan regel %lu niet vindenX
+log bestandX
+Er vindt geen logging plaats, kan wijzigingen niet ongedaan makenX
+geen wijzigingen om ongedaan te makenX
+Er vindt geen logging plaats, kan wijzigingen niet ongedaan makenX
+Er vindt geen logging plaats, herhaling niet mogelijkX
+geen wijzigingen om te herhalenX
+%s/%d: schrijven naar log misluktX
+Vi's standaard invoer en uitvoer moeten aan een terminal gekoppeld zijnX
+Merk %s: niet gezetX
+Merk %s: de regel is verwijderdX
+Merk %s: de cursor positie bestaat niet meerX
+Fout: X
+nieuw bestandX
+naam veranderdX
+gewijzigdX
+ongewijzigdX
+NIET BEVEILIGDX
+niet schrijfbaarX
+regel %lu uit %lu [%ld%%]X
+leeg bestandX
+regel %luX
+Het bestand %s is geen message catalogX
+Niet in staat om de standaard %s optie in te stellenX
+Gebruik: %sX
+set: optie %s onbekend: 'set all' laat alle opties zienX
+set: [no]%s optie kan geen waarde hebbenX
+set: %s optie moet een waarde hebbenX
+set: %s optie: %sX
+set: %s optie: %s: getal is te grootX
+set: %s optie: %s is een ongeldige waardeX
+set: %s optie moet een waarde hebbenX
+Te weinig kolommen op het scherm, minder dan %dX
+Aantal kolommen te groot, meer dan %dX
+Te weinig regels op het scherm, minder dan %dX
+Aantal regels te groot, meer dan %dX
+De lisp optie is niet ondersteundX
+messages niet uitgeschakeld: %sX
+messages niet geactiveerd: %sX
+
+De paragraph optie moet karakter paren bevattenX
+De section optie moet karakter paren bevattenX
+
+
+
+De standaard buffer is leegX
+Buffer %s is leegX
+Bestanden met newlines in de naam kunnen niet hersteld wordenX
+Wijzigingen kunnen niet ongedaan gemaakt worden als deze sessie misluktX
+Bestand wordt gecopieerd voor herstel...X
+Herstel mechanisme werkt niet: %sX
+Wijzigingen kunnen niet ongedaan gemaakt worden als deze sessie misluktX
+Kon bestand niet veilig stellen: %sX
+Bestand wordt gecopieerd voor herstel...X
+Informatie met betrekking tot gebruiker nummer %u niet gevondenX
+Kan herstel bestand niet beveiligenX
+herstel buffer overgelopenX
+herstel bestandX
+%s: verminkt herstel bestandX
+%s: verminkt herstel bestandX
+U heeft geen bestand genaamd %s te herstellenX
+U kan eerdere versies van dit bestand herstellenX
+U kan nog meer bestanden herstellenX
+kan geen email versturen: %sX
+Bestand leeg; niets om te doorzoekenX
+Einde van het bestand bereikt zonder dat het patroon gevonden isX
+Geen vorig zoek patroonX
+Patroon niet gevondenX
+Begin van het bestand bereikt zonder dat het patroon gevonden isX
+Zoek-operatie omgeslagenX
+Bezig met zoeken...X
+Geen niet-printbaar karakter gevondenX
+Onbekend commandoX
+
+Commando niet beschikbaar in ex modeX
+Aantal mag niet nul zijnX
+%s: ongeldige regel aanduidingX
+Interne fout in syntax tabel (%s: %s)X
+Gebruik: %sX
+%s: tijdelijke buffer niet vrijgegevenX
+Vlag offset voor regel 1X
+Vlag offset voorbij bestands eindeX
+bestand/scherm veranderd tijdens uitvoeren van @ in een blokX
+bestand/scherm veranderd tijdens uitvoeren van globaal/v commandoX
+Ex commando mislukt: rest van commando(s) genegeerdX
+Ex commando mislukt: gemappede toetsen genegeerdX
+Het tweede adres is kleiner dan het eersteX
+Geen merk naam opgegevenX
+\\ niet gevolgd door / of ?X
+Referentie aan een regel nummer kleiner dan 0X
+Het %s commando is onbekendX
+Adres waarde te grootX
+Adres waarde te kleinX
+Ongeldige adres combinatieX
+Ongeldig adres: slechts %lu regels in het bestand aanwezigX
+Ongeldig adres: het bestand is leegX
+Het %s commando staat het adres 0 niet toeX
+Geen afkortingen om weer te gevenX
+Afkortingen moeten eindigen met een "woord" letterX
+Afkortingen mogen geen tabulaties of spaties bevattenX
+Afkortingen mogen geen woord/niet-woord karakters mengen, behalve aan het eindeX
+"%s" is geen afkortingX
+Vi commando mislukt: gemappede toetsen genegeerdX
+Dit is het laatste bestandX
+Dit is het eerste bestandX
+Dit is het eerste bestandX
+lijst met bestanden is leegX
+Geen voorgaand commando om "!" te vervangenX
+Geen bestandsnaam voor %%X
+Geen bestandsnaam voor #X
+Fout: execl: %sX
+I/O fout: %sX
+Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forcerenX
+Kan uw home directory niet vindenX
+Nieuwe huidige directory: %sX
+Geen cut buffers aanwezigX
+Het %s commando kan niet gebruikt worden in een globaal of v commandoX
+%s/%s: niet gelezen: noch U noch root is de eigenaarX
+%s/%s: niet gelezen: U bent niet de eigenaarX
+%s/%s: niet gelezen: kan gewijzigd worden door andere gebruikersX
+%s: niet gelezen: noch U noch root is de eigenaar"X
+%s: niet gelezen: U bent niet de eigenaarX
+%s: niet gelezen: kan gewijzigd worden door andere gebruikersX
+Geen volgende regel om samen te voegenX
+Geen input map entriesX
+Geen command map entriesX
+Het %s karakter kan niet ge-remapped wordenX
+"%s" is niet gemappedX
+Merk naam moet een enkel karakter zijnX
+%s bestaat al, niet weggeschreven; gebruik ! om het te forcerenX
+Nieuw .exrc bestand: %s. X
+doel regel ligt in het blokX
+Het open commando vereist dat de open optie actief isX
+Het open commando is nog niet ondersteundX
+Kan dit bestand niet veilig stellenX
+Bestand veilig gesteldX
+%s resulteert in te veel bestandsnamenX
+Alleen echte bestanden en named pipes kunnen gelezen wordenX
+%s: lees beveiliging niet beschikbaarX
+Bezig met lezen...X
+%s: %lu regels, %lu karaktersX
+Geen achtergrond schermen aanwezigX
+Het script commando is alleen beschikbaar in vi modeX
+Geen comando om uit te voerenX
+shiftwidth optie op 0 gezetX
+Count te grootX
+Count te kleinX
+Reguliere expressie opgegeven; r vlag heeft geen betekenisX
+De #, l en p vlaggen kunnen niet gecombineerd worden met de c vlag in vi modeX
+Geen match gevondenX
+Geen voorafgaande tag aanwezigX
+Minder dan %s elementen op de tags stapel; gebruik :display t[ags]X
+Geen bestand genaamd %s op de tags stapel; gebruik :display t[ags]X
+Kies Enter om door te gaan: X
+%s: tag niet gevondenX
+%s: verminkte tag in %sX
+%s: Het regel nummer van deze tag is voorbij het einde van het bestandX
+De tags stapel is leegX
+%s: zoek patroon niet gevondenX
+%d andere bestanden te wijzigenX
+Buffer %s is leegX
+Bevestig wijziging? [n]X
+OnderbrokenX
+Geen voorafgaande buffer om uit te voerenX
+Geen vorige reguliere expressieX
+Het %s commando vereist dat er een bestand geladen isX
+Gebruik: %sX
+Het visual commando vereist dat de open optie actief isX
+
+Leeg bestandX
+Geen voorafgaand F, f, T of t zoek commandoX
+%s niet gevondenX
+Geen voorafgaand bestand te bewerkenX
+Cursor niet op een getalX
+Getal wordt te grootX
+Getal wordt te kleinX
+Geen overeenkomstig karakter op deze regelX
+Overeenkomstig karakter niet gevondenX
+Geen karakters te vervangenX
+Geen ander scherm aanwezigX
+Karakters achter het zoek patroon, de regel offset, en/of het z commandoX
+Geen voorafgaand zoek patroonX
+Zoekopdracht na omslag teruggekeerd op originele positieX
+Afkorting overschrijdt expansie limiet: karakters genegeerdX
+Ongeldig karakter; quote to enterX
+Reeds aan het begin van de invoerX
+Niet meer karakters te verwijderenX
+Verplaatsing voorbij het einde van het bestandX
+Verplaatsing voorbij het einde van de regelX
+Cursor niet verplaatstX
+Reeds aan het begin van het bestandX
+Verplaatsing voorbij het begin van het bestandX
+Reeds in de eerste kolomX
+Buffers moeten voor het commando opgegeven wordenX
+Reeds bij het einde van het bestandX
+Reeds bij het einde van de regelX
+%s is geen vi commandoX
+Gebruik: %sX
+Geen karakters te verwijderenX
+Het Q commando vereist de ex terminal interfaceX
+Geen commando om te herhalenX
+Het bestand is leegX
+%s mag niet gebruikt worden als een verplaatsings commandoX
+Al in commando modeX
+Cursor niet in een woordX
+
+Windows optie waarde is te groot, maximum is %uX
+ToevoegenX
+VeranderenX
+CommandoX
+InvoegenX
+VervangenX
+Verplaatsing voorbij het eind van het schermX
+Verplaatsing voorbij het begin van het schermX
+Scherm moet meer dan %d regels hebben om het te kunnen splitsenX
+Er zijn geen achtergrond schermenX
+Er is geen achtergrond scherm waarin U bestand %s aan het bewerken bentX
+U kan uw enige scherm niet in de achtergrond zettenX
+Het scherm kan slechts verkleind worden tot %d regelsX
+Het scherm kan niet kleinerX
+Het scherm kan niet groterX
+
+Dit scherm kan niet gesuspend wordenX
+Onderbroken: gemappede toetsen genegeerdX
+vi: tijdelijke buffer niet vrijgegevenX
+Deze terminal heeft geen %s toetsX
+Er kan slechts een buffer opgegeven wordenX
+Getal groter dan %luX
+OnderbrokenX
+Aanmaken van tijdelijk bestand is misluktX
+Waarschuwing: %s is geen regulier bestandX
+%s is al geopend, bestand is in deze sessie niet schrijfbaarX
+%s: verwijdering misluktX
+%s: sluiting misluktX
+%s: verwijdering misluktX
+%s: verwijdering misluktX
+Bestand niet schrijfbaar, niet weggeschreven; gebruik ! om het te forcerenX
+Bestand niet schrijfbaar, niet weggeschrevenX
+%s bestaat al, niet weggeschreven; gebruik ! om het te forcerenX
+%s bestaat al, niet weggeschrevenX
+Gebruik ! om een incompleet bestand weg te schrijvenX
+Bestand incompleet, niet weggeschrevenX
+%s: bestand op disk nieuwer dan deze versie; gebruik ! om het te forcerenX
+%s: bestand op disk nieuwer dan deze versieX
+%s: schrijf beveiliging niet beschikbaarX
+Bezig met schrijven...X
+%s: WAARSCHUWING: BESTAND INCOMPLEETX
+Reeds op de eerste tag van deze groepX
+%s: nieuw bestand: %lu regels, %lu karaktersX
+%s: %lu regels, %lu karaktersX
+%s resulteert in te veel bestandsnamenX
+%s: geen normaal bestandX
+%s: U bent niet de eigenaarX
+%s: kan gewijzigd worden door andere gebruikersX
+Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forcerenX
+Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik :edit! om het te forcerenX
+Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forcerenX
+Tijdelijk bestand; exit negeert wijzigingenX
+Bestand niet schrijfbaar, wijzigingen niet automatisch weggeschrevenX
+log opnieuw gestartX
+Bevestig? [ynq]X
+Druk op een toets om door te gaan: X
+Druk op een toets om door te gaan [: voor meer ex commandos]: X
+Druk op een toets om door te gaan [q om te stoppen]: X
+Deze vorm van %s vereist de ex terminal interfaceX
+Entering ex input mode.X
+Commando mislukt, nog geen bestand geladen.X
+ doorgaan?X
+Onverwacht character eventX
+Onverwacht end-of-file eventX
+Geen match gevonden voor dit patroonX
+Onverwacht interrupt eventX
+Onverwacht quit eventX
+Onverwacht repaint eventX
+Reeds op de laatste tag van deze groepX
+Het %s command vereist de ex terminal interfaceX
+Deze vorm van %s is niet ondersteund als de secure edit optie actief isX
+Onverwacht string eventX
+Onverwacht timeout eventX
+Onverwacht write eventX
+
+Shell expansies zijn niet ondersteund als de secure edit optie actief isX
+Het %s commando is niet ondersteund als de secure edit optie actief isX
+set: %s mag niet uitgezet wordenX
+Scherm te klein.X
+toegevoegdX
+gewijzigdX
+verwijderdX
+samengevoegdX
+verplaatstX
+verschovenX
+gebufferdX
+regelX
+regelsX
+Vi was niet geladen met een Tcl interpreterX
+Bestand gewijzigd sinds het de laatste keer weg is geschreven.X
+Shell expansie misluktX
+Geen %s edit optie opgegevenX
+Vi was niet geladen met een Perl interpreterX
+Geen ex commando om uit te voerenX
+Kies <CR> om commando uit te voeren, :q om te stoppenX
+Gebruik "cscope help" voor uitlegX
+Nog geen cscope connectie aanwezigX
+%s: onbekend zoek type: gebruik een van %sX
+%d: onbekende cscope sessieX
+set: de %s optie mag nooit aangezet wordenX
+set: de %s optie mag nooit op 0 gezet wordenX
+%s: toegevoegd: %lu regels, %lu karaktersX
+Onverwacht resize eventX
+%d bestanden te wijzigenX
diff --git a/contrib/nvi/catalog/dutch.base b/contrib/nvi/catalog/dutch.base
new file mode 100644
index 000000000000..2d8667e6d460
--- /dev/null
+++ b/contrib/nvi/catalog/dutch.base
@@ -0,0 +1,307 @@
+002 "regel te lang"
+003 "kan regel %lu niet verwijderen"
+004 "kan niet toevoegen aan regel %lu"
+005 "kan niet invoegen vooraan regel %lu"
+006 "kan regel %lu niet opslaan"
+007 "kan laatste regel niet lezen"
+008 "Fout: kan regel %lu niet vinden"
+009 "log bestand"
+010 "Er vindt geen logging plaats, kan wijzigingen niet ongedaan maken"
+011 "geen wijzigingen om ongedaan te maken"
+012 "Er vindt geen logging plaats, kan wijzigingen niet ongedaan maken"
+013 "Er vindt geen logging plaats, herhaling niet mogelijk"
+014 "geen wijzigingen om te herhalen"
+015 "%s/%d: schrijven naar log mislukt"
+016 "Vi's standaard invoer en uitvoer moeten aan een terminal gekoppeld zijn"
+017 "Merk %s: niet gezet"
+018 "Merk %s: de regel is verwijderd"
+019 "Merk %s: de cursor positie bestaat niet meer"
+020 "Fout: "
+021 "nieuw bestand"
+022 "naam veranderd"
+023 "gewijzigd"
+024 "ongewijzigd"
+025 "NIET BEVEILIGD"
+026 "niet schrijfbaar"
+027 "regel %lu uit %lu [%ld%%]"
+028 "leeg bestand"
+029 "regel %lu"
+030 "Het bestand %s is geen message catalog"
+031 "Niet in staat om de standaard %s optie in te stellen"
+032 "Gebruik: %s"
+033 "set: optie %s onbekend: 'set all' laat alle opties zien"
+034 "set: [no]%s optie kan geen waarde hebben"
+035 "set: %s optie moet een waarde hebben"
+036 "set: %s optie: %s"
+037 "set: %s optie: %s: getal is te groot"
+038 "set: %s optie: %s is een ongeldige waarde"
+039 "set: %s optie moet een waarde hebben"
+040 "Te weinig kolommen op het scherm, minder dan %d"
+041 "Aantal kolommen te groot, meer dan %d"
+042 "Te weinig regels op het scherm, minder dan %d"
+043 "Aantal regels te groot, meer dan %d"
+044 "De lisp optie is niet ondersteund"
+045 "messages niet uitgeschakeld: %s"
+046 "messages niet geactiveerd: %s"
+048 "De paragraph optie moet karakter paren bevatten"
+049 "De section optie moet karakter paren bevatten"
+053 "De standaard buffer is leeg"
+054 "Buffer %s is leeg"
+055 "Bestanden met newlines in de naam kunnen niet hersteld worden"
+056 "Wijzigingen kunnen niet ongedaan gemaakt worden als deze sessie mislukt"
+057 "Bestand wordt gecopieerd voor herstel..."
+058 "Herstel mechanisme werkt niet: %s"
+059 "Wijzigingen kunnen niet ongedaan gemaakt worden als deze sessie mislukt"
+060 "Kon bestand niet veilig stellen: %s"
+061 "Bestand wordt gecopieerd voor herstel..."
+062 "Informatie met betrekking tot gebruiker nummer %u niet gevonden"
+063 "Kan herstel bestand niet beveiligen"
+064 "herstel buffer overgelopen"
+065 "herstel bestand"
+066 "%s: verminkt herstel bestand"
+067 "%s: verminkt herstel bestand"
+068 "U heeft geen bestand genaamd %s te herstellen"
+069 "U kan eerdere versies van dit bestand herstellen"
+070 "U kan nog meer bestanden herstellen"
+071 "kan geen email versturen: %s"
+072 "Bestand leeg; niets om te doorzoeken"
+073 "Einde van het bestand bereikt zonder dat het patroon gevonden is"
+074 "Geen vorig zoek patroon"
+075 "Patroon niet gevonden"
+076 "Begin van het bestand bereikt zonder dat het patroon gevonden is"
+077 "Zoek-operatie omgeslagen"
+078 "Bezig met zoeken..."
+079 "Geen niet-printbaar karakter gevonden"
+080 "Onbekend commando"
+082 "Commando niet beschikbaar in ex mode"
+083 "Aantal mag niet nul zijn"
+084 "%s: ongeldige regel aanduiding"
+085 "Interne fout in syntax tabel (%s: %s)"
+086 "Gebruik: %s"
+087 "%s: tijdelijke buffer niet vrijgegeven"
+088 "Vlag offset voor regel 1"
+089 "Vlag offset voorbij bestands einde"
+090 "bestand/scherm veranderd tijdens uitvoeren van @ in een blok"
+091 "bestand/scherm veranderd tijdens uitvoeren van globaal/v commando"
+092 "Ex commando mislukt: rest van commando(s) genegeerd"
+093 "Ex commando mislukt: gemappede toetsen genegeerd"
+094 "Het tweede adres is kleiner dan het eerste"
+095 "Geen merk naam opgegeven"
+096 "\\ niet gevolgd door / of ?"
+097 "Referentie aan een regel nummer kleiner dan 0"
+098 "Het %s commando is onbekend"
+099 "Adres waarde te groot"
+100 "Adres waarde te klein"
+101 "Ongeldige adres combinatie"
+102 "Ongeldig adres: slechts %lu regels in het bestand aanwezig"
+103 "Ongeldig adres: het bestand is leeg"
+104 "Het %s commando staat het adres 0 niet toe"
+105 "Geen afkortingen om weer te geven"
+106 "Afkortingen moeten eindigen met een "woord" letter"
+107 "Afkortingen mogen geen tabulaties of spaties bevatten"
+108 "Afkortingen mogen geen woord/niet-woord karakters mengen, behalve aan het einde"
+109 ""%s" is geen afkorting"
+110 "Vi commando mislukt: gemappede toetsen genegeerd"
+111 "Dit is het laatste bestand"
+112 "Dit is het eerste bestand"
+113 "Dit is het eerste bestand"
+114 "lijst met bestanden is leeg"
+115 "Geen voorgaand commando om "!" te vervangen"
+116 "Geen bestandsnaam voor %%"
+117 "Geen bestandsnaam voor #"
+118 "Fout: execl: %s"
+119 "I/O fout: %s"
+120 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forceren"
+121 "Kan uw home directory niet vinden"
+122 "Nieuwe huidige directory: %s"
+123 "Geen cut buffers aanwezig"
+124 "Het %s commando kan niet gebruikt worden in een globaal of v commando"
+125 "%s/%s: niet gelezen: noch U noch root is de eigenaar"
+126 "%s/%s: niet gelezen: U bent niet de eigenaar"
+127 "%s/%s: niet gelezen: kan gewijzigd worden door andere gebruikers"
+128 "%s: niet gelezen: noch U noch root is de eigenaar""
+129 "%s: niet gelezen: U bent niet de eigenaar"
+130 "%s: niet gelezen: kan gewijzigd worden door andere gebruikers"
+131 "Geen volgende regel om samen te voegen"
+132 "Geen input map entries"
+133 "Geen command map entries"
+134 "Het %s karakter kan niet ge-remapped worden"
+135 ""%s" is niet gemapped"
+136 "Merk naam moet een enkel karakter zijn"
+137 "%s bestaat al, niet weggeschreven; gebruik ! om het te forceren"
+138 "Nieuw .exrc bestand: %s. "
+139 "doel regel ligt in het blok"
+140 "Het open commando vereist dat de open optie actief is"
+141 "Het open commando is nog niet ondersteund"
+142 "Kan dit bestand niet veilig stellen"
+143 "Bestand veilig gesteld"
+144 "%s resulteert in te veel bestandsnamen"
+145 "Alleen echte bestanden en named pipes kunnen gelezen worden"
+146 "%s: lees beveiliging niet beschikbaar"
+147 "Bezig met lezen..."
+148 "%s: %lu regels, %lu karakters"
+149 "Geen achtergrond schermen aanwezig"
+150 "Het script commando is alleen beschikbaar in vi mode"
+151 "Geen comando om uit te voeren"
+152 "shiftwidth optie op 0 gezet"
+153 "Count te groot"
+154 "Count te klein"
+155 "Reguliere expressie opgegeven; r vlag heeft geen betekenis"
+156 "De #, l en p vlaggen kunnen niet gecombineerd worden met de c vlag in vi mode"
+157 "Geen match gevonden"
+158 "Geen voorafgaande tag aanwezig"
+159 "Minder dan %s elementen op de tags stapel; gebruik :display t[ags]"
+160 "Geen bestand genaamd %s op de tags stapel; gebruik :display t[ags]"
+161 "Kies Enter om door te gaan: "
+162 "%s: tag niet gevonden"
+163 "%s: verminkte tag in %s"
+164 "%s: Het regel nummer van deze tag is voorbij het einde van het bestand"
+165 "De tags stapel is leeg"
+166 "%s: zoek patroon niet gevonden"
+167 "%d andere bestanden te wijzigen"
+168 "Buffer %s is leeg"
+169 "Bevestig wijziging? [n]"
+170 "Onderbroken"
+171 "Geen voorafgaande buffer om uit te voeren"
+172 "Geen vorige reguliere expressie"
+173 "Het %s commando vereist dat er een bestand geladen is"
+174 "Gebruik: %s"
+175 "Het visual commando vereist dat de open optie actief is"
+177 "Leeg bestand"
+178 "Geen voorafgaand F, f, T of t zoek commando"
+179 "%s niet gevonden"
+180 "Geen voorafgaand bestand te bewerken"
+181 "Cursor niet op een getal"
+182 "Getal wordt te groot"
+183 "Getal wordt te klein"
+184 "Geen overeenkomstig karakter op deze regel"
+185 "Overeenkomstig karakter niet gevonden"
+186 "Geen karakters te vervangen"
+187 "Geen ander scherm aanwezig"
+188 "Karakters achter het zoek patroon, de regel offset, en/of het z commando"
+189 "Geen voorafgaand zoek patroon"
+190 "Zoekopdracht na omslag teruggekeerd op originele positie"
+191 "Afkorting overschrijdt expansie limiet: karakters genegeerd"
+192 "Ongeldig karakter; quote to enter"
+193 "Reeds aan het begin van de invoer"
+194 "Niet meer karakters te verwijderen"
+195 "Verplaatsing voorbij het einde van het bestand"
+196 "Verplaatsing voorbij het einde van de regel"
+197 "Cursor niet verplaatst"
+198 "Reeds aan het begin van het bestand"
+199 "Verplaatsing voorbij het begin van het bestand"
+200 "Reeds in de eerste kolom"
+201 "Buffers moeten voor het commando opgegeven worden"
+202 "Reeds bij het einde van het bestand"
+203 "Reeds bij het einde van de regel"
+204 "%s is geen vi commando"
+205 "Gebruik: %s"
+206 "Geen karakters te verwijderen"
+207 "Het Q commando vereist de ex terminal interface"
+208 "Geen commando om te herhalen"
+209 "Het bestand is leeg"
+210 "%s mag niet gebruikt worden als een verplaatsings commando"
+211 "Al in commando mode"
+212 "Cursor niet in een woord"
+214 "Windows optie waarde is te groot, maximum is %u"
+215 "Toevoegen"
+216 "Veranderen"
+217 "Commando"
+218 "Invoegen"
+219 "Vervangen"
+220 "Verplaatsing voorbij het eind van het scherm"
+221 "Verplaatsing voorbij het begin van het scherm"
+222 "Scherm moet meer dan %d regels hebben om het te kunnen splitsen"
+223 "Er zijn geen achtergrond schermen"
+224 "Er is geen achtergrond scherm waarin U bestand %s aan het bewerken bent"
+225 "U kan uw enige scherm niet in de achtergrond zetten"
+226 "Het scherm kan slechts verkleind worden tot %d regels"
+227 "Het scherm kan niet kleiner"
+228 "Het scherm kan niet groter"
+230 "Dit scherm kan niet gesuspend worden"
+231 "Onderbroken: gemappede toetsen genegeerd"
+232 "vi: tijdelijke buffer niet vrijgegeven"
+233 "Deze terminal heeft geen %s toets"
+234 "Er kan slechts een buffer opgegeven worden"
+235 "Getal groter dan %lu"
+236 "Onderbroken"
+237 "Aanmaken van tijdelijk bestand is mislukt"
+238 "Waarschuwing: %s is geen regulier bestand"
+239 "%s is al geopend, bestand is in deze sessie niet schrijfbaar"
+240 "%s: verwijdering mislukt"
+241 "%s: sluiting mislukt"
+242 "%s: verwijdering mislukt"
+243 "%s: verwijdering mislukt"
+244 "Bestand niet schrijfbaar, niet weggeschreven; gebruik ! om het te forceren"
+245 "Bestand niet schrijfbaar, niet weggeschreven"
+246 "%s bestaat al, niet weggeschreven; gebruik ! om het te forceren"
+247 "%s bestaat al, niet weggeschreven"
+248 "Gebruik ! om een incompleet bestand weg te schrijven"
+249 "Bestand incompleet, niet weggeschreven"
+250 "%s: bestand op disk nieuwer dan deze versie; gebruik ! om het te forceren"
+251 "%s: bestand op disk nieuwer dan deze versie"
+252 "%s: schrijf beveiliging niet beschikbaar"
+253 "Bezig met schrijven..."
+254 "%s: WAARSCHUWING: BESTAND INCOMPLEET"
+255 "Reeds op de eerste tag van deze groep"
+256 "%s: nieuw bestand: %lu regels, %lu karakters"
+257 "%s: %lu regels, %lu karakters"
+258 "%s resulteert in te veel bestandsnamen"
+259 "%s: geen normaal bestand"
+260 "%s: U bent niet de eigenaar"
+261 "%s: kan gewijzigd worden door andere gebruikers"
+262 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forceren"
+263 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik :edit! om het te forceren"
+264 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forceren"
+265 "Tijdelijk bestand; exit negeert wijzigingen"
+266 "Bestand niet schrijfbaar, wijzigingen niet automatisch weggeschreven"
+267 "log opnieuw gestart"
+268 "Bevestig? [ynq]"
+269 "Druk op een toets om door te gaan: "
+270 "Druk op een toets om door te gaan [: voor meer ex commandos]: "
+271 "Druk op een toets om door te gaan [q om te stoppen]: "
+272 "Deze vorm van %s vereist de ex terminal interface"
+273 "Entering ex input mode."
+274 "Commando mislukt, nog geen bestand geladen."
+275 " doorgaan?"
+276 "Onverwacht character event"
+277 "Onverwacht end-of-file event"
+278 "Geen match gevonden voor dit patroon"
+279 "Onverwacht interrupt event"
+280 "Onverwacht quit event"
+281 "Onverwacht repaint event"
+282 "Reeds op de laatste tag van deze groep"
+283 "Het %s command vereist de ex terminal interface"
+284 "Deze vorm van %s is niet ondersteund als de secure edit optie actief is"
+285 "Onverwacht string event"
+286 "Onverwacht timeout event"
+287 "Onverwacht write event"
+289 "Shell expansies zijn niet ondersteund als de secure edit optie actief is"
+290 "Het %s commando is niet ondersteund als de secure edit optie actief is"
+291 "set: %s mag niet uitgezet worden"
+292 "Scherm te klein."
+293 "toegevoegd"
+294 "gewijzigd"
+295 "verwijderd"
+296 "samengevoegd"
+297 "verplaatst"
+298 "verschoven"
+299 "gebufferd"
+300 "regel"
+301 "regels"
+302 "Vi was niet geladen met een Tcl interpreter"
+303 "Bestand gewijzigd sinds het de laatste keer weg is geschreven."
+304 "Shell expansie mislukt"
+305 "Geen %s edit optie opgegeven"
+306 "Vi was niet geladen met een Perl interpreter"
+307 "Geen ex commando om uit te voeren"
+308 "Kies <CR> om commando uit te voeren, :q om te stoppen"
+309 "Gebruik "cscope help" voor uitleg"
+310 "Nog geen cscope connectie aanwezig"
+311 "%s: onbekend zoek type: gebruik een van %s"
+312 "%d: onbekende cscope sessie"
+313 "set: de %s optie mag nooit aangezet worden"
+314 "set: de %s optie mag nooit op 0 gezet worden"
+315 "%s: toegevoegd: %lu regels, %lu karakters"
+316 "Onverwacht resize event"
+317 "%d bestanden te wijzigen"
diff --git a/contrib/nvi/catalog/dutch.check b/contrib/nvi/catalog/dutch.check
new file mode 100644
index 000000000000..d651aec75cc2
--- /dev/null
+++ b/contrib/nvi/catalog/dutch.check
@@ -0,0 +1,37 @@
+Unused message id's (this is okay):
+001
+047
+050
+051
+052
+081
+176
+213
+229
+288
+=========================
+MISSING ERROR MESSAGES (Please add!):
+=========================
+Extra error messages (just delete them):
+=========================
+MESSAGES WITH THE SAME MESSAGE ID's (FIX!):
+=========================
+Duplicate messages, both id and message (this is okay):
+=========================
+Duplicate messages, just message (this is okay):
+ 2 %s bestaat al, niet weggeschreven; gebruik ! om het te forcerenX
+ 2 %s resulteert in te veel bestandsnamenX
+ 2 %s: %lu regels, %lu karaktersX
+ 2 %s: verminkt herstel bestandX
+ 2 Bestand wordt gecopieerd voor herstel...X
+ 2 Buffer %s is leegX
+ 2 Dit is het eerste bestandX
+ 2 Er vindt geen logging plaats, kan wijzigingen niet ongedaan makenX
+ 2 OnderbrokenX
+ 2 Wijzigingen kunnen niet ongedaan gemaakt worden als deze sessie misluktX
+ 2 gewijzigdX
+ 2 set: %s optie moet een waarde hebbenX
+ 3 %s: verwijdering misluktX
+ 3 Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forcerenX
+ 4 Gebruik: %sX
+=========================
diff --git a/contrib/nvi/catalog/dutch.owner b/contrib/nvi/catalog/dutch.owner
new file mode 100644
index 000000000000..27f47d30dbb3
--- /dev/null
+++ b/contrib/nvi/catalog/dutch.owner
@@ -0,0 +1 @@
+J.G. Vons <Gert-Jan.Vons@ocegr.fr>
diff --git a/contrib/nvi/catalog/english b/contrib/nvi/catalog/english
new file mode 100644
index 000000000000..f34451d9b6d5
--- /dev/null
+++ b/contrib/nvi/catalog/english
@@ -0,0 +1,317 @@
+VI_MESSAGE_CATALOG
+Line length overflowX
+unable to delete line %luX
+unable to append to line %luX
+unable to insert at line %luX
+unable to store line %luX
+unable to get last lineX
+Error: unable to retrieve line %luX
+Log fileX
+Logging not being performed, undo not possibleX
+No changes to undoX
+Logging not being performed, undo not possibleX
+Logging not being performed, roll-forward not possibleX
+No changes to re-doX
+%s/%d: log put errorX
+Vi's standard input and output must be a terminalX
+Mark %s: not setX
+Mark %s: the line was deletedX
+Mark %s: cursor position no longer existsX
+Error: X
+new fileX
+name changedX
+modifiedX
+unmodifiedX
+UNLOCKEDX
+readonlyX
+line %lu of %lu [%ld%%]X
+empty fileX
+line %luX
+The file %s is not a message catalogX
+Unable to set default %s optionX
+Usage: %sX
+set: no %s option: 'set all' gives all option valuesX
+set: [no]%s option doesn't take a valueX
+set: %s option isn't a booleanX
+set: %s option: %sX
+set: %s option: %s: value overflowX
+set: %s option: %s is an illegal numberX
+set: %s option isn't a booleanX
+Screen columns too small, less than %dX
+Screen columns too large, greater than %dX
+Screen lines too small, less than %dX
+Screen lines too large, greater than %dX
+The lisp option is not implementedX
+messages not turned off: %sX
+messages not turned on: %sX
+
+The paragraph option must be in two character groupsX
+The section option must be in two character groupsX
+
+
+
+The default buffer is emptyX
+Buffer %s is emptyX
+Files with newlines in the name are unrecoverableX
+Modifications not recoverable if the session failsX
+Copying file for recovery...X
+Preservation failed: %sX
+Modifications not recoverable if the session failsX
+File backup failed: %sX
+Copying file for recovery...X
+Information on user id %u not foundX
+Unable to lock recovery fileX
+Recovery file buffer overrunX
+Recovery fileX
+%s: malformed recovery fileX
+%s: malformed recovery fileX
+No files named %s, readable by you, to recoverX
+There are older versions of this file for you to recoverX
+There are other files for you to recoverX
+not sending email: %sX
+File empty; nothing to searchX
+Reached end-of-file without finding the patternX
+No previous search patternX
+Pattern not foundX
+Reached top-of-file without finding the patternX
+Search wrappedX
+Searching...X
+No non-printable character foundX
+Unknown command nameX
+
+%s: command not available in ex modeX
+Count may not be zeroX
+%s: bad line specificationX
+Internal syntax table error (%s: %s)X
+Usage: %sX
+%s: temporary buffer not releasedX
+Flag offset to before line 1X
+Flag offset past end-of-fileX
+@ with range running when the file/screen changedX
+Global/v command running when the file/screen changedX
+Ex command failed: pending commands discardedX
+Ex command failed: mapped keys discardedX
+The second address is smaller than the firstX
+No mark name suppliedX
+\\ not followed by / or ?X
+Reference to a line number less than 0X
+The %s command is unknownX
+Address value overflowX
+Address value underflowX
+Illegal address combinationX
+Illegal address: only %lu lines in the fileX
+Illegal address: the file is emptyX
+The %s command doesn't permit an address of 0X
+No abbreviations to displayX
+Abbreviations must end with a "word" characterX
+Abbreviations may not contain tabs or spacesX
+Abbreviations may not mix word/non-word characters, except at the endX
+"%s" is not an abbreviationX
+Vi command failed: mapped keys discardedX
+No more files to editX
+No previous files to editX
+No previous files to rewindX
+No file list to displayX
+No previous command to replace "!"X
+No filename to substitute for %%X
+No filename to substitute for #X
+Error: execl: %sX
+I/O error: %sX
+File modified since last complete write; write or use ! to overrideX
+Unable to find home directory locationX
+New current directory: %sX
+No cut buffers to displayX
+The %s command can't be used as part of a global or v commandX
+%s/%s: not sourced: not owned by you or rootX
+%s/%s: not sourced: not owned by youX
+%s/%s: not sourced: writeable by a user other than the ownerX
+%s: not sourced: not owned by you or rootX
+%s: not sourced: not owned by youX
+%s: not sourced: writeable by a user other than the ownerX
+No following lines to joinX
+No input map entriesX
+No command map entriesX
+The %s character may not be remappedX
+"%s" isn't currently mappedX
+Mark names must be a single characterX
+%s exists, not written; use ! to overrideX
+New exrc file: %sX
+Destination line is inside move rangeX
+The open command requires that the open option be setX
+The open command is not yet implementedX
+Preservation of this file not possibleX
+File preservedX
+%s: expanded into too many file namesX
+Only regular files and named pipes may be readX
+%s: read lock was unavailableX
+Reading...X
+%s: %lu lines, %lu charactersX
+No background screens to displayX
+The script command is only available in vi modeX
+No command to executeX
+shiftwidth option set to 0X
+Count overflowX
+Count underflowX
+Regular expression specified; r flag meaninglessX
+The #, l and p flags may not be combined with the c flag in vi modeX
+No match foundX
+No previous tag enteredX
+Less than %s entries on the tags stack; use :display t[ags]X
+No file %s on the tags stack to return to; use :display t[ags]X
+Press Enter to continue: X
+%s: tag not foundX
+%s: corrupted tag in %sX
+%s: the tag's line number is past the end of the fileX
+The tags stack is emptyX
+%s: search pattern not foundX
+%d more files to editX
+Buffer %s is emptyX
+Confirm change? [n]X
+InterruptedX
+No previous buffer to executeX
+No previous regular expressionX
+The %s command requires that a file have already been read inX
+Usage: %sX
+The visual command requires that the open option be setX
+
+Empty fileX
+No previous F, f, T or t searchX
+%s not foundX
+No previous file to editX
+Cursor not in a numberX
+Resulting number too largeX
+Resulting number too smallX
+No match character on this lineX
+Matching character not foundX
+No characters to replaceX
+No other screen to switch toX
+Characters after search string, line offset and/or z commandX
+No previous search patternX
+Search wrapped to original positionX
+Abbreviation exceeded expansion limit: characters discardedX
+Illegal character; quote to enterX
+Already at the beginning of the insertX
+No more characters to eraseX
+Movement past the end-of-fileX
+Movement past the end-of-lineX
+No cursor movement madeX
+Already at the beginning of the fileX
+Movement past the beginning of the fileX
+Already in the first columnX
+Buffers should be specified before the commandX
+Already at end-of-fileX
+Already at end-of-lineX
+%s isn't a vi commandX
+Usage: %sX
+No characters to deleteX
+The Q command requires the ex terminal interfaceX
+No command to repeatX
+The file is emptyX
+%s may not be used as a motion commandX
+Already in command modeX
+Cursor not in a wordX
+
+Windows option value is too large, max is %uX
+AppendX
+ChangeX
+CommandX
+InsertX
+ReplaceX
+Movement past the end-of-screenX
+Movement past the beginning-of-screenX
+Screen must be larger than %d lines to splitX
+There are no background screensX
+There's no background screen editing a file named %sX
+You may not background your only displayed screenX
+The screen can only shrink to %d rowsX
+The screen cannot shrinkX
+The screen cannot growX
+
+This screen may not be suspendedX
+Interrupted: mapped keys discardedX
+vi: temporary buffer not releasedX
+This terminal has no %s keyX
+Only one buffer may be specifiedX
+Number larger than %luX
+InterruptedX
+Unable to create temporary fileX
+Warning: %s is not a regular fileX
+%s already locked, session is read-onlyX
+%s: removeX
+%s: closeX
+%s: removeX
+%s: removeX
+Read-only file, not written; use ! to overrideX
+Read-only file, not writtenX
+%s exists, not written; use ! to overrideX
+%s exists, not writtenX
+Partial file, not written; use ! to overrideX
+Partial file, not writtenX
+%s: file modified more recently than this copy; use ! to overrideX
+%s: file modified more recently than this copyX
+%s: write lock was unavailableX
+Writing...X
+%s: WARNING: FILE TRUNCATEDX
+Already at the first tag of this groupX
+%s: new file: %lu lines, %lu charactersX
+%s: %lu lines, %lu charactersX
+%s expanded into too many file namesX
+%s: not a regular fileX
+%s: not owned by youX
+%s: accessible by a user other than the ownerX
+File modified since last complete write; write or use ! to overrideX
+File modified since last complete write; write or use :edit! to overrideX
+File modified since last complete write; write or use ! to overrideX
+File is a temporary; exit will discard modificationsX
+File readonly, modifications not auto-writtenX
+Log restartedX
+confirm? [ynq]X
+Press any key to continue: X
+Press any key to continue [: to enter more ex commands]: X
+Press any key to continue [q to quit]: X
+That form of %s requires the ex terminal interfaceX
+Entering ex input mode.X
+Command failed, no file read in yet.X
+ cont?X
+Unexpected character eventX
+Unexpected end-of-file eventX
+No matches for queryX
+Unexpected interrupt eventX
+Unexpected quit eventX
+Unexpected repaint eventX
+Already at the last tag of this groupX
+The %s command requires the ex terminal interfaceX
+That form of %s is not supported when the secure edit option is setX
+Unexpected string eventX
+Unexpected timeout eventX
+Unexpected write eventX
+
+Shell expansions not supported when the secure edit option is setX
+The %s command is not supported when the secure edit option is setX
+set: the %s option may not be turned offX
+Display too small.X
+addedX
+changedX
+deletedX
+joinedX
+movedX
+shiftedX
+yankedX
+lineX
+linesX
+Vi was not loaded with a Tcl interpreterX
+File modified since last write.X
+Shell expansion failedX
+No %s edit option specifiedX
+Vi was not loaded with a Perl interpreterX
+No ex command to executeX
+Enter <CR> to execute a command, :q to exitX
+Use "cscope help" for helpX
+No cscope connections runningX
+%s: unknown search type: use one of %sX
+%d: no such cscope sessionX
+set: the %s option may never be turned onX
+set: the %s option may never be set to 0X
+%s: appended: %lu lines, %lu charactersX
+Unexpected resize eventX
+%d files to editX
diff --git a/contrib/nvi/catalog/english.base b/contrib/nvi/catalog/english.base
new file mode 100644
index 000000000000..6d8d7bf60bbf
--- /dev/null
+++ b/contrib/nvi/catalog/english.base
@@ -0,0 +1,309 @@
+002 "Line length overflow"
+003 "unable to delete line %lu"
+004 "unable to append to line %lu"
+005 "unable to insert at line %lu"
+006 "unable to store line %lu"
+007 "unable to get last line"
+008 "Error: unable to retrieve line %lu"
+009 "Log file"
+010 "Logging not being performed, undo not possible"
+011 "No changes to undo"
+012 "Logging not being performed, undo not possible"
+013 "Logging not being performed, roll-forward not possible"
+014 "No changes to re-do"
+015 "%s/%d: log put error"
+016 "Vi's standard input and output must be a terminal"
+017 "Mark %s: not set"
+018 "Mark %s: the line was deleted"
+019 "Mark %s: cursor position no longer exists"
+020 "Error: "
+021 "new file"
+022 "name changed"
+023 "modified"
+024 "unmodified"
+025 "UNLOCKED"
+026 "readonly"
+027 "line %lu of %lu [%ld%%]"
+028 "empty file"
+029 "line %lu"
+030 "The file %s is not a message catalog"
+031 "Unable to set default %s option"
+032 "Usage: %s"
+033 "set: no %s option: 'set all' gives all option values"
+034 "set: [no]%s option doesn't take a value"
+035 "set: %s option isn't a boolean"
+036 "set: %s option: %s"
+037 "set: %s option: %s: value overflow"
+038 "set: %s option: %s is an illegal number"
+039 "set: %s option isn't a boolean"
+040 "Screen columns too small, less than %d"
+041 "Screen columns too large, greater than %d"
+042 "Screen lines too small, less than %d"
+043 "Screen lines too large, greater than %d"
+044 "The lisp option is not implemented"
+045 "messages not turned off: %s"
+046 "messages not turned on: %s"
+048 "The paragraph option must be in two character groups"
+049 "The section option must be in two character groups"
+053 "The default buffer is empty"
+054 "Buffer %s is empty"
+055 "Files with newlines in the name are unrecoverable"
+056 "Modifications not recoverable if the session fails"
+057 "Copying file for recovery..."
+058 "Preservation failed: %s"
+059 "Modifications not recoverable if the session fails"
+060 "File backup failed: %s"
+061 "Copying file for recovery..."
+062 "Information on user id %u not found"
+063 "Unable to lock recovery file"
+064 "Recovery file buffer overrun"
+065 "Recovery file"
+066 "%s: malformed recovery file"
+067 "%s: malformed recovery file"
+068 "No files named %s, readable by you, to recover"
+069 "There are older versions of this file for you to recover"
+070 "There are other files for you to recover"
+071 "not sending email: %s"
+072 "File empty; nothing to search"
+073 "Reached end-of-file without finding the pattern"
+074 "No previous search pattern"
+075 "Pattern not found"
+076 "Reached top-of-file without finding the pattern"
+077 "Search wrapped"
+078 "Searching..."
+079 "No non-printable character found"
+080 "Unknown command name"
+082 "%s: command not available in ex mode"
+083 "Count may not be zero"
+084 "%s: bad line specification"
+085 "Internal syntax table error (%s: %s)"
+086 "Usage: %s"
+087 "%s: temporary buffer not released"
+088 "Flag offset to before line 1"
+089 "Flag offset past end-of-file"
+090 "@ with range running when the file/screen changed"
+091 "Global/v command running when the file/screen changed"
+092 "Ex command failed: pending commands discarded"
+093 "Ex command failed: mapped keys discarded"
+094 "The second address is smaller than the first"
+095 "No mark name supplied"
+096 "\\ not followed by / or ?"
+097 "Reference to a line number less than 0"
+098 "The %s command is unknown"
+099 "Address value overflow"
+100 "Address value underflow"
+101 "Illegal address combination"
+102 "Illegal address: only %lu lines in the file"
+103 "Illegal address: the file is empty"
+104 "The %s command doesn't permit an address of 0"
+105 "No abbreviations to display"
+106 "Abbreviations must end with a "word" character"
+107 "Abbreviations may not contain tabs or spaces"
+108 "Abbreviations may not mix word/non-word characters, except at the end"
+109 ""%s" is not an abbreviation"
+110 "Vi command failed: mapped keys discarded"
+111 "No more files to edit"
+112 "No previous files to edit"
+113 "No previous files to rewind"
+114 "No file list to display"
+115 "No previous command to replace "!""
+116 "No filename to substitute for %%"
+117 "No filename to substitute for #"
+118 "Error: execl: %s"
+119 "I/O error: %s"
+120 "File modified since last complete write; write or use ! to override"
+121 "Unable to find home directory location"
+122 "New current directory: %s"
+123 "No cut buffers to display"
+124 "The %s command can't be used as part of a global or v command"
+125 "%s/%s: not sourced: not owned by you or root"
+126 "%s/%s: not sourced: not owned by you"
+127 "%s/%s: not sourced: writeable by a user other than the owner"
+128 "%s: not sourced: not owned by you or root"
+129 "%s: not sourced: not owned by you"
+130 "%s: not sourced: writeable by a user other than the owner"
+131 "No following lines to join"
+132 "No input map entries"
+133 "No command map entries"
+134 "The %s character may not be remapped"
+135 ""%s" isn't currently mapped"
+136 "Mark names must be a single character"
+137 "%s exists, not written; use ! to override"
+138 "New exrc file: %s"
+139 "Destination line is inside move range"
+140 "The open command requires that the open option be set"
+141 "The open command is not yet implemented"
+142 "Preservation of this file not possible"
+143 "File preserved"
+144 "%s: expanded into too many file names"
+145 "Only regular files and named pipes may be read"
+146 "%s: read lock was unavailable"
+147 "Reading..."
+148 "%s: %lu lines, %lu characters"
+149 "No background screens to display"
+150 "The script command is only available in vi mode"
+151 "No command to execute"
+152 "shiftwidth option set to 0"
+153 "Count overflow"
+154 "Count underflow"
+155 "Regular expression specified; r flag meaningless"
+156 "The #, l and p flags may not be combined with the c flag in vi mode"
+157 "No match found"
+158 "No previous tag entered"
+159 "Less than %s entries on the tags stack; use :display t[ags]"
+160 "No file %s on the tags stack to return to; use :display t[ags]"
+161 "Press Enter to continue: "
+162 "%s: tag not found"
+163 "%s: corrupted tag in %s"
+164 "%s: the tag's line number is past the end of the file"
+165 "The tags stack is empty"
+166 "%s: search pattern not found"
+167 "%d more files to edit"
+168 "Buffer %s is empty"
+169 "Confirm change? [n]"
+170 "Interrupted"
+171 "No previous buffer to execute"
+172 "No previous regular expression"
+173 "The %s command requires that a file have already been read in"
+174 "Usage: %s"
+175 "The visual command requires that the open option be set"
+177 "Empty file"
+178 "No previous F, f, T or t search"
+179 "%s not found"
+180 "No previous file to edit"
+181 "Cursor not in a number"
+182 "Resulting number too large"
+183 "Resulting number too small"
+184 "No match character on this line"
+185 "Matching character not found"
+186 "No characters to replace"
+187 "No other screen to switch to"
+188 "Characters after search string, line offset and/or z command"
+189 "No previous search pattern"
+190 "Search wrapped to original position"
+191 "Abbreviation exceeded expansion limit: characters discarded"
+192 "Illegal character; quote to enter"
+193 "Already at the beginning of the insert"
+194 "No more characters to erase"
+195 "Movement past the end-of-file"
+196 "Movement past the end-of-line"
+197 "No cursor movement made"
+198 "Already at the beginning of the file"
+199 "Movement past the beginning of the file"
+200 "Already in the first column"
+201 "Buffers should be specified before the command"
+202 "Already at end-of-file"
+203 "Already at end-of-line"
+204 "%s isn't a vi command"
+205 "Usage: %s"
+206 "No characters to delete"
+207 "The Q command requires the ex terminal interface"
+208 "No command to repeat"
+209 "The file is empty"
+209 "The file is empty"
+210 "%s may not be used as a motion command"
+211 "Already in command mode"
+212 "Cursor not in a word"
+214 "Windows option value is too large, max is %u"
+215 "Append"
+216 "Change"
+217 "Command"
+218 "Insert"
+219 "Replace"
+220 "Movement past the end-of-screen"
+221 "Movement past the beginning-of-screen"
+222 "Screen must be larger than %d lines to split"
+223 "There are no background screens"
+224 "There's no background screen editing a file named %s"
+225 "You may not background your only displayed screen"
+226 "The screen can only shrink to %d rows"
+227 "The screen cannot shrink"
+228 "The screen cannot grow"
+230 "This screen may not be suspended"
+231 "Interrupted: mapped keys discarded"
+232 "vi: temporary buffer not released"
+233 "This terminal has no %s key"
+234 "Only one buffer may be specified"
+235 "Number larger than %lu"
+236 "Interrupted"
+237 "Unable to create temporary file"
+238 "Warning: %s is not a regular file"
+239 "%s already locked, session is read-only"
+240 "%s: remove"
+241 "%s: close"
+242 "%s: remove"
+243 "%s: remove"
+244 "Read-only file, not written; use ! to override"
+245 "Read-only file, not written"
+246 "%s exists, not written; use ! to override"
+247 "%s exists, not written"
+248 "Partial file, not written; use ! to override"
+249 "Partial file, not written"
+250 "%s: file modified more recently than this copy; use ! to override"
+251 "%s: file modified more recently than this copy"
+252 "%s: write lock was unavailable"
+253 "Writing..."
+254 "%s: WARNING: FILE TRUNCATED"
+255 "Already at the first tag of this group"
+256 "%s: new file: %lu lines, %lu characters"
+257 "%s: %lu lines, %lu characters"
+258 "%s expanded into too many file names"
+259 "%s: not a regular file"
+260 "%s: not owned by you"
+261 "%s: accessible by a user other than the owner"
+262 "File modified since last complete write; write or use ! to override"
+263 "File modified since last complete write; write or use :edit! to override"
+264 "File modified since last complete write; write or use ! to override"
+265 "File is a temporary; exit will discard modifications"
+266 "File readonly, modifications not auto-written"
+267 "Log restarted"
+268 "confirm? [ynq]"
+269 "Press any key to continue: "
+270 "Press any key to continue [: to enter more ex commands]: "
+271 "Press any key to continue [q to quit]: "
+272 "That form of %s requires the ex terminal interface"
+273 "Entering ex input mode."
+274 "Command failed, no file read in yet."
+275 " cont?"
+276 "Unexpected character event"
+277 "Unexpected end-of-file event"
+278 "No matches for query"
+279 "Unexpected interrupt event"
+280 "Unexpected quit event"
+281 "Unexpected repaint event"
+282 "Already at the last tag of this group"
+283 "The %s command requires the ex terminal interface"
+284 "That form of %s is not supported when the secure edit option is set"
+285 "Unexpected string event"
+286 "Unexpected timeout event"
+287 "Unexpected write event"
+289 "Shell expansions not supported when the secure edit option is set"
+290 "The %s command is not supported when the secure edit option is set"
+291 "set: the %s option may not be turned off"
+292 "Display too small."
+293 "added"
+294 "changed"
+295 "deleted"
+296 "joined"
+297 "moved"
+298 "shifted"
+299 "yanked"
+300 "line"
+301 "lines"
+302 "Vi was not loaded with a Tcl interpreter"
+303 "File modified since last write."
+304 "Shell expansion failed"
+304 "Shell expansion failed"
+305 "No %s edit option specified"
+306 "Vi was not loaded with a Perl interpreter"
+307 "No ex command to execute"
+308 "Enter <CR> to execute a command, :q to exit"
+309 "Use "cscope help" for help"
+310 "No cscope connections running"
+311 "%s: unknown search type: use one of %s"
+312 "%d: no such cscope session"
+313 "set: the %s option may never be turned on"
+314 "set: the %s option may never be set to 0"
+315 "%s: appended: %lu lines, %lu characters"
+316 "Unexpected resize event"
+317 "%d files to edit"
diff --git a/contrib/nvi/catalog/english.check b/contrib/nvi/catalog/english.check
new file mode 100644
index 000000000000..51093785c87c
--- /dev/null
+++ b/contrib/nvi/catalog/english.check
@@ -0,0 +1,36 @@
+Unused message id's (this is okay):
+001
+047
+050
+051
+052
+081
+176
+229
+288
+=========================
+MISSING ERROR MESSAGES (Please add!):
+=========================
+Extra error messages (just delete them):
+=========================
+MESSAGES WITH THE SAME MESSAGE ID's (FIX!):
+=========================
+Duplicate messages, both id and message (this is okay):
+ 2 209 "The file is empty"
+ 2 304 "Shell expansion failed"
+=========================
+Duplicate messages, just message (this is okay):
+ 2 %s exists, not written; use ! to overrideX
+ 2 %s: %lu lines, %lu charactersX
+ 2 %s: malformed recovery fileX
+ 2 Buffer %s is emptyX
+ 2 Copying file for recovery...X
+ 2 InterruptedX
+ 2 Logging not being performed, undo not possibleX
+ 2 Modifications not recoverable if the session failsX
+ 2 No previous search patternX
+ 2 set: %s option isn't a booleanX
+ 3 %s: removeX
+ 3 File modified since last complete write; write or use ! to overrideX
+ 4 Usage: %sX
+=========================
diff --git a/contrib/nvi/catalog/english.owner b/contrib/nvi/catalog/english.owner
new file mode 100644
index 000000000000..034567ddd8b5
--- /dev/null
+++ b/contrib/nvi/catalog/english.owner
@@ -0,0 +1 @@
+Keith Bostic <bostic@cs.berkeley.edu>
diff --git a/contrib/nvi/catalog/french b/contrib/nvi/catalog/french
new file mode 100644
index 000000000000..a75c486ef9ba
--- /dev/null
+++ b/contrib/nvi/catalog/french
@@ -0,0 +1,317 @@
+VI_MESSAGE_CATALOG
+D‚passement de longueur de ligneX
+impossible de supprimer la ligne %luX
+impossible d'ajouter … la ligne %luX
+impossible d'ins‚rer devant la ligne %luX
+impossible de stocker la ligne %luX
+impossible d'obtenir la derniŠre ligneX
+Erreur : impossible de r‚cup‚rer la ligne %luX
+Fichier journalX
+Aucune connexion n'‚tant effectu‚e, impossible d'annulerX
+Aucune action … annulerX
+Aucune connexion n'‚tant effectu‚e, impossible d'annulerX
+Aucune connexion n'‚tant effectu‚e, reprise actualis‚e impossibleX
+Aucune action … refaireX
+%s/%d : Erreur d'‚criture de journalX
+L'entr‚e et la sortie Vi standards doivent ˆtre un terminalX
+Marque %s : non d‚finieX
+Marque %s : la ligne a ‚t‚ supprim‚eX
+Marque %s : la position du curseur n'existe plusX
+Erreur : X
+nouveau fichierX
+le nom a chang‚X
+modifi‚X
+non modifi‚X
+DEVERROUILLEX
+lecture seuleX
+ligne %lu de %lu [%ld%%]X
+fichier videX
+ligne %luX
+Ce fichier %s n'est pas un catalogue de messagesX
+Impossible de configurer option %s par d‚fautX
+Utilisation : %sX
+D‚finition : pas d'option %s : 'tout d‚finir' donne toutes les valeurs optionnellesX
+D‚finition : option [no]%s ne prend pas de valeurX
+D‚finition : l'option %s n'est pas bool‚enneX
+D‚finition : option %s : %sX
+D‚finition : option %s : %s : D‚passement de valeurX
+D‚finition : option %s : %s n'est pas un nombre valideX
+D‚finition : l'option %s n'est pas bool‚enneX
+Les colonnes de l'‚cran sont trop petites, inf‚rieures … %dX
+Les colonnes de l'‚cran sont trop grandes, sup‚rieures … %dX
+Les lignes de l'‚cran sont trop courtes, inf‚rieures … %dX
+Les lignes de l'‚cran sont trop longues, sup‚rieures … %dX
+L'option lisp n'est pas impl‚ment‚eX
+Les messages ne sont pas d‚sactiv‚s : %sX
+Les messages ne sont pas activ‚s : %sX
+
+L'option de paragraphe doit ˆtre en groupe de deux caractŠresX
+L'option de section doit ˆtre en groupe de deux caractŠresX
+
+
+
+Le tampon par d‚faut est videX
+Le tampon %s est videX
+Les fichiers dont le nom contient des caractŠres de saut de ligne sont irr‚cup‚rablesX
+Impossible de r‚cup‚rer les modifications si la session ‚choueX
+Copie en cours du fichier pour r‚cup‚ration...X
+La pr‚servation a ‚chou‚ : %sX
+Impossible de r‚cup‚rer les modifications si la session ‚choueX
+La sauvegarde du fichier a ‚chou‚ : %sX
+Copie en cours du fichier pour r‚cup‚ration...X
+Les renseignements sur l'identit‚ %u de l'utilisateur sont introuvablesX
+Impossible de verrouiller le fichier de r‚cup‚rationX
+D‚bordement de tampon du fichier de r‚cup‚rationX
+Fichier de r‚cup‚rationX
+%s : Fichier de r‚cup‚ration malform‚X
+%s : Fichier de r‚cup‚ration malform‚X
+Aucun fichier nomm‚ %s … r‚cup‚rer, que vous puissiez lireX
+Il existe des versions r‚cup‚rables ant‚rieures … ce fichierX
+Vous avez d'autres fichiers … r‚cup‚rerX
+pas d'envoi d'email : %sX
+Fichier vide, rien … rechercherX
+Fin de fichier atteinte sans trouver le motifX
+Pas de motif de recherche pr‚c‚dentX
+Motif introuvableX
+D‚but du fichier atteint sans trouver le motifX
+La recherche est revenue … son point de d‚partX
+Recherche en cours...X
+CaractŠre non-imprimable introuvableX
+Nom de commande inconnuX
+
+%s : Commande non disponible en ex modeX
+Le compte ne peut ˆtre z‚roX
+%s : mauvaise sp‚cification de ligneX
+Erreur de tableau de syntaxe interne (%s: %s)X
+Utilisation : %sX
+%s : tampon temporaire non lib‚r‚X
+D‚calage de drapeau hors de la ligne 1X
+D‚calage de drapeau hors de la fin du fichierX
+@ avec plage, en cours d'ex‚cution quand le fichier/l'‚cran a chang‚X
+Commande Global/v en cours d'ex‚cution quand le fichier/l'‚cran a chang‚X
+La commande ex a ‚chou‚ : commandes en attente abandonn‚esX
+La commande ex a ‚chou‚ : les touches affect‚es sont abandonn‚esX
+La deuxiŠme adresse est plus petite que la premiŠreX
+Aucun nom de marque fourniX
+\\ pas suivi par / ou ?X
+R‚f‚rence … un num‚ro de ligne inf‚rieure … 0X
+La commande %s est inconnueX
+D‚passement de la valeur adresseX
+D‚passement n‚gatif de la valeur adresseX
+Combinaison d'adresse non valideX
+Adresse non valide : il n'y a que des lignes %lu dans le fichierX
+Adresse non valide : le fichier est videX
+La commande %s ne permet pas une adresse de 0X
+Pas d'abr‚viations … afficherX
+Les abr‚viations doivent finir par un caractŠre"motX
+Les abr‚viations ne peuvent pas contenir de tabulations ni d'espacesX
+Les abr‚viations ne peuvent pas contenir un m‚lange de caractŠres mot/non-mot, sauf … la finX
+"%s" n'est pas une abr‚viationX
+La commande Vi a ‚chou‚ : Les touches affect‚es ont ‚t‚ abandonn‚esX
+Plus de fichiers … ‚diterX
+Pas de fichiers pr‚c‚dents … ‚diterX
+Pas de fichiers pr‚c‚dents … rembobinerX
+Pas de liste de fichiers … afficherX
+Pas de commande pr‚c‚dente … remplacer"!"X
+Pas de nom de fichier … substituer … %%X
+Pas de nom de fichier … substituer … #X
+Erreur : execl : %sX
+Erreur E/S : %sX
+Fichier modifi‚ depuis la derniŠre ‚criture complŠte ; ‚crire ou utiliser ! pour outrepasserX
+Impossible de trouver l'emplacement du r‚pertoire d'origineX
+Nouveau r‚pertoire en cours : %sX
+Pas de tampon de coupure … afficherX
+La commande %s ne peut pas ˆtre utilis‚e … l'int‚rieur d'une commande globale ou commande vX
+%s/%s : ‚chec de source : ni vous ni le super-utilisateur n'ˆtes les propri‚taires X
+%s/%s : ‚chec de source : vous n'ˆtes pas le propri‚taireX
+%s/%s : ‚chec de source : peut ˆtre ‚crit par un utilisateur autre que le propri‚taireX
+%s : ‚chec de source : ni vous ni le super-utilisateur n'ˆtes les propri‚tairesX
+%s : ‚chec de source : vous n'ˆtes pas le propri‚taireX
+%s : ‚chec de source : peut ˆtre ‚crit par un utilisateur autre que le propri‚taireX
+Pas de lignes suivantes … joindreX
+Pas d'entr‚es de mappage d'entr‚eX
+Pas d'entr‚es de mappage de commandesX
+Le caractŠre %s ne peut pas ˆtre remapp‚X
+"%s" n'est pas actuellement mapp‚X
+Les noms de marque ne doivent avoir qu'un caractŠreX
+%s existe, non enregistr‚; utiliser ! pour outrepasserX
+Nouveau fichier exrc : %sX
+La ligne de destination est … l'int‚rieur de la plage … d‚placerX
+La commande ouverte n‚cessite que l'option ouverte soit d‚finieX
+La commande ouverte n'est pas encore impl‚ment‚eX
+La pr‚servation de ce fichier est impossibleX
+Fichier pr‚serv‚X
+%s: ‚tendu dans trop de noms de fichiersX
+Vous ne pouvez lire que les fichiers standards et les canaux de transmission nomm‚sX
+%s: Interdiction de lecture non disponibleX
+Lecture en cours...X
+%s: %lu lignes, %lu caractŠresX
+Pas d'‚crans d'arriŠre-plan … afficherX
+La commande script n'est disponible qu'en mode viX
+Pas de commande … ex‚cuterX
+Option de largeur de d‚calage d‚finie sur 0X
+Compter d‚passementX
+Compter d‚passement n‚gatifX
+Expression standard sp‚cifi‚e; drapeau r superfluX
+Vous ne pouvez pas en mode vi, combiner les drapeaux #, l et p avec le drapeau cX
+Aucune correspondance trouv‚eX
+Aucune marque pr‚c‚dente entr‚eX
+Moins de %s entr‚es dans la pile de marques ; utilisez t[ags]X
+Pas de fichier %s vers lequel retourner dans la pile de marques ; utiliser : affichage t[ags]X
+Appuyez sur Entr‚e pour continuer :X
+%s : marque introuvableX
+%s : marque corrompue en %sX
+%s : le num‚ro de ligne de la marque d‚passe la fin du fichierX
+La pile de marques est videX
+%s : motif de recherche introuvableX
+%d fichiers suppl‚mentaires … ‚diterX
+Le tampon %s est vide
+Confirmer les changements ? [n]X
+InterrompuX
+Pas de tampon pr‚c‚dent … ex‚cuterX
+Pas d'expression standard pr‚c‚denteX
+La commande %s n‚cessite qu'un fichier ait d‚j… ‚t‚ lu en m‚moireX
+Utilisation : %sX
+La commande visuelle n‚cessite que l'option ouverte soit d‚finieX
+
+Fichier videX
+Pas de recherche pr‚c‚dente F, f, T ou tX
+%s introuvableX
+Pas de fichier pr‚c‚dent … ‚diterX
+Le curseur n'est pas dans un nombreX
+Le nombre obtenu est trop grandX
+Le nombre obtenu est trop petitX
+Pas de correspondance de caractŠre sur cette ligneX
+CaractŠre correspondant introuvableX
+Pas de caractŠres … remplacerX
+Pas d'autre ‚cran vers lequel basculerX
+CaractŠres aprŠs la chaŒne de recherche, d‚calage de ligne et/ou commande zX
+Pas de motif de recherche pr‚c‚dentX
+La recherche est revenue … son point de d‚partX
+L'abr‚viation a d‚pass‚ la limite de l'expansion : caractŠres abandonn‚sX
+CaractŠre non valide ; guillemet pour saisirX
+D‚j… au d‚but de l'insertionX
+Plus de caractŠres … effacerX
+D‚placement hors de fin de fichierX
+D‚placement hors de fin de ligneX
+Aucun mouvement de curseur n'a ‚t‚ effectu‚X
+D‚j… au d‚but du fichierX
+D‚placement hors du d‚but du fichierX
+D‚j… dans la premiŠre colonneX
+Les tampons doivent ˆtre sp‚cifi‚s avant la commandeX
+D‚j… … la fin du fichierX
+D‚j… … la fin de la ligneX
+%s n'est pas une commande viX
+Utilisation : %sX
+Pas de caractŠres … supprimerX
+La commande Q n‚cessite une interface terminal exX
+Pas de commande … r‚p‚terX
+Le fichier est videX
+Vous ne pouvez pas utiliser %s comme commande de d‚placementX
+D‚j… en mode commandeX
+Le curseur n'est pas dans un motX
+
+Valeur optionnelle de fenˆtre trop grande, maximum est %uX
+AjouterX
+ChangerX
+CommandeX
+Ins‚rerX
+RemplacerX
+D‚placement hors de la fin d'‚cranX
+D‚placement hors du d‚but d'‚cranX
+L'‚cran doit ˆtre sup‚rieur … %d lignes pour se fractionnerX
+Il n'y a pas d'‚cran d'arriŠre-planX
+Il n'y a pas d'‚cran d'arriŠre-plan qui ‚dite un fichier nomm‚ %sX
+Vous ne pouvez pas mettre … l'arriŠre-plan votre seul ‚cran affich‚X
+L'‚cran ne peut ˆtre r‚duit qu'… %d rangsX
+L'‚cran n'est pas auto-r‚ductibleX
+L'‚cran n'est pas auto-extensibleX
+
+Vous ne pouvez pas mettre cet ‚cran en attenteX
+Interrompu : les touches affect‚es ont ‚t‚ abandonn‚esX
+vi : le tampon temporaire n' a pas ‚t‚ lib‚r‚X
+Ce terminal n'a pas de touche %sX
+Vous ne pouvez sp‚cifier qu'un seul tamponX
+Nombre sup‚rieur … %luX
+InterrompuX
+Impossible de cr‚er un fichier temporaireX
+Avertissement : %s n'est pas un fichier standardX
+%s d‚j… verrouill‚, session en lecture seuleX
+%s: supprimerX
+%s: fermerX
+%s: supprimerX
+%s: supprimerX
+Fichier en lecture seule, pas ‚crit, utiliser ! pour outrepasserX
+Fichier en lecture seule, pas ‚critX
+%s existe, pas ‚crit; utiliser ! pour outrepasserX
+%s existe, pas ‚critX
+Fichier partiel, pas ‚crit; utiliser ! pour outrepasserX
+Fichier partiel, pas ‚critX
+%s: fichier modifi‚ plus r‚cemment que cet exemplaire; utiliser ! pour outrepasserX
+%s: fichier modifi‚ plus r‚cemment que cet exemplaireX
+%s: interdiction d'‚criture non disponibleX
+Ecriture en cours...X
+%s: AVERTISSEMENT : FICHIER TRONQUEX
+PremiŠre marque de ce groupe d‚j… atteinteX
+%s: nouveau fichier : %lu lignes, %lu caractŠresX
+%s: %lu lignes, %lu caractŠresX
+%s ‚tendue … trop de noms de fichiersX
+%s: pas un fichier standardX
+%s: ne vous appartient pasX
+%s: accessible par un utilisateur autre que son propri‚taireX
+Fichier modif‚ depuis la derniŠre ‚criture complŠte ; ‚crire ou utiliser ! pour outrepasser X
+Fichier modif‚ depuis la derniŠre ‚criture complŠte ; ‚crire ou utiliser :edit! pour outrepasserX
+Fichier modif‚ depuis la derniŠre ‚criture complŠte ; ‚crire ou utiliser ! pour outrepasserX
+Fichier temporaire ; quitter annulera les modificationsX
+Fichier en lecture seule ; les modifications ne sont pas ‚crites automatiquementX
+Journal red‚marr‚X
+confirmer ? [ynq]X
+Appuyez sur n'importe quelle touche pour continuer : X
+Appuyez sur n'importe quelle touche pour continuer [: pour entrer plus de commandes ex] : X
+Appuyez sur n'importe quelle touche pour continuer [q pour Quitter]: X
+Cette forme de %s n‚cessite l'interface de terminal exX
+Entr‚e de mode entr‚e ex.X
+La commande a ‚chou‚, aucun fichier n'a encore ‚t‚ lu.X
+cont?X
+Ev‚nement impr‚vu de caractŠreX
+Ev‚nement impr‚vu de fin-de-fichierX
+Pas de correspondances pour cette requˆteX
+Ev‚nement impr‚vu d'interruptionX
+Ev‚nement quitter impr‚vuX
+Ev‚nement impr‚vu de rafraŒchissementX
+La derniŠre marque de ce groupe a d‚j… ‚t‚ atteinteX
+La commande %s n‚cessite l'interface de terminal exX
+Cette forme de %s n'est pas reconnue quand l'option d'‚dition prot‚g‚e est activ‚eX
+Ev‚nement impr‚vu de chaŒneX
+Ev‚nement impr‚vu de d‚lai impartiX
+Ev‚nement d'‚criture impr‚vuX
+
+Les expansions du shell ne sont pas reconnues quand l'option d'‚dition prot‚g‚e est activ‚eX
+La commande %s n'est pas reconnue quand l'option d'‚dition prot‚g‚e est activ‚eX
+D‚finition : l'option %s ne peut pas ˆtre d‚sactiv‚eX
+Affichage trop petit.X
+ajout‚X
+chang‚X
+supprim‚X
+jointX
+d‚plac‚X
+d‚cal‚X
+coup‚X
+ligneX
+lignesX
+Vi n'a pas ‚t‚ charg‚ avec un interpr‚tateur TclX
+Ficher modifi‚ depuis le dernier enregistrement.X
+L'expansion du shell a ‚chou‚X
+Pas d'option d'‚dition %s sp‚cifi‚eX
+Vi n'a pas ‚t‚ charg‚ avec un interpr‚tateur PerlX
+Pas de commande ex … ex‚cuterX
+Entrez <CR> pour ex‚cuter une commande, :q pour quitterX
+Utiliser "cscope help" pour obtenir de l'aideX
+Aucune connexion cscope n'est lanc‚eX
+%s : type de recherche inconnu : utiliser un des %sX
+%d : Il n'existe pas de telle session cscopeX
+D‚finition : l'option %s ne peut jamais ˆtre activ‚eX
+D‚finition : l'option %s ne peut jamais ˆtre d‚finie sur 0X
+%s: joints : %lu lignes, %lu caractŠresX
+‚v‚nement impr‚vu de redimensionnementX
+%d fichiers … ‚diterX
diff --git a/contrib/nvi/catalog/french.base b/contrib/nvi/catalog/french.base
new file mode 100644
index 000000000000..db2d45f9b220
--- /dev/null
+++ b/contrib/nvi/catalog/french.base
@@ -0,0 +1,309 @@
+002 "D‚passement de longueur de ligne"
+003 "impossible de supprimer la ligne %lu"
+004 "impossible d'ajouter … la ligne %lu"
+005 "impossible d'ins‚rer devant la ligne %lu"
+006 "impossible de stocker la ligne %lu"
+007 "impossible d'obtenir la derniŠre ligne"
+008 "Erreur : impossible de r‚cup‚rer la ligne %lu"
+009 "Fichier journal"
+010 "Aucune connexion n'‚tant effectu‚e, impossible d'annuler"
+011 "Aucune action … annuler"
+012 "Aucune connexion n'‚tant effectu‚e, impossible d'annuler"
+013 "Aucune connexion n'‚tant effectu‚e, reprise actualis‚e impossible"
+014 "Aucune action … refaire"
+015 "%s/%d : Erreur d'‚criture de journal"
+016 "L'entr‚e et la sortie Vi standards doivent ˆtre un terminal"
+017 "Marque %s : non d‚finie"
+018 "Marque %s : la ligne a ‚t‚ supprim‚e"
+019 "Marque %s : la position du curseur n'existe plus"
+020 "Erreur : "
+021 "nouveau fichier"
+022 "le nom a chang‚"
+023 "modifi‚"
+024 "non modifi‚"
+025 "DEVERROUILLE"
+026 "lecture seule"
+027 "ligne %lu de %lu [%ld%%]"
+028 "fichier vide"
+029 "ligne %lu"
+030 "Ce fichier %s n'est pas un catalogue de messages"
+031 "Impossible de configurer option %s par d‚faut"
+032 "Utilisation : %s"
+033 "D‚finition : pas d'option %s : 'tout d‚finir' donne toutes les valeurs optionnelles"
+034 "D‚finition : option [no]%s ne prend pas de valeur"
+035 "D‚finition : l'option %s n'est pas bool‚enne"
+036 "D‚finition : option %s : %s"
+037 "D‚finition : option %s : %s : D‚passement de valeur"
+038 "D‚finition : option %s : %s n'est pas un nombre valide"
+039 "D‚finition : l'option %s n'est pas bool‚enne"
+040 "Les colonnes de l'‚cran sont trop petites, inf‚rieures … %d"
+041 "Les colonnes de l'‚cran sont trop grandes, sup‚rieures … %d"
+042 "Les lignes de l'‚cran sont trop courtes, inf‚rieures … %d"
+043 "Les lignes de l'‚cran sont trop longues, sup‚rieures … %d"
+044 "L'option lisp n'est pas impl‚ment‚e"
+045 "Les messages ne sont pas d‚sactiv‚s : %s"
+046 "Les messages ne sont pas activ‚s : %s"
+048 "L'option de paragraphe doit ˆtre en groupe de deux caractŠres"
+049 "L'option de section doit ˆtre en groupe de deux caractŠres"
+053 "Le tampon par d‚faut est vide"
+054 "Le tampon %s est vide"
+055 "Les fichiers dont le nom contient des caractŠres de saut de ligne sont irr‚cup‚rables"
+056 "Impossible de r‚cup‚rer les modifications si la session ‚choue"
+057 "Copie en cours du fichier pour r‚cup‚ration..."
+058 "La pr‚servation a ‚chou‚ : %s"
+059 "Impossible de r‚cup‚rer les modifications si la session ‚choue"
+060 "La sauvegarde du fichier a ‚chou‚ : %s"
+061 "Copie en cours du fichier pour r‚cup‚ration..."
+062 "Les renseignements sur l'identit‚ %u de l'utilisateur sont introuvables"
+063 "Impossible de verrouiller le fichier de r‚cup‚ration"
+064 "D‚bordement de tampon du fichier de r‚cup‚ration"
+065 "Fichier de r‚cup‚ration"
+066 "%s : Fichier de r‚cup‚ration malform‚"
+067 "%s : Fichier de r‚cup‚ration malform‚"
+068 "Aucun fichier nomm‚ %s … r‚cup‚rer, que vous puissiez lire"
+069 "Il existe des versions r‚cup‚rables ant‚rieures … ce fichier"
+070 "Vous avez d'autres fichiers … r‚cup‚rer"
+071 "pas d'envoi d'email : %s"
+072 "Fichier vide, rien … rechercher"
+073 "Fin de fichier atteinte sans trouver le motif"
+074 "Pas de motif de recherche pr‚c‚dent"
+075 "Motif introuvable"
+076 "D‚but du fichier atteint sans trouver le motif"
+077 "La recherche est revenue … son point de d‚part"
+078 "Recherche en cours..."
+079 "CaractŠre non-imprimable introuvable"
+080 "Nom de commande inconnu"
+082 "%s : Commande non disponible en ex mode"
+083 "Le compte ne peut ˆtre z‚ro"
+084 "%s : mauvaise sp‚cification de ligne"
+085 "Erreur de tableau de syntaxe interne (%s: %s)"
+086 "Utilisation : %s"
+087 "%s : tampon temporaire non lib‚r‚"
+088 "D‚calage de drapeau hors de la ligne 1"
+089 "D‚calage de drapeau hors de la fin du fichier"
+090 "@ avec plage, en cours d'ex‚cution quand le fichier/l'‚cran a chang‚"
+091 "Commande Global/v en cours d'ex‚cution quand le fichier/l'‚cran a chang‚"
+092 "La commande ex a ‚chou‚ : commandes en attente abandonn‚es"
+093 "La commande ex a ‚chou‚ : les touches affect‚es sont abandonn‚es"
+094 "La deuxiŠme adresse est plus petite que la premiŠre"
+095 "Aucun nom de marque fourni"
+096 "\\ pas suivi par / ou ?"
+097 "R‚f‚rence … un num‚ro de ligne inf‚rieure … 0"
+098 "La commande %s est inconnue"
+099 "D‚passement de la valeur adresse"
+100 "D‚passement n‚gatif de la valeur adresse"
+101 "Combinaison d'adresse non valide"
+102 "Adresse non valide : il n'y a que des lignes %lu dans le fichier"
+103 "Adresse non valide : le fichier est vide"
+104 "La commande %s ne permet pas une adresse de 0"
+105 "Pas d'abr‚viations … afficher"
+106 "Les abr‚viations doivent finir par un caractŠre"mot"
+107 "Les abr‚viations ne peuvent pas contenir de tabulations ni d'espaces"
+108 "Les abr‚viations ne peuvent pas contenir un m‚lange de caractŠres mot/non-mot, sauf … la fin"
+109 ""%s" n'est pas une abr‚viation"
+110 "La commande Vi a ‚chou‚ : Les touches affect‚es ont ‚t‚ abandonn‚es"
+111 "Plus de fichiers … ‚diter"
+112 "Pas de fichiers pr‚c‚dents … ‚diter"
+113 "Pas de fichiers pr‚c‚dents … rembobiner"
+114 "Pas de liste de fichiers … afficher"
+115 "Pas de commande pr‚c‚dente … remplacer"!""
+116 "Pas de nom de fichier … substituer … %%"
+117 "Pas de nom de fichier … substituer … #"
+118 "Erreur : execl : %s"
+119 "Erreur E/S : %s"
+120 "Fichier modifi‚ depuis la derniŠre ‚criture complŠte ; ‚crire ou utiliser ! pour outrepasser"
+121 "Impossible de trouver l'emplacement du r‚pertoire d'origine"
+122 "Nouveau r‚pertoire en cours : %s"
+123 "Pas de tampon de coupure … afficher"
+124 "La commande %s ne peut pas ˆtre utilis‚e … l'int‚rieur d'une commande globale ou commande v"
+125 "%s/%s : ‚chec de source : ni vous ni le super-utilisateur n'ˆtes les propri‚taires "
+126 "%s/%s : ‚chec de source : vous n'ˆtes pas le propri‚taire"
+127 "%s/%s : ‚chec de source : peut ˆtre ‚crit par un utilisateur autre que le propri‚taire"
+128 "%s : ‚chec de source : ni vous ni le super-utilisateur n'ˆtes les propri‚taires"
+129 "%s : ‚chec de source : vous n'ˆtes pas le propri‚taire"
+130 "%s : ‚chec de source : peut ˆtre ‚crit par un utilisateur autre que le propri‚taire"
+131 "Pas de lignes suivantes … joindre"
+132 "Pas d'entr‚es de mappage d'entr‚e"
+133 "Pas d'entr‚es de mappage de commandes"
+134 "Le caractŠre %s ne peut pas ˆtre remapp‚"
+135 ""%s" n'est pas actuellement mapp‚"
+136 "Les noms de marque ne doivent avoir qu'un caractŠre"
+137 "%s existe, non enregistr‚; utiliser ! pour outrepasser"
+138 "Nouveau fichier exrc : %s"
+139 "La ligne de destination est … l'int‚rieur de la plage … d‚placer"
+140 "La commande ouverte n‚cessite que l'option ouverte soit d‚finie"
+141 "La commande ouverte n'est pas encore impl‚ment‚e"
+142 "La pr‚servation de ce fichier est impossible"
+143 "Fichier pr‚serv‚"
+144 "%s: ‚tendu dans trop de noms de fichiers"
+145 "Vous ne pouvez lire que les fichiers standards et les canaux de transmission nomm‚s"
+146 "%s: Interdiction de lecture non disponible"
+147 "Lecture en cours..."
+148 "%s: %lu lignes, %lu caractŠres"
+149 "Pas d'‚crans d'arriŠre-plan … afficher"
+150 "La commande script n'est disponible qu'en mode vi"
+151 "Pas de commande … ex‚cuter"
+152 "Option de largeur de d‚calage d‚finie sur 0"
+153 "Compter d‚passement"
+154 "Compter d‚passement n‚gatif"
+155 "Expression standard sp‚cifi‚e; drapeau r superflu"
+156 "Vous ne pouvez pas en mode vi, combiner les drapeaux #, l et p avec le drapeau c"
+157 "Aucune correspondance trouv‚e"
+158 "Aucune marque pr‚c‚dente entr‚e"
+159 "Moins de %s entr‚es dans la pile de marques ; utilisez t[ags]"
+160 "Pas de fichier %s vers lequel retourner dans la pile de marques ; utiliser : affichage t[ags]"
+161 "Appuyez sur Entr‚e pour continuer :"
+162 "%s : marque introuvable"
+163 "%s : marque corrompue en %s"
+164 "%s : le num‚ro de ligne de la marque d‚passe la fin du fichier"
+165 "La pile de marques est vide"
+166 "%s : motif de recherche introuvable"
+167 "%d fichiers suppl‚mentaires … ‚diter"
+168 "Le tampon %s est vide
+169 "Confirmer les changements ? [n]"
+170 "Interrompu"
+171 "Pas de tampon pr‚c‚dent … ex‚cuter"
+172 "Pas d'expression standard pr‚c‚dente"
+173 "La commande %s n‚cessite qu'un fichier ait d‚j… ‚t‚ lu en m‚moire"
+174 "Utilisation : %s"
+175 "La commande visuelle n‚cessite que l'option ouverte soit d‚finie"
+177 "Fichier vide"
+178 "Pas de recherche pr‚c‚dente F, f, T ou t"
+179 "%s introuvable"
+180 "Pas de fichier pr‚c‚dent … ‚diter"
+181 "Le curseur n'est pas dans un nombre"
+182 "Le nombre obtenu est trop grand"
+183 "Le nombre obtenu est trop petit"
+184 "Pas de correspondance de caractŠre sur cette ligne"
+185 "CaractŠre correspondant introuvable"
+186 "Pas de caractŠres … remplacer"
+187 "Pas d'autre ‚cran vers lequel basculer"
+188 "CaractŠres aprŠs la chaŒne de recherche, d‚calage de ligne et/ou commande z"
+189 "Pas de motif de recherche pr‚c‚dent"
+190 "La recherche est revenue … son point de d‚part"
+191 "L'abr‚viation a d‚pass‚ la limite de l'expansion : caractŠres abandonn‚s"
+192 "CaractŠre non valide ; guillemet pour saisir"
+193 "D‚j… au d‚but de l'insertion"
+194 "Plus de caractŠres … effacer"
+195 "D‚placement hors de fin de fichier"
+196 "D‚placement hors de fin de ligne"
+197 "Aucun mouvement de curseur n'a ‚t‚ effectu‚"
+198 "D‚j… au d‚but du fichier"
+199 "D‚placement hors du d‚but du fichier"
+200 "D‚j… dans la premiŠre colonne"
+201 "Les tampons doivent ˆtre sp‚cifi‚s avant la commande"
+202 "D‚j… … la fin du fichier"
+203 "D‚j… … la fin de la ligne"
+204 "%s n'est pas une commande vi"
+205 "Utilisation : %s"
+206 "Pas de caractŠres … supprimer"
+207 "La commande Q n‚cessite une interface terminal ex"
+208 "Pas de commande … r‚p‚ter"
+209 "Le fichier est vide"
+209 "Le fichier est vide"
+210 "Vous ne pouvez pas utiliser %s comme commande de d‚placement"
+211 "D‚j… en mode commande"
+212 "Le curseur n'est pas dans un mot"
+214 "Valeur optionnelle de fenˆtre trop grande, maximum est %u"
+215 "Ajouter"
+216 "Changer"
+217 "Commande"
+218 "Ins‚rer"
+219 "Remplacer"
+220 "D‚placement hors de la fin d'‚cran"
+221 "D‚placement hors du d‚but d'‚cran"
+222 "L'‚cran doit ˆtre sup‚rieur … %d lignes pour se fractionner"
+223 "Il n'y a pas d'‚cran d'arriŠre-plan"
+224 "Il n'y a pas d'‚cran d'arriŠre-plan qui ‚dite un fichier nomm‚ %s"
+225 "Vous ne pouvez pas mettre … l'arriŠre-plan votre seul ‚cran affich‚"
+226 "L'‚cran ne peut ˆtre r‚duit qu'… %d rangs"
+227 "L'‚cran n'est pas auto-r‚ductible"
+228 "L'‚cran n'est pas auto-extensible"
+230 "Vous ne pouvez pas mettre cet ‚cran en attente"
+231 "Interrompu : les touches affect‚es ont ‚t‚ abandonn‚es"
+232 "vi : le tampon temporaire n' a pas ‚t‚ lib‚r‚"
+233 "Ce terminal n'a pas de touche %s"
+234 "Vous ne pouvez sp‚cifier qu'un seul tampon"
+235 "Nombre sup‚rieur … %lu"
+236 "Interrompu"
+237 "Impossible de cr‚er un fichier temporaire"
+238 "Avertissement : %s n'est pas un fichier standard"
+239 "%s d‚j… verrouill‚, session en lecture seule"
+240 "%s: supprimer"
+241 "%s: fermer"
+242 "%s: supprimer"
+243 "%s: supprimer"
+244 "Fichier en lecture seule, pas ‚crit, utiliser ! pour outrepasser"
+245 "Fichier en lecture seule, pas ‚crit"
+246 "%s existe, pas ‚crit; utiliser ! pour outrepasser"
+247 "%s existe, pas ‚crit"
+248 "Fichier partiel, pas ‚crit; utiliser ! pour outrepasser"
+249 "Fichier partiel, pas ‚crit"
+250 "%s: fichier modifi‚ plus r‚cemment que cet exemplaire; utiliser ! pour outrepasser"
+251 "%s: fichier modifi‚ plus r‚cemment que cet exemplaire"
+252 "%s: interdiction d'‚criture non disponible"
+253 "Ecriture en cours..."
+254 "%s: AVERTISSEMENT : FICHIER TRONQUE"
+255 "PremiŠre marque de ce groupe d‚j… atteinte"
+256 "%s: nouveau fichier : %lu lignes, %lu caractŠres"
+257 "%s: %lu lignes, %lu caractŠres"
+258 "%s ‚tendue … trop de noms de fichiers"
+259 "%s: pas un fichier standard"
+260 "%s: ne vous appartient pas"
+261 "%s: accessible par un utilisateur autre que son propri‚taire"
+262 "Fichier modif‚ depuis la derniŠre ‚criture complŠte ; ‚crire ou utiliser ! pour outrepasser "
+263 "Fichier modif‚ depuis la derniŠre ‚criture complŠte ; ‚crire ou utiliser :edit! pour outrepasser"
+264 "Fichier modif‚ depuis la derniŠre ‚criture complŠte ; ‚crire ou utiliser ! pour outrepasser"
+265 "Fichier temporaire ; quitter annulera les modifications"
+266 "Fichier en lecture seule ; les modifications ne sont pas ‚crites automatiquement"
+267 "Journal red‚marr‚"
+268 "confirmer ? [ynq]"
+269 "Appuyez sur n'importe quelle touche pour continuer : "
+270 "Appuyez sur n'importe quelle touche pour continuer [: pour entrer plus de commandes ex] : "
+271 "Appuyez sur n'importe quelle touche pour continuer [q pour Quitter]: "
+272 "Cette forme de %s n‚cessite l'interface de terminal ex"
+273 "Entr‚e de mode entr‚e ex."
+274 "La commande a ‚chou‚, aucun fichier n'a encore ‚t‚ lu."
+275 "cont?"
+276 "Ev‚nement impr‚vu de caractŠre"
+277 "Ev‚nement impr‚vu de fin-de-fichier"
+278 "Pas de correspondances pour cette requˆte"
+279 "Ev‚nement impr‚vu d'interruption"
+280 "Ev‚nement quitter impr‚vu"
+281 "Ev‚nement impr‚vu de rafraŒchissement"
+282 "La derniŠre marque de ce groupe a d‚j… ‚t‚ atteinte"
+283 "La commande %s n‚cessite l'interface de terminal ex"
+284 "Cette forme de %s n'est pas reconnue quand l'option d'‚dition prot‚g‚e est activ‚e"
+285 "Ev‚nement impr‚vu de chaŒne"
+286 "Ev‚nement impr‚vu de d‚lai imparti"
+287 "Ev‚nement d'‚criture impr‚vu"
+289 "Les expansions du shell ne sont pas reconnues quand l'option d'‚dition prot‚g‚e est activ‚e"
+290 "La commande %s n'est pas reconnue quand l'option d'‚dition prot‚g‚e est activ‚e"
+291 "D‚finition : l'option %s ne peut pas ˆtre d‚sactiv‚e"
+292 "Affichage trop petit."
+293 "ajout‚"
+294 "chang‚"
+295 "supprim‚"
+296 "joint"
+297 "d‚plac‚"
+298 "d‚cal‚"
+299 "coup‚"
+300 "ligne"
+301 "lignes"
+302 "Vi n'a pas ‚t‚ charg‚ avec un interpr‚tateur Tcl"
+303 "Ficher modifi‚ depuis le dernier enregistrement."
+304 "L'expansion du shell a ‚chou‚"
+304 "L'expansion du shell a ‚chou‚"
+305 "Pas d'option d'‚dition %s sp‚cifi‚e"
+306 "Vi n'a pas ‚t‚ charg‚ avec un interpr‚tateur Perl"
+307 "Pas de commande ex … ex‚cuter"
+308 "Entrez <CR> pour ex‚cuter une commande, :q pour quitter"
+309 "Utiliser "cscope help" pour obtenir de l'aide"
+310 "Aucune connexion cscope n'est lanc‚e"
+311 "%s : type de recherche inconnu : utiliser un des %s"
+312 "%d : Il n'existe pas de telle session cscope"
+313 "D‚finition : l'option %s ne peut jamais ˆtre activ‚e"
+314 "D‚finition : l'option %s ne peut jamais ˆtre d‚finie sur 0"
+315 "%s: joints : %lu lignes, %lu caractŠres"
+316 "‚v‚nement impr‚vu de redimensionnement"
+317 "%d fichiers … ‚diter"
diff --git a/contrib/nvi/catalog/french.check b/contrib/nvi/catalog/french.check
new file mode 100644
index 000000000000..1e53d93cb446
--- /dev/null
+++ b/contrib/nvi/catalog/french.check
@@ -0,0 +1,34 @@
+Unused message id's (this is okay):
+001
+047
+050
+051
+052
+081
+176
+229
+288
+=========================
+MISSING ERROR MESSAGES (Please add!):
+=========================
+Extra error messages (just delete them):
+=========================
+MESSAGES WITH THE SAME MESSAGE ID's (FIX!):
+=========================
+Duplicate messages, both id and message (this is okay):
+ 2 209 "Le fichier est vide"
+ 2 304 "L'expansion du shell a ‚chou‚"
+=========================
+Duplicate messages, just message (this is okay):
+ 2 %s : Fichier de r‚cup‚ration malform‚X
+ 2 %s: %lu lignes, %lu caractŠresX
+ 2 Aucune connexion n'‚tant effectu‚e, impossible d'annulerX
+ 2 Copie en cours du fichier pour r‚cup‚ration...X
+ 2 D‚finition : l'option %s n'est pas bool‚enneX
+ 2 Impossible de r‚cup‚rer les modifications si la session ‚choueX
+ 2 InterrompuX
+ 2 La recherche est revenue … son point de d‚partX
+ 2 Pas de motif de recherche pr‚c‚dentX
+ 3 %s: supprimerX
+ 4 Utilisation : %sX
+=========================
diff --git a/contrib/nvi/catalog/german b/contrib/nvi/catalog/german
new file mode 100644
index 000000000000..0810ba6cf9b4
--- /dev/null
+++ b/contrib/nvi/catalog/german
@@ -0,0 +1,317 @@
+VI_MESSAGE_CATALOG
+Zeilenlaengen UeberlaufX
+kann Zeile %lu nicht loeschenX
+kann an Zeile %lu nicht anfuegenX
+kann in Zeile %lu nicht einfuegenX
+kann Zeile %lu nicht speichernX
+kann letzte Zeile nicht lesenX
+Fehler: kann Zeile %lu nicht wiederherstellenX
+ProtokolldateiX
+Keine Protokollierung aktiv, rueckgaengig machen nicht moeglichX
+Keine Aenderungen rueckgaengig zu machenX
+Keine Protokollierung aktiv, rueckgaengig machen nicht moeglichX
+Keine Protokollierung aktiv, Wiederholung von Aenderungen nicht moeglichX
+Keine Aenderungen zu wiederholenX
+%s/%d: ProtokollschreibfehlerX
+Vi's Standardein- und ausgabe muss ein Terminal seinX
+Marke %s: nicht gesetztX
+Marke %s: die Zeile wurde geloeschtX
+Marke %s: Cursorposition existiert nicht mehrX
+Fehler: X
+neue DateiX
+Name geaendertX
+geaendertX
+nicht geaendertX
+NICHT GELOCKEDX
+nur zum LesenX
+Zeile %lu von %lu [%ld%%]X
+leere DateiX
+Zeile %luX
+Die Datei %s ist kein MeldungskatalogX
+Setzen der Voreinstellung fuer %s Option nicht moeglichX
+Benutzung: %sX
+set: keine %s Option: 'set all' zeigt alle Optionen mit Werten anX
+set: der [no]%s Option kann kein Wert zugewiesen werdenX
+set: %s ist keine boolsche OptionX
+set: %s Option: %sX
+set: %s Option: %s: Wert UeberlaufX
+set: %s Option: %s ist eine ungueltige ZahlX
+set: %s ist keine boolsche OptionX
+Anzeige hat zu wenig Spalten, weniger als %dX
+Anzeige hat zu viele Spalten, mehr als %dX
+Anzeige hat zu wenig Zeilen, weniger als %dX
+Anzeige hat zu viele Zeilen, mehr als %dX
+Die lisp Option ist nicht implementiertX
+Messages nicht abgeschalten: %sX
+Messages nicht eingeschalten: %sX
+
+Die paragraph Option muss Gruppen zu zwei Zeichen enthaltenX
+Die section Option muss Gruppen zu zwei Zeichen enthaltenX
+
+
+
+Der Standardpuffer ist leerX
+Puffer %s ist leerX
+Dateien mit newlines im Namen sind nicht wiederherstellbarX
+Aenderungen nicht wiederherstellbar falls die Editorsitzung schief gehtX
+kopiere Datei fuer Wiederherstellung ...X
+Rettungsmechanismus funktioniert nicht: %sX
+Aenderungen nicht wiederherstellbar falls die Editorsitzung schief gehtX
+Sicherung der Datei gescheitert: %sX
+kopiere Datei fuer Wiederherstellung ...X
+Informationen ueber den Benutzer mit id %u nicht gefundenX
+Wiederherstellungsdatei kann nicht gesperrt werdenX
+Puffer der Wiederherstellungsdatei uebergelaufenX
+WiederherstellungsdateiX
+%s: Wiederherstellungsdatei hat falsches FormatX
+%s: Wiederherstellungsdatei hat falsches FormatX
+Keine von Ihnen lesbaren Dateien mit Namen %s zum WiederherstellenX
+Es gibt aeltere Versionen dieser Datei von Ihnen zum WiederherstellenX
+Sie haben noch andere Dateien zum WiederherstellenX
+schicke keine email: %sX
+Datei leer; nichts zu suchenX
+Dateiende erreicht, ohne das Suchmuster zu findenX
+Kein altes SuchmusterX
+Suchmuster nicht gefundenX
+Dateianfang erreicht, ohne das Suchmuster zu findenX
+Suche umgeschlagenX
+suche ...X
+Keine nichtdruckbaren Zeichen gefundenX
+Unbekannter KommandonameX
+
+%s: Kommando im ex Modus nicht verfuegbarX
+Count darf nicht Null seinX
+%s: falsche ZeilenangabeX
+Interner Syntaxtabellenfehler (%s: %s)X
+Benutzung: %sX
+%s: temporaerer Puffer nicht freigegebenX
+Flagoffset vor Zeile 1X
+Flagoffset hinter dem DateiendeX
+@ mit Bereich lief als Datei/Anzeige geaendert wurdeX
+globales oder v-Kommando lief als Datei/Anzeige geaendert wurdeX
+Ex Kommando misslungen: restliche Kommandoeingabe ignoriertX
+Ex Kommando misslungen: umdefinierte Tasten ungueltigX
+Die zweite Adresse ist kleiner als die ersteX
+Kein Markenname angegebenX
+\\ ohne folgenden / oder ?X
+Referenz auf eine negative ZeilennummerX
+Das Kommando %s ist unbekanntX
+Adresswert zu grossX
+Adresswert zu kleinX
+Ungueltige AdresskombinationX
+Ungueltige Adresse: nur %lu Zeilen in der DateiX
+Ungueltige Adresse: die Datei ist leerX
+Das Kommando %s erlaubt keine Adresse 0X
+Keine Abkuerzungen zum AnzeigenX
+Abkuerzungen muessen mit einem "Wort"-Zeichen endenX
+Abkuerzungen duerfen keine Tabulator- oder Leerzeichen enthaltenX
+In Abkuerzungen duerfen ausser am Ende Wort- und Nicht-Wort-Zeichen nicht gemischt werdenX
+"%s" ist keine AbkuerzungX
+Vi Kommando misslungen: umdefinierte Tasten ungueltigX
+Keine weiteren Dateien zu edierenX
+Keine vorhergehenden Dateien zu edierenX
+Keine vorhergehenden Dateien fuer rewindX
+Keine Dateiliste zum AnzeigenX
+Kein vorhergehendes Kommando um "!" zu ersetzenX
+Kein Dateiname fuer %%X
+Kein Dateiname fuer #X
+Fehler: execl: %sX
+I/O Fehler: %sX
+Datei wurde seit dem letzten vollstaendigen Schreiben geaendert; schreibe oder verwende ! zum ignorierenX
+Kann Homedirectory nicht bestimmenX
+Neues aktuelles Directory: %sX
+Keine Puffer anzuzeigenX
+Das Kommando %s kann nicht als Teil eines global oder v Kommandos verwendet werdenX
+%s/%s: nicht gelesen: gehoehrt weder Ihnen noch rootX
+%s/%s: nicht gelesen: gehoehrt nicht IhnenX
+%s/%s: nicht gelesen: anderer Benutzer als Eigentuemer hat SchreibrechtX
+%s: nicht gelesen: gehoehrt weder Ihnen noch rootX
+%s: nicht gelesen: gehoehrt nicht IhnenX
+%s: nicht gelesen: anderer Benutzer als Eigentuemer hat SchreibrechtX
+Keine folgenden Zeilen zum VerbindenX
+Kein Eingabe-Map EintragX
+Kein Kommando-Map EintragX
+Das %s Zeichen kann nicht umgemappt werdenX
+"%s" ist momentan nicht gemapptX
+Markennamen muessen einzelne Buchstaben seinX
+%s existiert, nicht geschrieben; verwende ! zum UeberschreibenX
+Neue .exrc Datei: %s. X
+Zielzeile ist innerhalb des VerschiebebereichsX
+Das open Kommando verlangt, dass die open Option gesetzt istX
+Das open Kommando ist nocht nicht implementiertX
+Rettung dieser Datei nicht moeglichX
+Datei gerettetX
+%s wurde in zu viele Dateinamen expandiertX
+Nur regulaere Dateien und named pipes koennen gelesen werdenX
+%s: Lesesperrung war nicht moeglichX
+lese ...X
+%s: %lu Zeilen, %lu ZeichenX
+Keine Hintegrundanzeigen vorhandenX
+Das script Kommando ist nur im vi Modus verfuegbarX
+Kein Kommando auszufuehrenX
+shiftwidth Option auf 0 gesetztX
+Count ueberlaufX
+Count unterlaufX
+Regulaerer Ausdruck angegeben; r Flag bedeutungslosX
+Die #, l und p Flags koennen im vi Modus nicht mit dem c Flag kombiniert werdenX
+Keine Uebereinstimmung gefundenX
+Kein vorhergehender 'tag' angegebenX
+Weniger als %s Eintraege auf dem 'tag'-Stack; verwende :display t[ags]X
+Keine Datei namens %s auf dem 'tag'-Stack; verwende :display t[ags]X
+Druecke Enter um fortzufahren: X
+%s: 'tag' nicht gefundenX
+%s: kaputter 'tag' in %sX
+%s: die Zeilennummer des 'tag' ist hinter dem DateiendeX
+Der 'tag' Stack ist leerX
+%s: Suchmuster nicht gefundenX
+%d weitere Dateien zu edierenX
+Puffer %s ist leerX
+Bestaetige Aenderung [n]X
+Unterbrochen.X
+Kein vorhergehender Puffer zum AusfuehrenX
+Kein vorhergehender regulaerer AusdruckX
+Das Kommando %s verlangt, dass bereits eine Datei eingelesen wurdeX
+Benutzung: %sX
+Das visual Kommando verlangt dass die open Option gesetzt istX
+
+Leere DateiX
+Keine vorhergehende F, f, T oder t SucheX
+%s nicht gefundenX
+Keine vorhergehende Datei zu edierenX
+Cursor nicht auf einer ZahlX
+Sich ergebende Zahl ist zu grossX
+Sich ergebende Zahl ist zu kleinX
+Kein korrespondierendes Zeichen in dieser ZeileX
+Korrespondierendes Zeichen nicht gefundenX
+Keine Zeichen zu ersetzenX
+Keine andere Anzeige zum HinschaltenX
+Zeichen nach Suchmuster, Zeilenoffset und/oder z KommandoX
+Kein altes SuchmusterX
+Suche zur urspruenglichen Position umgeschlagenX
+Abkuerzung ueberschreitet Expansionsgrenze: Zeichen weggelassenX
+Nicht erlaubtes Zeichen; maskiere zum EingebenX
+Bereits am Anfang der EingabeX
+Keine weiteren Zeichen zu loeschenX
+Bewegung hinter das DateiendeX
+Bewegung hinter das ZeilenendeX
+Keine Cursorbewegung gemachtX
+Bereits am DateianfangX
+Bewegung vor den DateianfangX
+Bereits in der ersten SpalteX
+Puffer sollen vor dem Kommando angegeben werdenX
+Bereits am DateiendeX
+Bereits am ZeilenendeX
+%s ist kein vi KommandoX
+Benutzung: %sX
+Keine Zeichen zu loeschenX
+Das Q Kommando benoetigt das ex Terminal InterfaceX
+Kein Kommando zu wiederholenX
+Die Datei ist leerX
+%s kann nicht als Bewegungskommando verwendet werdenX
+Bereits im Kommando-ModusX
+ Cursor nicht auf einem WortX
+
+Wert der Window Option ist zu gross, max ist %uX
+AnfuegenX
+AendernX
+KommandoX
+EinfuegenX
+ErsetzenX
+Bewegung hinter das AnzeigenendeX
+Bewegung vor den AnzeigenanfangX
+Anzeige muss zum Zerlegen groesser als %d seinX
+Keine Hintergrundanzeigen vorhandenX
+Es gibt keine Hintergrundanzeige die eine Datei namens %s ediertX
+Die einzige dargestellte Anzeige kann nicht in den Hintergrund gebracht werdenX
+Die Anzeige kann nur auf %d Zeilen verkleinert werdenX
+Die Anzeige kann nicht verkleinert werdenX
+Die Anzeige kann nicht vergroessert werdenX
+
+Diese Anzeige kann nicht gestopped werdenX
+Unterbrochen: umdefinierte Tasten ungueltigX
+vi: temporaerer Puffer nicht freigegebenX
+Dieses Terminal hat keine %s TasteX
+es kann nur ein Puffer angegeben werdenX
+Zahl groesser als %luX
+UnterbrochenX
+Nicht moeglich temporaere Datei anzulegenX
+Warnung: %s ist keine regulaere DateiX
+%s ist bereits gesperrt, nur-lese EditorsitzungX
+%s: loeschenX
+%s: schliessenX
+%s: loeschenX
+%s: loeschenX
+Nur-lese Datei, nicht geschrieben; verwende ! zum UeberschreibenX
+Nur-lese Datei, nicht geschriebenX
+%s existiert, nicht geschrieben; verwende ! zum UeberschreibenX
+%s existiert, nicht geschriebenX
+Teil der Datei, nicht geschrieben; verwende ! zum UeberschreibenX
+Teil der Datei, nicht geschriebenX
+%s: Datei wurde spaeter als diese Kopie veraendert; verwende ! zum UeberschreibenX
+%s: Datei wurde spaeter als diese Kopie veraendertX
+%s: Schreibsperrung war nicht moeglichX
+schreibe ...X
+%s: WARNUNG: DATEI ABGESCHNITTENX
+Bereits am ersten 'tag' dieser GruppeX
+%s: neue Datei: %lu Zeilen, %lu ZeichenX
+%s: %lu Zeilen, %lu ZeichenX
+%s wurde in zu viele Dateinamen expandiertX
+%s: keine regulaere DateiX
+%s: gehoehrt nicht IhnenX
+%s: anderer Benutzer als Eigentuemer hat ZugriffX
+Datei wurde seit dem letzten vollstaendigen Schreiben geaendert; schreibe oder verwende ! zum ignorierenX
+Datei wurde seit dem letzten vollstaendigen Schreiben geaendert; schreibe oder verwende :edit! zum ignorierenX
+Datei wurde seit dem letzten vollstaendigen Schreiben geaendert; schreibe oder verwende ! zum ignorierenX
+Datei ist temporaer; beim Verlassen gehen die Aenderungen verlorenX
+Nur-lese Datei, Aenderungen werden nicht automatisch geschriebenX
+Portokollierung neu begonnenX
+bestaetigen [ynq]X
+Druecke beliebige Taste um fortzufahrenX
+Druecke beliebige Taste um fortzufahren [: um weitere Kommandos einzugeben]: X
+Druecke beliebige Taste um fortzufahren [q zum Verlassen]: X
+Diese Form von %s benoetigt das ex Terminal-InterfaceX
+Gehe in ex Eingabe-Modus.\nX
+Kommando schief gelaufen, noch keine Datei eingelesenX
+ weiter?X
+unerwartetes Zeichen - EreignisX
+unerwartetes Dateiende - EreignisX
+Keine Position zum Anspringen gefundenX
+unerwartetes Unterbrechungs - EreignisX
+unerwartetes Verlassen - EreignisX
+unerwartetes Wiederherstellungs - EreignisX
+Bereits am letzten 'tag' dieser GruppeX
+Das %s Kommando benoetigt das ex Terminal-InterfaceX
+Diese Form von %s wird nicht unterstuetzt wenn die 'secure edit' - Option gesetzt istX
+unerwartetes Zeichenketten - EreignisX
+unerwartetes timeout - EreignisX
+unerwartetes Schreibe - EreignisX
+
+Shell Expandierungen nicht unterstuetzt wenn die 'secure edit' - Option gesetzt istX
+Das %s Kommando wird nicht unterstuetzt wenn die 'secure edit' - Option gesetzt istX
+set: %s kann nicht ausgeschaltet werdenX
+Anzeige zu klein.X
+angefuegtX
+geaendertX
+geloeschtX
+verbundenX
+verschobenX
+geschobenX
+in Puffer geschriebenX
+ZeileX
+ZeilenX
+Vi wurde nicht mit dem Tcl Interpreter gelinktX
+Datei wurde seit dem letzten Schreiben veraendert.X
+Shell Expansion nicht geklapptX
+Es ist keine %s Edieroption angegebenX
+Vi wurde nicht mit einem Perl Interpreter geladenX
+Kein ex Kommando auszufuehrenX
+Druecke <CR> um ein Kommando auszufuehren, :q zum verlassenX
+Verwende "cscope help" fuer HilestellungX
+Keine cscope Verbindung aktivX
+%s: unbekannter Suchtyp: verwende einen aus %sX
+%d: keine solche cscope VerbindungX
+set: die %s Option kann nicht eingeschaltet werdenX
+set: die %s Option kann nicht auf 0 gesetzt werdenX
+%s: angefuegt: %lu Zeilen, %lu ZeichenX
+unerwartetes Groessenveraenderungs - EreignisX
+%d Dateien zu edierenX
diff --git a/contrib/nvi/catalog/german.base b/contrib/nvi/catalog/german.base
new file mode 100644
index 000000000000..135b72da7994
--- /dev/null
+++ b/contrib/nvi/catalog/german.base
@@ -0,0 +1,307 @@
+002 "Zeilenlaengen Ueberlauf"
+003 "kann Zeile %lu nicht loeschen"
+004 "kann an Zeile %lu nicht anfuegen"
+005 "kann in Zeile %lu nicht einfuegen"
+006 "kann Zeile %lu nicht speichern"
+007 "kann letzte Zeile nicht lesen"
+008 "Fehler: kann Zeile %lu nicht wiederherstellen"
+009 "Protokolldatei"
+010 "Keine Protokollierung aktiv, rueckgaengig machen nicht moeglich"
+011 "Keine Aenderungen rueckgaengig zu machen"
+012 "Keine Protokollierung aktiv, rueckgaengig machen nicht moeglich"
+013 "Keine Protokollierung aktiv, Wiederholung von Aenderungen nicht moeglich"
+014 "Keine Aenderungen zu wiederholen"
+015 "%s/%d: Protokollschreibfehler"
+016 "Vi's Standardein- und ausgabe muss ein Terminal sein"
+017 "Marke %s: nicht gesetzt"
+018 "Marke %s: die Zeile wurde geloescht"
+019 "Marke %s: Cursorposition existiert nicht mehr"
+020 "Fehler: "
+021 "neue Datei"
+022 "Name geaendert"
+023 "geaendert"
+024 "nicht geaendert"
+025 "NICHT GELOCKED"
+026 "nur zum Lesen"
+027 "Zeile %lu von %lu [%ld%%]"
+028 "leere Datei"
+029 "Zeile %lu"
+030 "Die Datei %s ist kein Meldungskatalog"
+031 "Setzen der Voreinstellung fuer %s Option nicht moeglich"
+032 "Benutzung: %s"
+033 "set: keine %s Option: 'set all' zeigt alle Optionen mit Werten an"
+034 "set: der [no]%s Option kann kein Wert zugewiesen werden"
+035 "set: %s ist keine boolsche Option"
+036 "set: %s Option: %s"
+037 "set: %s Option: %s: Wert Ueberlauf"
+038 "set: %s Option: %s ist eine ungueltige Zahl"
+039 "set: %s ist keine boolsche Option"
+040 "Anzeige hat zu wenig Spalten, weniger als %d"
+041 "Anzeige hat zu viele Spalten, mehr als %d"
+042 "Anzeige hat zu wenig Zeilen, weniger als %d"
+043 "Anzeige hat zu viele Zeilen, mehr als %d"
+044 "Die lisp Option ist nicht implementiert"
+045 "Messages nicht abgeschalten: %s"
+046 "Messages nicht eingeschalten: %s"
+048 "Die paragraph Option muss Gruppen zu zwei Zeichen enthalten"
+049 "Die section Option muss Gruppen zu zwei Zeichen enthalten"
+053 "Der Standardpuffer ist leer"
+054 "Puffer %s ist leer"
+055 "Dateien mit newlines im Namen sind nicht wiederherstellbar"
+056 "Aenderungen nicht wiederherstellbar falls die Editorsitzung schief geht"
+057 "kopiere Datei fuer Wiederherstellung ..."
+058 "Rettungsmechanismus funktioniert nicht: %s"
+059 "Aenderungen nicht wiederherstellbar falls die Editorsitzung schief geht"
+060 "Sicherung der Datei gescheitert: %s"
+061 "kopiere Datei fuer Wiederherstellung ..."
+062 "Informationen ueber den Benutzer mit id %u nicht gefunden"
+063 "Wiederherstellungsdatei kann nicht gesperrt werden"
+064 "Puffer der Wiederherstellungsdatei uebergelaufen"
+065 "Wiederherstellungsdatei"
+066 "%s: Wiederherstellungsdatei hat falsches Format"
+067 "%s: Wiederherstellungsdatei hat falsches Format"
+068 "Keine von Ihnen lesbaren Dateien mit Namen %s zum Wiederherstellen"
+069 "Es gibt aeltere Versionen dieser Datei von Ihnen zum Wiederherstellen"
+070 "Sie haben noch andere Dateien zum Wiederherstellen"
+071 "schicke keine email: %s"
+072 "Datei leer; nichts zu suchen"
+073 "Dateiende erreicht, ohne das Suchmuster zu finden"
+074 "Kein altes Suchmuster"
+075 "Suchmuster nicht gefunden"
+076 "Dateianfang erreicht, ohne das Suchmuster zu finden"
+077 "Suche umgeschlagen"
+078 "suche ..."
+079 "Keine nichtdruckbaren Zeichen gefunden"
+080 "Unbekannter Kommandoname"
+082 "%s: Kommando im ex Modus nicht verfuegbar"
+083 "Count darf nicht Null sein"
+084 "%s: falsche Zeilenangabe"
+085 "Interner Syntaxtabellenfehler (%s: %s)"
+086 "Benutzung: %s"
+087 "%s: temporaerer Puffer nicht freigegeben"
+088 "Flagoffset vor Zeile 1"
+089 "Flagoffset hinter dem Dateiende"
+090 "@ mit Bereich lief als Datei/Anzeige geaendert wurde"
+091 "globales oder v-Kommando lief als Datei/Anzeige geaendert wurde"
+092 "Ex Kommando misslungen: restliche Kommandoeingabe ignoriert"
+093 "Ex Kommando misslungen: umdefinierte Tasten ungueltig"
+094 "Die zweite Adresse ist kleiner als die erste"
+095 "Kein Markenname angegeben"
+096 "\\ ohne folgenden / oder ?"
+097 "Referenz auf eine negative Zeilennummer"
+098 "Das Kommando %s ist unbekannt"
+099 "Adresswert zu gross"
+100 "Adresswert zu klein"
+101 "Ungueltige Adresskombination"
+102 "Ungueltige Adresse: nur %lu Zeilen in der Datei"
+103 "Ungueltige Adresse: die Datei ist leer"
+104 "Das Kommando %s erlaubt keine Adresse 0"
+105 "Keine Abkuerzungen zum Anzeigen"
+106 "Abkuerzungen muessen mit einem "Wort"-Zeichen enden"
+107 "Abkuerzungen duerfen keine Tabulator- oder Leerzeichen enthalten"
+108 "In Abkuerzungen duerfen ausser am Ende Wort- und Nicht-Wort-Zeichen nicht gemischt werden"
+109 ""%s" ist keine Abkuerzung"
+110 "Vi Kommando misslungen: umdefinierte Tasten ungueltig"
+111 "Keine weiteren Dateien zu edieren"
+112 "Keine vorhergehenden Dateien zu edieren"
+113 "Keine vorhergehenden Dateien fuer rewind"
+114 "Keine Dateiliste zum Anzeigen"
+115 "Kein vorhergehendes Kommando um "!" zu ersetzen"
+116 "Kein Dateiname fuer %%"
+117 "Kein Dateiname fuer #"
+118 "Fehler: execl: %s"
+119 "I/O Fehler: %s"
+120 "Datei wurde seit dem letzten vollstaendigen Schreiben geaendert; schreibe oder verwende ! zum ignorieren"
+121 "Kann Homedirectory nicht bestimmen"
+122 "Neues aktuelles Directory: %s"
+123 "Keine Puffer anzuzeigen"
+124 "Das Kommando %s kann nicht als Teil eines global oder v Kommandos verwendet werden"
+125 "%s/%s: nicht gelesen: gehoehrt weder Ihnen noch root"
+126 "%s/%s: nicht gelesen: gehoehrt nicht Ihnen"
+127 "%s/%s: nicht gelesen: anderer Benutzer als Eigentuemer hat Schreibrecht"
+128 "%s: nicht gelesen: gehoehrt weder Ihnen noch root"
+129 "%s: nicht gelesen: gehoehrt nicht Ihnen"
+130 "%s: nicht gelesen: anderer Benutzer als Eigentuemer hat Schreibrecht"
+131 "Keine folgenden Zeilen zum Verbinden"
+132 "Kein Eingabe-Map Eintrag"
+133 "Kein Kommando-Map Eintrag"
+134 "Das %s Zeichen kann nicht umgemappt werden"
+135 ""%s" ist momentan nicht gemappt"
+136 "Markennamen muessen einzelne Buchstaben sein"
+137 "%s existiert, nicht geschrieben; verwende ! zum Ueberschreiben"
+138 "Neue .exrc Datei: %s. "
+139 "Zielzeile ist innerhalb des Verschiebebereichs"
+140 "Das open Kommando verlangt, dass die open Option gesetzt ist"
+141 "Das open Kommando ist nocht nicht implementiert"
+142 "Rettung dieser Datei nicht moeglich"
+143 "Datei gerettet"
+144 "%s wurde in zu viele Dateinamen expandiert"
+145 "Nur regulaere Dateien und named pipes koennen gelesen werden"
+146 "%s: Lesesperrung war nicht moeglich"
+147 "lese ..."
+148 "%s: %lu Zeilen, %lu Zeichen"
+149 "Keine Hintegrundanzeigen vorhanden"
+150 "Das script Kommando ist nur im vi Modus verfuegbar"
+151 "Kein Kommando auszufuehren"
+152 "shiftwidth Option auf 0 gesetzt"
+153 "Count ueberlauf"
+154 "Count unterlauf"
+155 "Regulaerer Ausdruck angegeben; r Flag bedeutungslos"
+156 "Die #, l und p Flags koennen im vi Modus nicht mit dem c Flag kombiniert werden"
+157 "Keine Uebereinstimmung gefunden"
+158 "Kein vorhergehender 'tag' angegeben"
+159 "Weniger als %s Eintraege auf dem 'tag'-Stack; verwende :display t[ags]"
+160 "Keine Datei namens %s auf dem 'tag'-Stack; verwende :display t[ags]"
+161 "Druecke Enter um fortzufahren: "
+162 "%s: 'tag' nicht gefunden"
+163 "%s: kaputter 'tag' in %s"
+164 "%s: die Zeilennummer des 'tag' ist hinter dem Dateiende"
+165 "Der 'tag' Stack ist leer"
+166 "%s: Suchmuster nicht gefunden"
+167 "%d weitere Dateien zu edieren"
+168 "Puffer %s ist leer"
+169 "Bestaetige Aenderung [n]"
+170 "Unterbrochen."
+171 "Kein vorhergehender Puffer zum Ausfuehren"
+172 "Kein vorhergehender regulaerer Ausdruck"
+173 "Das Kommando %s verlangt, dass bereits eine Datei eingelesen wurde"
+174 "Benutzung: %s"
+175 "Das visual Kommando verlangt dass die open Option gesetzt ist"
+177 "Leere Datei"
+178 "Keine vorhergehende F, f, T oder t Suche"
+179 "%s nicht gefunden"
+180 "Keine vorhergehende Datei zu edieren"
+181 "Cursor nicht auf einer Zahl"
+182 "Sich ergebende Zahl ist zu gross"
+183 "Sich ergebende Zahl ist zu klein"
+184 "Kein korrespondierendes Zeichen in dieser Zeile"
+185 "Korrespondierendes Zeichen nicht gefunden"
+186 "Keine Zeichen zu ersetzen"
+187 "Keine andere Anzeige zum Hinschalten"
+188 "Zeichen nach Suchmuster, Zeilenoffset und/oder z Kommando"
+189 "Kein altes Suchmuster"
+190 "Suche zur urspruenglichen Position umgeschlagen"
+191 "Abkuerzung ueberschreitet Expansionsgrenze: Zeichen weggelassen"
+192 "Nicht erlaubtes Zeichen; maskiere zum Eingeben"
+193 "Bereits am Anfang der Eingabe"
+194 "Keine weiteren Zeichen zu loeschen"
+195 "Bewegung hinter das Dateiende"
+196 "Bewegung hinter das Zeilenende"
+197 "Keine Cursorbewegung gemacht"
+198 "Bereits am Dateianfang"
+199 "Bewegung vor den Dateianfang"
+200 "Bereits in der ersten Spalte"
+201 "Puffer sollen vor dem Kommando angegeben werden"
+202 "Bereits am Dateiende"
+203 "Bereits am Zeilenende"
+204 "%s ist kein vi Kommando"
+205 "Benutzung: %s"
+206 "Keine Zeichen zu loeschen"
+207 "Das Q Kommando benoetigt das ex Terminal Interface"
+208 "Kein Kommando zu wiederholen"
+209 "Die Datei ist leer"
+210 "%s kann nicht als Bewegungskommando verwendet werden"
+211 "Bereits im Kommando-Modus"
+212 " Cursor nicht auf einem Wort"
+214 "Wert der Window Option ist zu gross, max ist %u"
+215 "Anfuegen"
+216 "Aendern"
+217 "Kommando"
+218 "Einfuegen"
+219 "Ersetzen"
+220 "Bewegung hinter das Anzeigenende"
+221 "Bewegung vor den Anzeigenanfang"
+222 "Anzeige muss zum Zerlegen groesser als %d sein"
+223 "Keine Hintergrundanzeigen vorhanden"
+224 "Es gibt keine Hintergrundanzeige die eine Datei namens %s ediert"
+225 "Die einzige dargestellte Anzeige kann nicht in den Hintergrund gebracht werden"
+226 "Die Anzeige kann nur auf %d Zeilen verkleinert werden"
+227 "Die Anzeige kann nicht verkleinert werden"
+228 "Die Anzeige kann nicht vergroessert werden"
+230 "Diese Anzeige kann nicht gestopped werden"
+231 "Unterbrochen: umdefinierte Tasten ungueltig"
+232 "vi: temporaerer Puffer nicht freigegeben"
+233 "Dieses Terminal hat keine %s Taste"
+234 "es kann nur ein Puffer angegeben werden"
+235 "Zahl groesser als %lu"
+236 "Unterbrochen"
+237 "Nicht moeglich temporaere Datei anzulegen"
+238 "Warnung: %s ist keine regulaere Datei"
+239 "%s ist bereits gesperrt, nur-lese Editorsitzung"
+240 "%s: loeschen"
+241 "%s: schliessen"
+242 "%s: loeschen"
+243 "%s: loeschen"
+244 "Nur-lese Datei, nicht geschrieben; verwende ! zum Ueberschreiben"
+245 "Nur-lese Datei, nicht geschrieben"
+246 "%s existiert, nicht geschrieben; verwende ! zum Ueberschreiben"
+247 "%s existiert, nicht geschrieben"
+248 "Teil der Datei, nicht geschrieben; verwende ! zum Ueberschreiben"
+249 "Teil der Datei, nicht geschrieben"
+250 "%s: Datei wurde spaeter als diese Kopie veraendert; verwende ! zum Ueberschreiben"
+251 "%s: Datei wurde spaeter als diese Kopie veraendert"
+252 "%s: Schreibsperrung war nicht moeglich"
+253 "schreibe ..."
+254 "%s: WARNUNG: DATEI ABGESCHNITTEN"
+255 "Bereits am ersten 'tag' dieser Gruppe"
+256 "%s: neue Datei: %lu Zeilen, %lu Zeichen"
+257 "%s: %lu Zeilen, %lu Zeichen"
+258 "%s wurde in zu viele Dateinamen expandiert"
+259 "%s: keine regulaere Datei"
+260 "%s: gehoehrt nicht Ihnen"
+261 "%s: anderer Benutzer als Eigentuemer hat Zugriff"
+262 "Datei wurde seit dem letzten vollstaendigen Schreiben geaendert; schreibe oder verwende ! zum ignorieren"
+263 "Datei wurde seit dem letzten vollstaendigen Schreiben geaendert; schreibe oder verwende :edit! zum ignorieren"
+264 "Datei wurde seit dem letzten vollstaendigen Schreiben geaendert; schreibe oder verwende ! zum ignorieren"
+265 "Datei ist temporaer; beim Verlassen gehen die Aenderungen verloren"
+266 "Nur-lese Datei, Aenderungen werden nicht automatisch geschrieben"
+267 "Portokollierung neu begonnen"
+268 "bestaetigen [ynq]"
+269 "Druecke beliebige Taste um fortzufahren"
+270 "Druecke beliebige Taste um fortzufahren [: um weitere Kommandos einzugeben]: "
+271 "Druecke beliebige Taste um fortzufahren [q zum Verlassen]: "
+272 "Diese Form von %s benoetigt das ex Terminal-Interface"
+273 "Gehe in ex Eingabe-Modus.\n"
+274 "Kommando schief gelaufen, noch keine Datei eingelesen"
+275 " weiter?"
+276 "unerwartetes Zeichen - Ereignis"
+277 "unerwartetes Dateiende - Ereignis"
+278 "Keine Position zum Anspringen gefunden"
+279 "unerwartetes Unterbrechungs - Ereignis"
+280 "unerwartetes Verlassen - Ereignis"
+281 "unerwartetes Wiederherstellungs - Ereignis"
+282 "Bereits am letzten 'tag' dieser Gruppe"
+283 "Das %s Kommando benoetigt das ex Terminal-Interface"
+284 "Diese Form von %s wird nicht unterstuetzt wenn die 'secure edit' - Option gesetzt ist"
+285 "unerwartetes Zeichenketten - Ereignis"
+286 "unerwartetes timeout - Ereignis"
+287 "unerwartetes Schreibe - Ereignis"
+289 "Shell Expandierungen nicht unterstuetzt wenn die 'secure edit' - Option gesetzt ist"
+290 "Das %s Kommando wird nicht unterstuetzt wenn die 'secure edit' - Option gesetzt ist"
+291 "set: %s kann nicht ausgeschaltet werden"
+292 "Anzeige zu klein."
+293 "angefuegt"
+294 "geaendert"
+295 "geloescht"
+296 "verbunden"
+297 "verschoben"
+298 "geschoben"
+299 "in Puffer geschrieben"
+300 "Zeile"
+301 "Zeilen"
+302 "Vi wurde nicht mit dem Tcl Interpreter gelinkt"
+303 "Datei wurde seit dem letzten Schreiben veraendert."
+304 "Shell Expansion nicht geklappt"
+305 "Es ist keine %s Edieroption angegeben"
+306 "Vi wurde nicht mit einem Perl Interpreter geladen"
+307 "Kein ex Kommando auszufuehren"
+308 "Druecke <CR> um ein Kommando auszufuehren, :q zum verlassen"
+309 "Verwende "cscope help" fuer Hilestellung"
+310 "Keine cscope Verbindung aktiv"
+311 "%s: unbekannter Suchtyp: verwende einen aus %s"
+312 "%d: keine solche cscope Verbindung"
+313 "set: die %s Option kann nicht eingeschaltet werden"
+314 "set: die %s Option kann nicht auf 0 gesetzt werden"
+315 "%s: angefuegt: %lu Zeilen, %lu Zeichen"
+316 "unerwartetes Groessenveraenderungs - Ereignis"
+317 "%d Dateien zu edieren"
diff --git a/contrib/nvi/catalog/german.check b/contrib/nvi/catalog/german.check
new file mode 100644
index 000000000000..4fd60c14e63b
--- /dev/null
+++ b/contrib/nvi/catalog/german.check
@@ -0,0 +1,36 @@
+Unused message id's (this is okay):
+001
+047
+050
+051
+052
+081
+176
+213
+229
+288
+=========================
+MISSING ERROR MESSAGES (Please add!):
+=========================
+Extra error messages (just delete them):
+=========================
+MESSAGES WITH THE SAME MESSAGE ID's (FIX!):
+=========================
+Duplicate messages, both id and message (this is okay):
+=========================
+Duplicate messages, just message (this is okay):
+ 2 %s existiert, nicht geschrieben; verwende ! zum UeberschreibenX
+ 2 %s wurde in zu viele Dateinamen expandiertX
+ 2 %s: %lu Zeilen, %lu ZeichenX
+ 2 %s: Wiederherstellungsdatei hat falsches FormatX
+ 2 Aenderungen nicht wiederherstellbar falls die Editorsitzung schief gehtX
+ 2 Kein altes SuchmusterX
+ 2 Keine Protokollierung aktiv, rueckgaengig machen nicht moeglichX
+ 2 Puffer %s ist leerX
+ 2 geaendertX
+ 2 kopiere Datei fuer Wiederherstellung ...X
+ 2 set: %s ist keine boolsche OptionX
+ 3 %s: loeschenX
+ 3 Datei wurde seit dem letzten vollstaendigen Schreiben geaendert; schreibe oder verwende ! zum ignorierenX
+ 4 Benutzung: %sX
+=========================
diff --git a/contrib/nvi/catalog/german.owner b/contrib/nvi/catalog/german.owner
new file mode 100644
index 000000000000..e72e8ae268fc
--- /dev/null
+++ b/contrib/nvi/catalog/german.owner
@@ -0,0 +1 @@
+Bernhard Daeubler <daeb@physik.uni-ulm.de>
diff --git a/contrib/nvi/catalog/ru_RU.KOI8-R b/contrib/nvi/catalog/ru_RU.KOI8-R
new file mode 100644
index 000000000000..7eb35b9cf262
--- /dev/null
+++ b/contrib/nvi/catalog/ru_RU.KOI8-R
@@ -0,0 +1,267 @@
+VI_MESSAGE_CATALOG
+pEREPOLNENIE ZNA^ENIQ DLINY STROKIX
+%s/%d: NEWOZMOVNO UDALITX STROKU %uX
+%s/%d: NEWOZMOVNO DOBAWITX K STROKE %uX
+%s/%d: NEWOZMOVNO WSTAWITX W STROKU %uX
+%s/%d: NEWOZMOVNO SOHRANITX STROKU %uX
+%s/%d: NEWOZMOVNO DOSTATX POSLEDN@@ STROKUX
+
+fAJL ZAPISEJX
+zAPISI NE WELISX, NEWOZMOVNO OTMENITX POSLEDN@@ KOMANDUX
+nET IZMENENIJ DLQ OTMENYX
+zAPISI NE WELISX, NEWOZMOVNO OTMENITX POSLEDN@@ KOMANDUX
+zAPISI NE WELISX, NEWOZMOVNO PROSMOTRETX WPEREDX
+nET IZMENENIJ DLQ PEREDELKIX
+%s/%d: O[IBKA PRI ZAPISI PROTOKOLAX
+sTANDARTNYJ WWOD/WYWOD DLQ VI DOLVEN BYTX TERMINALX
+oTMETKA %s: NE USTANOWLENAX
+oTMETKA %s: STROKA BYLA UDALENAX
+oTMETKA %s: POZICII KURSORA BOLX[E NE SU]ESTWUETX
+o[IBKA:X
+
+
+
+
+
+
+
+
+
+fAJL %s NE QWLQETSQ KATALOGOM SOOB]ENIJX
+nEWOZMOVNO USTANOWITX OPCI@ %s PO UMOL^ANI@X
+iSPOLXZOWANIE: %sX
+oPCII %s NET: 'set all' POKAZYWAET WSE WOZMOVNYE OPCIIX
+set: [no]%s NE PRINIMAET TAKOGO ZNA^ENIQX
+set: %s OPCIQ NE QWLQETSQ DWOI^NOJX
+
+
+set: NEPRAWILXNOE ZNA^ENIE %sX
+set: %s OPCIQ NE QWLQETSQ DWOI^NOJX
+kOLI^ESTWO KOLONOK \KRANA SLI[KOM MALO, MENX[E ^EM %dX
+kOLI^ESTWO KOLONOK \KRANA SLI[KOM WELIKO, BOLX[E ^EM %dX
+kOLI^ESTWO STROK \KRANA SLI[KOM MALO, MENX[E ^EM %dX
+kOLI^ESTWO STROK \KRANA SLI[KOM WELIKO, BOLX[E ^EM %dX
+oPCIQ lisp OTSUTSTWUETX
+sOOB]ENIQ NE WYKL@^ENY: %sX
+sOOB]ENIQ NE WKL@^ENY: %sX
+oPCIQ modeline(s) NE MOVET BYTX PEREUSTANOWLENAX
+oPCIQ paragraph DOLVNA SOSTOQTX IZ GRUPP S DWUMQ SIMWOLAMIX
+oPCIQ section DOLVNA SOSTOQTX IZ GRUPP S DWUMQ SIMWOLAMIX
+oPCIQ shiftwidth NE MOVET BYTX USTANOWLENA NA 0X
+oPCIQ sourceany NE MOVET BYTX USTANOWLENAX
+tABULQCIQ NE MOVET BYTX USTANOWLENA NA 0X
+sTARTOWYJ BUFER PUSTX
+bUFER %s PUSTX
+fAJLY S SIMWOLAMI PEREWODA STROKI W IMENI NE MOGUT BYTX WOSSTANOWLENYX
+iZMENENIQ NE SOHRANENY PRI KRAHE SESSIIX
+
+sOHRANENIE NE UDALOSX: %sX
+iZMENENIQ NE SOHRANQ@TSQ PRI OBRYWE SESSIIX
+sOHRANENIE KOPII FAJLA NE UDALOSX: %sX
+
+iNFORMACII NA POLXZOWATELQ %u NE NAJDENOX
+nEWOZMOVNO ZA]ITITX SPASENNYJ FAJLX
+bUFER WOSSTANOWLENNOGO FAJLA PEREPOLNENX
+wOSSTANOWLENNYJ FAJLX
+%s: NE DO KONCA WOSSTANOWLENNYJ FAJLX
+%s: NE DO KONCA WOSSTANOWLENNYJ FAJLX
+fAJLOW S IMENEM %s, KOTORYE wY MOVETE ^ITATX, NE SU]ESTWUETX
+eSTX STARYE WERSII FAJLA, KOTORYE MOVNO WOSSTANOWITXX
+sU]ESTWU@T DRUGIE FAJLY, KOTORYE MOVNO WOSSTANOWITXX
+E-mail NE POSLAN: %sX
+fAJL PUST - ISKATX NE^EGOX
+dOSTIGNUT KONEC FAJLA BEZ NAHOVDENIQ OBRAZCA POISKAX
+nE ZADAN OBRAZEC POISKAX
+oBRAZEC POISKA NE NAJDENX
+dOSTUPNO NA^ALO FAJLA BEZ NAHOVDENIQ OBRAZCA POISKAX
+pOISK ZACIKLENX
+
+nEPE^ATNYH SIMWOLOW NE NAJDENOX
+nEIZWESTNAQ KOMANDAX
+
+kOMANDA NE DOSTUPNA W REVIME exX
+s^ET^IK NE MOVET BYTX NULEMX
+%s: NEPRAWILXNOE UKAZANIE STROKIX
+wNUTRENNQQ O[IBKA W SINTAKSISE (%s: %s)X
+iSPOLXZOWANIE: %sX
+%s: WREMENNYJ BUFER NE ISPOLXZOWANX
+mETKA POSTAWLENA PERED STROKOJ 1X
+mETKA POSTAWLENA POSLE KONCA FAJLAX
+
+
+kOMANDA ex NE UDALASX: PARAMETRY KOMANDY ZABYTYX
+
+wTOROJ ADRES MENX[E ^EM PERWYJX
+nE UKAZANO NAZWANIE OTMETKIX
+\\ NE ZAWER[AETSQ / ILI ?X
+sSYLKA K STROKE S NOMEROM MENX[E 0X
+kOMANDA %s NEIZWESTNAX
+pEREPOLNENIE ZNA^ENIQ ADRESAX
+nEDOBOR ZNA^ENIQ ADRESAX
+nEDOPUSTIMAQ KOMBINACIQ W ADRESEX
+nEPRAWILXNYJ ADRES: WSEGO %lu STROK W FAJLEX
+nEPRAWILXNYJ ADRES: FAJL PUSTX
+kOMMANDA %s NE MOVET ISPOLXZOWATX ADRES 0X
+aBBREWIATURY OTSUTSTWU@TX
+aBBREWIATURY DOLVNY ZAKAN^IWATXSQ SIMWOLOM "word"X
+aBBREWIATURY NE MOGUT SODERVATX SIMWOLOY TABLQCII ILI PROBELYX
+aBBREWIATURY NE MOGUT SO^ETATXSQ S SIMWOLAMI SLOW/NE-SLOW, ZA ISKL@^ENIEM KONCA STROKIX
+"%s" NE QWLQETSQ ABBREWIATUROJX
+
+fAJLOW DLQ REDAKTIROWANIQ BOLX[E NETX
+oTSUTSTWIE PREDYDU]EGO FAJLA DLQ REDAKTIROWANIQX
+oTSUTSTWIE PREDYDU]EGO FAJLA DLQ PROSMOTRA NAZADX
+nET FAJLOWX
+oTSUTSTWIE PREDYDU]EJ KOMANDY DLQ ZAMENY "!"X
+oTSUTSTWIE ZAMENY DLQ %%X
+oTSUTSTWIE ZAMENY DLQ #X
+o[IBKA: execl: %sX
+o[IBKA WWODA/WYWODA: %sX
+fAJL IZMENEN S MOMENTA POSLEDNEJ POLNOJ ZAPISI: ISPOLXZUJTE ! DLQ OBHODAX
+nEWOZMOVNO NAJTI DOMA[NIJ KATALOGX
+nOWYJ KATALOG: %sX
+nET WYREZANYH BUFEROWX
+kOMANDA %s NE MOVET BYTX ISPOLXZOWANA WNUTRI OB]EJ KOMANDYX
+%s/%s: NE OTKRYT: NE PRINADLEVIT wAM ILI root-UX
+%s/%s: NE OTKRYT: NE PRINADLEVIT wAMX
+%s/%s: NE OTKRYT: WOZMOVNOSTX ZAPISI U POLXZOWATELQ, NE QWLQ@]EGOSQ WLADELXCEMX
+%s/%s: NE S^ITAN: NE PRINADLEVIT wAM ILI root-UX
+%s/%s: NE S^ITAN: NE PRINADLEVIT wAMX
+%s/%s: NE S^ITAN: WOZMOVNOSTX ZAPISI U POLXZOWATELQ, NE QWLQ@]EGOSQ WLADELXCEMX
+pOSLEDU@]IE STROKI OTSUTSTWU@TX
+oTSUTSTWIE PARAMETROW WWODAX
+oTSUTSTWIE PARAMETROW KOMANDYX
+sIMWOL %s NE MOVET BYTX PEREZAPOMNENX
+"%s" NA DANNYJ MOMENT NE OTME^ENX
+iMQ METKI DOLVNO BYTX ODNIM SIMWOLOMX
+%s SU]ESTWUET, NE ZAPISAN; ISPOLXZUJTE ! DLQ OBHODAX
+nOWYJ FAJL .exrc: %sX
+sTROKA PERENOSA NAHODITSQ WNUTRI PARAMETROW PERENOSAX
+kOMANDA open PODRAZUMEWAET USTANOWKU OPCII openX
+kOMANDA open NE REALIZOWANAX
+zA]ITA FAJLA NEWOZMOVNAX
+fAJL ZA]I]ENX
+%s RAS[IRILSQ W SLI[KOM BOLX[OE KOLI^ESTWO IMEN FAJLOWX
+
+%s: ZA]ITA NA ^TENIE BYLA NEDOSTUPNAX
+
+%s: %lu STROK, %lu SIMWOLOWX
+nET TENEWYH OKONX
+kOMANDA script ISPOLXZUETSQ TOLXKO W REVIME viX
+nET KOMANDY DLQ ISPOLNENIQX
+oPCIQ shiftwidth USTANOWLENA NA 0X
+pEREPOLNENIE S^ET^IKAX
+cIKL WYPOLNEN NE DO KONCAX
+uKAZANO REGULQRNOE WYRAVENIE: FLAG r NE NUVENX
+fLAGI #, l I p NE MOGUT BYTX OB_EDINENY S FLAGOM c W REVIME viX
+sOWPADENIJ NETX
+mETKA OTSUTSTWUETX
+w STEKE METOK ZAPISEJ MENX[E, ^EM %s, ISPOLXZUJTE :display t[ags]X
+fAJLA S IMENEM %s W STEKE METOK NET; ISPOLXZUJTE :display t[ags]X
+
+%s: METKA NE NAJDENAX
+%s: PLOHAQ METKA W %sX
+
+sTEK METOK PUSTX
+%s: ISKOMAQ PEREMENNAQ NE NAJDENAX
+
+bUFER %s PUSTX
+
+pRERWANOX
+oTSUTSTWIE BUFERA DLQ ISPOLXZOWANIQX
+nET PREDIDU]EGO REGULQRNOGO WYRAVENIQX
+kOMANDA %s PODRAZUMEWAET NALI^IE PRO^TENNOGO FAJLAX
+iSPOLXZOWANIE: %sX
+kOMANDA visual PODRAZUMEWAET OBQZATELXNU@ USTANOWKU OPCII openX
+%s RAS[IRILSQ DO SLI[KOM BOLX[OGO KOLI^ESTWA FAJLOWX
+pUSTOJ FAJLX
+nET PREDYDU]EGO POISKA F, f, T, ILI tX
+%s NE NAJDENOX
+nET PREDYDU]EGO FAJLA DLQ REDAKTIROWANIQX
+kURSOR STOIT NE NA CIFREX
+pOLU^ENNOE ^ISLO SLI[KOM WELIKOX
+pOLU^ENNOE ^ISLO SLI[KOM MALOX
+pODHODQ]EGO SIMWOLA NET NA \TOJ STROKEX
+pODHODQ]IJ SIMWOL NE NAJDENX
+nET SIMWOLOW DLQ UDALENIQX
+dRUGOGO \KRANA NE SU]ESTWUETX
+sIMWOLY POSLE STROKI DLQ POISKA I/ILI PEREBOR STROKIX
+pRO[LYJ OBRAZEC POISKA OTSUTSTWUETX
+pOISK ZAWER[ILSQ NA NA^ALXNOJ POZICIIX
+
+sIMWOL NEPRAWILEN; ZAKL@^EN W KAWY^KI DLQ WWODAX
+uVE NA NA^ALE WSTAWKIX
+nET SIMWOLOW DLQ UDALENIQX
+pEREDWIVENIE ZA KONEC FAJLAX
+pEREDWIVENIE ZA KONEC STROKIX
+dWIVENIE STROKI NE SDELANOX
+uVE NA NA^ALE FAJLAX
+dWIVENIE KURSORA ZA NA^ALO FAJLAX
+uVE W PERWOJ KOLONKEX
+bUFERY DOLVNY BYTX UKAZANY DO WYPOLNENIQ KOMANDYX
+uVE NA KONCE FAJLAX
+uVE NA KONSE STROKIX
+%s NE QWLQETSQ KOMANDOJ VIX
+iSPOLXZOWANIE: %sX
+nET SIMWOLOW DLQ UDALENIQX
+
+nET KOMANDY DLQ POWTORAX
+
+kOMANDA %s NE MOVET BYTX ISPOLXZOWANA KAK KOMANDA PRODWIVENIQX
+~ISLO BOLX[E ^EM %luX
+
+
+zNA^ENIE KOLI^ESTWA OKON SLI[KOM WELIKO, MAKSIMALXNOE ZNA^ENIE = %uX
+
+
+
+
+
+dWIVENIE KURSORA ZA KONEC \KRANAX
+dWIVENIE KURSORA ZA NA^ALO \KRANAX
+
+tENEWYH OKON NETX
+nE SU]ESTWUET TENEWOGO OKNA S REDAKTIROWANIEM FAJLA %sX
+wY NE MOVETE SDELATX EDINSTWENNOE OKNO TENEWYMX
+|KRAN MOVET BYTX SVATX
+|KRAN NE MOVET BYTX SVATX
+|KRAN NE MOVET BYTX RAS[IRENX
+
+
+
+
+dANNYJ TIP TERMINALA NE IMEET KLAWI[I %sX
+
+
+
+nEWOZMOVNO SOZDATX WREMENNYJ FAJLX
+wNIMANIE: %s SPECIALXNYJ FAJLX
+%s UVE ZABLOKIROWAN, DOSTUPEN TOLXKO NA ^TENIEX
+%s: UDALENX
+%s: ZAKRYTX
+%s: UDALENX
+%s: UDALENX
+fAJL TOLXKO DLQ ^TENIQ, NE ZAPISAN: iSPOLXZUJTE ! DLQ OBHODAX
+fAJL TOLXKO DLQ ^TENIQ, NE ZAPISANX
+%s SU]ESTWUET, NE ZAPISAN; ISPOLXZUJTE ! DLQ OBHODAX
+%s SU]ESTWUET, NE ZAPISANX
+iSPOLXZUJTE ! DLQ ^ASTI^NOJ ZAPISI FAJLAX
+~ASTX FAJLA, FAJL NE ZAPISANX
+%s: fAJL IZMENQLSQ POZDNEE, ^EM DANNAQ KOPIQ: ISPOLXZUJTE ! DLQ OBHODAX
+%s: fAJL IZMENQLSQ POZDNEE, ^EM DANNAQ KOPIQX
+%s: ZA]ITA NA ZAPISX BYLA NEDOSTUPNAX
+
+%s: wnimanie: fajl use~enX
+
+%s: NOWYJ FAJL: %lu STROK, %lu SIMWOLOWX
+%s: %lu STROK, %lu SIMWOLOWX
+%s RAS[IRILSQ W SLI[KOM BOLX[OE KOLI^ESTWO IMEN FAJLOWX
+%s SPECIALXNYJ FAJLX
+%s: NE PRINADLEVIT wAMX
+%s: DOSTUPEN NE TOLXKO wAMX
+fAJL IZMENEN SO WREMENI POSLEDNEJ ZAPISI: SOHRANITE ILI ISPOLXZUJTE ! DLQ OBHODAX
+fAJL IZMENEN SO WREMENI POSLEDNEJ ZAPISI: SOHRANITE ILI ISPOLXZUJTE :edit DLQ OBHODAX
+fAJL IZMENEN SO WREMENI POSLEDNEJ ZAPISI: SOHRANITE ILI ISPOLXZUJTE ! DLQ OBHODAX
+fAJL WREMENNYJ: WYHOD SOTRET L@BYE IZMENENIQX
+
+zAPISI NA^ATY ZANOWOX
diff --git a/contrib/nvi/catalog/ru_RU.KOI8-R.base b/contrib/nvi/catalog/ru_RU.KOI8-R.base
new file mode 100644
index 000000000000..59efd3f53a5f
--- /dev/null
+++ b/contrib/nvi/catalog/ru_RU.KOI8-R.base
@@ -0,0 +1,219 @@
+002 "pEREPOLNENIE ZNA^ENIQ DLINY STROKI"
+003 "%s/%d: NEWOZMOVNO UDALITX STROKU %u"
+004 "%s/%d: NEWOZMOVNO DOBAWITX K STROKE %u"
+005 "%s/%d: NEWOZMOVNO WSTAWITX W STROKU %u"
+006 "%s/%d: NEWOZMOVNO SOHRANITX STROKU %u"
+007 "%s/%d: NEWOZMOVNO DOSTATX POSLEDN@@ STROKU"
+009 "fAJL ZAPISEJ"
+010 "zAPISI NE WELISX, NEWOZMOVNO OTMENITX POSLEDN@@ KOMANDU"
+011 "nET IZMENENIJ DLQ OTMENY"
+012 "zAPISI NE WELISX, NEWOZMOVNO OTMENITX POSLEDN@@ KOMANDU"
+013 "zAPISI NE WELISX, NEWOZMOVNO PROSMOTRETX WPERED"
+014 "nET IZMENENIJ DLQ PEREDELKI"
+015 "%s/%d: O[IBKA PRI ZAPISI PROTOKOLA"
+016 "sTANDARTNYJ WWOD/WYWOD DLQ VI DOLVEN BYTX TERMINAL"
+017 "oTMETKA %s: NE USTANOWLENA"
+018 "oTMETKA %s: STROKA BYLA UDALENA"
+019 "oTMETKA %s: POZICII KURSORA BOLX[E NE SU]ESTWUET"
+020 "o[IBKA:"
+030 "fAJL %s NE QWLQETSQ KATALOGOM SOOB]ENIJ"
+031 "nEWOZMOVNO USTANOWITX OPCI@ %s PO UMOL^ANI@"
+032 "iSPOLXZOWANIE: %s"
+033 "oPCII %s NET: 'set all' POKAZYWAET WSE WOZMOVNYE OPCII"
+034 "set: [no]%s NE PRINIMAET TAKOGO ZNA^ENIQ"
+035 "set: %s OPCIQ NE QWLQETSQ DWOI^NOJ"
+038 "set: NEPRAWILXNOE ZNA^ENIE %s"
+039 "set: %s OPCIQ NE QWLQETSQ DWOI^NOJ"
+040 "kOLI^ESTWO KOLONOK \KRANA SLI[KOM MALO, MENX[E ^EM %d"
+041 "kOLI^ESTWO KOLONOK \KRANA SLI[KOM WELIKO, BOLX[E ^EM %d"
+042 "kOLI^ESTWO STROK \KRANA SLI[KOM MALO, MENX[E ^EM %d"
+043 "kOLI^ESTWO STROK \KRANA SLI[KOM WELIKO, BOLX[E ^EM %d"
+044 "oPCIQ lisp OTSUTSTWUET"
+045 "sOOB]ENIQ NE WYKL@^ENY: %s"
+046 "sOOB]ENIQ NE WKL@^ENY: %s"
+047 "oPCIQ modeline(s) NE MOVET BYTX PEREUSTANOWLENA"
+048 "oPCIQ paragraph DOLVNA SOSTOQTX IZ GRUPP S DWUMQ SIMWOLAMI"
+049 "oPCIQ section DOLVNA SOSTOQTX IZ GRUPP S DWUMQ SIMWOLAMI"
+050 "oPCIQ shiftwidth NE MOVET BYTX USTANOWLENA NA 0"
+051 "oPCIQ sourceany NE MOVET BYTX USTANOWLENA"
+052 "tABULQCIQ NE MOVET BYTX USTANOWLENA NA 0"
+053 "sTARTOWYJ BUFER PUST"
+054 "bUFER %s PUST"
+055 "fAJLY S SIMWOLAMI PEREWODA STROKI W IMENI NE MOGUT BYTX WOSSTANOWLENY"
+056 "iZMENENIQ NE SOHRANENY PRI KRAHE SESSII"
+058 "sOHRANENIE NE UDALOSX: %s"
+059 "iZMENENIQ NE SOHRANQ@TSQ PRI OBRYWE SESSII"
+060 "sOHRANENIE KOPII FAJLA NE UDALOSX: %s"
+062 "iNFORMACII NA POLXZOWATELQ %u NE NAJDENO"
+063 "nEWOZMOVNO ZA]ITITX SPASENNYJ FAJL"
+064 "bUFER WOSSTANOWLENNOGO FAJLA PEREPOLNEN"
+065 "wOSSTANOWLENNYJ FAJL"
+066 "%s: NE DO KONCA WOSSTANOWLENNYJ FAJL"
+067 "%s: NE DO KONCA WOSSTANOWLENNYJ FAJL"
+068 "fAJLOW S IMENEM %s, KOTORYE wY MOVETE ^ITATX, NE SU]ESTWUET"
+069 "eSTX STARYE WERSII FAJLA, KOTORYE MOVNO WOSSTANOWITX"
+070 "sU]ESTWU@T DRUGIE FAJLY, KOTORYE MOVNO WOSSTANOWITX"
+071 "E-mail NE POSLAN: %s"
+072 "fAJL PUST - ISKATX NE^EGO"
+073 "dOSTIGNUT KONEC FAJLA BEZ NAHOVDENIQ OBRAZCA POISKA"
+074 "nE ZADAN OBRAZEC POISKA"
+075 "oBRAZEC POISKA NE NAJDEN"
+076 "dOSTUPNO NA^ALO FAJLA BEZ NAHOVDENIQ OBRAZCA POISKA"
+077 "pOISK ZACIKLEN"
+079 "nEPE^ATNYH SIMWOLOW NE NAJDENO"
+080 "nEIZWESTNAQ KOMANDA"
+082 "kOMANDA NE DOSTUPNA W REVIME ex"
+083 "s^ET^IK NE MOVET BYTX NULEM"
+084 "%s: NEPRAWILXNOE UKAZANIE STROKI"
+085 "wNUTRENNQQ O[IBKA W SINTAKSISE (%s: %s)"
+086 "iSPOLXZOWANIE: %s"
+087 "%s: WREMENNYJ BUFER NE ISPOLXZOWAN"
+088 "mETKA POSTAWLENA PERED STROKOJ 1"
+089 "mETKA POSTAWLENA POSLE KONCA FAJLA"
+092 "kOMANDA ex NE UDALASX: PARAMETRY KOMANDY ZABYTY"
+094 "wTOROJ ADRES MENX[E ^EM PERWYJ"
+095 "nE UKAZANO NAZWANIE OTMETKI"
+096 "\\ NE ZAWER[AETSQ / ILI ?"
+097 "sSYLKA K STROKE S NOMEROM MENX[E 0"
+098 "kOMANDA %s NEIZWESTNA"
+099 "pEREPOLNENIE ZNA^ENIQ ADRESA"
+100 "nEDOBOR ZNA^ENIQ ADRESA"
+101 "nEDOPUSTIMAQ KOMBINACIQ W ADRESE"
+102 "nEPRAWILXNYJ ADRES: WSEGO %lu STROK W FAJLE"
+103 "nEPRAWILXNYJ ADRES: FAJL PUST"
+104 "kOMMANDA %s NE MOVET ISPOLXZOWATX ADRES 0"
+105 "aBBREWIATURY OTSUTSTWU@T"
+106 "aBBREWIATURY DOLVNY ZAKAN^IWATXSQ SIMWOLOM "word""
+107 "aBBREWIATURY NE MOGUT SODERVATX SIMWOLOY TABLQCII ILI PROBELY"
+108 "aBBREWIATURY NE MOGUT SO^ETATXSQ S SIMWOLAMI SLOW/NE-SLOW, ZA ISKL@^ENIEM KONCA STROKI"
+109 ""%s" NE QWLQETSQ ABBREWIATUROJ"
+111 "fAJLOW DLQ REDAKTIROWANIQ BOLX[E NET"
+112 "oTSUTSTWIE PREDYDU]EGO FAJLA DLQ REDAKTIROWANIQ"
+113 "oTSUTSTWIE PREDYDU]EGO FAJLA DLQ PROSMOTRA NAZAD"
+114 "nET FAJLOW"
+115 "oTSUTSTWIE PREDYDU]EJ KOMANDY DLQ ZAMENY "!""
+116 "oTSUTSTWIE ZAMENY DLQ %%"
+117 "oTSUTSTWIE ZAMENY DLQ #"
+118 "o[IBKA: execl: %s"
+119 "o[IBKA WWODA/WYWODA: %s"
+120 "fAJL IZMENEN S MOMENTA POSLEDNEJ POLNOJ ZAPISI: ISPOLXZUJTE ! DLQ OBHODA"
+121 "nEWOZMOVNO NAJTI DOMA[NIJ KATALOG"
+122 "nOWYJ KATALOG: %s"
+123 "nET WYREZANYH BUFEROW"
+124 "kOMANDA %s NE MOVET BYTX ISPOLXZOWANA WNUTRI OB]EJ KOMANDY"
+125 "%s/%s: NE OTKRYT: NE PRINADLEVIT wAM ILI root-U"
+126 "%s/%s: NE OTKRYT: NE PRINADLEVIT wAM"
+127 "%s/%s: NE OTKRYT: WOZMOVNOSTX ZAPISI U POLXZOWATELQ, NE QWLQ@]EGOSQ WLADELXCEM"
+128 "%s/%s: NE S^ITAN: NE PRINADLEVIT wAM ILI root-U"
+129 "%s/%s: NE S^ITAN: NE PRINADLEVIT wAM"
+130 "%s/%s: NE S^ITAN: WOZMOVNOSTX ZAPISI U POLXZOWATELQ, NE QWLQ@]EGOSQ WLADELXCEM"
+131 "pOSLEDU@]IE STROKI OTSUTSTWU@T"
+132 "oTSUTSTWIE PARAMETROW WWODA"
+133 "oTSUTSTWIE PARAMETROW KOMANDY"
+134 "sIMWOL %s NE MOVET BYTX PEREZAPOMNEN"
+135 ""%s" NA DANNYJ MOMENT NE OTME^EN"
+136 "iMQ METKI DOLVNO BYTX ODNIM SIMWOLOM"
+137 "%s SU]ESTWUET, NE ZAPISAN; ISPOLXZUJTE ! DLQ OBHODA"
+138 "nOWYJ FAJL .exrc: %s"
+139 "sTROKA PERENOSA NAHODITSQ WNUTRI PARAMETROW PERENOSA"
+140 "kOMANDA open PODRAZUMEWAET USTANOWKU OPCII open"
+141 "kOMANDA open NE REALIZOWANA"
+142 "zA]ITA FAJLA NEWOZMOVNA"
+143 "fAJL ZA]I]EN"
+144 "%s RAS[IRILSQ W SLI[KOM BOLX[OE KOLI^ESTWO IMEN FAJLOW"
+146 "%s: ZA]ITA NA ^TENIE BYLA NEDOSTUPNA"
+148 "%s: %lu STROK, %lu SIMWOLOW"
+149 "nET TENEWYH OKON"
+150 "kOMANDA script ISPOLXZUETSQ TOLXKO W REVIME vi"
+151 "nET KOMANDY DLQ ISPOLNENIQ"
+152 "oPCIQ shiftwidth USTANOWLENA NA 0"
+153 "pEREPOLNENIE S^ET^IKA"
+154 "cIKL WYPOLNEN NE DO KONCA"
+155 "uKAZANO REGULQRNOE WYRAVENIE: FLAG r NE NUVEN"
+156 "fLAGI #, l I p NE MOGUT BYTX OB_EDINENY S FLAGOM c W REVIME vi"
+157 "sOWPADENIJ NET"
+158 "mETKA OTSUTSTWUET"
+159 "w STEKE METOK ZAPISEJ MENX[E, ^EM %s, ISPOLXZUJTE :display t[ags]"
+160 "fAJLA S IMENEM %s W STEKE METOK NET; ISPOLXZUJTE :display t[ags]"
+162 "%s: METKA NE NAJDENA"
+163 "%s: PLOHAQ METKA W %s"
+165 "sTEK METOK PUST"
+166 "%s: ISKOMAQ PEREMENNAQ NE NAJDENA"
+168 "bUFER %s PUST"
+170 "pRERWANO"
+171 "oTSUTSTWIE BUFERA DLQ ISPOLXZOWANIQ"
+172 "nET PREDIDU]EGO REGULQRNOGO WYRAVENIQ"
+173 "kOMANDA %s PODRAZUMEWAET NALI^IE PRO^TENNOGO FAJLA"
+174 "iSPOLXZOWANIE: %s"
+175 "kOMANDA visual PODRAZUMEWAET OBQZATELXNU@ USTANOWKU OPCII open"
+176 "%s RAS[IRILSQ DO SLI[KOM BOLX[OGO KOLI^ESTWA FAJLOW"
+177 "pUSTOJ FAJL"
+178 "nET PREDYDU]EGO POISKA F, f, T, ILI t"
+179 "%s NE NAJDENO"
+180 "nET PREDYDU]EGO FAJLA DLQ REDAKTIROWANIQ"
+181 "kURSOR STOIT NE NA CIFRE"
+182 "pOLU^ENNOE ^ISLO SLI[KOM WELIKO"
+183 "pOLU^ENNOE ^ISLO SLI[KOM MALO"
+184 "pODHODQ]EGO SIMWOLA NET NA \TOJ STROKE"
+185 "pODHODQ]IJ SIMWOL NE NAJDEN"
+186 "nET SIMWOLOW DLQ UDALENIQ"
+187 "dRUGOGO \KRANA NE SU]ESTWUET"
+188 "sIMWOLY POSLE STROKI DLQ POISKA I/ILI PEREBOR STROKI"
+189 "pRO[LYJ OBRAZEC POISKA OTSUTSTWUET"
+190 "pOISK ZAWER[ILSQ NA NA^ALXNOJ POZICII"
+192 "sIMWOL NEPRAWILEN; ZAKL@^EN W KAWY^KI DLQ WWODA"
+193 "uVE NA NA^ALE WSTAWKI"
+194 "nET SIMWOLOW DLQ UDALENIQ"
+195 "pEREDWIVENIE ZA KONEC FAJLA"
+196 "pEREDWIVENIE ZA KONEC STROKI"
+197 "dWIVENIE STROKI NE SDELANO"
+198 "uVE NA NA^ALE FAJLA"
+199 "dWIVENIE KURSORA ZA NA^ALO FAJLA"
+200 "uVE W PERWOJ KOLONKE"
+201 "bUFERY DOLVNY BYTX UKAZANY DO WYPOLNENIQ KOMANDY"
+202 "uVE NA KONCE FAJLA"
+203 "uVE NA KONSE STROKI"
+204 "%s NE QWLQETSQ KOMANDOJ VI"
+205 "iSPOLXZOWANIE: %s"
+206 "nET SIMWOLOW DLQ UDALENIQ"
+208 "nET KOMANDY DLQ POWTORA"
+210 "kOMANDA %s NE MOVET BYTX ISPOLXZOWANA KAK KOMANDA PRODWIVENIQ"
+211 "~ISLO BOLX[E ^EM %lu"
+214 "zNA^ENIE KOLI^ESTWA OKON SLI[KOM WELIKO, MAKSIMALXNOE ZNA^ENIE = %u"
+220 "dWIVENIE KURSORA ZA KONEC \KRANA"
+221 "dWIVENIE KURSORA ZA NA^ALO \KRANA"
+223 "tENEWYH OKON NET"
+224 "nE SU]ESTWUET TENEWOGO OKNA S REDAKTIROWANIEM FAJLA %s"
+225 "wY NE MOVETE SDELATX EDINSTWENNOE OKNO TENEWYM"
+226 "|KRAN MOVET BYTX SVAT"
+227 "|KRAN NE MOVET BYTX SVAT"
+228 "|KRAN NE MOVET BYTX RAS[IREN"
+233 "dANNYJ TIP TERMINALA NE IMEET KLAWI[I %s"
+237 "nEWOZMOVNO SOZDATX WREMENNYJ FAJL"
+238 "wNIMANIE: %s SPECIALXNYJ FAJL"
+239 "%s UVE ZABLOKIROWAN, DOSTUPEN TOLXKO NA ^TENIE"
+240 "%s: UDALEN"
+241 "%s: ZAKRYT"
+242 "%s: UDALEN"
+243 "%s: UDALEN"
+244 "fAJL TOLXKO DLQ ^TENIQ, NE ZAPISAN: iSPOLXZUJTE ! DLQ OBHODA"
+245 "fAJL TOLXKO DLQ ^TENIQ, NE ZAPISAN"
+246 "%s SU]ESTWUET, NE ZAPISAN; ISPOLXZUJTE ! DLQ OBHODA"
+247 "%s SU]ESTWUET, NE ZAPISAN"
+248 "iSPOLXZUJTE ! DLQ ^ASTI^NOJ ZAPISI FAJLA"
+249 "~ASTX FAJLA, FAJL NE ZAPISAN"
+250 "%s: fAJL IZMENQLSQ POZDNEE, ^EM DANNAQ KOPIQ: ISPOLXZUJTE ! DLQ OBHODA"
+251 "%s: fAJL IZMENQLSQ POZDNEE, ^EM DANNAQ KOPIQ"
+252 "%s: ZA]ITA NA ZAPISX BYLA NEDOSTUPNA"
+254 "%s: wnimanie: fajl use~en"
+256 "%s: NOWYJ FAJL: %lu STROK, %lu SIMWOLOW"
+257 "%s: %lu STROK, %lu SIMWOLOW"
+258 "%s RAS[IRILSQ W SLI[KOM BOLX[OE KOLI^ESTWO IMEN FAJLOW"
+259 "%s SPECIALXNYJ FAJL"
+260 "%s: NE PRINADLEVIT wAM"
+261 "%s: DOSTUPEN NE TOLXKO wAM"
+262 "fAJL IZMENEN SO WREMENI POSLEDNEJ ZAPISI: SOHRANITE ILI ISPOLXZUJTE ! DLQ OBHODA"
+263 "fAJL IZMENEN SO WREMENI POSLEDNEJ ZAPISI: SOHRANITE ILI ISPOLXZUJTE :edit DLQ OBHODA"
+264 "fAJL IZMENEN SO WREMENI POSLEDNEJ ZAPISI: SOHRANITE ILI ISPOLXZUJTE ! DLQ OBHODA"
+265 "fAJL WREMENNYJ: WYHOD SOTRET L@BYE IZMENENIQ"
+267 "zAPISI NA^ATY ZANOWO"
diff --git a/contrib/nvi/catalog/ru_RU.KOI8-R.check b/contrib/nvi/catalog/ru_RU.KOI8-R.check
new file mode 100644
index 000000000000..ca77b891051a
--- /dev/null
+++ b/contrib/nvi/catalog/ru_RU.KOI8-R.check
@@ -0,0 +1,169 @@
+Unused message id's (this is okay):
+001
+008
+021
+022
+023
+024
+025
+026
+027
+028
+029
+036
+037
+057
+061
+078
+081
+090
+091
+093
+110
+145
+147
+161
+164
+167
+169
+191
+207
+209
+212
+213
+215
+216
+217
+218
+219
+222
+229
+230
+231
+232
+234
+235
+236
+253
+255
+266
+=========================
+MISSING ERROR MESSAGES (Please add!):
+008
+021
+022
+023
+024
+025
+026
+027
+028
+029
+036
+037
+057
+061
+078
+090
+091
+093
+110
+145
+147
+161
+164
+167
+169
+191
+207
+209
+212
+215
+216
+217
+218
+219
+222
+230
+231
+232
+234
+235
+236
+253
+255
+266
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+=========================
+Extra error messages (just delete them):
+047
+050
+051
+052
+176
+=========================
+MESSAGES WITH THE SAME MESSAGE ID's (FIX!):
+=========================
+Duplicate messages, both id and message (this is okay):
+=========================
+Duplicate messages, just message (this is okay):
+ 2 %s RAS[IRILSQ W SLI[KOM BOLX[OE KOLI^ESTWO IMEN FAJLOWX
+ 2 %s SU]ESTWUET, NE ZAPISAN; ISPOLXZUJTE ! DLQ OBHODAX
+ 2 %s: %lu STROK, %lu SIMWOLOWX
+ 2 %s: NE DO KONCA WOSSTANOWLENNYJ FAJLX
+ 2 bUFER %s PUSTX
+ 2 fAJL IZMENEN SO WREMENI POSLEDNEJ ZAPISI: SOHRANITE ILI ISPOLXZUJTE ! DLQ OBHODAX
+ 2 set: %s OPCIQ NE QWLQETSQ DWOI^NOJX
+ 2 zAPISI NE WELISX, NEWOZMOVNO OTMENITX POSLEDN@@ KOMANDUX
+ 3 %s: UDALENX
+ 3 nET SIMWOLOW DLQ UDALENIQX
+ 4 iSPOLXZOWANIE: %sX
+=========================
diff --git a/contrib/nvi/catalog/ru_RU.KOI8-R.owner b/contrib/nvi/catalog/ru_RU.KOI8-R.owner
new file mode 100644
index 000000000000..bf4fa180298c
--- /dev/null
+++ b/contrib/nvi/catalog/ru_RU.KOI8-R.owner
@@ -0,0 +1 @@
+Dima Ruban <dima@demos.su>
diff --git a/contrib/nvi/catalog/ru_SU.KOI8-R b/contrib/nvi/catalog/ru_SU.KOI8-R
new file mode 100644
index 000000000000..7eb35b9cf262
--- /dev/null
+++ b/contrib/nvi/catalog/ru_SU.KOI8-R
@@ -0,0 +1,267 @@
+VI_MESSAGE_CATALOG
+pEREPOLNENIE ZNA^ENIQ DLINY STROKIX
+%s/%d: NEWOZMOVNO UDALITX STROKU %uX
+%s/%d: NEWOZMOVNO DOBAWITX K STROKE %uX
+%s/%d: NEWOZMOVNO WSTAWITX W STROKU %uX
+%s/%d: NEWOZMOVNO SOHRANITX STROKU %uX
+%s/%d: NEWOZMOVNO DOSTATX POSLEDN@@ STROKUX
+
+fAJL ZAPISEJX
+zAPISI NE WELISX, NEWOZMOVNO OTMENITX POSLEDN@@ KOMANDUX
+nET IZMENENIJ DLQ OTMENYX
+zAPISI NE WELISX, NEWOZMOVNO OTMENITX POSLEDN@@ KOMANDUX
+zAPISI NE WELISX, NEWOZMOVNO PROSMOTRETX WPEREDX
+nET IZMENENIJ DLQ PEREDELKIX
+%s/%d: O[IBKA PRI ZAPISI PROTOKOLAX
+sTANDARTNYJ WWOD/WYWOD DLQ VI DOLVEN BYTX TERMINALX
+oTMETKA %s: NE USTANOWLENAX
+oTMETKA %s: STROKA BYLA UDALENAX
+oTMETKA %s: POZICII KURSORA BOLX[E NE SU]ESTWUETX
+o[IBKA:X
+
+
+
+
+
+
+
+
+
+fAJL %s NE QWLQETSQ KATALOGOM SOOB]ENIJX
+nEWOZMOVNO USTANOWITX OPCI@ %s PO UMOL^ANI@X
+iSPOLXZOWANIE: %sX
+oPCII %s NET: 'set all' POKAZYWAET WSE WOZMOVNYE OPCIIX
+set: [no]%s NE PRINIMAET TAKOGO ZNA^ENIQX
+set: %s OPCIQ NE QWLQETSQ DWOI^NOJX
+
+
+set: NEPRAWILXNOE ZNA^ENIE %sX
+set: %s OPCIQ NE QWLQETSQ DWOI^NOJX
+kOLI^ESTWO KOLONOK \KRANA SLI[KOM MALO, MENX[E ^EM %dX
+kOLI^ESTWO KOLONOK \KRANA SLI[KOM WELIKO, BOLX[E ^EM %dX
+kOLI^ESTWO STROK \KRANA SLI[KOM MALO, MENX[E ^EM %dX
+kOLI^ESTWO STROK \KRANA SLI[KOM WELIKO, BOLX[E ^EM %dX
+oPCIQ lisp OTSUTSTWUETX
+sOOB]ENIQ NE WYKL@^ENY: %sX
+sOOB]ENIQ NE WKL@^ENY: %sX
+oPCIQ modeline(s) NE MOVET BYTX PEREUSTANOWLENAX
+oPCIQ paragraph DOLVNA SOSTOQTX IZ GRUPP S DWUMQ SIMWOLAMIX
+oPCIQ section DOLVNA SOSTOQTX IZ GRUPP S DWUMQ SIMWOLAMIX
+oPCIQ shiftwidth NE MOVET BYTX USTANOWLENA NA 0X
+oPCIQ sourceany NE MOVET BYTX USTANOWLENAX
+tABULQCIQ NE MOVET BYTX USTANOWLENA NA 0X
+sTARTOWYJ BUFER PUSTX
+bUFER %s PUSTX
+fAJLY S SIMWOLAMI PEREWODA STROKI W IMENI NE MOGUT BYTX WOSSTANOWLENYX
+iZMENENIQ NE SOHRANENY PRI KRAHE SESSIIX
+
+sOHRANENIE NE UDALOSX: %sX
+iZMENENIQ NE SOHRANQ@TSQ PRI OBRYWE SESSIIX
+sOHRANENIE KOPII FAJLA NE UDALOSX: %sX
+
+iNFORMACII NA POLXZOWATELQ %u NE NAJDENOX
+nEWOZMOVNO ZA]ITITX SPASENNYJ FAJLX
+bUFER WOSSTANOWLENNOGO FAJLA PEREPOLNENX
+wOSSTANOWLENNYJ FAJLX
+%s: NE DO KONCA WOSSTANOWLENNYJ FAJLX
+%s: NE DO KONCA WOSSTANOWLENNYJ FAJLX
+fAJLOW S IMENEM %s, KOTORYE wY MOVETE ^ITATX, NE SU]ESTWUETX
+eSTX STARYE WERSII FAJLA, KOTORYE MOVNO WOSSTANOWITXX
+sU]ESTWU@T DRUGIE FAJLY, KOTORYE MOVNO WOSSTANOWITXX
+E-mail NE POSLAN: %sX
+fAJL PUST - ISKATX NE^EGOX
+dOSTIGNUT KONEC FAJLA BEZ NAHOVDENIQ OBRAZCA POISKAX
+nE ZADAN OBRAZEC POISKAX
+oBRAZEC POISKA NE NAJDENX
+dOSTUPNO NA^ALO FAJLA BEZ NAHOVDENIQ OBRAZCA POISKAX
+pOISK ZACIKLENX
+
+nEPE^ATNYH SIMWOLOW NE NAJDENOX
+nEIZWESTNAQ KOMANDAX
+
+kOMANDA NE DOSTUPNA W REVIME exX
+s^ET^IK NE MOVET BYTX NULEMX
+%s: NEPRAWILXNOE UKAZANIE STROKIX
+wNUTRENNQQ O[IBKA W SINTAKSISE (%s: %s)X
+iSPOLXZOWANIE: %sX
+%s: WREMENNYJ BUFER NE ISPOLXZOWANX
+mETKA POSTAWLENA PERED STROKOJ 1X
+mETKA POSTAWLENA POSLE KONCA FAJLAX
+
+
+kOMANDA ex NE UDALASX: PARAMETRY KOMANDY ZABYTYX
+
+wTOROJ ADRES MENX[E ^EM PERWYJX
+nE UKAZANO NAZWANIE OTMETKIX
+\\ NE ZAWER[AETSQ / ILI ?X
+sSYLKA K STROKE S NOMEROM MENX[E 0X
+kOMANDA %s NEIZWESTNAX
+pEREPOLNENIE ZNA^ENIQ ADRESAX
+nEDOBOR ZNA^ENIQ ADRESAX
+nEDOPUSTIMAQ KOMBINACIQ W ADRESEX
+nEPRAWILXNYJ ADRES: WSEGO %lu STROK W FAJLEX
+nEPRAWILXNYJ ADRES: FAJL PUSTX
+kOMMANDA %s NE MOVET ISPOLXZOWATX ADRES 0X
+aBBREWIATURY OTSUTSTWU@TX
+aBBREWIATURY DOLVNY ZAKAN^IWATXSQ SIMWOLOM "word"X
+aBBREWIATURY NE MOGUT SODERVATX SIMWOLOY TABLQCII ILI PROBELYX
+aBBREWIATURY NE MOGUT SO^ETATXSQ S SIMWOLAMI SLOW/NE-SLOW, ZA ISKL@^ENIEM KONCA STROKIX
+"%s" NE QWLQETSQ ABBREWIATUROJX
+
+fAJLOW DLQ REDAKTIROWANIQ BOLX[E NETX
+oTSUTSTWIE PREDYDU]EGO FAJLA DLQ REDAKTIROWANIQX
+oTSUTSTWIE PREDYDU]EGO FAJLA DLQ PROSMOTRA NAZADX
+nET FAJLOWX
+oTSUTSTWIE PREDYDU]EJ KOMANDY DLQ ZAMENY "!"X
+oTSUTSTWIE ZAMENY DLQ %%X
+oTSUTSTWIE ZAMENY DLQ #X
+o[IBKA: execl: %sX
+o[IBKA WWODA/WYWODA: %sX
+fAJL IZMENEN S MOMENTA POSLEDNEJ POLNOJ ZAPISI: ISPOLXZUJTE ! DLQ OBHODAX
+nEWOZMOVNO NAJTI DOMA[NIJ KATALOGX
+nOWYJ KATALOG: %sX
+nET WYREZANYH BUFEROWX
+kOMANDA %s NE MOVET BYTX ISPOLXZOWANA WNUTRI OB]EJ KOMANDYX
+%s/%s: NE OTKRYT: NE PRINADLEVIT wAM ILI root-UX
+%s/%s: NE OTKRYT: NE PRINADLEVIT wAMX
+%s/%s: NE OTKRYT: WOZMOVNOSTX ZAPISI U POLXZOWATELQ, NE QWLQ@]EGOSQ WLADELXCEMX
+%s/%s: NE S^ITAN: NE PRINADLEVIT wAM ILI root-UX
+%s/%s: NE S^ITAN: NE PRINADLEVIT wAMX
+%s/%s: NE S^ITAN: WOZMOVNOSTX ZAPISI U POLXZOWATELQ, NE QWLQ@]EGOSQ WLADELXCEMX
+pOSLEDU@]IE STROKI OTSUTSTWU@TX
+oTSUTSTWIE PARAMETROW WWODAX
+oTSUTSTWIE PARAMETROW KOMANDYX
+sIMWOL %s NE MOVET BYTX PEREZAPOMNENX
+"%s" NA DANNYJ MOMENT NE OTME^ENX
+iMQ METKI DOLVNO BYTX ODNIM SIMWOLOMX
+%s SU]ESTWUET, NE ZAPISAN; ISPOLXZUJTE ! DLQ OBHODAX
+nOWYJ FAJL .exrc: %sX
+sTROKA PERENOSA NAHODITSQ WNUTRI PARAMETROW PERENOSAX
+kOMANDA open PODRAZUMEWAET USTANOWKU OPCII openX
+kOMANDA open NE REALIZOWANAX
+zA]ITA FAJLA NEWOZMOVNAX
+fAJL ZA]I]ENX
+%s RAS[IRILSQ W SLI[KOM BOLX[OE KOLI^ESTWO IMEN FAJLOWX
+
+%s: ZA]ITA NA ^TENIE BYLA NEDOSTUPNAX
+
+%s: %lu STROK, %lu SIMWOLOWX
+nET TENEWYH OKONX
+kOMANDA script ISPOLXZUETSQ TOLXKO W REVIME viX
+nET KOMANDY DLQ ISPOLNENIQX
+oPCIQ shiftwidth USTANOWLENA NA 0X
+pEREPOLNENIE S^ET^IKAX
+cIKL WYPOLNEN NE DO KONCAX
+uKAZANO REGULQRNOE WYRAVENIE: FLAG r NE NUVENX
+fLAGI #, l I p NE MOGUT BYTX OB_EDINENY S FLAGOM c W REVIME viX
+sOWPADENIJ NETX
+mETKA OTSUTSTWUETX
+w STEKE METOK ZAPISEJ MENX[E, ^EM %s, ISPOLXZUJTE :display t[ags]X
+fAJLA S IMENEM %s W STEKE METOK NET; ISPOLXZUJTE :display t[ags]X
+
+%s: METKA NE NAJDENAX
+%s: PLOHAQ METKA W %sX
+
+sTEK METOK PUSTX
+%s: ISKOMAQ PEREMENNAQ NE NAJDENAX
+
+bUFER %s PUSTX
+
+pRERWANOX
+oTSUTSTWIE BUFERA DLQ ISPOLXZOWANIQX
+nET PREDIDU]EGO REGULQRNOGO WYRAVENIQX
+kOMANDA %s PODRAZUMEWAET NALI^IE PRO^TENNOGO FAJLAX
+iSPOLXZOWANIE: %sX
+kOMANDA visual PODRAZUMEWAET OBQZATELXNU@ USTANOWKU OPCII openX
+%s RAS[IRILSQ DO SLI[KOM BOLX[OGO KOLI^ESTWA FAJLOWX
+pUSTOJ FAJLX
+nET PREDYDU]EGO POISKA F, f, T, ILI tX
+%s NE NAJDENOX
+nET PREDYDU]EGO FAJLA DLQ REDAKTIROWANIQX
+kURSOR STOIT NE NA CIFREX
+pOLU^ENNOE ^ISLO SLI[KOM WELIKOX
+pOLU^ENNOE ^ISLO SLI[KOM MALOX
+pODHODQ]EGO SIMWOLA NET NA \TOJ STROKEX
+pODHODQ]IJ SIMWOL NE NAJDENX
+nET SIMWOLOW DLQ UDALENIQX
+dRUGOGO \KRANA NE SU]ESTWUETX
+sIMWOLY POSLE STROKI DLQ POISKA I/ILI PEREBOR STROKIX
+pRO[LYJ OBRAZEC POISKA OTSUTSTWUETX
+pOISK ZAWER[ILSQ NA NA^ALXNOJ POZICIIX
+
+sIMWOL NEPRAWILEN; ZAKL@^EN W KAWY^KI DLQ WWODAX
+uVE NA NA^ALE WSTAWKIX
+nET SIMWOLOW DLQ UDALENIQX
+pEREDWIVENIE ZA KONEC FAJLAX
+pEREDWIVENIE ZA KONEC STROKIX
+dWIVENIE STROKI NE SDELANOX
+uVE NA NA^ALE FAJLAX
+dWIVENIE KURSORA ZA NA^ALO FAJLAX
+uVE W PERWOJ KOLONKEX
+bUFERY DOLVNY BYTX UKAZANY DO WYPOLNENIQ KOMANDYX
+uVE NA KONCE FAJLAX
+uVE NA KONSE STROKIX
+%s NE QWLQETSQ KOMANDOJ VIX
+iSPOLXZOWANIE: %sX
+nET SIMWOLOW DLQ UDALENIQX
+
+nET KOMANDY DLQ POWTORAX
+
+kOMANDA %s NE MOVET BYTX ISPOLXZOWANA KAK KOMANDA PRODWIVENIQX
+~ISLO BOLX[E ^EM %luX
+
+
+zNA^ENIE KOLI^ESTWA OKON SLI[KOM WELIKO, MAKSIMALXNOE ZNA^ENIE = %uX
+
+
+
+
+
+dWIVENIE KURSORA ZA KONEC \KRANAX
+dWIVENIE KURSORA ZA NA^ALO \KRANAX
+
+tENEWYH OKON NETX
+nE SU]ESTWUET TENEWOGO OKNA S REDAKTIROWANIEM FAJLA %sX
+wY NE MOVETE SDELATX EDINSTWENNOE OKNO TENEWYMX
+|KRAN MOVET BYTX SVATX
+|KRAN NE MOVET BYTX SVATX
+|KRAN NE MOVET BYTX RAS[IRENX
+
+
+
+
+dANNYJ TIP TERMINALA NE IMEET KLAWI[I %sX
+
+
+
+nEWOZMOVNO SOZDATX WREMENNYJ FAJLX
+wNIMANIE: %s SPECIALXNYJ FAJLX
+%s UVE ZABLOKIROWAN, DOSTUPEN TOLXKO NA ^TENIEX
+%s: UDALENX
+%s: ZAKRYTX
+%s: UDALENX
+%s: UDALENX
+fAJL TOLXKO DLQ ^TENIQ, NE ZAPISAN: iSPOLXZUJTE ! DLQ OBHODAX
+fAJL TOLXKO DLQ ^TENIQ, NE ZAPISANX
+%s SU]ESTWUET, NE ZAPISAN; ISPOLXZUJTE ! DLQ OBHODAX
+%s SU]ESTWUET, NE ZAPISANX
+iSPOLXZUJTE ! DLQ ^ASTI^NOJ ZAPISI FAJLAX
+~ASTX FAJLA, FAJL NE ZAPISANX
+%s: fAJL IZMENQLSQ POZDNEE, ^EM DANNAQ KOPIQ: ISPOLXZUJTE ! DLQ OBHODAX
+%s: fAJL IZMENQLSQ POZDNEE, ^EM DANNAQ KOPIQX
+%s: ZA]ITA NA ZAPISX BYLA NEDOSTUPNAX
+
+%s: wnimanie: fajl use~enX
+
+%s: NOWYJ FAJL: %lu STROK, %lu SIMWOLOWX
+%s: %lu STROK, %lu SIMWOLOWX
+%s RAS[IRILSQ W SLI[KOM BOLX[OE KOLI^ESTWO IMEN FAJLOWX
+%s SPECIALXNYJ FAJLX
+%s: NE PRINADLEVIT wAMX
+%s: DOSTUPEN NE TOLXKO wAMX
+fAJL IZMENEN SO WREMENI POSLEDNEJ ZAPISI: SOHRANITE ILI ISPOLXZUJTE ! DLQ OBHODAX
+fAJL IZMENEN SO WREMENI POSLEDNEJ ZAPISI: SOHRANITE ILI ISPOLXZUJTE :edit DLQ OBHODAX
+fAJL IZMENEN SO WREMENI POSLEDNEJ ZAPISI: SOHRANITE ILI ISPOLXZUJTE ! DLQ OBHODAX
+fAJL WREMENNYJ: WYHOD SOTRET L@BYE IZMENENIQX
+
+zAPISI NA^ATY ZANOWOX
diff --git a/contrib/nvi/catalog/ru_SU.KOI8-R.base b/contrib/nvi/catalog/ru_SU.KOI8-R.base
new file mode 100644
index 000000000000..59efd3f53a5f
--- /dev/null
+++ b/contrib/nvi/catalog/ru_SU.KOI8-R.base
@@ -0,0 +1,219 @@
+002 "pEREPOLNENIE ZNA^ENIQ DLINY STROKI"
+003 "%s/%d: NEWOZMOVNO UDALITX STROKU %u"
+004 "%s/%d: NEWOZMOVNO DOBAWITX K STROKE %u"
+005 "%s/%d: NEWOZMOVNO WSTAWITX W STROKU %u"
+006 "%s/%d: NEWOZMOVNO SOHRANITX STROKU %u"
+007 "%s/%d: NEWOZMOVNO DOSTATX POSLEDN@@ STROKU"
+009 "fAJL ZAPISEJ"
+010 "zAPISI NE WELISX, NEWOZMOVNO OTMENITX POSLEDN@@ KOMANDU"
+011 "nET IZMENENIJ DLQ OTMENY"
+012 "zAPISI NE WELISX, NEWOZMOVNO OTMENITX POSLEDN@@ KOMANDU"
+013 "zAPISI NE WELISX, NEWOZMOVNO PROSMOTRETX WPERED"
+014 "nET IZMENENIJ DLQ PEREDELKI"
+015 "%s/%d: O[IBKA PRI ZAPISI PROTOKOLA"
+016 "sTANDARTNYJ WWOD/WYWOD DLQ VI DOLVEN BYTX TERMINAL"
+017 "oTMETKA %s: NE USTANOWLENA"
+018 "oTMETKA %s: STROKA BYLA UDALENA"
+019 "oTMETKA %s: POZICII KURSORA BOLX[E NE SU]ESTWUET"
+020 "o[IBKA:"
+030 "fAJL %s NE QWLQETSQ KATALOGOM SOOB]ENIJ"
+031 "nEWOZMOVNO USTANOWITX OPCI@ %s PO UMOL^ANI@"
+032 "iSPOLXZOWANIE: %s"
+033 "oPCII %s NET: 'set all' POKAZYWAET WSE WOZMOVNYE OPCII"
+034 "set: [no]%s NE PRINIMAET TAKOGO ZNA^ENIQ"
+035 "set: %s OPCIQ NE QWLQETSQ DWOI^NOJ"
+038 "set: NEPRAWILXNOE ZNA^ENIE %s"
+039 "set: %s OPCIQ NE QWLQETSQ DWOI^NOJ"
+040 "kOLI^ESTWO KOLONOK \KRANA SLI[KOM MALO, MENX[E ^EM %d"
+041 "kOLI^ESTWO KOLONOK \KRANA SLI[KOM WELIKO, BOLX[E ^EM %d"
+042 "kOLI^ESTWO STROK \KRANA SLI[KOM MALO, MENX[E ^EM %d"
+043 "kOLI^ESTWO STROK \KRANA SLI[KOM WELIKO, BOLX[E ^EM %d"
+044 "oPCIQ lisp OTSUTSTWUET"
+045 "sOOB]ENIQ NE WYKL@^ENY: %s"
+046 "sOOB]ENIQ NE WKL@^ENY: %s"
+047 "oPCIQ modeline(s) NE MOVET BYTX PEREUSTANOWLENA"
+048 "oPCIQ paragraph DOLVNA SOSTOQTX IZ GRUPP S DWUMQ SIMWOLAMI"
+049 "oPCIQ section DOLVNA SOSTOQTX IZ GRUPP S DWUMQ SIMWOLAMI"
+050 "oPCIQ shiftwidth NE MOVET BYTX USTANOWLENA NA 0"
+051 "oPCIQ sourceany NE MOVET BYTX USTANOWLENA"
+052 "tABULQCIQ NE MOVET BYTX USTANOWLENA NA 0"
+053 "sTARTOWYJ BUFER PUST"
+054 "bUFER %s PUST"
+055 "fAJLY S SIMWOLAMI PEREWODA STROKI W IMENI NE MOGUT BYTX WOSSTANOWLENY"
+056 "iZMENENIQ NE SOHRANENY PRI KRAHE SESSII"
+058 "sOHRANENIE NE UDALOSX: %s"
+059 "iZMENENIQ NE SOHRANQ@TSQ PRI OBRYWE SESSII"
+060 "sOHRANENIE KOPII FAJLA NE UDALOSX: %s"
+062 "iNFORMACII NA POLXZOWATELQ %u NE NAJDENO"
+063 "nEWOZMOVNO ZA]ITITX SPASENNYJ FAJL"
+064 "bUFER WOSSTANOWLENNOGO FAJLA PEREPOLNEN"
+065 "wOSSTANOWLENNYJ FAJL"
+066 "%s: NE DO KONCA WOSSTANOWLENNYJ FAJL"
+067 "%s: NE DO KONCA WOSSTANOWLENNYJ FAJL"
+068 "fAJLOW S IMENEM %s, KOTORYE wY MOVETE ^ITATX, NE SU]ESTWUET"
+069 "eSTX STARYE WERSII FAJLA, KOTORYE MOVNO WOSSTANOWITX"
+070 "sU]ESTWU@T DRUGIE FAJLY, KOTORYE MOVNO WOSSTANOWITX"
+071 "E-mail NE POSLAN: %s"
+072 "fAJL PUST - ISKATX NE^EGO"
+073 "dOSTIGNUT KONEC FAJLA BEZ NAHOVDENIQ OBRAZCA POISKA"
+074 "nE ZADAN OBRAZEC POISKA"
+075 "oBRAZEC POISKA NE NAJDEN"
+076 "dOSTUPNO NA^ALO FAJLA BEZ NAHOVDENIQ OBRAZCA POISKA"
+077 "pOISK ZACIKLEN"
+079 "nEPE^ATNYH SIMWOLOW NE NAJDENO"
+080 "nEIZWESTNAQ KOMANDA"
+082 "kOMANDA NE DOSTUPNA W REVIME ex"
+083 "s^ET^IK NE MOVET BYTX NULEM"
+084 "%s: NEPRAWILXNOE UKAZANIE STROKI"
+085 "wNUTRENNQQ O[IBKA W SINTAKSISE (%s: %s)"
+086 "iSPOLXZOWANIE: %s"
+087 "%s: WREMENNYJ BUFER NE ISPOLXZOWAN"
+088 "mETKA POSTAWLENA PERED STROKOJ 1"
+089 "mETKA POSTAWLENA POSLE KONCA FAJLA"
+092 "kOMANDA ex NE UDALASX: PARAMETRY KOMANDY ZABYTY"
+094 "wTOROJ ADRES MENX[E ^EM PERWYJ"
+095 "nE UKAZANO NAZWANIE OTMETKI"
+096 "\\ NE ZAWER[AETSQ / ILI ?"
+097 "sSYLKA K STROKE S NOMEROM MENX[E 0"
+098 "kOMANDA %s NEIZWESTNA"
+099 "pEREPOLNENIE ZNA^ENIQ ADRESA"
+100 "nEDOBOR ZNA^ENIQ ADRESA"
+101 "nEDOPUSTIMAQ KOMBINACIQ W ADRESE"
+102 "nEPRAWILXNYJ ADRES: WSEGO %lu STROK W FAJLE"
+103 "nEPRAWILXNYJ ADRES: FAJL PUST"
+104 "kOMMANDA %s NE MOVET ISPOLXZOWATX ADRES 0"
+105 "aBBREWIATURY OTSUTSTWU@T"
+106 "aBBREWIATURY DOLVNY ZAKAN^IWATXSQ SIMWOLOM "word""
+107 "aBBREWIATURY NE MOGUT SODERVATX SIMWOLOY TABLQCII ILI PROBELY"
+108 "aBBREWIATURY NE MOGUT SO^ETATXSQ S SIMWOLAMI SLOW/NE-SLOW, ZA ISKL@^ENIEM KONCA STROKI"
+109 ""%s" NE QWLQETSQ ABBREWIATUROJ"
+111 "fAJLOW DLQ REDAKTIROWANIQ BOLX[E NET"
+112 "oTSUTSTWIE PREDYDU]EGO FAJLA DLQ REDAKTIROWANIQ"
+113 "oTSUTSTWIE PREDYDU]EGO FAJLA DLQ PROSMOTRA NAZAD"
+114 "nET FAJLOW"
+115 "oTSUTSTWIE PREDYDU]EJ KOMANDY DLQ ZAMENY "!""
+116 "oTSUTSTWIE ZAMENY DLQ %%"
+117 "oTSUTSTWIE ZAMENY DLQ #"
+118 "o[IBKA: execl: %s"
+119 "o[IBKA WWODA/WYWODA: %s"
+120 "fAJL IZMENEN S MOMENTA POSLEDNEJ POLNOJ ZAPISI: ISPOLXZUJTE ! DLQ OBHODA"
+121 "nEWOZMOVNO NAJTI DOMA[NIJ KATALOG"
+122 "nOWYJ KATALOG: %s"
+123 "nET WYREZANYH BUFEROW"
+124 "kOMANDA %s NE MOVET BYTX ISPOLXZOWANA WNUTRI OB]EJ KOMANDY"
+125 "%s/%s: NE OTKRYT: NE PRINADLEVIT wAM ILI root-U"
+126 "%s/%s: NE OTKRYT: NE PRINADLEVIT wAM"
+127 "%s/%s: NE OTKRYT: WOZMOVNOSTX ZAPISI U POLXZOWATELQ, NE QWLQ@]EGOSQ WLADELXCEM"
+128 "%s/%s: NE S^ITAN: NE PRINADLEVIT wAM ILI root-U"
+129 "%s/%s: NE S^ITAN: NE PRINADLEVIT wAM"
+130 "%s/%s: NE S^ITAN: WOZMOVNOSTX ZAPISI U POLXZOWATELQ, NE QWLQ@]EGOSQ WLADELXCEM"
+131 "pOSLEDU@]IE STROKI OTSUTSTWU@T"
+132 "oTSUTSTWIE PARAMETROW WWODA"
+133 "oTSUTSTWIE PARAMETROW KOMANDY"
+134 "sIMWOL %s NE MOVET BYTX PEREZAPOMNEN"
+135 ""%s" NA DANNYJ MOMENT NE OTME^EN"
+136 "iMQ METKI DOLVNO BYTX ODNIM SIMWOLOM"
+137 "%s SU]ESTWUET, NE ZAPISAN; ISPOLXZUJTE ! DLQ OBHODA"
+138 "nOWYJ FAJL .exrc: %s"
+139 "sTROKA PERENOSA NAHODITSQ WNUTRI PARAMETROW PERENOSA"
+140 "kOMANDA open PODRAZUMEWAET USTANOWKU OPCII open"
+141 "kOMANDA open NE REALIZOWANA"
+142 "zA]ITA FAJLA NEWOZMOVNA"
+143 "fAJL ZA]I]EN"
+144 "%s RAS[IRILSQ W SLI[KOM BOLX[OE KOLI^ESTWO IMEN FAJLOW"
+146 "%s: ZA]ITA NA ^TENIE BYLA NEDOSTUPNA"
+148 "%s: %lu STROK, %lu SIMWOLOW"
+149 "nET TENEWYH OKON"
+150 "kOMANDA script ISPOLXZUETSQ TOLXKO W REVIME vi"
+151 "nET KOMANDY DLQ ISPOLNENIQ"
+152 "oPCIQ shiftwidth USTANOWLENA NA 0"
+153 "pEREPOLNENIE S^ET^IKA"
+154 "cIKL WYPOLNEN NE DO KONCA"
+155 "uKAZANO REGULQRNOE WYRAVENIE: FLAG r NE NUVEN"
+156 "fLAGI #, l I p NE MOGUT BYTX OB_EDINENY S FLAGOM c W REVIME vi"
+157 "sOWPADENIJ NET"
+158 "mETKA OTSUTSTWUET"
+159 "w STEKE METOK ZAPISEJ MENX[E, ^EM %s, ISPOLXZUJTE :display t[ags]"
+160 "fAJLA S IMENEM %s W STEKE METOK NET; ISPOLXZUJTE :display t[ags]"
+162 "%s: METKA NE NAJDENA"
+163 "%s: PLOHAQ METKA W %s"
+165 "sTEK METOK PUST"
+166 "%s: ISKOMAQ PEREMENNAQ NE NAJDENA"
+168 "bUFER %s PUST"
+170 "pRERWANO"
+171 "oTSUTSTWIE BUFERA DLQ ISPOLXZOWANIQ"
+172 "nET PREDIDU]EGO REGULQRNOGO WYRAVENIQ"
+173 "kOMANDA %s PODRAZUMEWAET NALI^IE PRO^TENNOGO FAJLA"
+174 "iSPOLXZOWANIE: %s"
+175 "kOMANDA visual PODRAZUMEWAET OBQZATELXNU@ USTANOWKU OPCII open"
+176 "%s RAS[IRILSQ DO SLI[KOM BOLX[OGO KOLI^ESTWA FAJLOW"
+177 "pUSTOJ FAJL"
+178 "nET PREDYDU]EGO POISKA F, f, T, ILI t"
+179 "%s NE NAJDENO"
+180 "nET PREDYDU]EGO FAJLA DLQ REDAKTIROWANIQ"
+181 "kURSOR STOIT NE NA CIFRE"
+182 "pOLU^ENNOE ^ISLO SLI[KOM WELIKO"
+183 "pOLU^ENNOE ^ISLO SLI[KOM MALO"
+184 "pODHODQ]EGO SIMWOLA NET NA \TOJ STROKE"
+185 "pODHODQ]IJ SIMWOL NE NAJDEN"
+186 "nET SIMWOLOW DLQ UDALENIQ"
+187 "dRUGOGO \KRANA NE SU]ESTWUET"
+188 "sIMWOLY POSLE STROKI DLQ POISKA I/ILI PEREBOR STROKI"
+189 "pRO[LYJ OBRAZEC POISKA OTSUTSTWUET"
+190 "pOISK ZAWER[ILSQ NA NA^ALXNOJ POZICII"
+192 "sIMWOL NEPRAWILEN; ZAKL@^EN W KAWY^KI DLQ WWODA"
+193 "uVE NA NA^ALE WSTAWKI"
+194 "nET SIMWOLOW DLQ UDALENIQ"
+195 "pEREDWIVENIE ZA KONEC FAJLA"
+196 "pEREDWIVENIE ZA KONEC STROKI"
+197 "dWIVENIE STROKI NE SDELANO"
+198 "uVE NA NA^ALE FAJLA"
+199 "dWIVENIE KURSORA ZA NA^ALO FAJLA"
+200 "uVE W PERWOJ KOLONKE"
+201 "bUFERY DOLVNY BYTX UKAZANY DO WYPOLNENIQ KOMANDY"
+202 "uVE NA KONCE FAJLA"
+203 "uVE NA KONSE STROKI"
+204 "%s NE QWLQETSQ KOMANDOJ VI"
+205 "iSPOLXZOWANIE: %s"
+206 "nET SIMWOLOW DLQ UDALENIQ"
+208 "nET KOMANDY DLQ POWTORA"
+210 "kOMANDA %s NE MOVET BYTX ISPOLXZOWANA KAK KOMANDA PRODWIVENIQ"
+211 "~ISLO BOLX[E ^EM %lu"
+214 "zNA^ENIE KOLI^ESTWA OKON SLI[KOM WELIKO, MAKSIMALXNOE ZNA^ENIE = %u"
+220 "dWIVENIE KURSORA ZA KONEC \KRANA"
+221 "dWIVENIE KURSORA ZA NA^ALO \KRANA"
+223 "tENEWYH OKON NET"
+224 "nE SU]ESTWUET TENEWOGO OKNA S REDAKTIROWANIEM FAJLA %s"
+225 "wY NE MOVETE SDELATX EDINSTWENNOE OKNO TENEWYM"
+226 "|KRAN MOVET BYTX SVAT"
+227 "|KRAN NE MOVET BYTX SVAT"
+228 "|KRAN NE MOVET BYTX RAS[IREN"
+233 "dANNYJ TIP TERMINALA NE IMEET KLAWI[I %s"
+237 "nEWOZMOVNO SOZDATX WREMENNYJ FAJL"
+238 "wNIMANIE: %s SPECIALXNYJ FAJL"
+239 "%s UVE ZABLOKIROWAN, DOSTUPEN TOLXKO NA ^TENIE"
+240 "%s: UDALEN"
+241 "%s: ZAKRYT"
+242 "%s: UDALEN"
+243 "%s: UDALEN"
+244 "fAJL TOLXKO DLQ ^TENIQ, NE ZAPISAN: iSPOLXZUJTE ! DLQ OBHODA"
+245 "fAJL TOLXKO DLQ ^TENIQ, NE ZAPISAN"
+246 "%s SU]ESTWUET, NE ZAPISAN; ISPOLXZUJTE ! DLQ OBHODA"
+247 "%s SU]ESTWUET, NE ZAPISAN"
+248 "iSPOLXZUJTE ! DLQ ^ASTI^NOJ ZAPISI FAJLA"
+249 "~ASTX FAJLA, FAJL NE ZAPISAN"
+250 "%s: fAJL IZMENQLSQ POZDNEE, ^EM DANNAQ KOPIQ: ISPOLXZUJTE ! DLQ OBHODA"
+251 "%s: fAJL IZMENQLSQ POZDNEE, ^EM DANNAQ KOPIQ"
+252 "%s: ZA]ITA NA ZAPISX BYLA NEDOSTUPNA"
+254 "%s: wnimanie: fajl use~en"
+256 "%s: NOWYJ FAJL: %lu STROK, %lu SIMWOLOW"
+257 "%s: %lu STROK, %lu SIMWOLOW"
+258 "%s RAS[IRILSQ W SLI[KOM BOLX[OE KOLI^ESTWO IMEN FAJLOW"
+259 "%s SPECIALXNYJ FAJL"
+260 "%s: NE PRINADLEVIT wAM"
+261 "%s: DOSTUPEN NE TOLXKO wAM"
+262 "fAJL IZMENEN SO WREMENI POSLEDNEJ ZAPISI: SOHRANITE ILI ISPOLXZUJTE ! DLQ OBHODA"
+263 "fAJL IZMENEN SO WREMENI POSLEDNEJ ZAPISI: SOHRANITE ILI ISPOLXZUJTE :edit DLQ OBHODA"
+264 "fAJL IZMENEN SO WREMENI POSLEDNEJ ZAPISI: SOHRANITE ILI ISPOLXZUJTE ! DLQ OBHODA"
+265 "fAJL WREMENNYJ: WYHOD SOTRET L@BYE IZMENENIQ"
+267 "zAPISI NA^ATY ZANOWO"
diff --git a/contrib/nvi/catalog/ru_SU.KOI8-R.check b/contrib/nvi/catalog/ru_SU.KOI8-R.check
new file mode 100644
index 000000000000..ca77b891051a
--- /dev/null
+++ b/contrib/nvi/catalog/ru_SU.KOI8-R.check
@@ -0,0 +1,169 @@
+Unused message id's (this is okay):
+001
+008
+021
+022
+023
+024
+025
+026
+027
+028
+029
+036
+037
+057
+061
+078
+081
+090
+091
+093
+110
+145
+147
+161
+164
+167
+169
+191
+207
+209
+212
+213
+215
+216
+217
+218
+219
+222
+229
+230
+231
+232
+234
+235
+236
+253
+255
+266
+=========================
+MISSING ERROR MESSAGES (Please add!):
+008
+021
+022
+023
+024
+025
+026
+027
+028
+029
+036
+037
+057
+061
+078
+090
+091
+093
+110
+145
+147
+161
+164
+167
+169
+191
+207
+209
+212
+215
+216
+217
+218
+219
+222
+230
+231
+232
+234
+235
+236
+253
+255
+266
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+=========================
+Extra error messages (just delete them):
+047
+050
+051
+052
+176
+=========================
+MESSAGES WITH THE SAME MESSAGE ID's (FIX!):
+=========================
+Duplicate messages, both id and message (this is okay):
+=========================
+Duplicate messages, just message (this is okay):
+ 2 %s RAS[IRILSQ W SLI[KOM BOLX[OE KOLI^ESTWO IMEN FAJLOWX
+ 2 %s SU]ESTWUET, NE ZAPISAN; ISPOLXZUJTE ! DLQ OBHODAX
+ 2 %s: %lu STROK, %lu SIMWOLOWX
+ 2 %s: NE DO KONCA WOSSTANOWLENNYJ FAJLX
+ 2 bUFER %s PUSTX
+ 2 fAJL IZMENEN SO WREMENI POSLEDNEJ ZAPISI: SOHRANITE ILI ISPOLXZUJTE ! DLQ OBHODAX
+ 2 set: %s OPCIQ NE QWLQETSQ DWOI^NOJX
+ 2 zAPISI NE WELISX, NEWOZMOVNO OTMENITX POSLEDN@@ KOMANDUX
+ 3 %s: UDALENX
+ 3 nET SIMWOLOW DLQ UDALENIQX
+ 4 iSPOLXZOWANIE: %sX
+=========================
diff --git a/contrib/nvi/catalog/ru_SU.KOI8-R.owner b/contrib/nvi/catalog/ru_SU.KOI8-R.owner
new file mode 100644
index 000000000000..bf4fa180298c
--- /dev/null
+++ b/contrib/nvi/catalog/ru_SU.KOI8-R.owner
@@ -0,0 +1 @@
+Dima Ruban <dima@demos.su>
diff --git a/contrib/nvi/catalog/spanish b/contrib/nvi/catalog/spanish
new file mode 100644
index 000000000000..fb67ee9dc422
--- /dev/null
+++ b/contrib/nvi/catalog/spanish
@@ -0,0 +1,317 @@
+VI_MESSAGE_CATALOG
+Desbordamiento de longitud de l¡neaX
+no se puede borrar la l¡nea %luX
+no se puede a¤adir la l¡nea %luX
+no se puede insertar en la l¡nea %luX
+no se puede guardar la l¡nea %luX
+no se puede obtener la £ltima l¡neaX
+Error: no se puede recuperar la l¡nea %luX
+Archivo de logX
+No se realiza log, no se puede deshacerX
+No hay cambios para deshacerX
+No se realiza log, no se puede deshacerX
+No se realiza log, no se puede remontar hacia adelanteX
+No hay cambios para rehacerX
+%s/%d: error de logX
+La entrada y salida est ndar de Vi debe ser una terminalX
+Marcar %s: no determinadoX
+Marcar %s: se borr¢ la l¡neaX
+Marcar %s: la posici¢n del cursor ya no existeX
+Error: X
+nuevo archivoX
+nombre cambiadoX
+modificadoX
+no modificadoX
+DESTRABADOX
+lectura solamenteX
+l¡nea %lu de %lu [%ld%%]X
+archivo vac¡oX
+l¡nea %luX
+El archivo %s no es un cat logo de mensajesX
+No se puede determinar la opci¢n por omisi¢n %sX
+Uso: %sX
+determinar: no hay opci¢n %s: 'determinar todo' establece todos los valores de opci¢nX
+determinar: [no] hay opci¢n %s no tiene valorX
+determinar: opci¢n %s no es booleanoX
+determinar: opci¢n %s: %sX
+determinar: opci¢n %s: %s: desbordamiento de valoresX
+determinar: opci¢n %s: %s es un n£mero ilegalX
+determinar: opci¢n %s no es booleanoX
+Las columnas en pantalla son demasiado peque¤as, menos de %dX
+Las columnas en pantalla son demasiado grandes, m s de %dX
+Las l¡neas en pantalla son demasiado peque¤as, menos de %dX
+Las l¡neas en pantalla son demasiado grandes, m s de %dX
+La opci¢n lisp no est  implementadaX
+mensajes no desconectados: %sX
+mensajes no conectados: %sX
+
+La opci¢n de p rrafo debe estar en dos grupos de caracteresX
+La opci¢n de secci¢n debe estar en dos grupos de caracteresX
+
+
+
+El buffer por omisi¢n est  vac¡oX
+El buffer %s est  vac¡oX
+Los archivos con nuevas l¡neas en el nombre son irrecuperablesX
+Las modificaciones no pueden recuperarse si la sesi¢n fallaX
+Copiando archivo para recuperaci¢n...X
+Preservaci¢n fracasada: %sX
+Las modificaciones no pueden recuperarse si la sesi¢n fallaX
+Archivo de respaldo fracasado: %sX
+Copiando archivo para recuperaci¢n...X
+Informaci¢n sobre identificaci¢n del usuario %u no encontradaX
+No se puede trabar archivo de recuperaci¢nX
+Desbordamiento de buffer de archivo de recuperaci¢nX
+Archivo de recuperaci¢nX
+%s: archivo de recuperaci¢n defectuosoX
+%s: archivo de recuperaci¢n defectuosoX
+No hay archivos denominados %s, que usted pueda leer, para recuperarX
+Existen versiones m s antiguas de este archivo que usted puede recuperarX
+Existen otros archivos que usted puede recuperarX
+no env¡a email: %sX
+Archivo vac¡o; no hay nada para buscarX
+Se alcanz¢ el final del archivo sin encontrar el patr¢nX
+No hay patr¢n anterior de b£squedaX
+No se encontr¢ el patr¢nX
+ Se alcanz¢ el principio del archivo sin encontrar el patr¢nX
+B£squeda reiniciadaX
+Buscando...X
+No se encontr¢ ning£n car cter no imprimibleX
+Nombre de comando desconocidoX
+
+%s: comando no disponible en modalidad exX
+La cuenta no puede ser ceroX
+%s: mala especificaci¢n de l¡neaX
+Error interno de tabla de sintaxis (%s: %s)X
+Uso: %sX
+%s: buffer temporario no liberadoX
+Desplazamiento de marcador a antes de la l¡nea 1X
+Desplazamiento de marcador m s all  del final del archivoX
+@ con rango que corre cuando se cambia el archivo/la pantallaX
+Comando global/v que corre cuando se cambia el archivo/la pantallaX
+Comando Ex fracasado: comandos pendientes descartadosX
+Comando Ex fracasado: teclas mapeadas descartadasX
+La segunda direcci¢n es m s peque¤a que la primeraX
+No se suministra nombre de marcaX
+\\ no es seguido por / o ?X
+Referencia a un n£mero de l¡nea menor que 0X
+El comando %s es desconocidoX
+Desbordamiento de valor de direcci¢nX
+Subdesbordamiento de valor de direcci¢nX
+Combinaci¢n de direcci¢n ilegalX
+Direcci¢n ilegal: s¢lo %lu l¡neas en el archivoX
+Direcci¢n ilegal: el archivo est  vac¡oX
+El comando %s no permite una direcci¢n de 0X
+No hay abreviaturas para visualizarX
+Las abreviaturas deben terminar con un car cter de \"palabra\" X
+Las abreviaturas no pueden contener tabs o espaciosX
+Las abreviaturas no pueden mezclar caracteres palabra/no-palabra, salvo al finalX
+\"%s\" no es una abreviaturaX
+Comando Vi fracasado: teclas mapeadas descartadasX
+No hay m s archivos para editarX
+No hay archivos anteriores para editarX
+No hay archivos anteriores para rebobinarX
+No hay lista de archivos para visualizarX
+No hay un comando anterior para reemplazar a \"!\"X
+No hay nombre de archivo para sustituir por %%X
+No hay nombre de archivo para sustituir por #X
+Error: execl: %sX
+Error de E/S: %sX
+Archivo modificado desde la £ltima escritura completa; escribir o usar ! para alterarX
+No se puede encontrar la ubicaci¢n del directorio inicialX
+Nuevo directorio actual: %sX
+No hay buffers sueltos para visualizarX
+El comando %s no puede usarse como parte de un comando global o vX
+%s/%s: sin fuente: no le pertenece a usted o a ra¡zX
+%s/%s: sin fuente: no le pertenece a ustedX
+%s/%s: sin fuente: puede ser escrito por un usuario que no sea el propietarioX
+%s: sin fuente: no le pertenece a usted o a ra¡zX
+%s: sin fuente: no le pertenece a ustedX
+%s: sin fuente: puede ser escrito por un usuario que no sea el propietarioX
+No hay l¡neas siguientes para unirX
+No hay anotaciones de mapa de entradaX
+No hay anotaciones de mapa de comandoX
+El car cter %s no puede remapearseX
+\"%s\" no est  mapeado actualmenteX
+Marca de nombres debe ser un s¢lo car cterX
+%s existe, no est  escrito; usar ! para alterarX
+Nuevo archivo exrc: %sX
+La l¡nea de destino se encuentra dentro del rango de movimientoX
+El comando abierto requiere que se determine la opci¢n abiertaX
+El comando abierto no se ha implementado a£nX
+No es posible preservar este archivoX
+Archivo preservadoX
+%s: expandido a demasiados nombres de archivoX
+S¢lo pueden leerse los archivos regulares y los conductos nombradosX
+%s: traba de lectura no disponibleX
+Leyendo...X
+%s: %lu l¡neas, %lu caracteresX
+No hay pantallas de fondo para mostrarX
+El comando de script s¢lo est  disponible en modalidad viX
+No hay comando para ejecutarX
+opci¢n de ancho de desplazamiento en 0X
+Desbordamiento de cuentaX
+Subdesbordamiento de cuentaX
+Expresi¢n regular especificada; marcador r no tiene significadoX
+Los marcadores #, l y p no pueden combinarse con el marcador c en la modalidad viX
+No se encontr¢ coincidenciaX
+No se ingres¢ un identificador anteriorX
+Se encontraron menos de %s anotaciones en la pila de identificadores; usar :visualizar i[dentificadores]X
+No hay archivo %s en la pila de identificadores al que se pueda volver; usar :visualizar i[dentificadores]"
+Presionar Intro para continuar: X
+%s: no se encontr¢ el identificadorX
+%s: identificador corrompido en %sX
+%s: el n£mero de l¡nea del identificador es posterior al final del archivoX
+La pila de identificadores est  vac¡aX
+%s: patr¢n de b£squeda no encontradoX
+%d archivos m s para editarX
+El buffer %s est  vac¡oX
+¨Confirmar cambio? [n]X
+InterrumpidoX
+No hay buffer anterior para ejecutarX
+No hay expresi¢n regular anteriorX
+El comando %s requiere que se haya le¡do un archivoX
+Uso: %sX
+El comando visual requiere que se determine la opci¢n abiertaX
+
+Archivo vac¡oX
+No hay b£squeda F, f, T o t anteriorX
+%s no se encontr¢X
+No hay archivo anterior para editarX
+El cursor no est  en un n£meroX
+El n£mero resultante es demasiado grandeX
+ El n£mero resultante es demasiado peque¤oX
+No hay car cter coincidente en esta l¡neaX
+No se encontr¢ un car cter coincidenteX
+No hay caracteres para reemplazarX
+No hay otra pantalla a la que se pueda pasarX
+Caracteres despu‚s de cadena de b£squeda, desplazamiento de l¡nea y/o comando zX
+No hay patr¢n anterior de b£squedaX
+B£squeda vuelve a la posici¢n inicialX
+Se super¢ el l¡mite de expansi¢n de abreviatura: se descartaron caracteresX
+Car cter ilegal; mencionar para entrarX
+Ya se encuentra al principio de la inserci¢nX
+No hay m s caracteres para borrarX
+Movimiento m s all  del final del archivoX
+Movimiento m s all  del final de la l¡neaX
+No hay movimiento del cursorX
+Ya se encuentra al principio del archivoX
+Movimiento m s all  del principio del archivoX
+Ya se encuentra en la primera columnaX
+Los buffers deben especificarse antes del comandoX
+Ya se encuentra al final del archivoX
+Ya se encuentra al final de la l¡neaX
+%s no es un comando viX
+Uso: %sX
+No hay caracteres para borrarX
+El comando Q requiere la interfase de terminal exX
+No hay comando para repetirX
+El archivo est  vac¡oX
+%s no puede usarse como comando de movimientoX
+Ya se encuentra en modalidad de comandoX
+El cursor no se encuentra en una palabraX
+
+El valor de opci¢n de Windows es demasiado grande, el m x. es %uX
+A¤adirX
+CambiarX
+ComandoX
+InsertarX
+ReemplazarX
+El movimiento va m s all  del final de la pantallaX
+El movimiento va m s all  del principio de la pantallaX
+La pantalla debe tener m s de %d l¡neas para dividirseX
+No hay pantallas de fondoX
+No hay pantalla de fondo editando un archivo denominado %sX
+No se puede poner fondo a la £nica pantalla que se visualizaX
+La pantalla s¢lo puede reducirse a %d hilerasX
+La pantalla no puede reducirseX
+La pantalla no puede aumentarseX
+
+Esta pantalla no puede suspenderseX
+Interrumpido: teclas mapeadas descartadasX
+vi: buffer temporario no liberadoX
+Esta terminal no tiene tecla %sX
+S¢lo un buffer puede especificarseX
+N£mero mayor que %luX
+InterrumpidoX
+No se puede crear archivo temporarioX
+Advertencia: %s no es un archivo regularX
+%s ya se encuentra trabado, la sesi¢n es de lectura solamenteX
+%s: eliminarX
+%s: cerrarX
+%s: eliminarX
+%s: eliminarX
+Archivo de lectura solamente, no escrito; usar ! para alterarX
+ Archivo de lectura solamente, no escritoX
+%s existe, no escrito; usar ! para alterarX
+%s existe, no escritoX
+Archivo parcial, no escrito; usar ! para alterarX
+Archivo parcial, no escritoX
+%s: archivo modificado m s recientemente que esta copia; usar ! para alterarX
+%s: archivo modificado m s recientemente que esta copiaX
+%s: la traba de escritura no estaba disponibleX
+Escribiendo...X
+%s: ADVERTENCIA: ARCHIVO TRUNCADOX
+Ya se encuentra en el primer identificador de este grupoX
+%s: nuevo archivo: %lu l¡neas, %lu caracteresX
+%s: %lu l¡neas, %lu caracteresX
+%s expandido a demasiados nombres de archivosX
+%s: no es un archivo regularX
+%s: no le perteneceX
+%s: accesible por un usuario que no sea el propietarioX
+Archivo modificado desde la £ltima escritura completa; escribir o usar ! para alterarX
+Archivo modificado desde la £ltima escritura completa; escribir o usar :editar! para alterarX
+Archivo modificado desde la £ltima escritura completa; escribir o usar ! para alterarX
+El archivo es temporario; al salir se descartar n las modificacionesX
+Archivo de lectura solamente, las modificaciones no se autoescribenX
+Se reinici¢ el logX
+confirmar? [snq]X
+Presionar cualquier tecla para continuar: X
+Presionar cualquier tecla para continuar [: para ingresar m s comandos ex]: X
+Presionar cualquier tecla para continuar [q para salir]: X
+Esta forma de %s requiere la interfase terminal exX
+Ingresando en la modalidad de entrada ex.X
+Comando fracasado, no hay archivo le¡do aun.X
+ cont?X
+Evento inesperado de car cterX
+Evento inesperado de final de archivoX
+No hay coincidencias para consultaX
+Evento inesperado de interrupci¢nX
+Evento inesperado de salidaX
+Evento inesperado de repinturaX
+Ya se encuentra en el £ltimo identificador de este grupoX
+El comando %s requiere la interfase terminal exX
+Esta forma de %s no se encuentra soportada cuando se determina la opci¢n de edici¢n seguraX
+Evento inesperado de cadenaX
+Evento inesperado de tiempo excedidoX
+Evento inesperado de escrituraX
+
+Las expansiones de shell no se encuentran soportadas cuando se determina la opci¢n de edici¢n seguraX
+El comando %s no se encuentra soportado cuando se determina la opci¢n de edici¢n seguraX
+determinar: la opci¢n %s puede no estar desconectadaX
+El monitor es demasiado peque¤o.X
+agregadoX
+cambiadoX
+borradoX
+unidoX
+movidoX
+desplazadoX
+arrancadoX
+l¡neaX
+l¡neasX
+Vi no se carg¢ con un int‚rprete TclX
+Archivo modificado desde la £ltima escritura.X
+Expansi¢n de shell fracasadaX
+No hay opci¢n de edici¢n %s especificadaX
+Vi no se carg¢ con un int‚rprete PerlX
+No hay comando ex para ejecutarX
+Ingresar <CR> para ejecutar un comando, :q para salirX
+Usar \"cscope ayuda\" para obtener ayudaX
+No hay conexiones cscope corriendoX
+%s: tipo de b£squeda desconocido: usar uno de %sX
+%d: no existe esta sesi¢n cscopeX
+determinar: la opci¢n %s no puede conectarse nuncaX
+determinar: la opci¢n %s no puede determinarse nunca en 0X
+%s: a¤adido: %lu l¡neas, %lu caracteresX
+Evento inesperado de modificaci¢n de tama¤oX
+%d archivos para editarX
diff --git a/contrib/nvi/catalog/spanish.base b/contrib/nvi/catalog/spanish.base
new file mode 100644
index 000000000000..270199eee5c8
--- /dev/null
+++ b/contrib/nvi/catalog/spanish.base
@@ -0,0 +1,309 @@
+002 "Desbordamiento de longitud de l¡nea"
+003 "no se puede borrar la l¡nea %lu"
+004 "no se puede a¤adir la l¡nea %lu"
+005 "no se puede insertar en la l¡nea %lu"
+006 "no se puede guardar la l¡nea %lu"
+007 "no se puede obtener la £ltima l¡nea"
+008 "Error: no se puede recuperar la l¡nea %lu"
+009 "Archivo de log"
+010 "No se realiza log, no se puede deshacer"
+011 "No hay cambios para deshacer"
+012 "No se realiza log, no se puede deshacer"
+013 "No se realiza log, no se puede remontar hacia adelante"
+014 "No hay cambios para rehacer"
+015 "%s/%d: error de log"
+016 "La entrada y salida est ndar de Vi debe ser una terminal"
+017 "Marcar %s: no determinado"
+018 "Marcar %s: se borr¢ la l¡nea"
+019 "Marcar %s: la posici¢n del cursor ya no existe"
+020 "Error: "
+021 "nuevo archivo"
+022 "nombre cambiado"
+023 "modificado"
+024 "no modificado"
+025 "DESTRABADO"
+026 "lectura solamente"
+027 "l¡nea %lu de %lu [%ld%%]"
+028 "archivo vac¡o"
+029 "l¡nea %lu"
+030 "El archivo %s no es un cat logo de mensajes"
+031 "No se puede determinar la opci¢n por omisi¢n %s"
+032 "Uso: %s"
+033 "determinar: no hay opci¢n %s: 'determinar todo' establece todos los valores de opci¢n"
+034 "determinar: [no] hay opci¢n %s no tiene valor"
+035 "determinar: opci¢n %s no es booleano"
+036 "determinar: opci¢n %s: %s"
+037 "determinar: opci¢n %s: %s: desbordamiento de valores"
+038 "determinar: opci¢n %s: %s es un n£mero ilegal"
+039 "determinar: opci¢n %s no es booleano"
+040 "Las columnas en pantalla son demasiado peque¤as, menos de %d"
+041 "Las columnas en pantalla son demasiado grandes, m s de %d"
+042 "Las l¡neas en pantalla son demasiado peque¤as, menos de %d"
+043 "Las l¡neas en pantalla son demasiado grandes, m s de %d"
+044 "La opci¢n lisp no est  implementada"
+045 "mensajes no desconectados: %s"
+046 "mensajes no conectados: %s"
+048 "La opci¢n de p rrafo debe estar en dos grupos de caracteres"
+049 "La opci¢n de secci¢n debe estar en dos grupos de caracteres"
+053 "El buffer por omisi¢n est  vac¡o"
+054 "El buffer %s est  vac¡o"
+055 "Los archivos con nuevas l¡neas en el nombre son irrecuperables"
+056 "Las modificaciones no pueden recuperarse si la sesi¢n falla"
+057 "Copiando archivo para recuperaci¢n..."
+058 "Preservaci¢n fracasada: %s"
+059 "Las modificaciones no pueden recuperarse si la sesi¢n falla"
+060 "Archivo de respaldo fracasado: %s"
+061 "Copiando archivo para recuperaci¢n..."
+062 "Informaci¢n sobre identificaci¢n del usuario %u no encontrada"
+063 "No se puede trabar archivo de recuperaci¢n"
+064 "Desbordamiento de buffer de archivo de recuperaci¢n"
+065 "Archivo de recuperaci¢n"
+066 "%s: archivo de recuperaci¢n defectuoso"
+067 "%s: archivo de recuperaci¢n defectuoso"
+068 "No hay archivos denominados %s, que usted pueda leer, para recuperar"
+069 "Existen versiones m s antiguas de este archivo que usted puede recuperar"
+070 "Existen otros archivos que usted puede recuperar"
+071 "no env¡a email: %s"
+072 "Archivo vac¡o; no hay nada para buscar"
+073 "Se alcanz¢ el final del archivo sin encontrar el patr¢n"
+074 "No hay patr¢n anterior de b£squeda"
+075 "No se encontr¢ el patr¢n"
+076 " Se alcanz¢ el principio del archivo sin encontrar el patr¢n"
+077 "B£squeda reiniciada"
+078 "Buscando..."
+079 "No se encontr¢ ning£n car cter no imprimible"
+080 "Nombre de comando desconocido"
+082 "%s: comando no disponible en modalidad ex"
+083 "La cuenta no puede ser cero"
+084 "%s: mala especificaci¢n de l¡nea"
+085 "Error interno de tabla de sintaxis (%s: %s)"
+086 "Uso: %s"
+087 "%s: buffer temporario no liberado"
+088 "Desplazamiento de marcador a antes de la l¡nea 1"
+089 "Desplazamiento de marcador m s all  del final del archivo"
+090 "@ con rango que corre cuando se cambia el archivo/la pantalla"
+091 "Comando global/v que corre cuando se cambia el archivo/la pantalla"
+092 "Comando Ex fracasado: comandos pendientes descartados"
+093 "Comando Ex fracasado: teclas mapeadas descartadas"
+094 "La segunda direcci¢n es m s peque¤a que la primera"
+095 "No se suministra nombre de marca"
+096 "\\ no es seguido por / o ?"
+097 "Referencia a un n£mero de l¡nea menor que 0"
+098 "El comando %s es desconocido"
+099 "Desbordamiento de valor de direcci¢n"
+100 "Subdesbordamiento de valor de direcci¢n"
+101 "Combinaci¢n de direcci¢n ilegal"
+102 "Direcci¢n ilegal: s¢lo %lu l¡neas en el archivo"
+103 "Direcci¢n ilegal: el archivo est  vac¡o"
+104 "El comando %s no permite una direcci¢n de 0"
+105 "No hay abreviaturas para visualizar"
+106 "Las abreviaturas deben terminar con un car cter de \"palabra\" "
+107 "Las abreviaturas no pueden contener tabs o espacios"
+108 "Las abreviaturas no pueden mezclar caracteres palabra/no-palabra, salvo al final"
+109 "\"%s\" no es una abreviatura"
+110 "Comando Vi fracasado: teclas mapeadas descartadas"
+111 "No hay m s archivos para editar"
+112 "No hay archivos anteriores para editar"
+113 "No hay archivos anteriores para rebobinar"
+114 "No hay lista de archivos para visualizar"
+115 "No hay un comando anterior para reemplazar a \"!\""
+116 "No hay nombre de archivo para sustituir por %%"
+117 "No hay nombre de archivo para sustituir por #"
+118 "Error: execl: %s"
+119 "Error de E/S: %s"
+120 "Archivo modificado desde la £ltima escritura completa; escribir o usar ! para alterar"
+121 "No se puede encontrar la ubicaci¢n del directorio inicial"
+122 "Nuevo directorio actual: %s"
+123 "No hay buffers sueltos para visualizar"
+124 "El comando %s no puede usarse como parte de un comando global o v"
+125 "%s/%s: sin fuente: no le pertenece a usted o a ra¡z"
+126 "%s/%s: sin fuente: no le pertenece a usted"
+127 "%s/%s: sin fuente: puede ser escrito por un usuario que no sea el propietario"
+128 "%s: sin fuente: no le pertenece a usted o a ra¡z"
+129 "%s: sin fuente: no le pertenece a usted"
+130 "%s: sin fuente: puede ser escrito por un usuario que no sea el propietario"
+131 "No hay l¡neas siguientes para unir"
+132 "No hay anotaciones de mapa de entrada"
+133 "No hay anotaciones de mapa de comando"
+134 "El car cter %s no puede remapearse"
+135 "\"%s\" no est  mapeado actualmente"
+136 "Marca de nombres debe ser un s¢lo car cter"
+137 "%s existe, no est  escrito; usar ! para alterar"
+138 "Nuevo archivo exrc: %s"
+139 "La l¡nea de destino se encuentra dentro del rango de movimiento"
+140 "El comando abierto requiere que se determine la opci¢n abierta"
+141 "El comando abierto no se ha implementado a£n"
+142 "No es posible preservar este archivo"
+143 "Archivo preservado"
+144 "%s: expandido a demasiados nombres de archivo"
+145 "S¢lo pueden leerse los archivos regulares y los conductos nombrados"
+146 "%s: traba de lectura no disponible"
+147 "Leyendo..."
+148 "%s: %lu l¡neas, %lu caracteres"
+149 "No hay pantallas de fondo para mostrar"
+150 "El comando de script s¢lo est  disponible en modalidad vi"
+151 "No hay comando para ejecutar"
+152 "opci¢n de ancho de desplazamiento en 0"
+153 "Desbordamiento de cuenta"
+154 "Subdesbordamiento de cuenta"
+155 "Expresi¢n regular especificada; marcador r no tiene significado"
+156 "Los marcadores #, l y p no pueden combinarse con el marcador c en la modalidad vi"
+157 "No se encontr¢ coincidencia"
+158 "No se ingres¢ un identificador anterior"
+159 "Se encontraron menos de %s anotaciones en la pila de identificadores; usar :visualizar i[dentificadores]"
+160 "No hay archivo %s en la pila de identificadores al que se pueda volver; usar :visualizar i[dentificadores]"
+161 "Presionar Intro para continuar: "
+162 "%s: no se encontr¢ el identificador"
+163 "%s: identificador corrompido en %s"
+164 "%s: el n£mero de l¡nea del identificador es posterior al final del archivo"
+165 "La pila de identificadores est  vac¡a"
+166 "%s: patr¢n de b£squeda no encontrado"
+167 "%d archivos m s para editar"
+168 "El buffer %s est  vac¡o"
+169 "¨Confirmar cambio? [n]"
+170 "Interrumpido"
+171 "No hay buffer anterior para ejecutar"
+172 "No hay expresi¢n regular anterior"
+173 "El comando %s requiere que se haya le¡do un archivo"
+174 "Uso: %s"
+175 "El comando visual requiere que se determine la opci¢n abierta"
+177 "Archivo vac¡o"
+178 "No hay b£squeda F, f, T o t anterior"
+179 "%s no se encontr¢"
+180 "No hay archivo anterior para editar"
+181 "El cursor no est  en un n£mero"
+182 "El n£mero resultante es demasiado grande"
+183 " El n£mero resultante es demasiado peque¤o"
+184 "No hay car cter coincidente en esta l¡nea"
+185 "No se encontr¢ un car cter coincidente"
+186 "No hay caracteres para reemplazar"
+187 "No hay otra pantalla a la que se pueda pasar"
+188 "Caracteres despu‚s de cadena de b£squeda, desplazamiento de l¡nea y/o comando z"
+189 "No hay patr¢n anterior de b£squeda"
+190 "B£squeda vuelve a la posici¢n inicial"
+191 "Se super¢ el l¡mite de expansi¢n de abreviatura: se descartaron caracteres"
+192 "Car cter ilegal; mencionar para entrar"
+193 "Ya se encuentra al principio de la inserci¢n"
+194 "No hay m s caracteres para borrar"
+195 "Movimiento m s all  del final del archivo"
+196 "Movimiento m s all  del final de la l¡nea"
+197 "No hay movimiento del cursor"
+198 "Ya se encuentra al principio del archivo"
+199 "Movimiento m s all  del principio del archivo"
+200 "Ya se encuentra en la primera columna"
+201 "Los buffers deben especificarse antes del comando"
+202 "Ya se encuentra al final del archivo"
+203 "Ya se encuentra al final de la l¡nea"
+204 "%s no es un comando vi"
+205 "Uso: %s"
+206 "No hay caracteres para borrar"
+207 "El comando Q requiere la interfase de terminal ex"
+208 "No hay comando para repetir"
+209 "El archivo est  vac¡o"
+209 "El archivo est  vac¡o"
+210 "%s no puede usarse como comando de movimiento"
+211 "Ya se encuentra en modalidad de comando"
+212 "El cursor no se encuentra en una palabra"
+214 "El valor de opci¢n de Windows es demasiado grande, el m x. es %u"
+215 "A¤adir"
+216 "Cambiar"
+217 "Comando"
+218 "Insertar"
+219 "Reemplazar"
+220 "El movimiento va m s all  del final de la pantalla"
+221 "El movimiento va m s all  del principio de la pantalla"
+222 "La pantalla debe tener m s de %d l¡neas para dividirse"
+223 "No hay pantallas de fondo"
+224 "No hay pantalla de fondo editando un archivo denominado %s"
+225 "No se puede poner fondo a la £nica pantalla que se visualiza"
+226 "La pantalla s¢lo puede reducirse a %d hileras"
+227 "La pantalla no puede reducirse"
+228 "La pantalla no puede aumentarse"
+230 "Esta pantalla no puede suspenderse"
+231 "Interrumpido: teclas mapeadas descartadas"
+232 "vi: buffer temporario no liberado"
+233 "Esta terminal no tiene tecla %s"
+234 "S¢lo un buffer puede especificarse"
+235 "N£mero mayor que %lu"
+236 "Interrumpido"
+237 "No se puede crear archivo temporario"
+238 "Advertencia: %s no es un archivo regular"
+239 "%s ya se encuentra trabado, la sesi¢n es de lectura solamente"
+240 "%s: eliminar"
+241 "%s: cerrar"
+242 "%s: eliminar"
+243 "%s: eliminar"
+244 "Archivo de lectura solamente, no escrito; usar ! para alterar"
+245 " Archivo de lectura solamente, no escrito"
+246 "%s existe, no escrito; usar ! para alterar"
+247 "%s existe, no escrito"
+248 "Archivo parcial, no escrito; usar ! para alterar"
+249 "Archivo parcial, no escrito"
+250 "%s: archivo modificado m s recientemente que esta copia; usar ! para alterar"
+251 "%s: archivo modificado m s recientemente que esta copia"
+252 "%s: la traba de escritura no estaba disponible"
+253 "Escribiendo..."
+254 "%s: ADVERTENCIA: ARCHIVO TRUNCADO"
+255 "Ya se encuentra en el primer identificador de este grupo"
+256 "%s: nuevo archivo: %lu l¡neas, %lu caracteres"
+257 "%s: %lu l¡neas, %lu caracteres"
+258 "%s expandido a demasiados nombres de archivos"
+259 "%s: no es un archivo regular"
+260 "%s: no le pertenece"
+261 "%s: accesible por un usuario que no sea el propietario"
+262 "Archivo modificado desde la £ltima escritura completa; escribir o usar ! para alterar"
+263 "Archivo modificado desde la £ltima escritura completa; escribir o usar :editar! para alterar"
+264 "Archivo modificado desde la £ltima escritura completa; escribir o usar ! para alterar"
+265 "El archivo es temporario; al salir se descartar n las modificaciones"
+266 "Archivo de lectura solamente, las modificaciones no se autoescriben"
+267 "Se reinici¢ el log"
+268 "confirmar? [snq]"
+269 "Presionar cualquier tecla para continuar: "
+270 "Presionar cualquier tecla para continuar [: para ingresar m s comandos ex]: "
+271 "Presionar cualquier tecla para continuar [q para salir]: "
+272 "Esta forma de %s requiere la interfase terminal ex"
+273 "Ingresando en la modalidad de entrada ex."
+274 "Comando fracasado, no hay archivo le¡do aun."
+275 " cont?"
+276 "Evento inesperado de car cter"
+277 "Evento inesperado de final de archivo"
+278 "No hay coincidencias para consulta"
+279 "Evento inesperado de interrupci¢n"
+280 "Evento inesperado de salida"
+281 "Evento inesperado de repintura"
+282 "Ya se encuentra en el £ltimo identificador de este grupo"
+283 "El comando %s requiere la interfase terminal ex"
+284 "Esta forma de %s no se encuentra soportada cuando se determina la opci¢n de edici¢n segura"
+285 "Evento inesperado de cadena"
+286 "Evento inesperado de tiempo excedido"
+287 "Evento inesperado de escritura"
+289 "Las expansiones de shell no se encuentran soportadas cuando se determina la opci¢n de edici¢n segura"
+290 "El comando %s no se encuentra soportado cuando se determina la opci¢n de edici¢n segura"
+291 "determinar: la opci¢n %s puede no estar desconectada"
+292 "El monitor es demasiado peque¤o."
+293 "agregado"
+294 "cambiado"
+295 "borrado"
+296 "unido"
+297 "movido"
+298 "desplazado"
+299 "arrancado"
+300 "l¡nea"
+301 "l¡neas"
+302 "Vi no se carg¢ con un int‚rprete Tcl"
+303 "Archivo modificado desde la £ltima escritura."
+304 "Expansi¢n de shell fracasada"
+304 "Expansi¢n de shell fracasada"
+305 "No hay opci¢n de edici¢n %s especificada"
+306 "Vi no se carg¢ con un int‚rprete Perl"
+307 "No hay comando ex para ejecutar"
+308 "Ingresar <CR> para ejecutar un comando, :q para salir"
+309 "Usar \"cscope ayuda\" para obtener ayuda"
+310 "No hay conexiones cscope corriendo"
+311 "%s: tipo de b£squeda desconocido: usar uno de %s"
+312 "%d: no existe esta sesi¢n cscope"
+313 "determinar: la opci¢n %s no puede conectarse nunca"
+314 "determinar: la opci¢n %s no puede determinarse nunca en 0"
+315 "%s: a¤adido: %lu l¡neas, %lu caracteres"
+316 "Evento inesperado de modificaci¢n de tama¤o"
+317 "%d archivos para editar"
diff --git a/contrib/nvi/catalog/spanish.check b/contrib/nvi/catalog/spanish.check
new file mode 100644
index 000000000000..c04785e3a2ef
--- /dev/null
+++ b/contrib/nvi/catalog/spanish.check
@@ -0,0 +1,35 @@
+Unused message id's (this is okay):
+001
+047
+050
+051
+052
+081
+176
+229
+288
+=========================
+MISSING ERROR MESSAGES (Please add!):
+=========================
+Extra error messages (just delete them):
+=========================
+MESSAGES WITH THE SAME MESSAGE ID's (FIX!):
+=========================
+Duplicate messages, both id and message (this is okay):
+ 2 209 "El archivo est  vac¡o"
+ 2 304 "Expansi¢n de shell fracasada"
+=========================
+Duplicate messages, just message (this is okay):
+ 2 %s: %lu l¡neas, %lu caracteresX
+ 2 %s: archivo de recuperaci¢n defectuosoX
+ 2 Copiando archivo para recuperaci¢n...X
+ 2 El buffer %s est  vac¡oX
+ 2 InterrumpidoX
+ 2 Las modificaciones no pueden recuperarse si la sesi¢n fallaX
+ 2 No hay patr¢n anterior de b£squedaX
+ 2 No se realiza log, no se puede deshacerX
+ 2 determinar: opci¢n %s no es booleanoX
+ 3 %s: eliminarX
+ 3 Archivo modificado desde la £ltima escritura completa; escribir o usar ! para alterarX
+ 4 Uso: %sX
+=========================
diff --git a/contrib/nvi/catalog/spell.ok b/contrib/nvi/catalog/spell.ok
new file mode 100644
index 000000000000..00be47141879
--- /dev/null
+++ b/contrib/nvi/catalog/spell.ok
@@ -0,0 +1,19 @@
+ARGMAX
+LC
+NL
+XXXX
+arg1
+arg2
+chys
+english
+english.base
+german.base
+langauge
+msg
+msg.c
+msgcat
+msgq
+nvi
+nvi's
+pathname
+sp
diff --git a/contrib/nvi/catalog/swedish b/contrib/nvi/catalog/swedish
new file mode 100644
index 000000000000..044b354fa070
--- /dev/null
+++ b/contrib/nvi/catalog/swedish
@@ -0,0 +1,317 @@
+VI_MESSAGE_CATALOG
+För långa raderX
+kan inte ta bort rad %luX
+kan inte lägga till på rad %luX
+kan inte sätta in på rad %luX
+kan inte lagra rad %luX
+kan inte hämta sista radenX
+Fel: kan inte hämta rad %luX
+LoggningsfilX
+Loggning utförs inte, ångra är inte möjligtX
+Inga ändringar att ångraX
+Loggning utförs inte, ångra är inte möjligtX
+Loggning utförs inte, ångra ångra är inte möjligtX
+Inga ändringar att återgöraX
+%s/%d: fel vid loggningX
+Vi:s standard in och ut måste gå till en terminalX
+Markering %s: inte sattX
+Markering %s: raden har tagits bortX
+Markering %s: markörpositionen finns inte längreX
+Fel: X
+ny filX
+namnet ändradesX
+ändradX
+oförändradX
+OLÅSTX
+inte skrivbarX
+rad %lu av %lu [%ld%%]X
+tom filX
+rad %luX
+Filen %s är ingen meddelandekatalogX
+Kan inte sätta standardvärde för %s flagganX
+Användning: %sX
+set: %s är en okänd flagga: "set all" visar alla flaggorX
+set: [no]%s flaggan kan inte ges ett värdeX
+set: %s flaggan är inte boleanskX
+set: %s flaggan: %sX
+set: %s flaggan: %s: för stort värdeX
+set: %s flaggan: %s är ett otillåtet talX
+set: %s flaggan är inte boleanskX
+Fönsterkolumnerna är för få, mindre än %dX
+Fönsterkolumnerna är för många, fler än %dX
+Fönsterraderna är för få, mindre än %dX
+Fönsterraderna är för många, fler än %dX
+Lisp flaggan är inte implementeradX
+meddelanden är inte avslagna: %sX
+meddelanden är inte påslagna: %sX
+
+Paragraph flaggan måste ges i teckengrupper om tvåX
+Section flaggan måste ges i teckengrupper om tvåX
+
+
+
+Standardbufferten är tomX
+Buffer %s är tomX
+Filer med radmatning i namnet kan inte återskapasX
+Ändringar kan inte återskapas om programmet krascharX
+Kopierar filen för återskapning...X
+Säkerhetskopiering misslyckades: %sX
+Ändringar kan inte återskapas om programmet krascharX
+Misslyckades att säkerhetskopiera filen: %sX
+Kopierar filen för återskapning...X
+Kan inte hitta information om användaridentitet %uX
+Kan inte låsa återskapningsfilenX
+Återskapningsfilens buffer överskrivenX
+ÅterskapningsfilX
+%s: Återskapningsfilen är korruptX
+%s: Återskapningsfilen är korruptX
+Det finns ingen fil %s, läsbar av dig, att återskapaX
+Det finns äldre versioner av denna fil som du kan återskapaX
+Det finns andra filer du kan återskapaX
+skickar inte email: %sX
+Filen är tom; inget att söka iX
+Kom till slutet på filen utan att hitta söksträngenX
+Ingen tidigare söksträngX
+Hittar inte söksträngenX
+Kom till början av filen utan att hitta söksträngenX
+Sökningen slog runtX
+Söker...X
+Inga icke skrivbara tecken funnaX
+Okänt kommandonamnX
+
+%s: kommandot är inte tillgängligt i "ex" lägeX
+Talet får inte vara nollX
+%s: Ogiltig radspecifikationX
+Fel i intern syntaxtabell (%s: %s)X
+Användning: %sX
+%s: temporärbuffert inte frisläpptX
+Offset är före rad 1X
+Offset är efter slutet på filenX
+@ med intervall exekverades när filen/fönstret ändradesX
+Global/v kommando exekverades när filen/fönstret ändradesX
+Ex kommando misslyckades: efterföljande kommandon ignoreradeX
+Ex kommando misslyckades: omdefinierade tangenter ignoreradeX
+Den andra adressen är mindre än den förstaX
+Inget namn på markering givetX
+\\ följs inte av / eller ?X
+Referens till ett radnummer mindre än 0X
+%s kommandot är inte käntX
+Värdet på adressen är för stortX
+Värdet på adressen är för litetX
+Otillåten adresskombinationX
+Otillåten adress: bara %lu rader finns i filenX
+Otillåten adress: filen är tomX
+%s kommandot tillåter inte en adress som är 0X
+Inga förkortningar att visaX
+Förkortningar måste sluta med ett "ord" teckenX
+Förkortningar kan inte innehålla mellanslag eller tabX
+Förkortningar kan inte blanda "ord"/"icke ord" tecken, utom i slutetX
+"%s" är ingen förkortningX
+Vi kommando misslyckades: omdefinierade tangenter ignoreradeX
+Inga fler filer att editeraX
+Inga tidigare filer att editeraX
+Inga tidigare filer att spela tillbakaX
+Ingen fillista att visaX
+Inget tidigare kommando att ersätta "!" medX
+Inget filnamn att ersätta %% medX
+Inget filnamn att ersätta # medX
+Fel: execl: %sX
+I/O fel: %sX
+Filen ändrad efter sista skrivning; spara eller använd !X
+Kan inte hitta hemkatalogX
+Ny nuvarande katalog: %sX
+Inga "cut buffers" att visaX
+%s kommandot kan inte används som del i ett "global" eller v kommandoX
+%s/%s: inte läst: varken du eller root är ägareX
+%s/%s: inte läst: du är inte ägareX
+%s/%s: inte läst: skrivbar av annan än ägarenX
+%s: inte läst: varken du eller root är ägareX
+%s: inte läst: du är inte ägareX
+%s: inte läst: skrivbar av annan än ägarenX
+Ingen nästa rad att sätta ihop medX
+Det finns inget i inmatningsmappningenX
+Det finns inget i kommandomappningenX
+%s tecknet kan inte mappas omX
+"%s" är inte ommappat just nuX
+Namn på markeringar måste vara ett tecken långaX
+%s finns, inget sparat; använd ! för att sparaX
+Ny exrc fil: %sX
+Målraden ligger inne i området som ska flyttasX
+Open kommandot kräver att open flaggan är sattX
+Open kommandot är inte implementerat ännuX
+Säkerhetskopiering av filen är inte möjligtX
+Filen säkerhetskopieradX
+%s expanderade till för många filnamnX
+Endast vanliga filer och namngivna rör kan läsasX
+%s: läslåset är otillgängligtX
+Läser...X
+%s: %lu rader, %lu teckenX
+Inga bakgrundsfönster att visaX
+Script kommandot finns bara i "vi" lägeX
+Inget kommando att exekveraX
+shiftwidth flaggan satt till 0X
+Talet har för stort värdeX
+Talet har för litet värdeX
+Reguljärt uttryck är givet; r flaggan är meningslösX
+#, l och p flaggorna kan inte kombineras med c flaggan i "vi" lägeX
+Ingen matchande text funnenX
+Inget tidigare märke har givitsX
+Det är färre än %s märken i stacken; använd :display t[ags]X
+Det finns ingen fil %s i märkesstacken; använd :display t[ags]X
+Tryck Enter för att fortsätta: X
+%s: märke inte funnetX
+%s: korrupt märke i %sX
+%s: märkets radnummer är bortom filslutetX
+Märkesstacken är tomX
+%s: söksträngen inte funnenX
+%d filer till att editeraX
+Buffert %s är tomX
+Bekräfta ändring? [n]X
+AvbrutenX
+Ingen tidigare buffert att exekveraX
+Inget tidigare reguljärt uttryckX
+%s kommandot kräver att en fil redan lästs inX
+Användning: %sX
+Visual kommandot kräver att open flaggan är sattX
+
+Tom filX
+Ingen tidigare F, f, T eller t sökningX
+%s inte funnenX
+Ingen tidigare fil att editeraX
+Markören är inte i ett talX
+Det resulterande talet är för stortX
+Det resulterande talet är för litetX
+Inget matchande tecken på denna radX
+Matchande tecken inte funnetX
+Det finns inga tecken att ersättaX
+Det finns inget fönster att byta tillX
+Tecken efter söksträng, radoffset och/eller z kommandotX
+Ingen tidigare söksträngX
+Sökningen slog runt till ursprungliga positionenX
+Förkortning överskred expanderingsgränsen: tecken har tagits bortX
+Ogiltigt tecken; använd "quote" för att sätta inX
+Redan i början på insättningenX
+Inga fler tecken att ta bortX
+Försök att gå bortom slutet på filenX
+Försök att gå bortom slutet på radenX
+Ingen förflyttning gjordX
+Redan i början på filenX
+Försök att gå före början på filenX
+Redan i första kolumnenX
+Buffertar måste anges före kommandotX
+Redan i slutet av filenX
+Redan på slutet av radenX
+%s är inte ett "vi" kommandoX
+Användning: %sX
+Inga tecken att ta bortX
+Q kommandot kräver "ex" i terminallägeX
+Inget kommando att repeteraX
+Filen är tomX
+%s kan inte användas som ett förflyttningskommandoX
+Redan i kommando lägeX
+Markören är inte i ett ordX
+
+Windows flaggans värde är för stor, största värde är %uX
+Lägg tillX
+ÄndraX
+KommandoX
+Sätt inX
+ErsättX
+Förflyttning bortom fönsterslutX
+Förflyttning till före fönstrets börjanX
+Fönstret måste vara större än %d rader för delningX
+Det finns inga fönster i bakgrundenX
+Det finns inget fönster i bakgrunden som editerar filen %sX
+Du får inte sätta ditt enda synliga fönster i bakgrundenX
+Fönstret kan bara krympa till %d raderX
+Fönstret kan inte krympaX
+Fönstret kan inte växaX
+
+Detta fönster kan inte pausasX
+Avbrutet: omdefinierade tangenter ignoreradeX
+vi: temporärbuffertar inte frisläpptaX
+Denna terminal har ingen %s tangentX
+Endast en buffert kan angesX
+Talet är större än %luX
+AvbrutetX
+Kan inte skapa temporär filX
+Warning: %s är inte en normal filX
+%s är redan låst, detta blir en icke skrivbar sessionX
+%s: ta bortX
+%s: stängX
+%s: ta bortX
+%s: ta bortX
+Ej skrivbar fil, filen inte sparad; använd ! för att skriva överX
+Ej skrivbar fil, filen inte sparadX
+%s finns, ej sparad; använd ! för att utföra operationenX
+%s finns, filen inte sparadX
+Ofullständig fil, filen inte sparad, använd ! för att skriva överX
+Ofullständig fil, filen inte sparadX
+%s: filen ändrad efter denna kopia togs; använd ! för att utföra operationenX
+%s: filen ändrad efter denna kopia togsX
+%s: skrivlåset är otillgängligtX
+Skriver...X
+%s: VARNING: FILEN TRUNKERADX
+Redan vid första märket i denna gruppX
+%s: ny fil: %lu rader, %lu teckenX
+%s: %lu rader, %lu teckenX
+%s expanderade till för många filnamnX
+%s är inte en normal filX
+%s ägs inte av digX
+%s är åtkomstbar av andra än ägarenX
+Filen har ändrats efter den sparats; spara eller använd !X
+Filen har ändrats efter den sparats; spara eller använd :edit!X
+Filen har ändrats efter den sparats; spara eller använd !X
+Filen är temporär; exit kastar bort ändringarnaX
+Ej skrivbar fil, ändringar har inte automatsparatsX
+Loggningen startar omX
+bekräfta? [ynq]X
+Tryck på en tangent för att fortsätta: X
+Tryck på en tangent för att fortsätta [: för att ge fler kommandon]: X
+Tryck på en tangent för att fortsätta [q för att avsluta]: X
+Den formen av %s kräver "ex" i terminallägeX
+Går till "ex" inmatningsläge.X
+Kommandot misslyckades, ingen fil inläst ännu.X
+ forts?X
+Oväntad teckenhändelseX
+Oväntad filslutshändelseX
+Sökningen hittade ingentingX
+Oväntad avbrottshändelseX
+Oväntad avslutningshändelseX
+Oväntad omritningshändelseX
+Redan vid sista märket i denna gruppX
+%s kommandot kräver "ex" i terminallägeX
+Den formen av %s är inte tillgänglig när secure edit flaggan är sattX
+Oväntad stränghändelseX
+Oväntad tidshändelseX
+Oväntad skrivhändelseX
+
+Skalexpansion är inte tillgänglig när secure edit flaggan är sattX
+%s kommandot är inte tillgänglig när secure edit flaggan är sattX
+set: %s kan inte slås avX
+Fönstret för litet.X
+tillagdaX
+ändradeX
+borttagnaX
+ihopsattaX
+flyttadeX
+flyttadeX
+inklistradeX
+radX
+raderX
+Vi har inte länkats med en Tcl tolkX
+Filen har ändrats efter den sparats.X
+Skalexpansion misslyckadesX
+Ingen %s edit flagga givenX
+Vi har inte länkats med en Perl tolkX
+Inga "ex" kommandon att exekveraX
+Tryck <CR> för att exekvera kommando, :q för att avslutaX
+Gör "cscope help" för hjälpX
+Inga cscope kopplingar körsX
+%s: okänd söktyp: använd en av %sX
+%d: ingen sådan cscope sessionX
+set: %s flaggan får aldrig slås påX
+set: %s flaggan får aldrig sättas till 0X
+%s: tillagt: %lu rader, %lu teckenX
+Oväntad storleksändringX
+%d filer att editeraX
diff --git a/contrib/nvi/catalog/swedish.base b/contrib/nvi/catalog/swedish.base
new file mode 100644
index 000000000000..43bf7765a25e
--- /dev/null
+++ b/contrib/nvi/catalog/swedish.base
@@ -0,0 +1,307 @@
+002 "För långa rader"
+003 "kan inte ta bort rad %lu"
+004 "kan inte lägga till på rad %lu"
+005 "kan inte sätta in på rad %lu"
+006 "kan inte lagra rad %lu"
+007 "kan inte hämta sista raden"
+008 "Fel: kan inte hämta rad %lu"
+009 "Loggningsfil"
+010 "Loggning utförs inte, ångra är inte möjligt"
+011 "Inga ändringar att ångra"
+012 "Loggning utförs inte, ångra är inte möjligt"
+013 "Loggning utförs inte, ångra ångra är inte möjligt"
+014 "Inga ändringar att återgöra"
+015 "%s/%d: fel vid loggning"
+016 "Vi:s standard in och ut måste gå till en terminal"
+017 "Markering %s: inte satt"
+018 "Markering %s: raden har tagits bort"
+019 "Markering %s: markörpositionen finns inte längre"
+020 "Fel: "
+021 "ny fil"
+022 "namnet ändrades"
+023 "ändrad"
+024 "oförändrad"
+025 "OLÅST"
+026 "inte skrivbar"
+027 "rad %lu av %lu [%ld%%]"
+028 "tom fil"
+029 "rad %lu"
+030 "Filen %s är ingen meddelandekatalog"
+031 "Kan inte sätta standardvärde för %s flaggan"
+032 "Användning: %s"
+033 "set: %s är en okänd flagga: "set all" visar alla flaggor"
+034 "set: [no]%s flaggan kan inte ges ett värde"
+035 "set: %s flaggan är inte boleansk"
+036 "set: %s flaggan: %s"
+037 "set: %s flaggan: %s: för stort värde"
+038 "set: %s flaggan: %s är ett otillåtet tal"
+039 "set: %s flaggan är inte boleansk"
+040 "Fönsterkolumnerna är för få, mindre än %d"
+041 "Fönsterkolumnerna är för många, fler än %d"
+042 "Fönsterraderna är för få, mindre än %d"
+043 "Fönsterraderna är för många, fler än %d"
+044 "Lisp flaggan är inte implementerad"
+045 "meddelanden är inte avslagna: %s"
+046 "meddelanden är inte påslagna: %s"
+048 "Paragraph flaggan måste ges i teckengrupper om två"
+049 "Section flaggan måste ges i teckengrupper om två"
+053 "Standardbufferten är tom"
+054 "Buffer %s är tom"
+055 "Filer med radmatning i namnet kan inte återskapas"
+056 "Ändringar kan inte återskapas om programmet kraschar"
+057 "Kopierar filen för återskapning..."
+058 "Säkerhetskopiering misslyckades: %s"
+059 "Ändringar kan inte återskapas om programmet kraschar"
+060 "Misslyckades att säkerhetskopiera filen: %s"
+061 "Kopierar filen för återskapning..."
+062 "Kan inte hitta information om användaridentitet %u"
+063 "Kan inte låsa återskapningsfilen"
+064 "Återskapningsfilens buffer överskriven"
+065 "Återskapningsfil"
+066 "%s: Återskapningsfilen är korrupt"
+067 "%s: Återskapningsfilen är korrupt"
+068 "Det finns ingen fil %s, läsbar av dig, att återskapa"
+069 "Det finns äldre versioner av denna fil som du kan återskapa"
+070 "Det finns andra filer du kan återskapa"
+071 "skickar inte email: %s"
+072 "Filen är tom; inget att söka i"
+073 "Kom till slutet på filen utan att hitta söksträngen"
+074 "Ingen tidigare söksträng"
+075 "Hittar inte söksträngen"
+076 "Kom till början av filen utan att hitta söksträngen"
+077 "Sökningen slog runt"
+078 "Söker..."
+079 "Inga icke skrivbara tecken funna"
+080 "Okänt kommandonamn"
+082 "%s: kommandot är inte tillgängligt i "ex" läge"
+083 "Talet får inte vara noll"
+084 "%s: Ogiltig radspecifikation"
+085 "Fel i intern syntaxtabell (%s: %s)"
+086 "Användning: %s"
+087 "%s: temporärbuffert inte frisläppt"
+088 "Offset är före rad 1"
+089 "Offset är efter slutet på filen"
+090 "@ med intervall exekverades när filen/fönstret ändrades"
+091 "Global/v kommando exekverades när filen/fönstret ändrades"
+092 "Ex kommando misslyckades: efterföljande kommandon ignorerade"
+093 "Ex kommando misslyckades: omdefinierade tangenter ignorerade"
+094 "Den andra adressen är mindre än den första"
+095 "Inget namn på markering givet"
+096 "\\ följs inte av / eller ?"
+097 "Referens till ett radnummer mindre än 0"
+098 "%s kommandot är inte känt"
+099 "Värdet på adressen är för stort"
+100 "Värdet på adressen är för litet"
+101 "Otillåten adresskombination"
+102 "Otillåten adress: bara %lu rader finns i filen"
+103 "Otillåten adress: filen är tom"
+104 "%s kommandot tillåter inte en adress som är 0"
+105 "Inga förkortningar att visa"
+106 "Förkortningar måste sluta med ett "ord" tecken"
+107 "Förkortningar kan inte innehålla mellanslag eller tab"
+108 "Förkortningar kan inte blanda "ord"/"icke ord" tecken, utom i slutet"
+109 ""%s" är ingen förkortning"
+110 "Vi kommando misslyckades: omdefinierade tangenter ignorerade"
+111 "Inga fler filer att editera"
+112 "Inga tidigare filer att editera"
+113 "Inga tidigare filer att spela tillbaka"
+114 "Ingen fillista att visa"
+115 "Inget tidigare kommando att ersätta "!" med"
+116 "Inget filnamn att ersätta %% med"
+117 "Inget filnamn att ersätta # med"
+118 "Fel: execl: %s"
+119 "I/O fel: %s"
+120 "Filen ändrad efter sista skrivning; spara eller använd !"
+121 "Kan inte hitta hemkatalog"
+122 "Ny nuvarande katalog: %s"
+123 "Inga "cut buffers" att visa"
+124 "%s kommandot kan inte används som del i ett "global" eller v kommando"
+125 "%s/%s: inte läst: varken du eller root är ägare"
+126 "%s/%s: inte läst: du är inte ägare"
+127 "%s/%s: inte läst: skrivbar av annan än ägaren"
+128 "%s: inte läst: varken du eller root är ägare"
+129 "%s: inte läst: du är inte ägare"
+130 "%s: inte läst: skrivbar av annan än ägaren"
+131 "Ingen nästa rad att sätta ihop med"
+132 "Det finns inget i inmatningsmappningen"
+133 "Det finns inget i kommandomappningen"
+134 "%s tecknet kan inte mappas om"
+135 ""%s" är inte ommappat just nu"
+136 "Namn på markeringar måste vara ett tecken långa"
+137 "%s finns, inget sparat; använd ! för att spara"
+138 "Ny exrc fil: %s"
+139 "Målraden ligger inne i området som ska flyttas"
+140 "Open kommandot kräver att open flaggan är satt"
+141 "Open kommandot är inte implementerat ännu"
+142 "Säkerhetskopiering av filen är inte möjligt"
+143 "Filen säkerhetskopierad"
+144 "%s expanderade till för många filnamn"
+145 "Endast vanliga filer och namngivna rör kan läsas"
+146 "%s: läslåset är otillgängligt"
+147 "Läser..."
+148 "%s: %lu rader, %lu tecken"
+149 "Inga bakgrundsfönster att visa"
+150 "Script kommandot finns bara i "vi" läge"
+151 "Inget kommando att exekvera"
+152 "shiftwidth flaggan satt till 0"
+153 "Talet har för stort värde"
+154 "Talet har för litet värde"
+155 "Reguljärt uttryck är givet; r flaggan är meningslös"
+156 "#, l och p flaggorna kan inte kombineras med c flaggan i "vi" läge"
+157 "Ingen matchande text funnen"
+158 "Inget tidigare märke har givits"
+159 "Det är färre än %s märken i stacken; använd :display t[ags]"
+160 "Det finns ingen fil %s i märkesstacken; använd :display t[ags]"
+161 "Tryck Enter för att fortsätta: "
+162 "%s: märke inte funnet"
+163 "%s: korrupt märke i %s"
+164 "%s: märkets radnummer är bortom filslutet"
+165 "Märkesstacken är tom"
+166 "%s: söksträngen inte funnen"
+167 "%d filer till att editera"
+168 "Buffert %s är tom"
+169 "Bekräfta ändring? [n]"
+170 "Avbruten"
+171 "Ingen tidigare buffert att exekvera"
+172 "Inget tidigare reguljärt uttryck"
+173 "%s kommandot kräver att en fil redan lästs in"
+174 "Användning: %s"
+175 "Visual kommandot kräver att open flaggan är satt"
+177 "Tom fil"
+178 "Ingen tidigare F, f, T eller t sökning"
+179 "%s inte funnen"
+180 "Ingen tidigare fil att editera"
+181 "Markören är inte i ett tal"
+182 "Det resulterande talet är för stort"
+183 "Det resulterande talet är för litet"
+184 "Inget matchande tecken på denna rad"
+185 "Matchande tecken inte funnet"
+186 "Det finns inga tecken att ersätta"
+187 "Det finns inget fönster att byta till"
+188 "Tecken efter söksträng, radoffset och/eller z kommandot"
+189 "Ingen tidigare söksträng"
+190 "Sökningen slog runt till ursprungliga positionen"
+191 "Förkortning överskred expanderingsgränsen: tecken har tagits bort"
+192 "Ogiltigt tecken; använd "quote" för att sätta in"
+193 "Redan i början på insättningen"
+194 "Inga fler tecken att ta bort"
+195 "Försök att gå bortom slutet på filen"
+196 "Försök att gå bortom slutet på raden"
+197 "Ingen förflyttning gjord"
+198 "Redan i början på filen"
+199 "Försök att gå före början på filen"
+200 "Redan i första kolumnen"
+201 "Buffertar måste anges före kommandot"
+202 "Redan i slutet av filen"
+203 "Redan på slutet av raden"
+204 "%s är inte ett "vi" kommando"
+205 "Användning: %s"
+206 "Inga tecken att ta bort"
+207 "Q kommandot kräver "ex" i terminalläge"
+208 "Inget kommando att repetera"
+209 "Filen är tom"
+210 "%s kan inte användas som ett förflyttningskommando"
+211 "Redan i kommando läge"
+212 "Markören är inte i ett ord"
+214 "Windows flaggans värde är för stor, största värde är %u"
+215 "Lägg till"
+216 "Ändra"
+217 "Kommando"
+218 "Sätt in"
+219 "Ersätt"
+220 "Förflyttning bortom fönsterslut"
+221 "Förflyttning till före fönstrets början"
+222 "Fönstret måste vara större än %d rader för delning"
+223 "Det finns inga fönster i bakgrunden"
+224 "Det finns inget fönster i bakgrunden som editerar filen %s"
+225 "Du får inte sätta ditt enda synliga fönster i bakgrunden"
+226 "Fönstret kan bara krympa till %d rader"
+227 "Fönstret kan inte krympa"
+228 "Fönstret kan inte växa"
+230 "Detta fönster kan inte pausas"
+231 "Avbrutet: omdefinierade tangenter ignorerade"
+232 "vi: temporärbuffertar inte frisläppta"
+233 "Denna terminal har ingen %s tangent"
+234 "Endast en buffert kan anges"
+235 "Talet är större än %lu"
+236 "Avbrutet"
+237 "Kan inte skapa temporär fil"
+238 "Warning: %s är inte en normal fil"
+239 "%s är redan låst, detta blir en icke skrivbar session"
+240 "%s: ta bort"
+241 "%s: stäng"
+242 "%s: ta bort"
+243 "%s: ta bort"
+244 "Ej skrivbar fil, filen inte sparad; använd ! för att skriva över"
+245 "Ej skrivbar fil, filen inte sparad"
+246 "%s finns, ej sparad; använd ! för att utföra operationen"
+247 "%s finns, filen inte sparad"
+248 "Ofullständig fil, filen inte sparad, använd ! för att skriva över"
+249 "Ofullständig fil, filen inte sparad"
+250 "%s: filen ändrad efter denna kopia togs; använd ! för att utföra operationen"
+251 "%s: filen ändrad efter denna kopia togs"
+252 "%s: skrivlåset är otillgängligt"
+253 "Skriver..."
+254 "%s: VARNING: FILEN TRUNKERAD"
+255 "Redan vid första märket i denna grupp"
+256 "%s: ny fil: %lu rader, %lu tecken"
+257 "%s: %lu rader, %lu tecken"
+258 "%s expanderade till för många filnamn"
+259 "%s är inte en normal fil"
+260 "%s ägs inte av dig"
+261 "%s är åtkomstbar av andra än ägaren"
+262 "Filen har ändrats efter den sparats; spara eller använd !"
+263 "Filen har ändrats efter den sparats; spara eller använd :edit!"
+264 "Filen har ändrats efter den sparats; spara eller använd !"
+265 "Filen är temporär; exit kastar bort ändringarna"
+266 "Ej skrivbar fil, ändringar har inte automatsparats"
+267 "Loggningen startar om"
+268 "bekräfta? [ynq]"
+269 "Tryck på en tangent för att fortsätta: "
+270 "Tryck på en tangent för att fortsätta [: för att ge fler kommandon]: "
+271 "Tryck på en tangent för att fortsätta [q för att avsluta]: "
+272 "Den formen av %s kräver "ex" i terminalläge"
+273 "Går till "ex" inmatningsläge."
+274 "Kommandot misslyckades, ingen fil inläst ännu."
+275 " forts?"
+276 "Oväntad teckenhändelse"
+277 "Oväntad filslutshändelse"
+278 "Sökningen hittade ingenting"
+279 "Oväntad avbrottshändelse"
+280 "Oväntad avslutningshändelse"
+281 "Oväntad omritningshändelse"
+282 "Redan vid sista märket i denna grupp"
+283 "%s kommandot kräver "ex" i terminalläge"
+284 "Den formen av %s är inte tillgänglig när secure edit flaggan är satt"
+285 "Oväntad stränghändelse"
+286 "Oväntad tidshändelse"
+287 "Oväntad skrivhändelse"
+289 "Skalexpansion är inte tillgänglig när secure edit flaggan är satt"
+290 "%s kommandot är inte tillgänglig när secure edit flaggan är satt"
+291 "set: %s kan inte slås av"
+292 "Fönstret för litet."
+293 "tillagda"
+294 "ändrade"
+295 "borttagna"
+296 "ihopsatta"
+297 "flyttade"
+298 "flyttade"
+299 "inklistrade"
+300 "rad"
+301 "rader"
+302 "Vi har inte länkats med en Tcl tolk"
+303 "Filen har ändrats efter den sparats."
+304 "Skalexpansion misslyckades"
+305 "Ingen %s edit flagga given"
+306 "Vi har inte länkats med en Perl tolk"
+307 "Inga "ex" kommandon att exekvera"
+308 "Tryck <CR> för att exekvera kommando, :q för att avsluta"
+309 "Gör "cscope help" för hjälp"
+310 "Inga cscope kopplingar körs"
+311 "%s: okänd söktyp: använd en av %s"
+312 "%d: ingen sådan cscope session"
+313 "set: %s flaggan får aldrig slås på"
+314 "set: %s flaggan får aldrig sättas till 0"
+315 "%s: tillagt: %lu rader, %lu tecken"
+316 "Oväntad storleksändring"
+317 "%d filer att editera"
diff --git a/contrib/nvi/catalog/swedish.check b/contrib/nvi/catalog/swedish.check
new file mode 100644
index 000000000000..c70b9bbd4095
--- /dev/null
+++ b/contrib/nvi/catalog/swedish.check
@@ -0,0 +1,34 @@
+Unused message id's (this is okay):
+001
+047
+050
+051
+052
+081
+176
+213
+229
+288
+=========================
+MISSING ERROR MESSAGES (Please add!):
+=========================
+Extra error messages (just delete them):
+=========================
+MESSAGES WITH THE SAME MESSAGE ID's (FIX!):
+=========================
+Duplicate messages, both id and message (this is okay):
+=========================
+Duplicate messages, just message (this is okay):
+ 2 %s expanderade till för många filnamnX
+ 2 %s: %lu rader, %lu teckenX
+ 2 %s: Återskapningsfilen är korruptX
+ 2 Filen har ändrats efter den sparats; spara eller använd !X
+ 2 Ingen tidigare söksträngX
+ 2 Kopierar filen för återskapning...X
+ 2 Loggning utförs inte, ångra är inte möjligtX
+ 2 flyttadeX
+ 2 set: %s flaggan är inte boleanskX
+ 2 Ändringar kan inte återskapas om programmet krascharX
+ 3 %s: ta bortX
+ 4 Användning: %sX
+=========================
diff --git a/contrib/nvi/catalog/swedish.owner b/contrib/nvi/catalog/swedish.owner
new file mode 100644
index 000000000000..2b36f2d324b8
--- /dev/null
+++ b/contrib/nvi/catalog/swedish.owner
@@ -0,0 +1 @@
+Jan Djarv <jan.djarv@mbox200.swipnet.se>
diff --git a/contrib/nvi/cl/README.signal b/contrib/nvi/cl/README.signal
new file mode 100644
index 000000000000..7faa45673b75
--- /dev/null
+++ b/contrib/nvi/cl/README.signal
@@ -0,0 +1,174 @@
+# @(#)README.signal 10.1 (Berkeley) 6/23/95
+
+There are six (normally) asynchronous actions about which vi cares:
+SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGTSTP and SIGWINCH.
+
+The assumptions:
+ 1: The DB routines are not reentrant.
+ 2: The curses routines may not be reentrant.
+ 3: Neither DB nor curses will restart system calls.
+
+XXX
+Note, most C library functions don't restart system calls. So, we should
+*probably* start blocking around any imported function that we don't know
+doesn't make a system call. This is going to be a genuine annoyance...
+
+SIGHUP, SIGTERM
+ Used for file recovery. The DB routines can't be reentered, nor
+ can they handle interrupted system calls, so the vi routines that
+ call DB block signals. This means that DB routines could be
+ called at interrupt time, if necessary.
+
+SIGQUIT
+ Disabled by the signal initialization routines. Historically, ^\
+ switched vi into ex mode, and we continue that practice.
+
+SIGWINCH:
+ The interrupt routine sets a global bit which is checked by the
+ key-read routine, so there are no reentrancy issues. This means
+ that the screen will not resize until vi runs out of keys, but
+ that doesn't seem like a problem.
+
+SIGINT and SIGTSTP are a much more difficult issue to resolve. Vi has
+to permit the user to interrupt long-running operations. Generally, a
+search, substitution or read/write is done on a large file, or, the user
+creates a key mapping with an infinite loop. This problem will become
+worse as more complex semantics are added to vi, especially things like
+making it a pure text widget. There are four major solutions on the table,
+each of which have minor permutations.
+
+1: Run in raw mode.
+
+ The up side is that there's no asynchronous behavior to worry about,
+ and obviously no reentrancy problems. The down side is that it's easy
+ to misinterpret characters (e.g. :w big_file^Mi^V^C is going to look
+ like an interrupt) and it's easy to get into places where we won't see
+ interrupt characters (e.g. ":map a ixx^[hxxaXXX" infinitely loops in
+ historic implementations of vi). Periodically reading the terminal
+ input buffer might solve the latter problem, but it's not going to be
+ pretty.
+
+ Also, we're going to be checking for ^C's and ^Z's both, all over
+ the place -- I hate to litter the source code with that. For example,
+ the historic version of vi didn't permit you to suspend the screen if
+ you were on the colon command line. This isn't right. ^Z isn't a vi
+ command, it's a terminal event. (Dammit.)
+
+2: Run in cbreak mode. There are two problems in this area. First, the
+ current curses implementations (both System V and Berkeley) don't give
+ you clean cbreak modes. For example, the IEXTEN bit is left on, turning
+ on DISCARD and LNEXT. To clarify, what vi WANTS is 8-bit clean, with
+ the exception that flow control and signals are turned on, and curses
+ cbreak mode doesn't give you this.
+
+ We can either set raw mode and twiddle the tty, or cbreak mode and
+ twiddle the tty. I chose to use raw mode, on the grounds that raw
+ mode is better defined and I'm less likely to be surprised by a curses
+ implementation down the road. The twiddling consists of setting ISIG,
+ IXON/IXOFF, and disabling some of the interrupt characters (see the
+ comments in cl_init.c). This is all found in historic System V (SVID
+ 3) and POSIX 1003.1-1992, so it should be fairly portable.
+
+ The second problem is that vi permits you to enter literal signal
+ characters, e.g. ^V^C. There are two possible solutions. First, you
+ can turn off signals when you get a ^V, but that means that a network
+ packet containing ^V and ^C will lose, since the ^C may take effect
+ before vi reads the ^V. (This is particularly problematic if you're
+ talking over a protocol that recognizes signals locally and sends OOB
+ packets when it sees them.) Second, you can turn the ^C into a literal
+ character in vi, but that means that there's a race between entering
+ ^V<character>^C, i.e. the sequence may end up being ^V^C<character>.
+ Also, the second solution doesn't work for flow control characters, as
+ they aren't delivered to the program as signals.
+
+ Generally, this is what historic vi did. (It didn't have the curses
+ problems because it didn't use curses.) It entered signals following
+ ^V characters into the input stream, (which is why there's no way to
+ enter a literal flow control character).
+
+3: Run in mostly raw mode; turn signals on when doing an operation the
+ user might want to interrupt, but leave them off most of the time.
+
+ This works well for things like file reads and writes. This doesn't
+ work well for trying to detect infinite maps. The problem is that
+ you can write the code so that you don't have to turn on interrupts
+ per keystroke, but the code isn't pretty and it's hard to make sure
+ that an optimization doesn't cover up an infinite loop. This also
+ requires interaction or state between the vi parser and the key
+ reading routines, as an infinite loop may still be returning keys
+ to the parser.
+
+ Also, if the user inserts an interrupt into the tty queue while the
+ interrupts are turned off, the key won't be treated as an interrupt,
+ and requiring the user to pound the keyboard to catch an interrupt
+ window is nasty.
+
+4: Run in mostly raw mode, leaving signals on all of the time. Done
+ by setting raw mode, and twiddling the tty's termios ISIG bit.
+
+ This works well for the interrupt cases, because the code only has
+ to check to see if the interrupt flag has been set, and can otherwise
+ ignore signals. It's also less likely that we'll miss a case, and we
+ don't have to worry about synchronizing between the vi parser and the
+ key read routines.
+
+ The down side is that we have to turn signals off if the user wants
+ to enter a literal character (e.g. ^V^C). If the user enters the
+ combination fast enough, or as part of a single network packet,
+ the text input routines will treat it as a signal instead of as a
+ literal character. To some extent, we have this problem already,
+ since we turn off flow control so that the user can enter literal
+ XON/XOFF characters.
+
+ This is probably the easiest to code, and provides the smoothest
+ programming interface.
+
+There are a couple of other problems to consider.
+
+First, System V's curses doesn't handle SIGTSTP correctly. If you use the
+newterm() interface, the TSTP signal will leave you in raw mode, and the
+final endwin() will leave you in the correct shell mode. If you use the
+initscr() interface, the TSTP signal will return you to the correct shell
+mode, but the final endwin() will leave you in raw mode. There you have
+it: proof that drug testing is not making any significant headway in the
+computer industry. The 4BSD curses is deficient in that it does not have
+an interface to the terminal keypad. So, regardless, we have to do our
+own SIGTSTP handling.
+
+The problem with this is that if we do our own SIGTSTP handling, in either
+models #3 or #4, we're going to have to call curses routines at interrupt
+time, which means that we might be reentering curses, which is something we
+don't want to do.
+
+Second, SIGTSTP has its own little problems. It's broadcast to the entire
+process group, not sent to a single process. The scenario goes something
+like this: the shell execs the mail program, which execs vi. The user hits
+^Z, and all three programs get the signal, in some random order. The mail
+program goes to sleep immediately (since it probably didn't have a SIGTSTP
+handler in place). The shell gets a SIGCHLD, does a wait, and finds out
+that the only child in its foreground process group (of which it's aware)
+is asleep. It then optionally resets the terminal (because the modes aren't
+how it left them), and starts prompting the user for input. The problem is
+that somewhere in the middle of all of this, vi is resetting the terminal,
+and getting ready to send a SIGTSTP to the process group in order to put
+itself to sleep. There's a solution to all of this: when vi starts, it puts
+itself into its own process group, and then only it (and possible child
+processes) receive the SIGTSTP. This permits it to clean up the terminal
+and switch back to the original process group, where it sends that process
+group a SIGTSTP, putting everyone to sleep and waking the shell.
+
+Third, handing SIGTSTP asynchronously is further complicated by the child
+processes vi may fork off. If vi calls ex, ex resets the terminal and
+starts running some filter, and SIGTSTP stops them both, vi has to know
+when it restarts that it can't repaint the screen until ex's child has
+finished running. This is solveable, but it's annoying.
+
+Well, somebody had to make a decision, and this is the way it's going to be
+(unless I get talked out of it). SIGINT is handled asynchronously, so
+that we can pretty much guarantee that the user can interrupt any operation
+at any time. SIGTSTP is handled synchronously, so that we don't have to
+reenter curses and so that we don't have to play the process group games.
+^Z is recognized in the standard text input and command modes. (^Z should
+also be recognized during operations that may potentially take a long time.
+The simplest solution is probably to twiddle the tty, install a handler for
+SIGTSTP, and then restore normal tty modes when the operation is complete.)
diff --git a/contrib/nvi/cl/cl.h b/contrib/nvi/cl/cl.h
new file mode 100644
index 000000000000..2ef2b8d1f81e
--- /dev/null
+++ b/contrib/nvi/cl/cl.h
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)cl.h 10.19 (Berkeley) 9/24/96
+ */
+
+typedef struct _cl_private {
+ CHAR_T ibuf[256]; /* Input keys. */
+
+ int eof_count; /* EOF count. */
+
+ struct termios orig; /* Original terminal values. */
+ struct termios ex_enter;/* Terminal values to enter ex. */
+ struct termios vi_enter;/* Terminal values to enter vi. */
+
+ char *el; /* Clear to EOL terminal string. */
+ char *cup; /* Cursor movement terminal string. */
+ char *cuu1; /* Cursor up terminal string. */
+ char *rmso, *smso; /* Inverse video terminal strings. */
+ char *smcup, *rmcup; /* Terminal start/stop strings. */
+
+ int killersig; /* Killer signal. */
+#define INDX_HUP 0
+#define INDX_INT 1
+#define INDX_TERM 2
+#define INDX_WINCH 3
+#define INDX_MAX 4 /* Original signal information. */
+ struct sigaction oact[INDX_MAX];
+
+ enum { /* Tty group write mode. */
+ TGW_UNKNOWN=0, TGW_SET, TGW_UNSET } tgw;
+
+ enum { /* Terminal initialization strings. */
+ TE_SENT=0, TI_SENT } ti_te;
+
+#define CL_IN_EX 0x0001 /* Currently running ex. */
+#define CL_RENAME 0x0002 /* X11 xterm icon/window renamed. */
+#define CL_RENAME_OK 0x0004 /* User wants the windows renamed. */
+#define CL_SCR_EX_INIT 0x0008 /* Ex screen initialized. */
+#define CL_SCR_VI_INIT 0x0010 /* Vi screen initialized. */
+#define CL_SIGHUP 0x0020 /* SIGHUP arrived. */
+#define CL_SIGINT 0x0040 /* SIGINT arrived. */
+#define CL_SIGTERM 0x0080 /* SIGTERM arrived. */
+#define CL_SIGWINCH 0x0100 /* SIGWINCH arrived. */
+#define CL_STDIN_TTY 0x0200 /* Talking to a terminal. */
+ u_int32_t flags;
+} CL_PRIVATE;
+
+#define CLP(sp) ((CL_PRIVATE *)((sp)->gp->cl_private))
+#define GCLP(gp) ((CL_PRIVATE *)gp->cl_private)
+
+/* Return possibilities from the keyboard read routine. */
+typedef enum { INP_OK=0, INP_EOF, INP_ERR, INP_INTR, INP_TIMEOUT } input_t;
+
+/* The screen line relative to a specific window. */
+#define RLNO(sp, lno) (sp)->woff + (lno)
+
+/* X11 xterm escape sequence to rename the icon/window. */
+#define XTERM_RENAME "\033]0;%s\007"
+
+/*
+ * XXX
+ * Some implementations of curses.h don't define these for us. Used for
+ * compatibility only.
+ */
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#include "cl_extern.h"
diff --git a/contrib/nvi/cl/cl_bsd.c b/contrib/nvi/cl/cl_bsd.c
new file mode 100644
index 000000000000..4a06a54af2f1
--- /dev/null
+++ b/contrib/nvi/cl/cl_bsd.c
@@ -0,0 +1,345 @@
+/*-
+ * Copyright (c) 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)cl_bsd.c 8.29 (Berkeley) 7/1/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <curses.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+#include "cl.h"
+
+static char *ke; /* Keypad on. */
+static char *ks; /* Keypad off. */
+static char *vb; /* Visible bell string. */
+
+/*
+ * HP's support the entire System V curses package except for the tigetstr
+ * and tigetnum functions. Ultrix supports the BSD curses package except
+ * for the idlok function. Cthulu only knows why. Break things up into a
+ * minimal set of functions.
+ */
+
+#ifndef HAVE_CURSES_ADDNSTR
+/*
+ * addnstr --
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_ADDNSTR
+ * PUBLIC: int addnstr __P((char *, int));
+ * PUBLIC: #endif
+ */
+int
+addnstr(s, n)
+ char *s;
+ int n;
+{
+ int ch;
+
+ while (n-- && (ch = *s++))
+ addch(ch);
+ return (OK);
+}
+#endif
+
+#ifndef HAVE_CURSES_BEEP
+/*
+ * beep --
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_BEEP
+ * PUBLIC: void beep __P((void));
+ * PUBLIC: #endif
+ */
+void
+beep()
+{
+ (void)write(1, "\007", 1); /* '\a' */
+}
+#endif /* !HAVE_CURSES_BEEP */
+
+#ifndef HAVE_CURSES_FLASH
+/*
+ * flash --
+ * Flash the screen.
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_FLASH
+ * PUBLIC: void flash __P((void));
+ * PUBLIC: #endif
+ */
+void
+flash()
+{
+ if (vb != NULL) {
+ (void)tputs(vb, 1, cl_putchar);
+ (void)fflush(stdout);
+ } else
+ beep();
+}
+#endif /* !HAVE_CURSES_FLASH */
+
+#ifndef HAVE_CURSES_IDLOK
+/*
+ * idlok --
+ * Turn on/off hardware line insert/delete.
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_IDLOK
+ * PUBLIC: void idlok __P((WINDOW *, int));
+ * PUBLIC: #endif
+ */
+void
+idlok(win, bf)
+ WINDOW *win;
+ int bf;
+{
+ return;
+}
+#endif /* !HAVE_CURSES_IDLOK */
+
+#ifndef HAVE_CURSES_KEYPAD
+/*
+ * keypad --
+ * Put the keypad/cursor arrows into or out of application mode.
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_KEYPAD
+ * PUBLIC: int keypad __P((void *, int));
+ * PUBLIC: #endif
+ */
+int
+keypad(a, on)
+ void *a;
+ int on;
+{
+ char *p;
+
+ if ((p = tigetstr(on ? "smkx" : "rmkx")) != (char *)-1) {
+ (void)tputs(p, 0, cl_putchar);
+ (void)fflush(stdout);
+ }
+ return (0);
+}
+#endif /* !HAVE_CURSES_KEYPAD */
+
+#ifndef HAVE_CURSES_NEWTERM
+/*
+ * newterm --
+ * Create a new curses screen.
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_NEWTERM
+ * PUBLIC: void *newterm __P((const char *, FILE *, FILE *));
+ * PUBLIC: #endif
+ */
+void *
+newterm(a, b, c)
+ const char *a;
+ FILE *b, *c;
+{
+ return (initscr());
+}
+#endif /* !HAVE_CURSES_NEWTERM */
+
+#ifndef HAVE_CURSES_SETUPTERM
+/*
+ * setupterm --
+ * Set up terminal.
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_SETUPTERM
+ * PUBLIC: void setupterm __P((char *, int, int *));
+ * PUBLIC: #endif
+ */
+void
+setupterm(ttype, fno, errp)
+ char *ttype;
+ int fno, *errp;
+{
+ static char buf[2048];
+ char *p;
+
+ if ((*errp = tgetent(buf, ttype)) > 0) {
+ if (ke != NULL)
+ free(ke);
+ ke = ((p = tigetstr("rmkx")) == (char *)-1) ?
+ NULL : strdup(p);
+ if (ks != NULL)
+ free(ks);
+ ks = ((p = tigetstr("smkx")) == (char *)-1) ?
+ NULL : strdup(p);
+ if (vb != NULL)
+ free(vb);
+ vb = ((p = tigetstr("flash")) == (char *)-1) ?
+ NULL : strdup(p);
+ }
+}
+#endif /* !HAVE_CURSES_SETUPTERM */
+
+#ifndef HAVE_CURSES_TIGETSTR
+/* Terminfo-to-termcap translation table. */
+typedef struct _tl {
+ char *terminfo; /* Terminfo name. */
+ char *termcap; /* Termcap name. */
+} TL;
+static const TL list[] = {
+ "cols", "co", /* Terminal columns. */
+ "cup", "cm", /* Cursor up. */
+ "cuu1", "up", /* Cursor up. */
+ "el", "ce", /* Clear to end-of-line. */
+ "flash", "vb", /* Visible bell. */
+ "kcub1", "kl", /* Cursor left. */
+ "kcud1", "kd", /* Cursor down. */
+ "kcuf1", "kr", /* Cursor right. */
+ "kcuu1", "ku", /* Cursor up. */
+ "kdch1", "kD", /* Delete character. */
+ "kdl1", "kL", /* Delete line. */
+ "ked", "kS", /* Delete to end of screen. */
+ "kel", "kE", /* Delete to eol. */
+ "khome", "kh", /* Go to sol. */
+ "kich1", "kI", /* Insert at cursor. */
+ "kil1", "kA", /* Insert line. */
+ "kind", "kF", /* Scroll down. */
+ "kll", "kH", /* Go to eol. */
+ "knp", "kN", /* Page down. */
+ "kpp", "kP", /* Page up. */
+ "kri", "kR", /* Scroll up. */
+ "lines", "li", /* Terminal lines. */
+ "rmcup", "te", /* Terminal end string. */
+ "rmkx", "ke", /* Exit "keypad-transmit" mode. */
+ "rmso", "se", /* Standout end. */
+ "smcup", "ti", /* Terminal initialization string. */
+ "smkx", "ks", /* Enter "keypad-transmit" mode. */
+ "smso", "so", /* Standout begin. */
+};
+
+#ifdef _AIX
+/*
+ * AIX's implementation for function keys greater than 10 is different and
+ * only goes as far as 36.
+ */
+static const char codes[] = {
+/* 0-10 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';',
+/* 11-20 */ '<', '>', '!', '@', '#', '$', '%', '^', '&', '*',
+/* 21-30 */ '(', ')', '-', '_', '+', ',', ':', '?', '[', ']',
+/* 31-36 */ '{', '}', '|', '~', '/', '='
+};
+
+#else
+
+/*
+ * !!!
+ * Historically, the 4BSD termcap code didn't support functions keys greater
+ * than 9. This was silently enforced -- asking for key k12 would return the
+ * value for k1. We try and get around this by using the tables specified in
+ * the terminfo(TI_ENV) man page from the 3rd Edition SVID. This assumes the
+ * implementors of any System V compatibility code or an extended termcap used
+ * those codes.
+ */
+static const char codes[] = {
+/* 0-10 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';',
+/* 11-19 */ '1', '2', '3', '4', '5', '6', '7', '8', '9',
+/* 20-63 */ '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',
+ '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',
+};
+#endif /* _AIX */
+
+/*
+ * lcmp --
+ * list comparison routine for bsearch.
+ */
+static int
+lcmp(a, b)
+ const void *a, *b;
+{
+ return (strcmp(a, ((TL *)b)->terminfo));
+}
+
+/*
+ * tigetstr --
+ *
+ * Vendors put the prototype for tigetstr into random include files, including
+ * <term.h>, which we can't include because it makes other systems unhappy.
+ * Try and work around the problem, since we only care about the return value.
+ *
+ * PUBLIC: #ifdef HAVE_CURSES_TIGETSTR
+ * PUBLIC: char *tigetstr();
+ * PUBLIC: #else
+ * PUBLIC: char *tigetstr __P((char *));
+ * PUBLIC: #endif
+ */
+char *
+tigetstr(name)
+ char *name;
+{
+ static char sbuf[256];
+ TL *tlp;
+ int n;
+ char *p, keyname[3];
+
+ if ((tlp = bsearch(name,
+ list, sizeof(list) / sizeof(TL), sizeof(TL), lcmp)) == NULL) {
+#ifdef _AIX
+ if (name[0] == 'k' &&
+ name[1] == 'f' && (n = atoi(name + 2)) <= 36) {
+ keyname[0] = 'k';
+ keyname[1] = codes[n];
+ keyname[2] = '\0';
+#else
+ if (name[0] == 'k' &&
+ name[1] == 'f' && (n = atoi(name + 2)) <= 63) {
+ keyname[0] = n <= 10 ? 'k' : 'F';
+ keyname[1] = codes[n];
+ keyname[2] = '\0';
+#endif
+ name = keyname;
+ }
+ } else
+ name = tlp->termcap;
+
+ p = sbuf;
+#ifdef _AIX
+ return ((p = tgetstr(name, &p)) == NULL ? (char *)-1 : strcpy(sbuf, p));
+#else
+ return (tgetstr(name, &p) == NULL ? (char *)-1 : sbuf);
+#endif
+}
+
+/*
+ * tigetnum --
+ *
+ * PUBLIC: #ifndef HAVE_CURSES_TIGETSTR
+ * PUBLIC: int tigetnum __P((char *));
+ * PUBLIC: #endif
+ */
+int
+tigetnum(name)
+ char *name;
+{
+ TL *tlp;
+ int val;
+
+ if ((tlp = bsearch(name,
+ list, sizeof(list) / sizeof(TL), sizeof(TL), lcmp)) != NULL) {
+ name = tlp->termcap;
+ }
+
+ return ((val = tgetnum(name)) == -1 ? -2 : val);
+}
+#endif /* !HAVE_CURSES_TIGETSTR */
diff --git a/contrib/nvi/cl/cl_funcs.c b/contrib/nvi/cl/cl_funcs.c
new file mode 100644
index 000000000000..40315ee85e89
--- /dev/null
+++ b/contrib/nvi/cl/cl_funcs.c
@@ -0,0 +1,704 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)cl_funcs.c 10.50 (Berkeley) 9/24/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <curses.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+#include "cl.h"
+
+/*
+ * cl_addstr --
+ * Add len bytes from the string at the cursor, advancing the cursor.
+ *
+ * PUBLIC: int cl_addstr __P((SCR *, const char *, size_t));
+ */
+int
+cl_addstr(sp, str, len)
+ SCR *sp;
+ const char *str;
+ size_t len;
+{
+ CL_PRIVATE *clp;
+ size_t oldy, oldx;
+ int iv;
+
+ clp = CLP(sp);
+
+ /*
+ * If ex isn't in control, it's the last line of the screen and
+ * it's a split screen, use inverse video.
+ */
+ iv = 0;
+ getyx(stdscr, oldy, oldx);
+ if (!F_ISSET(sp, SC_SCR_EXWROTE) &&
+ oldy == RLNO(sp, LASTLINE(sp)) && IS_SPLIT(sp)) {
+ iv = 1;
+ (void)standout();
+ }
+
+ if (addnstr(str, len) == ERR)
+ return (1);
+
+ if (iv)
+ (void)standend();
+ return (0);
+}
+
+/*
+ * cl_attr --
+ * Toggle a screen attribute on/off.
+ *
+ * PUBLIC: int cl_attr __P((SCR *, scr_attr_t, int));
+ */
+int
+cl_attr(sp, attribute, on)
+ SCR *sp;
+ scr_attr_t attribute;
+ int on;
+{
+ CL_PRIVATE *clp;
+
+ clp = CLP(sp);
+
+ switch (attribute) {
+ case SA_ALTERNATE:
+ /*
+ * !!!
+ * There's a major layering violation here. The problem is that the
+ * X11 xterm screen has what's known as an "alternate" screen. Some
+ * xterm termcap/terminfo entries include sequences to switch to/from
+ * that alternate screen as part of the ti/te (smcup/rmcup) strings.
+ * Vi runs in the alternate screen, so that you are returned to the
+ * same screen contents on exit from vi that you had when you entered
+ * vi. Further, when you run :shell, or :!date or similar ex commands,
+ * you also see the original screen contents. This wasn't deliberate
+ * on vi's part, it's just that it historically sent terminal init/end
+ * sequences at those times, and the addition of the alternate screen
+ * sequences to the strings changed the behavior of vi. The problem
+ * caused by this is that we don't want to switch back to the alternate
+ * screen while getting a new command from the user, when the user is
+ * continuing to enter ex commands, e.g.:
+ *
+ * :!date <<< switch to original screen
+ * [Hit return to continue] <<< prompt user to continue
+ * :command <<< get command from user
+ *
+ * Note that the :command input is a true vi input mode, e.g., input
+ * maps and abbreviations are being done. So, we need to be able to
+ * switch back into the vi screen mode, without flashing the screen.
+ *
+ * To make matters worse, the curses initscr() and endwin() calls will
+ * do this automatically -- so, this attribute isn't as controlled by
+ * the higher level screen as closely as one might like.
+ */
+ if (on) {
+ if (clp->ti_te != TI_SENT) {
+ clp->ti_te = TI_SENT;
+ if (clp->smcup == NULL)
+ (void)cl_getcap(sp, "smcup", &clp->smcup);
+ if (clp->smcup != NULL)
+ (void)tputs(clp->smcup, 1, cl_putchar);
+ }
+ } else
+ if (clp->ti_te != TE_SENT) {
+ clp->ti_te = TE_SENT;
+ if (clp->rmcup == NULL)
+ (void)cl_getcap(sp, "rmcup", &clp->rmcup);
+ if (clp->rmcup != NULL)
+ (void)tputs(clp->rmcup, 1, cl_putchar);
+ (void)fflush(stdout);
+ }
+ (void)fflush(stdout);
+ break;
+ case SA_INVERSE:
+ if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE)) {
+ if (clp->smso == NULL)
+ return (1);
+ if (on)
+ (void)tputs(clp->smso, 1, cl_putchar);
+ else
+ (void)tputs(clp->rmso, 1, cl_putchar);
+ (void)fflush(stdout);
+ } else {
+ if (on)
+ (void)standout();
+ else
+ (void)standend();
+ }
+ break;
+ default:
+ abort();
+ }
+ return (0);
+}
+
+/*
+ * cl_baud --
+ * Return the baud rate.
+ *
+ * PUBLIC: int cl_baud __P((SCR *, u_long *));
+ */
+int
+cl_baud(sp, ratep)
+ SCR *sp;
+ u_long *ratep;
+{
+ CL_PRIVATE *clp;
+
+ /*
+ * XXX
+ * There's no portable way to get a "baud rate" -- cfgetospeed(3)
+ * returns the value associated with some #define, which we may
+ * never have heard of, or which may be a purely local speed. Vi
+ * only cares if it's SLOW (w300), slow (w1200) or fast (w9600).
+ * Try and detect the slow ones, and default to fast.
+ */
+ clp = CLP(sp);
+ switch (cfgetospeed(&clp->orig)) {
+ case B50:
+ case B75:
+ case B110:
+ case B134:
+ case B150:
+ case B200:
+ case B300:
+ case B600:
+ *ratep = 600;
+ break;
+ case B1200:
+ *ratep = 1200;
+ break;
+ default:
+ *ratep = 9600;
+ break;
+ }
+ return (0);
+}
+
+/*
+ * cl_bell --
+ * Ring the bell/flash the screen.
+ *
+ * PUBLIC: int cl_bell __P((SCR *));
+ */
+int
+cl_bell(sp)
+ SCR *sp;
+{
+ if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE))
+ (void)write(STDOUT_FILENO, "\07", 1); /* \a */
+ else {
+ /*
+ * Vi has an edit option which determines if the terminal
+ * should be beeped or the screen flashed.
+ */
+ if (O_ISSET(sp, O_FLASH))
+ (void)flash();
+ else
+ (void)beep();
+ }
+ return (0);
+}
+
+/*
+ * cl_clrtoeol --
+ * Clear from the current cursor to the end of the line.
+ *
+ * PUBLIC: int cl_clrtoeol __P((SCR *));
+ */
+int
+cl_clrtoeol(sp)
+ SCR *sp;
+{
+ return (clrtoeol() == ERR);
+}
+
+/*
+ * cl_cursor --
+ * Return the current cursor position.
+ *
+ * PUBLIC: int cl_cursor __P((SCR *, size_t *, size_t *));
+ */
+int
+cl_cursor(sp, yp, xp)
+ SCR *sp;
+ size_t *yp, *xp;
+{
+ /*
+ * The curses screen support splits a single underlying curses screen
+ * into multiple screens to support split screen semantics. For this
+ * reason the returned value must be adjusted to be relative to the
+ * current screen, and not absolute. Screens that implement the split
+ * using physically distinct screens won't need this hack.
+ */
+ getyx(stdscr, *yp, *xp);
+ *yp -= sp->woff;
+ return (0);
+}
+
+/*
+ * cl_deleteln --
+ * Delete the current line, scrolling all lines below it.
+ *
+ * PUBLIC: int cl_deleteln __P((SCR *));
+ */
+int
+cl_deleteln(sp)
+ SCR *sp;
+{
+ CHAR_T ch;
+ CL_PRIVATE *clp;
+ size_t col, lno, spcnt, oldy, oldx;
+
+ clp = CLP(sp);
+
+ /*
+ * This clause is required because the curses screen uses reverse
+ * video to delimit split screens. If the screen does not do this,
+ * this code won't be necessary.
+ *
+ * If the bottom line was in reverse video, rewrite it in normal
+ * video before it's scrolled.
+ *
+ * Check for the existence of a chgat function; XSI requires it, but
+ * historic implementations of System V curses don't. If it's not
+ * a #define, we'll fall back to doing it by hand, which is slow but
+ * acceptable.
+ *
+ * By hand means walking through the line, retrieving and rewriting
+ * each character. Curses has no EOL marker, so track strings of
+ * spaces, and copy the trailing spaces only if there's a non-space
+ * character following.
+ */
+ if (!F_ISSET(sp, SC_SCR_EXWROTE) && IS_SPLIT(sp)) {
+ getyx(stdscr, oldy, oldx);
+#ifdef mvchgat
+ mvchgat(RLNO(sp, LASTLINE(sp)), 0, -1, A_NORMAL, 0, NULL);
+#else
+ for (lno = RLNO(sp, LASTLINE(sp)), col = spcnt = 0;;) {
+ (void)move(lno, col);
+ ch = winch(stdscr);
+ if (isblank(ch))
+ ++spcnt;
+ else {
+ (void)move(lno, col - spcnt);
+ for (; spcnt > 0; --spcnt)
+ (void)addch(' ');
+ (void)addch(ch);
+ }
+ if (++col >= sp->cols)
+ break;
+ }
+#endif
+ (void)move(oldy, oldx);
+ }
+
+ /*
+ * The bottom line is expected to be blank after this operation,
+ * and other screens must support that semantic.
+ */
+ return (deleteln() == ERR);
+}
+
+/*
+ * cl_ex_adjust --
+ * Adjust the screen for ex. This routine is purely for standalone
+ * ex programs. All special purpose, all special case.
+ *
+ * PUBLIC: int cl_ex_adjust __P((SCR *, exadj_t));
+ */
+int
+cl_ex_adjust(sp, action)
+ SCR *sp;
+ exadj_t action;
+{
+ CL_PRIVATE *clp;
+ int cnt;
+
+ clp = CLP(sp);
+ switch (action) {
+ case EX_TERM_SCROLL:
+ /* Move the cursor up one line if that's possible. */
+ if (clp->cuu1 != NULL)
+ (void)tputs(clp->cuu1, 1, cl_putchar);
+ else if (clp->cup != NULL)
+ (void)tputs(tgoto(clp->cup,
+ 0, LINES - 2), 1, cl_putchar);
+ else
+ return (0);
+ /* FALLTHROUGH */
+ case EX_TERM_CE:
+ /* Clear the line. */
+ if (clp->el != NULL) {
+ (void)putchar('\r');
+ (void)tputs(clp->el, 1, cl_putchar);
+ } else {
+ /*
+ * Historically, ex didn't erase the line, so, if the
+ * displayed line was only a single glyph, and <eof>
+ * was more than one glyph, the output would not fully
+ * overwrite the user's input. To fix this, output
+ * the maxiumum character number of spaces. Note,
+ * this won't help if the user entered extra prompt
+ * or <blank> characters before the command character.
+ * We'd have to do a lot of work to make that work, and
+ * it's almost certainly not worth the effort.
+ */
+ for (cnt = 0; cnt < MAX_CHARACTER_COLUMNS; ++cnt)
+ (void)putchar('\b');
+ for (cnt = 0; cnt < MAX_CHARACTER_COLUMNS; ++cnt)
+ (void)putchar(' ');
+ (void)putchar('\r');
+ (void)fflush(stdout);
+ }
+ break;
+ default:
+ abort();
+ }
+ return (0);
+}
+
+/*
+ * cl_insertln --
+ * Push down the current line, discarding the bottom line.
+ *
+ * PUBLIC: int cl_insertln __P((SCR *));
+ */
+int
+cl_insertln(sp)
+ SCR *sp;
+{
+ /*
+ * The current line is expected to be blank after this operation,
+ * and the screen must support that semantic.
+ */
+ return (insertln() == ERR);
+}
+
+/*
+ * cl_keyval --
+ * Return the value for a special key.
+ *
+ * PUBLIC: int cl_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
+ */
+int
+cl_keyval(sp, val, chp, dnep)
+ SCR *sp;
+ scr_keyval_t val;
+ CHAR_T *chp;
+ int *dnep;
+{
+ CL_PRIVATE *clp;
+
+ /*
+ * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990,
+ * VWERASE is a 4BSD extension.
+ */
+ clp = CLP(sp);
+ switch (val) {
+ case KEY_VEOF:
+ *dnep = (*chp = clp->orig.c_cc[VEOF]) == _POSIX_VDISABLE;
+ break;
+ case KEY_VERASE:
+ *dnep = (*chp = clp->orig.c_cc[VERASE]) == _POSIX_VDISABLE;
+ break;
+ case KEY_VKILL:
+ *dnep = (*chp = clp->orig.c_cc[VKILL]) == _POSIX_VDISABLE;
+ break;
+#ifdef VWERASE
+ case KEY_VWERASE:
+ *dnep = (*chp = clp->orig.c_cc[VWERASE]) == _POSIX_VDISABLE;
+ break;
+#endif
+ default:
+ *dnep = 1;
+ break;
+ }
+ return (0);
+}
+
+/*
+ * cl_move --
+ * Move the cursor.
+ *
+ * PUBLIC: int cl_move __P((SCR *, size_t, size_t));
+ */
+int
+cl_move(sp, lno, cno)
+ SCR *sp;
+ size_t lno, cno;
+{
+ /* See the comment in cl_cursor. */
+ if (move(RLNO(sp, lno), cno) == ERR) {
+ msgq(sp, M_ERR,
+ "Error: move: l(%u) c(%u) o(%u)", lno, cno, sp->woff);
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * cl_refresh --
+ * Refresh the screen.
+ *
+ * PUBLIC: int cl_refresh __P((SCR *, int));
+ */
+int
+cl_refresh(sp, repaint)
+ SCR *sp;
+ int repaint;
+{
+ CL_PRIVATE *clp;
+
+ clp = CLP(sp);
+
+ /*
+ * If we received a killer signal, we're done, there's no point
+ * in refreshing the screen.
+ */
+ if (clp->killersig)
+ return (0);
+
+ /*
+ * If repaint is set, the editor is telling us that we don't know
+ * what's on the screen, so we have to repaint from scratch.
+ *
+ * In the curses library, doing wrefresh(curscr) is okay, but the
+ * screen flashes when we then apply the refresh() to bring it up
+ * to date. So, use clearok().
+ */
+ if (repaint)
+ clearok(curscr, 1);
+ return (refresh() == ERR);
+}
+
+/*
+ * cl_rename --
+ * Rename the file.
+ *
+ * PUBLIC: int cl_rename __P((SCR *, char *, int));
+ */
+int
+cl_rename(sp, name, on)
+ SCR *sp;
+ char *name;
+ int on;
+{
+ GS *gp;
+ CL_PRIVATE *clp;
+ char *ttype;
+
+ gp = sp->gp;
+ clp = CLP(sp);
+
+ ttype = OG_STR(gp, GO_TERM);
+
+ /*
+ * XXX
+ * We can only rename windows for xterm.
+ */
+ if (on) {
+ if (F_ISSET(clp, CL_RENAME_OK) &&
+ !strncmp(ttype, "xterm", sizeof("xterm") - 1)) {
+ F_SET(clp, CL_RENAME);
+ (void)printf(XTERM_RENAME, name);
+ (void)fflush(stdout);
+ }
+ } else
+ if (F_ISSET(clp, CL_RENAME)) {
+ F_CLR(clp, CL_RENAME);
+ (void)printf(XTERM_RENAME, ttype);
+ (void)fflush(stdout);
+ }
+ return (0);
+}
+
+/*
+ * cl_suspend --
+ * Suspend a screen.
+ *
+ * PUBLIC: int cl_suspend __P((SCR *, int *));
+ */
+int
+cl_suspend(sp, allowedp)
+ SCR *sp;
+ int *allowedp;
+{
+ struct termios t;
+ CL_PRIVATE *clp;
+ GS *gp;
+ size_t oldy, oldx;
+ int changed;
+
+ gp = sp->gp;
+ clp = CLP(sp);
+ *allowedp = 1;
+
+ /*
+ * The ex implementation of this function isn't needed by screens not
+ * supporting ex commands that require full terminal canonical mode
+ * (e.g. :suspend).
+ *
+ * The vi implementation of this function isn't needed by screens not
+ * supporting vi process suspension, i.e. any screen that isn't backed
+ * by a UNIX shell.
+ *
+ * Setting allowedp to 0 will cause the editor to reject the command.
+ */
+ if (F_ISSET(sp, SC_EX)) {
+ /* Save the terminal settings, and restore the original ones. */
+ if (F_ISSET(clp, CL_STDIN_TTY)) {
+ (void)tcgetattr(STDIN_FILENO, &t);
+ (void)tcsetattr(STDIN_FILENO,
+ TCSASOFT | TCSADRAIN, &clp->orig);
+ }
+
+ /* Stop the process group. */
+ (void)kill(0, SIGTSTP);
+
+ /* Time passes ... */
+
+ /* Restore terminal settings. */
+ if (F_ISSET(clp, CL_STDIN_TTY))
+ (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t);
+ return (0);
+ }
+
+ /*
+ * Move to the lower left-hand corner of the screen.
+ *
+ * XXX
+ * Not sure this is necessary in System V implementations, but it
+ * shouldn't hurt.
+ */
+ getyx(stdscr, oldy, oldx);
+ (void)move(LINES - 1, 0);
+ (void)refresh();
+
+ /*
+ * Temporarily end the screen. System V introduced a semantic where
+ * endwin() could be restarted. We use it because restarting curses
+ * from scratch often fails in System V. 4BSD curses didn't support
+ * restarting after endwin(), so we have to do what clean up we can
+ * without calling it.
+ */
+#ifdef HAVE_BSD_CURSES
+ /* Save the terminal settings. */
+ (void)tcgetattr(STDIN_FILENO, &t);
+#endif
+
+ /* Restore the cursor keys to normal mode. */
+ (void)keypad(stdscr, FALSE);
+
+ /* Restore the window name. */
+ (void)cl_rename(sp, NULL, 0);
+
+#ifdef HAVE_BSD_CURSES
+ (void)cl_attr(sp, SA_ALTERNATE, 0);
+#else
+ (void)endwin();
+#endif
+ /*
+ * XXX
+ * Restore the original terminal settings. This is bad -- the
+ * reset can cause character loss from the tty queue. However,
+ * we can't call endwin() in BSD curses implementations, and too
+ * many System V curses implementations don't get it right.
+ */
+ (void)tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->orig);
+
+ /* Stop the process group. */
+ (void)kill(0, SIGTSTP);
+
+ /* Time passes ... */
+
+ /*
+ * If we received a killer signal, we're done. Leave everything
+ * unchanged. In addition, the terminal has already been reset
+ * correctly, so leave it alone.
+ */
+ if (clp->killersig) {
+ F_CLR(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT);
+ return (0);
+ }
+
+#ifdef HAVE_BSD_CURSES
+ /* Restore terminal settings. */
+ if (F_ISSET(clp, CL_STDIN_TTY))
+ (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t);
+
+ (void)cl_attr(sp, SA_ALTERNATE, 1);
+#endif
+
+ /* Set the window name. */
+ (void)cl_rename(sp, sp->frp->name, 1);
+
+ /* Put the cursor keys into application mode. */
+ (void)keypad(stdscr, TRUE);
+
+ /* Refresh and repaint the screen. */
+ (void)move(oldy, oldx);
+ (void)cl_refresh(sp, 1);
+
+ /* If the screen changed size, set the SIGWINCH bit. */
+ if (cl_ssize(sp, 1, NULL, NULL, &changed))
+ return (1);
+ if (changed)
+ F_SET(CLP(sp), CL_SIGWINCH);
+
+ return (0);
+}
+
+/*
+ * cl_usage --
+ * Print out the curses usage messages.
+ *
+ * PUBLIC: void cl_usage __P((void));
+ */
+void
+cl_usage()
+{
+#define USAGE "\
+usage: ex [-eFRrSsv] [-c command] [-t tag] [-w size] [file ...]\n\
+usage: vi [-eFlRrSv] [-c command] [-t tag] [-w size] [file ...]\n"
+ (void)fprintf(stderr, "%s", USAGE);
+#undef USAGE
+}
+
+#ifdef DEBUG
+/*
+ * gdbrefresh --
+ * Stub routine so can flush out curses screen changes using gdb.
+ */
+int
+gdbrefresh()
+{
+ refresh();
+ return (0); /* XXX Convince gdb to run it. */
+}
+#endif
diff --git a/contrib/nvi/cl/cl_main.c b/contrib/nvi/cl/cl_main.c
new file mode 100644
index 000000000000..2889f709cbb2
--- /dev/null
+++ b/contrib/nvi/cl/cl_main.c
@@ -0,0 +1,471 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)cl_main.c 10.36 (Berkeley) 10/14/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <curses.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#ifdef RUNNING_IP
+#include "../ip/ip.h"
+#endif
+#include "cl.h"
+#include "pathnames.h"
+
+GS *__global_list; /* GLOBAL: List of screens. */
+sigset_t __sigblockset; /* GLOBAL: Blocked signals. */
+
+static void cl_func_std __P((GS *));
+static CL_PRIVATE *cl_init __P((GS *));
+static GS *gs_init __P((char *));
+static void perr __P((char *, char *));
+static int setsig __P((int, struct sigaction *, void (*)(int)));
+static void sig_end __P((GS *));
+static void term_init __P((char *, char *));
+
+/*
+ * main --
+ * This is the main loop for the standalone curses editor.
+ */
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ static int reenter;
+ CL_PRIVATE *clp;
+ GS *gp;
+ size_t rows, cols;
+ int rval;
+ char *ip_arg, **p_av, **t_av, *ttype;
+
+ /* If loaded at 0 and jumping through a NULL pointer, stop. */
+ if (reenter++)
+ abort();
+
+ /* Create and initialize the global structure. */
+ __global_list = gp = gs_init(argv[0]);
+
+ /*
+ * Strip out any arguments that vi isn't going to understand. There's
+ * no way to portably call getopt twice, so arguments parsed here must
+ * be removed from the argument list.
+ */
+#ifdef RUNNING_IP
+ ip_arg = NULL;
+ for (p_av = t_av = argv;;) {
+ if (*t_av == NULL) {
+ *p_av = NULL;
+ break;
+ }
+ if (!strcmp(*t_av, "--")) {
+ while ((*p_av++ = *t_av++) != NULL);
+ break;
+ }
+ if (!memcmp(*t_av, "-I", sizeof("-I") - 1)) {
+ if (t_av[0][2] != '\0') {
+ ip_arg = t_av[0] + 2;
+ ++t_av;
+ --argc;
+ continue;
+ }
+ if (t_av[1] != NULL) {
+ ip_arg = t_av[1];
+ t_av += 2;
+ argc -= 2;
+ continue;
+ }
+ }
+ *p_av++ = *t_av++;
+ }
+
+ /*
+ * If we're being called as an editor library, we're done here, we
+ * get loaded with the curses screen, we don't share much code.
+ */
+ if (ip_arg != NULL)
+ exit (ip_main(argc, argv, gp, ip_arg));
+#else
+ ip_arg = argv[0];
+#endif
+
+ /* Create and initialize the CL_PRIVATE structure. */
+ clp = cl_init(gp);
+
+ /*
+ * Initialize the terminal information.
+ *
+ * We have to know what terminal it is from the start, since we may
+ * have to use termcap/terminfo to find out how big the screen is.
+ */
+ if ((ttype = getenv("TERM")) == NULL)
+ ttype = "unknown";
+ term_init(gp->progname, ttype);
+
+ /* Add the terminal type to the global structure. */
+ if ((OG_D_STR(gp, GO_TERM) =
+ OG_STR(gp, GO_TERM) = strdup(ttype)) == NULL)
+ perr(gp->progname, NULL);
+
+ /* Figure out how big the screen is. */
+ if (cl_ssize(NULL, 0, &rows, &cols, NULL))
+ exit (1);
+
+ /* Add the rows and columns to the global structure. */
+ OG_VAL(gp, GO_LINES) = OG_D_VAL(gp, GO_LINES) = rows;
+ OG_VAL(gp, GO_COLUMNS) = OG_D_VAL(gp, GO_COLUMNS) = cols;
+
+ /* Ex wants stdout to be buffered. */
+ (void)setvbuf(stdout, NULL, _IOFBF, 0);
+
+ /* Start catching signals. */
+ if (sig_init(gp, NULL))
+ exit (1);
+
+ /* Run ex/vi. */
+ rval = editor(gp, argc, argv);
+
+ /* Clean up signals. */
+ sig_end(gp);
+
+ /* Clean up the terminal. */
+ (void)cl_quit(gp);
+
+ /*
+ * XXX
+ * Reset the O_MESG option.
+ */
+ if (clp->tgw != TGW_UNKNOWN)
+ (void)cl_omesg(NULL, clp, clp->tgw == TGW_SET);
+
+ /*
+ * XXX
+ * Reset the X11 xterm icon/window name.
+ */
+ if (F_ISSET(clp, CL_RENAME)) {
+ (void)printf(XTERM_RENAME, ttype);
+ (void)fflush(stdout);
+ }
+
+ /* If a killer signal arrived, pretend we just got it. */
+ if (clp->killersig) {
+ (void)signal(clp->killersig, SIG_DFL);
+ (void)kill(getpid(), clp->killersig);
+ /* NOTREACHED */
+ }
+
+ /* Free the global and CL private areas. */
+#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
+ free(clp);
+ free(gp);
+#endif
+
+ exit (rval);
+}
+
+/*
+ * gs_init --
+ * Create and partially initialize the GS structure.
+ */
+static GS *
+gs_init(name)
+ char *name;
+{
+ CL_PRIVATE *clp;
+ GS *gp;
+ char *p;
+
+ /* Figure out what our name is. */
+ if ((p = strrchr(name, '/')) != NULL)
+ name = p + 1;
+
+ /* Allocate the global structure. */
+ CALLOC_NOMSG(NULL, gp, GS *, 1, sizeof(GS));
+ if (gp == NULL)
+ perr(name, NULL);
+
+
+ gp->progname = name;
+ return (gp);
+}
+
+/*
+ * cl_init --
+ * Create and partially initialize the CL structure.
+ */
+static CL_PRIVATE *
+cl_init(gp)
+ GS *gp;
+{
+ CL_PRIVATE *clp;
+ int fd;
+
+ /* Allocate the CL private structure. */
+ CALLOC_NOMSG(NULL, clp, CL_PRIVATE *, 1, sizeof(CL_PRIVATE));
+ if (clp == NULL)
+ perr(gp->progname, NULL);
+ gp->cl_private = clp;
+
+ /*
+ * Set the CL_STDIN_TTY flag. It's purpose is to avoid setting
+ * and resetting the tty if the input isn't from there. We also
+ * use the same test to determine if we're running a script or
+ * not.
+ */
+ if (isatty(STDIN_FILENO))
+ F_SET(clp, CL_STDIN_TTY);
+ else
+ F_SET(gp, G_SCRIPTED);
+
+ /*
+ * We expect that if we've lost our controlling terminal that the
+ * open() (but not the tcgetattr()) will fail.
+ */
+ if (F_ISSET(clp, CL_STDIN_TTY)) {
+ if (tcgetattr(STDIN_FILENO, &clp->orig) == -1)
+ goto tcfail;
+ } else if ((fd = open(_PATH_TTY, O_RDONLY, 0)) != -1) {
+ if (tcgetattr(fd, &clp->orig) == -1) {
+tcfail: perr(gp->progname, "tcgetattr");
+ exit (1);
+ }
+ (void)close(fd);
+ }
+
+ /* Initialize the list of curses functions. */
+ cl_func_std(gp);
+
+ return (clp);
+}
+
+/*
+ * term_init --
+ * Initialize terminal information.
+ */
+static void
+term_init(name, ttype)
+ char *name, *ttype;
+{
+ int err;
+
+ /* Set up the terminal database information. */
+ setupterm(ttype, STDOUT_FILENO, &err);
+ switch (err) {
+ case -1:
+ (void)fprintf(stderr,
+ "%s: No terminal database found\n", name);
+ exit (1);
+ case 0:
+ (void)fprintf(stderr,
+ "%s: %s: unknown terminal type\n", name, ttype);
+ exit (1);
+ }
+}
+
+#define GLOBAL_CLP \
+ CL_PRIVATE *clp = GCLP(__global_list);
+static void
+h_hup(signo)
+ int signo;
+{
+ GLOBAL_CLP;
+
+ F_SET(clp, CL_SIGHUP);
+ clp->killersig = SIGHUP;
+}
+
+static void
+h_int(signo)
+ int signo;
+{
+ GLOBAL_CLP;
+
+ F_SET(clp, CL_SIGINT);
+}
+
+static void
+h_term(signo)
+ int signo;
+{
+ GLOBAL_CLP;
+
+ F_SET(clp, CL_SIGTERM);
+ clp->killersig = SIGTERM;
+}
+
+static void
+h_winch(signo)
+ int signo;
+{
+ GLOBAL_CLP;
+
+ F_SET(clp, CL_SIGWINCH);
+}
+#undef GLOBAL_CLP
+
+/*
+ * sig_init --
+ * Initialize signals.
+ *
+ * PUBLIC: int sig_init __P((GS *, SCR *));
+ */
+int
+sig_init(gp, sp)
+ GS *gp;
+ SCR *sp;
+{
+ CL_PRIVATE *clp;
+
+ clp = GCLP(gp);
+
+ if (sp == NULL) {
+ (void)sigemptyset(&__sigblockset);
+ if (sigaddset(&__sigblockset, SIGHUP) ||
+ setsig(SIGHUP, &clp->oact[INDX_HUP], h_hup) ||
+ sigaddset(&__sigblockset, SIGINT) ||
+ setsig(SIGINT, &clp->oact[INDX_INT], h_int) ||
+ sigaddset(&__sigblockset, SIGTERM) ||
+ setsig(SIGTERM, &clp->oact[INDX_TERM], h_term)
+#ifdef SIGWINCH
+ ||
+ sigaddset(&__sigblockset, SIGWINCH) ||
+ setsig(SIGWINCH, &clp->oact[INDX_WINCH], h_winch)
+#endif
+ ) {
+ perr(gp->progname, NULL);
+ return (1);
+ }
+ } else
+ if (setsig(SIGHUP, NULL, h_hup) ||
+ setsig(SIGINT, NULL, h_int) ||
+ setsig(SIGTERM, NULL, h_term)
+#ifdef SIGWINCH
+ ||
+ setsig(SIGWINCH, NULL, h_winch)
+#endif
+ ) {
+ msgq(sp, M_SYSERR, "signal-reset");
+ }
+ return (0);
+}
+
+/*
+ * setsig --
+ * Set a signal handler.
+ */
+static int
+setsig(signo, oactp, handler)
+ int signo;
+ struct sigaction *oactp;
+ void (*handler) __P((int));
+{
+ struct sigaction act;
+
+ /*
+ * Use sigaction(2), not signal(3), since we don't always want to
+ * restart system calls. The example is when waiting for a command
+ * mode keystroke and SIGWINCH arrives. Besides, you can't portably
+ * restart system calls (thanks, POSIX!). On the other hand, you
+ * can't portably NOT restart system calls (thanks, Sun!). SunOS
+ * used SA_INTERRUPT as their extension to NOT restart read calls.
+ * We sure hope nobody else used it for anything else. Mom told me
+ * there'd be days like this. She just never told me that there'd
+ * be so many.
+ */
+ act.sa_handler = handler;
+ sigemptyset(&act.sa_mask);
+
+#ifdef SA_INTERRUPT
+ act.sa_flags = SA_INTERRUPT;
+#else
+ act.sa_flags = 0;
+#endif
+ return (sigaction(signo, &act, oactp));
+}
+
+/*
+ * sig_end --
+ * End signal setup.
+ */
+static void
+sig_end(gp)
+ GS *gp;
+{
+ CL_PRIVATE *clp;
+
+ clp = GCLP(gp);
+ (void)sigaction(SIGHUP, NULL, &clp->oact[INDX_HUP]);
+ (void)sigaction(SIGINT, NULL, &clp->oact[INDX_INT]);
+ (void)sigaction(SIGTERM, NULL, &clp->oact[INDX_TERM]);
+#ifdef SIGWINCH
+ (void)sigaction(SIGWINCH, NULL, &clp->oact[INDX_WINCH]);
+#endif
+}
+
+/*
+ * cl_func_std --
+ * Initialize the standard curses functions.
+ */
+static void
+cl_func_std(gp)
+ GS *gp;
+{
+ gp->scr_addstr = cl_addstr;
+ gp->scr_attr = cl_attr;
+ gp->scr_baud = cl_baud;
+ gp->scr_bell = cl_bell;
+ gp->scr_busy = NULL;
+ gp->scr_clrtoeol = cl_clrtoeol;
+ gp->scr_cursor = cl_cursor;
+ gp->scr_deleteln = cl_deleteln;
+ gp->scr_event = cl_event;
+ gp->scr_ex_adjust = cl_ex_adjust;
+ gp->scr_fmap = cl_fmap;
+ gp->scr_insertln = cl_insertln;
+ gp->scr_keyval = cl_keyval;
+ gp->scr_move = cl_move;
+ gp->scr_msg = NULL;
+ gp->scr_optchange = cl_optchange;
+ gp->scr_refresh = cl_refresh;
+ gp->scr_rename = cl_rename;
+ gp->scr_screen = cl_screen;
+ gp->scr_suspend = cl_suspend;
+ gp->scr_usage = cl_usage;
+}
+
+/*
+ * perr --
+ * Print system error.
+ */
+static void
+perr(name, msg)
+ char *name, *msg;
+{
+ (void)fprintf(stderr, "%s:", name);
+ if (msg != NULL)
+ (void)fprintf(stderr, "%s:", msg);
+ (void)fprintf(stderr, "%s\n", strerror(errno));
+ exit(1);
+}
diff --git a/contrib/nvi/cl/cl_read.c b/contrib/nvi/cl/cl_read.c
new file mode 100644
index 000000000000..8a95a77b2438
--- /dev/null
+++ b/contrib/nvi/cl/cl_read.c
@@ -0,0 +1,334 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)cl_read.c 10.15 (Berkeley) 9/24/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <curses.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../ex/script.h"
+#include "cl.h"
+
+static input_t cl_read __P((SCR *,
+ u_int32_t, CHAR_T *, size_t, int *, struct timeval *));
+static int cl_resize __P((SCR *, size_t, size_t));
+
+/*
+ * cl_event --
+ * Return a single event.
+ *
+ * PUBLIC: int cl_event __P((SCR *, EVENT *, u_int32_t, int));
+ */
+int
+cl_event(sp, evp, flags, ms)
+ SCR *sp;
+ EVENT *evp;
+ u_int32_t flags;
+ int ms;
+{
+ struct timeval t, *tp;
+ CL_PRIVATE *clp;
+ size_t lines, columns;
+ int changed, nr;
+
+ /*
+ * Queue signal based events. We never clear SIGHUP or SIGTERM events,
+ * so that we just keep returning them until the editor dies.
+ */
+ clp = CLP(sp);
+retest: if (LF_ISSET(EC_INTERRUPT) || F_ISSET(clp, CL_SIGINT)) {
+ if (F_ISSET(clp, CL_SIGINT)) {
+ F_CLR(clp, CL_SIGINT);
+ evp->e_event = E_INTERRUPT;
+ } else
+ evp->e_event = E_TIMEOUT;
+ return (0);
+ }
+ if (F_ISSET(clp, CL_SIGHUP | CL_SIGTERM | CL_SIGWINCH)) {
+ if (F_ISSET(clp, CL_SIGHUP)) {
+ evp->e_event = E_SIGHUP;
+ return (0);
+ }
+ if (F_ISSET(clp, CL_SIGTERM)) {
+ evp->e_event = E_SIGTERM;
+ return (0);
+ }
+ if (F_ISSET(clp, CL_SIGWINCH)) {
+ F_CLR(clp, CL_SIGWINCH);
+ if (cl_ssize(sp, 1, &lines, &columns, &changed))
+ return (1);
+ if (changed) {
+ (void)cl_resize(sp, lines, columns);
+ evp->e_event = E_WRESIZE;
+ return (0);
+ }
+ /* No real change, ignore the signal. */
+ }
+ }
+
+ /* Set timer. */
+ if (ms == 0)
+ tp = NULL;
+ else {
+ t.tv_sec = ms / 1000;
+ t.tv_usec = (ms % 1000) * 1000;
+ tp = &t;
+ }
+
+ /* Read input characters. */
+ switch (cl_read(sp, LF_ISSET(EC_QUOTED | EC_RAW),
+ clp->ibuf, sizeof(clp->ibuf), &nr, tp)) {
+ case INP_OK:
+ evp->e_csp = clp->ibuf;
+ evp->e_len = nr;
+ evp->e_event = E_STRING;
+ break;
+ case INP_EOF:
+ evp->e_event = E_EOF;
+ break;
+ case INP_ERR:
+ evp->e_event = E_ERR;
+ break;
+ case INP_INTR:
+ goto retest;
+ case INP_TIMEOUT:
+ evp->e_event = E_TIMEOUT;
+ break;
+ default:
+ abort();
+ }
+ return (0);
+}
+
+/*
+ * cl_read --
+ * Read characters from the input.
+ */
+static input_t
+cl_read(sp, flags, bp, blen, nrp, tp)
+ SCR *sp;
+ u_int32_t flags;
+ CHAR_T *bp;
+ size_t blen;
+ int *nrp;
+ struct timeval *tp;
+{
+ struct termios term1, term2;
+ struct timeval poll;
+ CL_PRIVATE *clp;
+ GS *gp;
+ SCR *tsp;
+ fd_set rdfd;
+ input_t rval;
+ int maxfd, nr, term_reset;
+
+ gp = sp->gp;
+ clp = CLP(sp);
+ term_reset = 0;
+
+ /*
+ * 1: A read from a file or a pipe. In this case, the reads
+ * never timeout regardless. This means that we can hang
+ * when trying to complete a map, but we're going to hang
+ * on the next read anyway.
+ */
+ if (!F_ISSET(clp, CL_STDIN_TTY)) {
+ switch (nr = read(STDIN_FILENO, bp, blen)) {
+ case 0:
+ return (INP_EOF);
+ case -1:
+ goto err;
+ default:
+ *nrp = nr;
+ return (INP_OK);
+ }
+ /* NOTREACHED */
+ }
+
+ /*
+ * 2: A read with an associated timeout, e.g., trying to complete
+ * a map sequence. If input exists, we fall into #3.
+ */
+ FD_ZERO(&rdfd);
+ poll.tv_sec = 0;
+ poll.tv_usec = 0;
+ if (tp != NULL) {
+ FD_SET(STDIN_FILENO, &rdfd);
+ switch (select(STDIN_FILENO + 1,
+ &rdfd, NULL, NULL, tp == NULL ? &poll : tp)) {
+ case 0:
+ return (INP_TIMEOUT);
+ case -1:
+ goto err;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * The user can enter a key in the editor to quote a character. If we
+ * get here and the next key is supposed to be quoted, do what we can.
+ * Reset the tty so that the user can enter a ^C, ^Q, ^S. There's an
+ * obvious race here, when the key has already been entered, but there's
+ * nothing that we can do to fix that problem.
+ *
+ * The editor can ask for the next literal character even thought it's
+ * generally running in line-at-a-time mode. Do what we can.
+ */
+ if (LF_ISSET(EC_QUOTED | EC_RAW) && !tcgetattr(STDIN_FILENO, &term1)) {
+ term_reset = 1;
+ if (LF_ISSET(EC_QUOTED)) {
+ term2 = term1;
+ term2.c_lflag &= ~ISIG;
+ term2.c_iflag &= ~(IXON | IXOFF);
+ (void)tcsetattr(STDIN_FILENO,
+ TCSASOFT | TCSADRAIN, &term2);
+ } else
+ (void)tcsetattr(STDIN_FILENO,
+ TCSASOFT | TCSADRAIN, &clp->vi_enter);
+ }
+
+ /*
+ * 3: Wait for input.
+ *
+ * Select on the command input and scripting window file descriptors.
+ * It's ugly that we wait on scripting file descriptors here, but it's
+ * the only way to keep from locking out scripting windows.
+ */
+ if (F_ISSET(gp, G_SCRWIN)) {
+loop: FD_ZERO(&rdfd);
+ FD_SET(STDIN_FILENO, &rdfd);
+ maxfd = STDIN_FILENO;
+ for (tsp = gp->dq.cqh_first;
+ tsp != (void *)&gp->dq; tsp = tsp->q.cqe_next)
+ if (F_ISSET(sp, SC_SCRIPT)) {
+ FD_SET(sp->script->sh_master, &rdfd);
+ if (sp->script->sh_master > maxfd)
+ maxfd = sp->script->sh_master;
+ }
+ switch (select(maxfd + 1, &rdfd, NULL, NULL, NULL)) {
+ case 0:
+ abort();
+ case -1:
+ goto err;
+ default:
+ break;
+ }
+ if (!FD_ISSET(STDIN_FILENO, &rdfd)) {
+ if (sscr_input(sp))
+ return (INP_ERR);
+ goto loop;
+ }
+ }
+
+ /*
+ * 4: Read the input.
+ *
+ * !!!
+ * What's going on here is some scary stuff. Ex runs the terminal in
+ * canonical mode. So, the <newline> character terminating a line of
+ * input is returned in the buffer, but a trailing <EOF> character is
+ * not similarly included. As ex uses 0<EOF> and ^<EOF> as autoindent
+ * commands, it has to see the trailing <EOF> characters to determine
+ * the difference between the user entering "0ab" and "0<EOF>ab". We
+ * leave an extra slot in the buffer, so that we can add a trailing
+ * <EOF> character if the buffer isn't terminated by a <newline>. We
+ * lose if the buffer is too small for the line and exactly N characters
+ * are entered followed by an <EOF> character.
+ */
+#define ONE_FOR_EOF 1
+ switch (nr = read(STDIN_FILENO, bp, blen - ONE_FOR_EOF)) {
+ case 0: /* EOF. */
+ /*
+ * ^D in canonical mode returns a read of 0, i.e. EOF. EOF is
+ * a valid command, but we don't want to loop forever because
+ * the terminal driver is returning EOF because the user has
+ * disconnected. The editor will almost certainly try to write
+ * something before this fires, which should kill us, but You
+ * Never Know.
+ */
+ if (++clp->eof_count < 50) {
+ bp[0] = clp->orig.c_cc[VEOF];
+ *nrp = 1;
+ rval = INP_OK;
+
+ } else
+ rval = INP_EOF;
+ break;
+ case -1: /* Error or interrupt. */
+err: if (errno == EINTR)
+ rval = INP_INTR;
+ else {
+ rval = INP_ERR;
+ msgq(sp, M_SYSERR, "input");
+ }
+ break;
+ default: /* Input characters. */
+ if (F_ISSET(sp, SC_EX) && bp[nr - 1] != '\n')
+ bp[nr++] = clp->orig.c_cc[VEOF];
+ *nrp = nr;
+ clp->eof_count = 0;
+ rval = INP_OK;
+ break;
+ }
+
+ /* Restore the terminal state if it was modified. */
+ if (term_reset)
+ (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &term1);
+ return (rval);
+}
+
+/*
+ * cl_resize --
+ * Reset the options for a resize event.
+ */
+static int
+cl_resize(sp, lines, columns)
+ SCR *sp;
+ size_t lines, columns;
+{
+ ARGS *argv[2], a, b;
+ char b1[1024];
+
+ a.bp = b1;
+ b.bp = NULL;
+ a.len = b.len = 0;
+ argv[0] = &a;
+ argv[1] = &b;
+
+ (void)snprintf(b1, sizeof(b1), "lines=%lu", (u_long)lines);
+ a.len = strlen(b1);
+ if (opts_set(sp, argv, NULL))
+ return (1);
+ (void)snprintf(b1, sizeof(b1), "columns=%lu", (u_long)columns);
+ a.len = strlen(b1);
+ if (opts_set(sp, argv, NULL))
+ return (1);
+ return (0);
+}
diff --git a/contrib/nvi/cl/cl_screen.c b/contrib/nvi/cl/cl_screen.c
new file mode 100644
index 000000000000..2ce58e80cc78
--- /dev/null
+++ b/contrib/nvi/cl/cl_screen.c
@@ -0,0 +1,581 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)cl_screen.c 10.49 (Berkeley) 9/24/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <curses.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "cl.h"
+
+static int cl_ex_end __P((GS *));
+static int cl_ex_init __P((SCR *));
+static void cl_freecap __P((CL_PRIVATE *));
+static int cl_vi_end __P((GS *));
+static int cl_vi_init __P((SCR *));
+static int cl_putenv __P((char *, char *, u_long));
+
+/*
+ * cl_screen --
+ * Switch screen types.
+ *
+ * PUBLIC: int cl_screen __P((SCR *, u_int32_t));
+ */
+int
+cl_screen(sp, flags)
+ SCR *sp;
+ u_int32_t flags;
+{
+ CL_PRIVATE *clp;
+ GS *gp;
+
+ gp = sp->gp;
+ clp = CLP(sp);
+
+ /* See if the current information is incorrect. */
+ if (F_ISSET(gp, G_SRESTART)) {
+ if (cl_quit(gp))
+ return (1);
+ F_CLR(gp, G_SRESTART);
+ }
+
+ /* See if we're already in the right mode. */
+ if (LF_ISSET(SC_EX) && F_ISSET(sp, SC_SCR_EX) ||
+ LF_ISSET(SC_VI) && F_ISSET(sp, SC_SCR_VI))
+ return (0);
+
+ /*
+ * Fake leaving ex mode.
+ *
+ * We don't actually exit ex or vi mode unless forced (e.g. by a window
+ * size change). This is because many curses implementations can't be
+ * called twice in a single program. Plus, it's faster. If the editor
+ * "leaves" vi to enter ex, when it exits ex we'll just fall back into
+ * vi.
+ */
+ if (F_ISSET(sp, SC_SCR_EX))
+ F_CLR(sp, SC_SCR_EX);
+
+ /*
+ * Fake leaving vi mode.
+ *
+ * Clear out the rest of the screen if we're in the middle of a split
+ * screen. Move to the last line in the current screen -- this makes
+ * terminal scrolling happen naturally. Note: *don't* move past the
+ * end of the screen, as there are ex commands (e.g., :read ! cat file)
+ * that don't want to. Don't clear the info line, its contents may be
+ * valid, e.g. :file|append.
+ */
+ if (F_ISSET(sp, SC_SCR_VI)) {
+ F_CLR(sp, SC_SCR_VI);
+
+ if (sp->q.cqe_next != (void *)&gp->dq) {
+ (void)move(RLNO(sp, sp->rows), 0);
+ clrtobot();
+ }
+ (void)move(RLNO(sp, sp->rows) - 1, 0);
+ refresh();
+ }
+
+ /* Enter the requested mode. */
+ if (LF_ISSET(SC_EX)) {
+ if (cl_ex_init(sp))
+ return (1);
+ F_SET(clp, CL_IN_EX | CL_SCR_EX_INIT);
+
+ /*
+ * If doing an ex screen for ex mode, move to the last line
+ * on the screen.
+ */
+ if (F_ISSET(sp, SC_EX) && clp->cup != NULL)
+ tputs(tgoto(clp->cup,
+ 0, O_VAL(sp, O_LINES) - 1), 1, cl_putchar);
+ } else {
+ if (cl_vi_init(sp))
+ return (1);
+ F_CLR(clp, CL_IN_EX);
+ F_SET(clp, CL_SCR_VI_INIT);
+ }
+ return (0);
+}
+
+/*
+ * cl_quit --
+ * Shutdown the screens.
+ *
+ * PUBLIC: int cl_quit __P((GS *));
+ */
+int
+cl_quit(gp)
+ GS *gp;
+{
+ CL_PRIVATE *clp;
+ int rval;
+
+ rval = 0;
+ clp = GCLP(gp);
+
+ /*
+ * If we weren't really running, ignore it. This happens if the
+ * screen changes size before we've called curses.
+ */
+ if (!F_ISSET(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT))
+ return (0);
+
+ /* Clean up the terminal mappings. */
+ if (cl_term_end(gp))
+ rval = 1;
+
+ /* Really leave vi mode. */
+ if (F_ISSET(clp, CL_STDIN_TTY) &&
+ F_ISSET(clp, CL_SCR_VI_INIT) && cl_vi_end(gp))
+ rval = 1;
+
+ /* Really leave ex mode. */
+ if (F_ISSET(clp, CL_STDIN_TTY) &&
+ F_ISSET(clp, CL_SCR_EX_INIT) && cl_ex_end(gp))
+ rval = 1;
+
+ /*
+ * If we were running ex when we quit, or we're using an implementation
+ * of curses where endwin() doesn't get this right, restore the original
+ * terminal modes.
+ *
+ * XXX
+ * We always do this because it's too hard to figure out what curses
+ * implementations get it wrong. It may discard type-ahead characters
+ * from the tty queue.
+ */
+ (void)tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->orig);
+
+ F_CLR(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT);
+ return (rval);
+}
+
+/*
+ * cl_vi_init --
+ * Initialize the curses vi screen.
+ */
+static int
+cl_vi_init(sp)
+ SCR *sp;
+{
+ CL_PRIVATE *clp;
+ GS *gp;
+ char *o_cols, *o_lines, *o_term, *ttype;
+
+ gp = sp->gp;
+ clp = CLP(sp);
+
+ /* If already initialized, just set the terminal modes. */
+ if (F_ISSET(clp, CL_SCR_VI_INIT))
+ goto fast;
+
+ /* Curses vi always reads from (and writes to) a terminal. */
+ if (!F_ISSET(clp, CL_STDIN_TTY) || !isatty(STDOUT_FILENO)) {
+ msgq(sp, M_ERR,
+ "016|Vi's standard input and output must be a terminal");
+ return (1);
+ }
+
+ /* We'll need a terminal type. */
+ if (opts_empty(sp, O_TERM, 0))
+ return (1);
+ ttype = O_STR(sp, O_TERM);
+
+ /*
+ * XXX
+ * Changing the row/column and terminal values is done by putting them
+ * into the environment, which is then read by curses. What this loses
+ * in ugliness, it makes up for in stupidity. We can't simply put the
+ * values into the environment ourselves, because in the presence of a
+ * kernel mechanism for returning the window size, entering values into
+ * the environment will screw up future screen resizing events, e.g. if
+ * the user enters a :shell command and then resizes their window. So,
+ * if they weren't already in the environment, we make sure to delete
+ * them immediately after setting them.
+ *
+ * XXX
+ * Putting the TERM variable into the environment is necessary, even
+ * though we're using newterm() here. We may be using initscr() as
+ * the underlying function.
+ */
+ o_term = getenv("TERM");
+ cl_putenv("TERM", ttype, 0);
+ o_lines = getenv("LINES");
+ cl_putenv("LINES", NULL, (u_long)O_VAL(sp, O_LINES));
+ o_cols = getenv("COLUMNS");
+ cl_putenv("COLUMNS", NULL, (u_long)O_VAL(sp, O_COLUMNS));
+
+ /*
+ * We don't care about the SCREEN reference returned by newterm, we
+ * never have more than one SCREEN at a time.
+ *
+ * XXX
+ * The SunOS initscr() can't be called twice. Don't even think about
+ * using it. It fails in subtle ways (e.g. select(2) on fileno(stdin)
+ * stops working). (The SVID notes that applications should only call
+ * initscr() once.)
+ *
+ * XXX
+ * The HP/UX newterm doesn't support the NULL first argument, so we
+ * have to specify the terminal type.
+ */
+ errno = 0;
+ if (newterm(ttype, stdout, stdin) == NULL) {
+ if (errno)
+ msgq(sp, M_SYSERR, "%s", ttype);
+ else
+ msgq(sp, M_ERR, "%s: unknown terminal type", ttype);
+ return (1);
+ }
+
+ if (o_term == NULL)
+ unsetenv("TERM");
+ if (o_lines == NULL)
+ unsetenv("LINES");
+ if (o_cols == NULL)
+ unsetenv("COLUMNS");
+
+ /*
+ * XXX
+ * Someone got let out alone without adult supervision -- the SunOS
+ * newterm resets the signal handlers. There's a race, but it's not
+ * worth closing.
+ */
+ (void)sig_init(sp->gp, sp);
+
+ /*
+ * We use raw mode. What we want is 8-bit clean, however, signals
+ * and flow control should continue to work. Admittedly, it sounds
+ * like cbreak, but it isn't. Using cbreak() can get you additional
+ * things like IEXTEN, which turns on flags like DISCARD and LNEXT.
+ *
+ * !!!
+ * If raw isn't turning off echo and newlines, something's wrong.
+ * However, it shouldn't hurt.
+ */
+ noecho(); /* No character echo. */
+ nonl(); /* No CR/NL translation. */
+ raw(); /* 8-bit clean. */
+ idlok(stdscr, 1); /* Use hardware insert/delete line. */
+
+ /* Put the cursor keys into application mode. */
+ (void)keypad(stdscr, TRUE);
+
+ /*
+ * XXX
+ * The screen TI sequence just got sent. See the comment in
+ * cl_funcs.c:cl_attr().
+ */
+ clp->ti_te = TI_SENT;
+
+ /*
+ * XXX
+ * Historic implementations of curses handled SIGTSTP signals
+ * in one of three ways. They either:
+ *
+ * 1: Set their own handler, regardless.
+ * 2: Did not set a handler if a handler was already installed.
+ * 3: Set their own handler, but then called any previously set
+ * handler after completing their own cleanup.
+ *
+ * We don't try and figure out which behavior is in place, we force
+ * it to SIG_DFL after initializing the curses interface, which means
+ * that curses isn't going to take the signal. Since curses isn't
+ * reentrant (i.e., the whole curses SIGTSTP interface is a fantasy),
+ * we're doing The Right Thing.
+ */
+ (void)signal(SIGTSTP, SIG_DFL);
+
+ /*
+ * If flow control was on, turn it back on. Turn signals on. ISIG
+ * turns on VINTR, VQUIT, VDSUSP and VSUSP. The main curses code
+ * already installed a handler for VINTR. We're going to disable the
+ * other three.
+ *
+ * XXX
+ * We want to use ^Y as a vi scrolling command. If the user has the
+ * DSUSP character set to ^Y (common practice) clean it up. As it's
+ * equally possible that the user has VDSUSP set to 'a', we disable
+ * it regardless. It doesn't make much sense to suspend vi at read,
+ * so I don't think anyone will care. Alternatively, we could look
+ * it up in the table of legal command characters and turn it off if
+ * it matches one. VDSUSP wasn't in POSIX 1003.1-1990, so we test for
+ * it.
+ *
+ * XXX
+ * We don't check to see if the user had signals enabled originally.
+ * If they didn't, it's unclear what we're supposed to do here, but
+ * it's also pretty unlikely.
+ */
+ if (tcgetattr(STDIN_FILENO, &clp->vi_enter)) {
+ msgq(sp, M_SYSERR, "tcgetattr");
+ goto err;
+ }
+ if (clp->orig.c_iflag & IXON)
+ clp->vi_enter.c_iflag |= IXON;
+ if (clp->orig.c_iflag & IXOFF)
+ clp->vi_enter.c_iflag |= IXOFF;
+
+ clp->vi_enter.c_lflag |= ISIG;
+#ifdef VDSUSP
+ clp->vi_enter.c_cc[VDSUSP] = _POSIX_VDISABLE;
+#endif
+ clp->vi_enter.c_cc[VQUIT] = _POSIX_VDISABLE;
+ clp->vi_enter.c_cc[VSUSP] = _POSIX_VDISABLE;
+
+ /*
+ * XXX
+ * OSF/1 doesn't turn off the <discard>, <literal-next> or <status>
+ * characters when curses switches into raw mode. It should be OK
+ * to do it explicitly for everyone.
+ */
+#ifdef VDISCARD
+ clp->vi_enter.c_cc[VDISCARD] = _POSIX_VDISABLE;
+#endif
+#ifdef VLNEXT
+ clp->vi_enter.c_cc[VLNEXT] = _POSIX_VDISABLE;
+#endif
+#ifdef VSTATUS
+ clp->vi_enter.c_cc[VSTATUS] = _POSIX_VDISABLE;
+#endif
+
+ /* Initialize terminal based information. */
+ if (cl_term_init(sp))
+ goto err;
+
+fast: /* Set the terminal modes. */
+ if (tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &clp->vi_enter)) {
+ msgq(sp, M_SYSERR, "tcsetattr");
+err: (void)cl_vi_end(sp->gp);
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * cl_vi_end --
+ * Shutdown the vi screen.
+ */
+static int
+cl_vi_end(gp)
+ GS *gp;
+{
+ CL_PRIVATE *clp;
+
+ clp = GCLP(gp);
+
+ /* Restore the cursor keys to normal mode. */
+ (void)keypad(stdscr, FALSE);
+
+ /*
+ * If we were running vi when we quit, scroll the screen up a single
+ * line so we don't lose any information.
+ *
+ * Move to the bottom of the window (some endwin implementations don't
+ * do this for you).
+ */
+ if (!F_ISSET(clp, CL_IN_EX)) {
+ (void)move(0, 0);
+ (void)deleteln();
+ (void)move(LINES - 1, 0);
+ (void)refresh();
+ }
+
+ cl_freecap(clp);
+
+ /* End curses window. */
+ (void)endwin();
+
+ /*
+ * XXX
+ * The screen TE sequence just got sent. See the comment in
+ * cl_funcs.c:cl_attr().
+ */
+ clp->ti_te = TE_SENT;
+
+ return (0);
+}
+
+/*
+ * cl_ex_init --
+ * Initialize the ex screen.
+ */
+static int
+cl_ex_init(sp)
+ SCR *sp;
+{
+ CL_PRIVATE *clp;
+
+ clp = CLP(sp);
+
+ /* If already initialized, just set the terminal modes. */
+ if (F_ISSET(clp, CL_SCR_EX_INIT))
+ goto fast;
+
+ /* If not reading from a file, we're done. */
+ if (!F_ISSET(clp, CL_STDIN_TTY))
+ return (0);
+
+ /* Get the ex termcap/terminfo strings. */
+ (void)cl_getcap(sp, "cup", &clp->cup);
+ (void)cl_getcap(sp, "smso", &clp->smso);
+ (void)cl_getcap(sp, "rmso", &clp->rmso);
+ (void)cl_getcap(sp, "el", &clp->el);
+ (void)cl_getcap(sp, "cuu1", &clp->cuu1);
+
+ /* Enter_standout_mode and exit_standout_mode are paired. */
+ if (clp->smso == NULL || clp->rmso == NULL) {
+ if (clp->smso != NULL) {
+ free(clp->smso);
+ clp->smso = NULL;
+ }
+ if (clp->rmso != NULL) {
+ free(clp->rmso);
+ clp->rmso = NULL;
+ }
+ }
+
+ /*
+ * Turn on canonical mode, with normal input and output processing.
+ * Start with the original terminal settings as the user probably
+ * had them (including any local extensions) set correctly for the
+ * current terminal.
+ *
+ * !!!
+ * We can't get everything that we need portably; for example, ONLCR,
+ * mapping <newline> to <carriage-return> on output isn't required
+ * by POSIX 1003.1b-1993. If this turns out to be a problem, then
+ * we'll either have to play some games on the mapping, or we'll have
+ * to make all ex printf's output \r\n instead of \n.
+ */
+ clp->ex_enter = clp->orig;
+ clp->ex_enter.c_lflag |= ECHO | ECHOE | ECHOK | ICANON | IEXTEN | ISIG;
+#ifdef ECHOCTL
+ clp->ex_enter.c_lflag |= ECHOCTL;
+#endif
+#ifdef ECHOKE
+ clp->ex_enter.c_lflag |= ECHOKE;
+#endif
+ clp->ex_enter.c_iflag |= ICRNL;
+ clp->ex_enter.c_oflag |= OPOST;
+#ifdef ONLCR
+ clp->ex_enter.c_oflag |= ONLCR;
+#endif
+
+fast: if (tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->ex_enter)) {
+ msgq(sp, M_SYSERR, "tcsetattr");
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * cl_ex_end --
+ * Shutdown the ex screen.
+ */
+static int
+cl_ex_end(gp)
+ GS *gp;
+{
+ CL_PRIVATE *clp;
+
+ clp = GCLP(gp);
+
+ cl_freecap(clp);
+
+ return (0);
+}
+
+/*
+ * cl_getcap --
+ * Retrieve termcap/terminfo strings.
+ *
+ * PUBLIC: int cl_getcap __P((SCR *, char *, char **));
+ */
+int
+cl_getcap(sp, name, elementp)
+ SCR *sp;
+ char *name, **elementp;
+{
+ size_t len;
+ char *t;
+
+ if ((t = tigetstr(name)) != NULL &&
+ t != (char *)-1 && (len = strlen(t)) != 0) {
+ MALLOC_RET(sp, *elementp, char *, len + 1);
+ memmove(*elementp, t, len + 1);
+ }
+ return (0);
+}
+
+/*
+ * cl_freecap --
+ * Free any allocated termcap/terminfo strings.
+ */
+static void
+cl_freecap(clp)
+ CL_PRIVATE *clp;
+{
+ if (clp->el != NULL) {
+ free(clp->el);
+ clp->el = NULL;
+ }
+ if (clp->cup != NULL) {
+ free(clp->cup);
+ clp->cup = NULL;
+ }
+ if (clp->cuu1 != NULL) {
+ free(clp->cuu1);
+ clp->cuu1 = NULL;
+ }
+ if (clp->rmso != NULL) {
+ free(clp->rmso);
+ clp->rmso = NULL;
+ }
+ if (clp->smso != NULL) {
+ free(clp->smso);
+ clp->smso = NULL;
+ }
+}
+
+/*
+ * cl_putenv --
+ * Put a value into the environment.
+ */
+static int
+cl_putenv(name, str, value)
+ char *name, *str;
+ u_long value;
+
+{
+ char buf[40];
+
+ if (str == NULL) {
+ (void)snprintf(buf, sizeof(buf), "%lu", value);
+ return (setenv(name, buf, 1));
+ } else
+ return (setenv(name, str, 1));
+}
diff --git a/contrib/nvi/cl/cl_term.c b/contrib/nvi/cl/cl_term.c
new file mode 100644
index 000000000000..e4007403870e
--- /dev/null
+++ b/contrib/nvi/cl/cl_term.c
@@ -0,0 +1,459 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)cl_term.c 10.22 (Berkeley) 9/15/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <curses.h>
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "cl.h"
+
+static int cl_pfmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
+
+/*
+ * XXX
+ * THIS REQUIRES THAT ALL SCREENS SHARE A TERMINAL TYPE.
+ */
+typedef struct _tklist {
+ char *ts; /* Key's termcap string. */
+ char *output; /* Corresponding vi command. */
+ char *name; /* Name. */
+ u_char value; /* Special value (for lookup). */
+} TKLIST;
+static TKLIST const c_tklist[] = { /* Command mappings. */
+ {"kil1", "O", "insert line"},
+ {"kdch1", "x", "delete character"},
+ {"kcud1", "j", "cursor down"},
+ {"kel", "D", "delete to eol"},
+ {"kind", "\004", "scroll down"}, /* ^D */
+ {"kll", "$", "go to eol"},
+ {"khome", "^", "go to sol"},
+ {"kich1", "i", "insert at cursor"},
+ {"kdl1", "dd", "delete line"},
+ {"kcub1", "h", "cursor left"},
+ {"knp", "\006", "page down"}, /* ^F */
+ {"kpp", "\002", "page up"}, /* ^B */
+ {"kri", "\025", "scroll up"}, /* ^U */
+ {"ked", "dG", "delete to end of screen"},
+ {"kcuf1", "l", "cursor right"},
+ {"kcuu1", "k", "cursor up"},
+ {NULL},
+};
+static TKLIST const m1_tklist[] = { /* Input mappings (lookup). */
+ {NULL},
+};
+static TKLIST const m2_tklist[] = { /* Input mappings (set or delete). */
+ {"kcud1", "\033ja", "cursor down"}, /* ^[ja */
+ {"kcub1", "\033ha", "cursor left"}, /* ^[ha */
+ {"kcuu1", "\033ka", "cursor up"}, /* ^[ka */
+ {"kcuf1", "\033la", "cursor right"}, /* ^[la */
+ {NULL},
+};
+
+/*
+ * cl_term_init --
+ * Initialize the special keys defined by the termcap/terminfo entry.
+ *
+ * PUBLIC: int cl_term_init __P((SCR *));
+ */
+int
+cl_term_init(sp)
+ SCR *sp;
+{
+ KEYLIST *kp;
+ SEQ *qp;
+ TKLIST const *tkp;
+ char *t;
+
+ /* Command mappings. */
+ for (tkp = c_tklist; tkp->name != NULL; ++tkp) {
+ if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
+ continue;
+ if (seq_set(sp, tkp->name, strlen(tkp->name), t, strlen(t),
+ tkp->output, strlen(tkp->output), SEQ_COMMAND,
+ SEQ_NOOVERWRITE | SEQ_SCREEN))
+ return (1);
+ }
+
+ /* Input mappings needing to be looked up. */
+ for (tkp = m1_tklist; tkp->name != NULL; ++tkp) {
+ if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
+ continue;
+ for (kp = keylist;; ++kp)
+ if (kp->value == tkp->value)
+ break;
+ if (kp == NULL)
+ continue;
+ if (seq_set(sp, tkp->name, strlen(tkp->name), t, strlen(t),
+ &kp->ch, 1, SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
+ return (1);
+ }
+
+ /* Input mappings that are already set or are text deletions. */
+ for (tkp = m2_tklist; tkp->name != NULL; ++tkp) {
+ if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
+ continue;
+ /*
+ * !!!
+ * Some terminals' <cursor_left> keys send single <backspace>
+ * characters. This is okay in command mapping, but not okay
+ * in input mapping. That combination is the only one we'll
+ * ever see, hopefully, so kluge it here for now.
+ */
+ if (!strcmp(t, "\b"))
+ continue;
+ if (tkp->output == NULL) {
+ if (seq_set(sp, tkp->name, strlen(tkp->name),
+ t, strlen(t), NULL, 0,
+ SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
+ return (1);
+ } else
+ if (seq_set(sp, tkp->name, strlen(tkp->name),
+ t, strlen(t), tkp->output, strlen(tkp->output),
+ SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
+ return (1);
+ }
+
+ /*
+ * Rework any function key mappings that were set before the
+ * screen was initialized.
+ */
+ for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next)
+ if (F_ISSET(qp, SEQ_FUNCMAP))
+ (void)cl_pfmap(sp, qp->stype,
+ qp->input, qp->ilen, qp->output, qp->olen);
+ return (0);
+}
+
+/*
+ * cl_term_end --
+ * End the special keys defined by the termcap/terminfo entry.
+ *
+ * PUBLIC: int cl_term_end __P((GS *));
+ */
+int
+cl_term_end(gp)
+ GS *gp;
+{
+ SEQ *qp, *nqp;
+
+ /* Delete screen specific mappings. */
+ for (qp = gp->seqq.lh_first; qp != NULL; qp = nqp) {
+ nqp = qp->q.le_next;
+ if (F_ISSET(qp, SEQ_SCREEN))
+ (void)seq_mdel(qp);
+ }
+ return (0);
+}
+
+/*
+ * cl_fmap --
+ * Map a function key.
+ *
+ * PUBLIC: int cl_fmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
+ */
+int
+cl_fmap(sp, stype, from, flen, to, tlen)
+ SCR *sp;
+ seq_t stype;
+ CHAR_T *from, *to;
+ size_t flen, tlen;
+{
+ /* Ignore until the screen is running, do the real work then. */
+ if (F_ISSET(sp, SC_VI) && !F_ISSET(sp, SC_SCR_VI))
+ return (0);
+ if (F_ISSET(sp, SC_EX) && !F_ISSET(sp, SC_SCR_EX))
+ return (0);
+
+ return (cl_pfmap(sp, stype, from, flen, to, tlen));
+}
+
+/*
+ * cl_pfmap --
+ * Map a function key (private version).
+ */
+static int
+cl_pfmap(sp, stype, from, flen, to, tlen)
+ SCR *sp;
+ seq_t stype;
+ CHAR_T *from, *to;
+ size_t flen, tlen;
+{
+ size_t nlen;
+ char *p, keyname[64];
+
+ (void)snprintf(keyname, sizeof(keyname), "kf%d", atoi(from + 1));
+ if ((p = tigetstr(keyname)) == NULL ||
+ p == (char *)-1 || strlen(p) == 0)
+ p = NULL;
+ if (p == NULL) {
+ msgq_str(sp, M_ERR, from, "233|This terminal has no %s key");
+ return (1);
+ }
+
+ nlen = snprintf(keyname,
+ sizeof(keyname), "function key %d", atoi(from + 1));
+ return (seq_set(sp, keyname, nlen,
+ p, strlen(p), to, tlen, stype, SEQ_NOOVERWRITE | SEQ_SCREEN));
+}
+
+/*
+ * cl_optchange --
+ * Curses screen specific "option changed" routine.
+ *
+ * PUBLIC: int cl_optchange __P((SCR *, int, char *, u_long *));
+ */
+int
+cl_optchange(sp, opt, str, valp)
+ SCR *sp;
+ int opt;
+ char *str;
+ u_long *valp;
+{
+ CL_PRIVATE *clp;
+
+ clp = CLP(sp);
+
+ switch (opt) {
+ case O_COLUMNS:
+ case O_LINES:
+ case O_TERM:
+ /*
+ * Changing the columns, lines or terminal require that
+ * we restart the screen.
+ */
+ F_SET(sp->gp, G_SRESTART);
+ F_CLR(sp, SC_SCR_EX | SC_SCR_VI);
+ break;
+ case O_MESG:
+ (void)cl_omesg(sp, clp, !*valp);
+ break;
+ case O_WINDOWNAME:
+ if (*valp) {
+ F_CLR(clp, CL_RENAME_OK);
+
+ (void)cl_rename(sp, NULL, 0);
+ } else {
+ F_SET(clp, CL_RENAME_OK);
+
+ /*
+ * If the screen is live, i.e. we're not reading the
+ * .exrc file, update the window.
+ */
+ if (sp->frp != NULL && sp->frp->name != NULL)
+ (void)cl_rename(sp, sp->frp->name, 1);
+ }
+ break;
+ }
+ return (0);
+}
+
+/*
+ * cl_omesg --
+ * Turn the tty write permission on or off.
+ *
+ * PUBLIC: int cl_omesg __P((SCR *, CL_PRIVATE *, int));
+ */
+int
+cl_omesg(sp, clp, on)
+ SCR *sp;
+ CL_PRIVATE *clp;
+ int on;
+{
+ struct stat sb;
+ char *tty;
+
+ /* Find the tty, get the current permissions. */
+ if ((tty = ttyname(STDERR_FILENO)) == NULL) {
+ if (sp != NULL)
+ msgq(sp, M_SYSERR, "stderr");
+ return (1);
+ }
+ if (stat(tty, &sb) < 0) {
+ if (sp != NULL)
+ msgq(sp, M_SYSERR, "%s", tty);
+ return (1);
+ }
+
+ /* Save the original status if it's unknown. */
+ if (clp->tgw == TGW_UNKNOWN)
+ clp->tgw = sb.st_mode & S_IWGRP ? TGW_SET : TGW_UNSET;
+
+ /* Toggle the permissions. */
+ if (on) {
+ if (chmod(tty, sb.st_mode | S_IWGRP) < 0) {
+ if (sp != NULL)
+ msgq(sp, M_SYSERR,
+ "046|messages not turned on: %s", tty);
+ return (1);
+ }
+ } else
+ if (chmod(tty, sb.st_mode & ~S_IWGRP) < 0) {
+ if (sp != NULL)
+ msgq(sp, M_SYSERR,
+ "045|messages not turned off: %s", tty);
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * cl_ssize --
+ * Return the terminal size.
+ *
+ * PUBLIC: int cl_ssize __P((SCR *, int, size_t *, size_t *, int *));
+ */
+int
+cl_ssize(sp, sigwinch, rowp, colp, changedp)
+ SCR *sp;
+ int sigwinch;
+ size_t *rowp, *colp;
+ int *changedp;
+{
+#ifdef TIOCGWINSZ
+ struct winsize win;
+#endif
+ size_t col, row;
+ int rval;
+ char *p;
+
+ /* Assume it's changed. */
+ if (changedp != NULL)
+ *changedp = 1;
+
+ /*
+ * !!!
+ * sp may be NULL.
+ *
+ * Get the screen rows and columns. If the values are wrong, it's
+ * not a big deal -- as soon as the user sets them explicitly the
+ * environment will be set and the screen package will use the new
+ * values.
+ *
+ * Try TIOCGWINSZ.
+ */
+ row = col = 0;
+#ifdef TIOCGWINSZ
+ if (ioctl(STDERR_FILENO, TIOCGWINSZ, &win) != -1) {
+ row = win.ws_row;
+ col = win.ws_col;
+ }
+#endif
+ /* If here because of suspend or a signal, only trust TIOCGWINSZ. */
+ if (sigwinch) {
+ /*
+ * Somebody didn't get TIOCGWINSZ right, or has suspend
+ * without window resizing support. The user just lost,
+ * but there's nothing we can do.
+ */
+ if (row == 0 || col == 0) {
+ if (changedp != NULL)
+ *changedp = 0;
+ return (0);
+ }
+
+ /*
+ * SunOS systems deliver SIGWINCH when windows are uncovered
+ * as well as when they change size. In addition, we call
+ * here when continuing after being suspended since the window
+ * may have changed size. Since we don't want to background
+ * all of the screens just because the window was uncovered,
+ * ignore the signal if there's no change.
+ */
+ if (sp != NULL &&
+ row == O_VAL(sp, O_LINES) && col == O_VAL(sp, O_COLUMNS)) {
+ if (changedp != NULL)
+ *changedp = 0;
+ return (0);
+ }
+
+ if (rowp != NULL)
+ *rowp = row;
+ if (colp != NULL)
+ *colp = col;
+ return (0);
+ }
+
+ /*
+ * !!!
+ * If TIOCGWINSZ failed, or had entries of 0, try termcap. This
+ * routine is called before any termcap or terminal information
+ * has been set up. If there's no TERM environmental variable set,
+ * let it go, at least ex can run.
+ */
+ if (row == 0 || col == 0) {
+ if ((p = getenv("TERM")) == NULL)
+ goto noterm;
+ if (row == 0)
+ if ((rval = tigetnum("lines")) < 0)
+ msgq(sp, M_SYSERR, "tigetnum: lines");
+ else
+ row = rval;
+ if (col == 0)
+ if ((rval = tigetnum("cols")) < 0)
+ msgq(sp, M_SYSERR, "tigetnum: cols");
+ else
+ col = rval;
+ }
+
+ /* If nothing else, well, it's probably a VT100. */
+noterm: if (row == 0)
+ row = 24;
+ if (col == 0)
+ col = 80;
+
+ /*
+ * !!!
+ * POSIX 1003.2 requires the environment to override everything.
+ * Often, people can get nvi to stop messing up their screen by
+ * deleting the LINES and COLUMNS environment variables from their
+ * dot-files.
+ */
+ if ((p = getenv("LINES")) != NULL)
+ row = strtol(p, NULL, 10);
+ if ((p = getenv("COLUMNS")) != NULL)
+ col = strtol(p, NULL, 10);
+
+ if (rowp != NULL)
+ *rowp = row;
+ if (colp != NULL)
+ *colp = col;
+ return (0);
+}
+
+/*
+ * cl_putchar --
+ * Function version of putchar, for tputs.
+ *
+ * PUBLIC: int cl_putchar __P((int));
+ */
+int
+cl_putchar(ch)
+ int ch;
+{
+ return (putchar(ch));
+}
diff --git a/usr.bin/vi/ex/ex_abbrev.c b/contrib/nvi/clib/bsearch.c
index a0af8cd8d13b..6b41ab5fcef8 100644
--- a/usr.bin/vi/ex/ex_abbrev.c
+++ b/contrib/nvi/clib/bsearch.c
@@ -1,5 +1,5 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
+/*
+ * Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,99 +31,60 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static char sccsid[] = "@(#)ex_abbrev.c 8.12 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
+#include "config.h"
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)bsearch.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
+#include <stddef.h>
+#include <stdlib.h>
-#include "vi.h"
-#include "excmd.h"
-#include "../vi/vcmd.h"
+#include "port.h"
/*
- * ex_abbr -- :abbreviate [key replacement]
- * Create an abbreviation or display abbreviations.
- */
-int
-ex_abbr(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- CHAR_T *p;
- size_t len;
-
- switch (cmdp->argc) {
- case 0:
- if (seq_dump(sp, SEQ_ABBREV, 0) == 0)
- msgq(sp, M_INFO, "No abbreviations to display");
- return (0);
- case 2:
- break;
- default:
- abort();
- }
-
- /* Check for illegal characters. */
- for (p = cmdp->argv[0]->bp, len = cmdp->argv[0]->len; len--; ++p)
- if (!inword(*p)) {
- msgq(sp, M_ERR,
- "%s may not be part of an abbreviated word",
- KEY_NAME(sp, *p));
- return (1);
- }
-
- if (seq_set(sp, NULL, 0, cmdp->argv[0]->bp, cmdp->argv[0]->len,
- cmdp->argv[1]->bp, cmdp->argv[1]->len, SEQ_ABBREV, SEQ_USERDEF))
- return (1);
-
- F_SET(sp->gp, G_ABBREV);
- return (0);
-}
-
-/*
- * ex_unabbr -- :unabbreviate key
- * Delete an abbreviation.
+ * Perform a binary search.
+ *
+ * The code below is a bit sneaky. After a comparison fails, we
+ * divide the work in half by moving either left or right. If lim
+ * is odd, moving left simply involves halving lim: e.g., when lim
+ * is 5 we look at item 2, so we change lim to 2 so that we will
+ * look at items 0 & 1. If lim is even, the same applies. If lim
+ * is odd, moving right again involes halving lim, this time moving
+ * the base up one item past p: e.g., when lim is 5 we change base
+ * to item 3 and make lim 2 so that we will look at items 3 and 4.
+ * If lim is even, however, we have to shrink it by one before
+ * halving: e.g., when lim is 4, we still looked at item 2, so we
+ * have to make lim 3, then halve, obtaining 1, so that we will only
+ * look at item 3.
+ *
+ * PUBLIC: #ifndef HAVE_BSEARCH
+ * PUBLIC: void *bsearch __P((const void *, const void *, size_t,
+ * PUBLIC: size_t, int (*)(const void *, const void *)));
+ * PUBLIC: #endif
*/
-int
-ex_unabbr(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+void *
+bsearch(key, base0, nmemb, size, compar)
+ register const void *key;
+ const void *base0;
+ size_t nmemb;
+ register size_t size;
+ register int (*compar) __P((const void *, const void *));
{
- ARGS *ap;
+ register const char *base = base0;
+ register size_t lim;
+ register int cmp;
+ register const void *p;
- ap = cmdp->argv[0];
- if (!F_ISSET(sp->gp, G_ABBREV) ||
- seq_delete(sp, ap->bp, ap->len, SEQ_ABBREV)) {
- msgq(sp, M_ERR, "\"%s\" is not an abbreviation", ap->bp);
- return (1);
+ for (lim = nmemb; lim != 0; lim >>= 1) {
+ p = base + (lim >> 1) * size;
+ cmp = (*compar)(key, p);
+ if (cmp == 0)
+ return ((void *)p);
+ if (cmp > 0) { /* key > p: move right */
+ base = (char *)p + size;
+ lim--;
+ } /* else move left */
}
- return (0);
-}
-
-/*
- * abbr_save --
- * Save the abbreviation sequences to a file.
- */
-int
-abbr_save(sp, fp)
- SCR *sp;
- FILE *fp;
-{
- return (seq_save(sp, fp, "abbreviate ", SEQ_ABBREV));
+ return (NULL);
}
diff --git a/contrib/nvi/clib/env.c b/contrib/nvi/clib/env.c
new file mode 100644
index 000000000000..5a45dc1760a6
--- /dev/null
+++ b/contrib/nvi/clib/env.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)getenv.c 8.1 (Berkeley) 6/4/93";
+static const char sccsid[] = "@(#)setenv.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * __findenv --
+ * Returns pointer to value associated with name, if any, else NULL.
+ * Sets offset to be the offset of the name/value combination in the
+ * environmental array, for use by setenv(3) and unsetenv(3).
+ * Explicitly removes '=' in argument name.
+ *
+ * This routine *should* be a static; don't use it.
+ */
+static char *
+__findenv(name, offset)
+ register char *name;
+ int *offset;
+{
+ extern char **environ;
+ register int len;
+ register char *np;
+ register char **p, *c;
+
+ if (name == NULL || environ == NULL)
+ return (NULL);
+ for (np = name; *np && *np != '='; ++np)
+ continue;
+ len = np - name;
+ for (p = environ; (c = *p) != NULL; ++p)
+ if (strncmp(c, name, len) == 0 && c[len] == '=') {
+ *offset = p - environ;
+ return (c + len + 1);
+ }
+ return (NULL);
+}
+
+#ifndef HAVE_SETENV
+/*
+ * setenv --
+ * Set the value of the environmental variable "name" to be
+ * "value". If rewrite is set, replace any current value.
+ *
+ * PUBLIC: #ifndef HAVE_SETENV
+ * PUBLIC: int setenv __P((const char *, const char *, int));
+ * PUBLIC: #endif
+ */
+setenv(name, value, rewrite)
+ register char *name;
+ register char *value;
+ int rewrite;
+{
+ extern char **environ;
+ static int alloced; /* if allocated space before */
+ register char *c;
+ int l_value, offset;
+
+ if (*value == '=') /* no `=' in value */
+ ++value;
+ l_value = strlen(value);
+ if ((c = __findenv(name, &offset))) { /* find if already exists */
+ if (!rewrite)
+ return (0);
+ if (strlen(c) >= l_value) { /* old larger; copy over */
+ while (*c++ = *value++);
+ return (0);
+ }
+ } else { /* create new slot */
+ register int cnt;
+ register char **p;
+
+ for (p = environ, cnt = 0; *p; ++p, ++cnt);
+ if (alloced) { /* just increase size */
+ environ = (char **)realloc((char *)environ,
+ (size_t)(sizeof(char *) * (cnt + 2)));
+ if (!environ)
+ return (-1);
+ }
+ else { /* get new space */
+ alloced = 1; /* copy old entries into it */
+ p = malloc((size_t)(sizeof(char *) * (cnt + 2)));
+ if (!p)
+ return (-1);
+ memmove(p, environ, cnt * sizeof(char *));
+ environ = p;
+ }
+ environ[cnt + 1] = NULL;
+ offset = cnt;
+ }
+ for (c = (char *)name; *c && *c != '='; ++c); /* no `=' in name */
+ if (!(environ[offset] = /* name + `=' + value */
+ malloc((size_t)((int)(c - name) + l_value + 2))))
+ return (-1);
+ for (c = environ[offset]; (*c = *name++) && *c != '='; ++c);
+ for (*c++ = '='; *c++ = *value++;);
+ return (0);
+}
+#endif
+
+#ifndef HAVE_UNSETENV
+/*
+ * unsetenv(name) --
+ * Delete environmental variable "name".
+ *
+ * PUBLIC: #ifndef HAVE_UNSETENV
+ * PUBLIC: void unsetenv __P((const char *));
+ * PUBLIC: #endif
+ */
+void
+unsetenv(name)
+ char *name;
+{
+ extern char **environ;
+ register char **p;
+ int offset;
+
+ while (__findenv(name, &offset)) /* if set multiple times */
+ for (p = &environ[offset];; ++p)
+ if (!(*p = *(p + 1)))
+ break;
+}
+#endif
diff --git a/contrib/nvi/clib/gethostname.c b/contrib/nvi/clib/gethostname.c
new file mode 100644
index 000000000000..5b8e85acf9f2
--- /dev/null
+++ b/contrib/nvi/clib/gethostname.c
@@ -0,0 +1,22 @@
+#include "config.h"
+
+/*
+ * Solaris doesn't include the gethostname call by default.
+ */
+#include <sys/utsname.h>
+#include <sys/systeminfo.h>
+
+#include <netdb.h>
+
+/*
+ * PUBLIC: #ifndef HAVE_GETHOSTNAME
+ * PUBLIC: int gethostname __P((char *, int));
+ * PUBLIC: #endif
+ */
+int
+gethostname(host, len)
+ char *host;
+ int len;
+{
+ return (sysinfo(SI_HOSTNAME, host, len) == -1 ? -1 : 0);
+}
diff --git a/contrib/nvi/clib/getopt.c b/contrib/nvi/clib/getopt.c
new file mode 100644
index 000000000000..b173017503e1
--- /dev/null
+++ b/contrib/nvi/clib/getopt.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)getopt.c 8.2 (Berkeley) 4/2/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int opterr = 1, /* if error message should be printed */
+ optind = 1, /* index into parent argv vector */
+ optopt, /* character checked for validity */
+ optreset; /* reset getopt */
+char *optarg; /* argument associated with option */
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ *
+ * PUBLIC: #ifndef HAVE_GETOPT
+ * PUBLIC: int getopt __P((int, char * const *, const char *));
+ * PUBLIC: #endif
+ */
+int
+getopt(nargc, nargv, ostr)
+ int nargc;
+ char * const *nargv;
+ const char *ostr;
+{
+ static char *progname;
+ static char *place = EMSG; /* option letter processing */
+ char *oli; /* option letter list index */
+
+ if (!progname) {
+ if ((progname = strrchr(*nargv, '/')) == NULL)
+ progname = *nargv;
+ else
+ ++progname;
+ }
+
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc || *(place = nargv[optind]) != '-') {
+ place = EMSG;
+ return (EOF);
+ }
+ if (place[1] && *++place == '-') { /* found "--" */
+ ++optind;
+ place = EMSG;
+ return (EOF);
+ }
+ } /* option letter okay? */
+ if ((optopt = (int)*place++) == (int)':' ||
+ !(oli = strchr(ostr, optopt))) {
+ /*
+ * if the user didn't specify '-' as an option,
+ * assume it means EOF.
+ */
+ if (optopt == (int)'-')
+ return (EOF);
+ if (!*place)
+ ++optind;
+ if (opterr && *ostr != ':')
+ (void)fprintf(stderr,
+ "%s: illegal option -- %c\n", progname, optopt);
+ return (BADCH);
+ }
+ if (*++oli != ':') { /* don't need argument */
+ optarg = NULL;
+ if (!*place)
+ ++optind;
+ }
+ else { /* need an argument */
+ if (*place) /* no white space */
+ optarg = place;
+ else if (nargc <= ++optind) { /* no arg */
+ place = EMSG;
+ if (*ostr == ':')
+ return (BADARG);
+ if (opterr)
+ (void)fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ progname, optopt);
+ return (BADCH);
+ }
+ else /* white space */
+ optarg = nargv[optind];
+ place = EMSG;
+ ++optind;
+ }
+ return (optopt); /* dump back option letter */
+}
diff --git a/usr.bin/vi/ex/ex_source.c b/contrib/nvi/clib/memchr.c
index 70b85b9568b1..b6d4c311bff6 100644
--- a/usr.bin/vi/ex/ex_source.c
+++ b/contrib/nvi/clib/memchr.c
@@ -1,7 +1,10 @@
/*-
- * Copyright (c) 1992, 1993, 1994
+ * Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -31,36 +34,32 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static char sccsid[] = "@(#)ex_source.c 8.5 (Berkeley) 8/8/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
+#include "config.h"
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)memchr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
+#include <string.h>
/*
- * ex_source -- :source file
- * Execute ex commands from a file.
+ * PUBLIC: #ifndef HAVE_MEMCHR
+ * PUBLIC: void *memchr __P((const void *, int, size_t));
+ * PUBLIC: #endif
*/
-int
-ex_source(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+void *
+memchr(s, c, n)
+ const void *s;
+ register unsigned char c;
+ register size_t n;
{
- return (ex_cfile(sp, ep, cmdp->argv[0]->bp, 0));
+ if (n != 0) {
+ register const unsigned char *p = s;
+
+ do {
+ if (*p++ == c)
+ return ((void *)(p - 1));
+ } while (--n != 0);
+ }
+ return (NULL);
}
diff --git a/contrib/nvi/clib/memmove.c b/contrib/nvi/clib/memmove.c
new file mode 100644
index 000000000000..7f4376272b67
--- /dev/null
+++ b/contrib/nvi/clib/memmove.c
@@ -0,0 +1,147 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)bcopy.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <string.h>
+
+/*
+ * sizeof(word) MUST BE A POWER OF TWO
+ * SO THAT wmask BELOW IS ALL ONES
+ */
+typedef int word; /* "word" used for optimal copy speed */
+
+#define wsize sizeof(word)
+#define wmask (wsize - 1)
+
+/*
+ * Copy a block of memory, handling overlap.
+ * This is the routine that actually implements
+ * (the portable versions of) bcopy, memcpy, and memmove.
+ *
+ * PUBLIC: #ifndef HAVE_MEMCPY
+ * PUBLIC: void *memcpy __P((void *, const void *, size_t));
+ * PUBLIC: #endif
+ * PUBLIC: #ifndef HAVE_MEMMOVE
+ * PUBLIC: void *memmove __P((void *, const void *, size_t));
+ * PUBLIC: #endif
+ */
+#ifdef MEMCOPY
+void *
+memcpy(dst0, src0, length)
+#else
+#ifdef MEMMOVE
+void *
+memmove(dst0, src0, length)
+#else
+void
+bcopy(src0, dst0, length)
+#endif
+#endif
+ void *dst0;
+ const void *src0;
+ register size_t length;
+{
+ register char *dst = dst0;
+ register const char *src = src0;
+ register size_t t;
+
+ if (length == 0 || dst == src) /* nothing to do */
+ goto done;
+
+ /*
+ * Macros: loop-t-times; and loop-t-times, t>0
+ */
+#define TLOOP(s) if (t) TLOOP1(s)
+#define TLOOP1(s) do { s; } while (--t)
+
+ if ((unsigned long)dst < (unsigned long)src) {
+ /*
+ * Copy forward.
+ */
+ t = (int)src; /* only need low bits */
+ if ((t | (int)dst) & wmask) {
+ /*
+ * Try to align operands. This cannot be done
+ * unless the low bits match.
+ */
+ if ((t ^ (int)dst) & wmask || length < wsize)
+ t = length;
+ else
+ t = wsize - (t & wmask);
+ length -= t;
+ TLOOP1(*dst++ = *src++);
+ }
+ /*
+ * Copy whole words, then mop up any trailing bytes.
+ */
+ t = length / wsize;
+ TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
+ t = length & wmask;
+ TLOOP(*dst++ = *src++);
+ } else {
+ /*
+ * Copy backwards. Otherwise essentially the same.
+ * Alignment works as before, except that it takes
+ * (t&wmask) bytes to align, not wsize-(t&wmask).
+ */
+ src += length;
+ dst += length;
+ t = (int)src;
+ if ((t | (int)dst) & wmask) {
+ if ((t ^ (int)dst) & wmask || length <= wsize)
+ t = length;
+ else
+ t &= wmask;
+ length -= t;
+ TLOOP1(*--dst = *--src);
+ }
+ t = length / wsize;
+ TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
+ t = length & wmask;
+ TLOOP(*--dst = *--src);
+ }
+done:
+#if defined(MEMCOPY) || defined(MEMMOVE)
+ return (dst0);
+#else
+ return;
+#endif
+}
diff --git a/contrib/nvi/clib/memset.c b/contrib/nvi/clib/memset.c
new file mode 100644
index 000000000000..0013d66df06d
--- /dev/null
+++ b/contrib/nvi/clib/memset.c
@@ -0,0 +1,137 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Hibler and Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)memset.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <limits.h>
+#include <string.h>
+
+/*
+ * PUBLIC: #ifndef HAVE_MEMSET
+ * PUBLIC: void *memset __P((void *, int, size_t));
+ * PUBLIC: #endif
+ */
+#define wsize sizeof(u_int)
+#define wmask (wsize - 1)
+
+#ifdef BZERO
+#define RETURN return
+#define VAL 0
+#define WIDEVAL 0
+
+void
+bzero(dst0, length)
+ void *dst0;
+ register size_t length;
+#else
+#define RETURN return (dst0)
+#define VAL c0
+#define WIDEVAL c
+
+void *
+memset(dst0, c0, length)
+ void *dst0;
+ register int c0;
+ register size_t length;
+#endif
+{
+ register size_t t;
+ register u_int c;
+ register u_char *dst;
+
+ dst = dst0;
+ /*
+ * If not enough words, just fill bytes. A length >= 2 words
+ * guarantees that at least one of them is `complete' after
+ * any necessary alignment. For instance:
+ *
+ * |-----------|-----------|-----------|
+ * |00|01|02|03|04|05|06|07|08|09|0A|00|
+ * ^---------------------^
+ * dst dst+length-1
+ *
+ * but we use a minimum of 3 here since the overhead of the code
+ * to do word writes is substantial.
+ */
+ if (length < 3 * wsize) {
+ while (length != 0) {
+ *dst++ = VAL;
+ --length;
+ }
+ RETURN;
+ }
+
+#ifndef BZERO
+ if ((c = (u_char)c0) != 0) { /* Fill the word. */
+ c = (c << 8) | c; /* u_int is 16 bits. */
+#if UINT_MAX > 0xffff
+ c = (c << 16) | c; /* u_int is 32 bits. */
+#endif
+#if UINT_MAX > 0xffffffff
+ c = (c << 32) | c; /* u_int is 64 bits. */
+#endif
+ }
+#endif
+ /* Align destination by filling in bytes. */
+ if ((t = (int)dst & wmask) != 0) {
+ t = wsize - t;
+ length -= t;
+ do {
+ *dst++ = VAL;
+ } while (--t != 0);
+ }
+
+ /* Fill words. Length was >= 2*words so we know t >= 1 here. */
+ t = length / wsize;
+ do {
+ *(u_int *)dst = WIDEVAL;
+ dst += wsize;
+ } while (--t != 0);
+
+ /* Mop up trailing bytes, if any. */
+ t = length & wmask;
+ if (t != 0)
+ do {
+ *dst++ = VAL;
+ } while (--t != 0);
+ RETURN;
+}
diff --git a/usr.bin/vi/ex/ex_preserve.c b/contrib/nvi/clib/mkstemp.c
index 8960f98adf84..1faffddfbe2d 100644
--- a/usr.bin/vi/ex/ex_preserve.c
+++ b/contrib/nvi/clib/mkstemp.c
@@ -1,5 +1,5 @@
-/*-
- * Copyright (c) 1993, 1994
+/*
+ * Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,98 +31,103 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static char sccsid[] = "@(#)ex_preserve.c 8.12 (Berkeley) 8/4/94";
-#endif /* not lint */
+#include "config.h"
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
-#include <bitstring.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <errno.h>
-#include <limits.h>
-#include <signal.h>
#include <stdio.h>
-#include <string.h>
-#include <termios.h>
+#include <ctype.h>
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
+static int _gettemp();
/*
- * ex_preserve -- :pre[serve]
- * Push the file to recovery.
+ * PUBLIC: #ifndef HAVE_MKSTEMP
+ * PUBLIC: int mkstemp __P((char *));
+ * PUBLIC: #endif
*/
-int
-ex_preserve(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+mkstemp(path)
+ char *path;
{
- recno_t lno;
-
- if (!F_ISSET(ep, F_RCV_ON)) {
- msgq(sp, M_ERR, "Preservation of this file not possible");
- return (1);
- }
-
- /* If recovery not initialized, do so. */
- if (F_ISSET(ep, F_FIRSTMODIFY) && rcv_init(sp, ep))
- return (1);
-
- /* Force the file to be read in, in case it hasn't yet. */
- if (file_lline(sp, ep, &lno))
- return (1);
+ int fd;
- /* Sync to disk. */
- if (rcv_sync(sp, ep, RCV_SNAPSHOT))
- return (1);
-
- msgq(sp, M_INFO, "File preserved");
- return (0);
+ return (_gettemp(path, &fd) ? fd : -1);
}
-/*
- * ex_recover -- :rec[over][!] file
- *
- * Recover the file.
- */
-int
-ex_recover(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+char *
+mktemp(path)
+ char *path;
{
- ARGS *ap;
- FREF *frp;
-
- ap = cmdp->argv[0];
+ return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
+}
- /* Set the alternate file name. */
- set_alt_name(sp, ap->bp);
+static
+_gettemp(path, doopen)
+ char *path;
+ register int *doopen;
+{
+ extern int errno;
+ register char *start, *trv;
+ struct stat sbuf;
+ u_int pid;
+
+ pid = getpid();
+ for (trv = path; *trv; ++trv); /* extra X's get set to 0's */
+ while (*--trv == 'X') {
+ *trv = (pid % 10) + '0';
+ pid /= 10;
+ }
/*
- * Check for modifications. Autowrite did not historically
- * affect :recover.
+ * check the target directory; if you have six X's and it
+ * doesn't exist this runs for a *very* long time.
*/
- if (file_m2(sp, ep, F_ISSET(cmdp, E_FORCE)))
- return (1);
-
- /* Get a file structure for the file. */
- if ((frp = file_add(sp, ap->bp)) == NULL)
- return (1);
-
- /* Set the recover bit. */
- F_SET(frp, FR_RECOVER);
+ for (start = trv + 1;; --trv) {
+ if (trv <= path)
+ break;
+ if (*trv == '/') {
+ *trv = '\0';
+ if (stat(path, &sbuf))
+ return(0);
+ if (!S_ISDIR(sbuf.st_mode)) {
+ errno = ENOTDIR;
+ return(0);
+ }
+ *trv = '/';
+ break;
+ }
+ }
- /* Switch files. */
- if (file_init(sp, frp, NULL, F_ISSET(cmdp, E_FORCE)))
- return (1);
- F_SET(sp, S_FSWITCH);
- return (0);
+ for (;;) {
+ if (doopen) {
+ if ((*doopen =
+ open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
+ return(1);
+ if (errno != EEXIST)
+ return(0);
+ }
+ else if (stat(path, &sbuf))
+ return(errno == ENOENT ? 1 : 0);
+
+ /* tricky little algorithm for backward compatibility */
+ for (trv = start;;) {
+ if (!*trv)
+ return(0);
+ if (*trv == 'z')
+ *trv++ = 'a';
+ else {
+ if (isdigit(*trv))
+ *trv = 'a';
+ else
+ ++*trv;
+ break;
+ }
+ }
+ }
+ /*NOTREACHED*/
}
diff --git a/contrib/nvi/clib/mmap.c b/contrib/nvi/clib/mmap.c
new file mode 100644
index 000000000000..7cea169650b4
--- /dev/null
+++ b/contrib/nvi/clib/mmap.c
@@ -0,0 +1,50 @@
+#include "config.h"
+
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+ * This function fakes mmap() by reading `len' bytes from the file descriptor
+ * `fd' and returning a pointer to that memory. The "mapped" region can later
+ * be deallocated with munmap().
+ *
+ * Note: ONLY reading is supported and only reading of the exact size of the
+ * file will work.
+ *
+ * PUBLIC: #ifndef HAVE_MMAP
+ * PUBLIC: char *mmap __P((char *, size_t, int, int, int, off_t));
+ * PUBLIC: #endif
+ */
+char *
+mmap(addr, len, prot, flags, fd, off)
+ char *addr;
+ size_t len;
+ int prot, flags, fd;
+ off_t off;
+{
+ char *ptr;
+
+ if ((ptr = (char *)malloc(len)) == 0)
+ return ((char *)-1);
+ if (read(fd, ptr, len) < 0) {
+ free(ptr);
+ return ((char *)-1);
+ }
+ return (ptr);
+}
+
+/*
+ * PUBLIC: #ifndef HAVE_MMAP
+ * PUBLIC: int munmap __P((char *, size_t));
+ * PUBLIC: #endif
+ */
+int
+munmap(addr, len)
+ char *addr;
+ size_t len;
+{
+ free(addr);
+ return (0);
+}
diff --git a/contrib/nvi/clib/snprintf.c b/contrib/nvi/clib/snprintf.c
new file mode 100644
index 000000000000..935522ce5436
--- /dev/null
+++ b/contrib/nvi/clib/snprintf.c
@@ -0,0 +1,45 @@
+#include "config.h"
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+/*
+ * PUBLIC: #ifndef HAVE_SNPRINTF
+ * PUBLIC: int snprintf __P((char *, size_t, const char *, ...));
+ * PUBLIC: #endif
+ */
+int
+#ifdef __STDC__
+snprintf(char *str, size_t n, const char *fmt, ...)
+#else
+snprintf(str, n, fmt, va_alist)
+ char *str;
+ size_t n;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+ int rval;
+#ifdef __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+#ifdef SPRINTF_RET_CHARPNT
+ (void)vsprintf(str, fmt, ap);
+ va_end(ap);
+ return (strlen(str));
+#else
+ rval = vsprintf(str, fmt, ap);
+ va_end(ap);
+ return (rval);
+#endif
+}
diff --git a/usr.bin/vi/vi/v_redraw.c b/contrib/nvi/clib/strdup.c
index 8f7054ca9522..4bc2303cee54 100644
--- a/usr.bin/vi/vi/v_redraw.c
+++ b/contrib/nvi/clib/strdup.c
@@ -1,5 +1,5 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
+/*
+ * Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,37 +31,33 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static char sccsid[] = "@(#)v_redraw.c 8.4 (Berkeley) 3/8/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
+#include "config.h"
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strdup.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
+#include <sys/types.h>
-#include "vi.h"
-#include "vcmd.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
/*
- * v_redraw -- ^R
- * Redraw the screen.
+ * PUBLIC: #ifndef HAVE_STRDUP
+ * PUBLIC: char *strdup __P((const char *));
+ * PUBLIC: #endif
*/
-int
-v_redraw(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+char *
+strdup(str)
+ const char *str;
{
- F_SET(sp, S_REFRESH);
- return (0);
+ size_t len;
+ char *copy;
+
+ len = strlen(str) + 1;
+ if (!(copy = malloc((u_int)len)))
+ return (NULL);
+ memcpy(copy, str, len);
+ return (copy);
}
diff --git a/usr.bin/vi/vi/v_stop.c b/contrib/nvi/clib/strerror.c
index 1e865d97da4d..cf5910d0fc83 100644
--- a/usr.bin/vi/vi/v_stop.c
+++ b/contrib/nvi/clib/strerror.c
@@ -1,5 +1,5 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
+/*
+ * Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,45 +31,44 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static char sccsid[] = "@(#)v_stop.c 8.7 (Berkeley) 3/8/94";
-#endif /* not lint */
+#include "config.h"
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
/*
- * v_stop -- ^Z
- * Suspend vi.
+ * PUBLIC: #ifndef HAVE_STRERROR
+ * PUBLIC: char *strerror __P((int));
+ * PUBLIC: #endif
*/
-int
-v_stop(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+char *
+strerror(num)
+ int num;
{
- /* If autowrite is set, write out the file. */
- if (F_ISSET(ep, F_MODIFIED) && O_ISSET(sp, O_AUTOWRITE)) {
- if (file_write(sp, ep, NULL, NULL, NULL, FS_ALL))
- return (1);
- if (sp->s_refresh(sp, ep))
- return (1);
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+#define UPREFIX "Unknown error: "
+ static char ebuf[40] = UPREFIX; /* 64-bit number + slop */
+ register unsigned int errnum;
+ register char *p, *t;
+ char tmp[40];
+
+ errnum = num; /* convert to unsigned */
+ if (errnum < sys_nerr)
+ return(sys_errlist[errnum]);
+
+ /* Do this by hand, so we don't include stdio(3). */
+ t = tmp;
+ do {
+ *t++ = "0123456789"[errnum % 10];
+ } while (errnum /= 10);
+ for (p = ebuf + sizeof(UPREFIX) - 1;;) {
+ *p++ = *--t;
+ if (t <= tmp)
+ break;
}
- return (sp->s_suspend(sp));
+ return(ebuf);
}
diff --git a/usr.bin/vi/ex/ex_set.c b/contrib/nvi/clib/strpbrk.c
index 1ad19f71ae91..22abbb0da4b5 100644
--- a/usr.bin/vi/ex/ex_set.c
+++ b/contrib/nvi/clib/strpbrk.c
@@ -1,5 +1,5 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
+/*
+ * Copyright (c) 1985, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,40 +31,32 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static char sccsid[] = "@(#)ex_set.c 8.4 (Berkeley) 7/22/94";
-#endif /* not lint */
+#include "config.h"
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strpbrk.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
+#include <string.h>
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-int
-ex_set(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+/*
+ * Find the first occurrence in s1 of a character in s2 (excluding NUL).
+ *
+ * PUBLIC: #ifndef HAVE_STRPBRK
+ * PUBLIC: char *strpbrk __P((const char *, const char *));
+ * PUBLIC: #endif
+ */
+char *
+strpbrk(s1, s2)
+ register const char *s1, *s2;
{
- switch(cmdp->argc) {
- case 0:
- opts_dump(sp, CHANGED_DISPLAY);
- break;
- default:
- opts_set(sp, cmdp->cmd->usage, cmdp->argv);
- break;
+ register const char *scanp;
+ register int c, sc;
+
+ while ((c = *s1++) != 0) {
+ for (scanp = s2; (sc = *scanp++) != 0;)
+ if (sc == c)
+ return ((char *)(s1 - 1));
}
- return (0);
+ return (NULL);
}
diff --git a/usr.bin/vi/ex/ex_put.c b/contrib/nvi/clib/strsep.c
index ce44b5faa278..33115f0e4121 100644
--- a/usr.bin/vi/ex/ex_put.c
+++ b/contrib/nvi/clib/strsep.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1992, 1993, 1994
+ * Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,48 +31,55 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static char sccsid[] = "@(#)ex_put.c 8.6 (Berkeley) 7/23/94";
-#endif /* not lint */
+#include "config.h"
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
+#include <stdio.h>
/*
- * ex_put -- [line] pu[t] [buffer]
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
*
- * Append a cut buffer into the file.
+ * PUBLIC: #ifndef HAVE_STRSEP
+ * PUBLIC: char *strsep __P((char **, const char *));
+ * PUBLIC: #endif
*/
-int
-ex_put(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+char *
+strsep(stringp, delim)
+ register char **stringp;
+ register const char *delim;
{
- MARK m;
+ register char *s;
+ register const char *spanp;
+ register int c, sc;
+ char *tok;
- m.lno = sp->lno;
- m.cno = sp->cno;
- if (put(sp, ep, NULL, F_ISSET(cmdp, E_BUFFER) ? &cmdp->buffer : NULL,
- &cmdp->addr1, &m, 1))
- return (1);
- sp->lno = m.lno;
- sp->cno = m.cno;
- return (0);
+ if ((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
}
diff --git a/contrib/nvi/clib/strtol.c b/contrib/nvi/clib/strtol.c
new file mode 100644
index 000000000000..50c724ff432f
--- /dev/null
+++ b/contrib/nvi/clib/strtol.c
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/*
+ * Convert a string to a long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ *
+ * PUBLIC: #ifndef HAVE_STRTOL
+ * PUBLIC: long strtol __P((const char *, char **, int));
+ * PUBLIC: #endif
+ */
+long
+strtol(nptr, endptr, base)
+ const char *nptr;
+ char **endptr;
+ register int base;
+{
+ register const char *s = nptr;
+ register unsigned long acc;
+ register int c;
+ register unsigned long cutoff;
+ register int neg = 0, any, cutlim;
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+ cutlim = cutoff % (unsigned long)base;
+ cutoff /= (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_MIN : LONG_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *)(any ? s - 1 : nptr);
+ return (acc);
+}
diff --git a/usr.bin/vi/ex/ex_file.c b/contrib/nvi/clib/strtoul.c
index b2c68e762dc1..890bdbd747a7 100644
--- a/usr.bin/vi/ex/ex_file.c
+++ b/contrib/nvi/clib/strtoul.c
@@ -1,5 +1,5 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
+/*
+ * Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,73 +31,83 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static char sccsid[] = "@(#)ex_file.c 8.10 (Berkeley) 8/8/94";
-#endif /* not lint */
+#include "config.h"
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
-#include <bitstring.h>
-#include <errno.h>
#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
/*
- * ex_file -- :f[ile] [name]
- * Change the file's name and display the status line.
+ * Convert a string to an unsigned long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ *
+ * PUBLIC: #ifndef HAVE_STRTOUL
+ * PUBLIC: unsigned long strtoul __P((const char *, char **, int));
+ * PUBLIC: #endif
*/
-int
-ex_file(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+unsigned long
+strtoul(nptr, endptr, base)
+ const char *nptr;
+ char **endptr;
+ register int base;
{
- CHAR_T *p;
- FREF *frp;
+ register const char *s = nptr;
+ register unsigned long acc;
+ register int c;
+ register unsigned long cutoff;
+ register int neg = 0, any, cutlim;
- switch (cmdp->argc) {
- case 0:
- break;
- case 1:
- frp = sp->frp;
-
- /* Make sure can allocate enough space. */
- if ((p = v_strdup(sp,
- cmdp->argv[0]->bp, cmdp->argv[0]->len)) == NULL)
- return (1);
-
- /* If already have a file name, it becomes the alternate. */
- if (!F_ISSET(frp, FR_TMPFILE))
- set_alt_name(sp, frp->name);
-
- /* Free the previous name. */
- free(frp->name);
- frp->name = p;
-
- /*
- * The read-only bit follows the file name; clear it.
- * The file has a real name, it's no longer a temporary.
- */
- F_CLR(frp, FR_RDONLY | FR_TMPFILE);
-
- /* Have to force a write if the file exists, next time. */
- F_SET(frp, FR_NAMECHANGE);
- break;
- default:
- abort();
+ /*
+ * See strtol for comments as to the logic used.
+ */
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
+ cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
}
- return (msg_status(sp, ep, sp->lno, 1));
+ if (any < 0) {
+ acc = ULONG_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *)(any ? s - 1 : nptr);
+ return (acc);
}
diff --git a/contrib/nvi/clib/vsnprintf.c b/contrib/nvi/clib/vsnprintf.c
new file mode 100644
index 000000000000..a1b013ad196f
--- /dev/null
+++ b/contrib/nvi/clib/vsnprintf.c
@@ -0,0 +1,31 @@
+#include "config.h"
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+/*
+ * PUBLIC: #ifndef HAVE_VSNPRINTF
+ * PUBLIC: int vsnprintf __P((char *, size_t, const char *, ...));
+ * PUBLIC: #endif
+ */
+int
+vsnprintf(str, n, fmt, ap)
+ char *str;
+ size_t n;
+ const char *fmt;
+ va_list ap;
+{
+#ifdef SPRINTF_RET_CHARPNT
+ (void)vsprintf(str, fmt, ap);
+ return (strlen(str));
+#else
+ return (vsprintf(str, fmt, ap));
+#endif
+}
diff --git a/contrib/nvi/common/api.c b/contrib/nvi/common/api.c
new file mode 100644
index 000000000000..35d9f0c8f66e
--- /dev/null
+++ b/contrib/nvi/common/api.c
@@ -0,0 +1,525 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ * Copyright (c) 1995
+ * George V. Neville-Neil. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)api.c 8.26 (Berkeley) 10/14/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+extern GS *__global_list; /* XXX */
+
+/*
+ * api_fscreen --
+ * Return a pointer to the screen specified by the screen id
+ * or a file name.
+ *
+ * PUBLIC: SCR *api_fscreen __P((int, char *));
+ */
+SCR *
+api_fscreen(id, name)
+ int id;
+ char *name;
+{
+ GS *gp;
+ SCR *tsp;
+
+ gp = __global_list;
+
+ /* Search the displayed list. */
+ for (tsp = gp->dq.cqh_first;
+ tsp != (void *)&gp->dq; tsp = tsp->q.cqe_next)
+ if (name == NULL) {
+ if (id == tsp->id)
+ return (tsp);
+ } else if (!strcmp(name, tsp->frp->name))
+ return (tsp);
+
+ /* Search the hidden list. */
+ for (tsp = gp->hq.cqh_first;
+ tsp != (void *)&gp->hq; tsp = tsp->q.cqe_next)
+ if (name == NULL) {
+ if (id == tsp->id)
+ return (tsp);
+ } else if (!strcmp(name, tsp->frp->name))
+ return (tsp);
+ return (NULL);
+}
+
+/*
+ * api_aline --
+ * Append a line.
+ *
+ * PUBLIC: int api_aline __P((SCR *, recno_t, char *, size_t));
+ */
+int
+api_aline(sp, lno, line, len)
+ SCR *sp;
+ recno_t lno;
+ char *line;
+ size_t len;
+{
+ return (db_append(sp, 1, lno, line, len));
+}
+
+/*
+ * api_dline --
+ * Delete a line.
+ *
+ * PUBLIC: int api_dline __P((SCR *, recno_t));
+ */
+int
+api_dline(sp, lno)
+ SCR *sp;
+ recno_t lno;
+{
+ return (db_delete(sp, lno));
+}
+
+/*
+ * api_gline --
+ * Get a line.
+ *
+ * PUBLIC: int api_gline __P((SCR *, recno_t, char **, size_t *));
+ */
+int
+api_gline(sp, lno, linepp, lenp)
+ SCR *sp;
+ recno_t lno;
+ char **linepp;
+ size_t *lenp;
+{
+ int isempty;
+
+ if (db_eget(sp, lno, linepp, lenp, &isempty)) {
+ if (isempty)
+ msgq(sp, M_ERR, "209|The file is empty");
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * api_iline --
+ * Insert a line.
+ *
+ * PUBLIC: int api_iline __P((SCR *, recno_t, char *, size_t));
+ */
+int
+api_iline(sp, lno, line, len)
+ SCR *sp;
+ recno_t lno;
+ char *line;
+ size_t len;
+{
+ return (db_insert(sp, lno, line, len));
+}
+
+/*
+ * api_lline --
+ * Return the line number of the last line in the file.
+ *
+ * PUBLIC: int api_lline __P((SCR *, recno_t *));
+ */
+int
+api_lline(sp, lnop)
+ SCR *sp;
+ recno_t *lnop;
+{
+ return (db_last(sp, lnop));
+}
+
+/*
+ * api_sline --
+ * Set a line.
+ *
+ * PUBLIC: int api_sline __P((SCR *, recno_t, char *, size_t));
+ */
+int
+api_sline(sp, lno, line, len)
+ SCR *sp;
+ recno_t lno;
+ char *line;
+ size_t len;
+{
+ return (db_set(sp, lno, line, len));
+}
+
+/*
+ * api_getmark --
+ * Get the mark.
+ *
+ * PUBLIC: int api_getmark __P((SCR *, int, MARK *));
+ */
+int
+api_getmark(sp, markname, mp)
+ SCR *sp;
+ int markname;
+ MARK *mp;
+{
+ return (mark_get(sp, (ARG_CHAR_T)markname, mp, M_ERR));
+}
+
+/*
+ * api_setmark --
+ * Set the mark.
+ *
+ * PUBLIC: int api_setmark __P((SCR *, int, MARK *));
+ */
+int
+api_setmark(sp, markname, mp)
+ SCR *sp;
+ int markname;
+ MARK *mp;
+{
+ return (mark_set(sp, (ARG_CHAR_T)markname, mp, 1));
+}
+
+/*
+ * api_nextmark --
+ * Return the first mark if next not set, otherwise return the
+ * subsequent mark.
+ *
+ * PUBLIC: int api_nextmark __P((SCR *, int, char *));
+ */
+int
+api_nextmark(sp, next, namep)
+ SCR *sp;
+ int next;
+ char *namep;
+{
+ LMARK *mp;
+
+ mp = sp->ep->marks.lh_first;
+ if (next)
+ for (; mp != NULL; mp = mp->q.le_next)
+ if (mp->name == *namep) {
+ mp = mp->q.le_next;
+ break;
+ }
+ if (mp == NULL)
+ return (1);
+ *namep = mp->name;
+ return (0);
+}
+
+/*
+ * api_getcursor --
+ * Get the cursor.
+ *
+ * PUBLIC: int api_getcursor __P((SCR *, MARK *));
+ */
+int
+api_getcursor(sp, mp)
+ SCR *sp;
+ MARK *mp;
+{
+ mp->lno = sp->lno;
+ mp->cno = sp->cno;
+ return (0);
+}
+
+/*
+ * api_setcursor --
+ * Set the cursor.
+ *
+ * PUBLIC: int api_setcursor __P((SCR *, MARK *));
+ */
+int
+api_setcursor(sp, mp)
+ SCR *sp;
+ MARK *mp;
+{
+ size_t len;
+
+ if (db_get(sp, mp->lno, DBG_FATAL, NULL, &len))
+ return (1);
+ if (mp->cno < 0 || mp->cno > len) {
+ msgq(sp, M_ERR, "Cursor set to nonexistent column");
+ return (1);
+ }
+
+ /* Set the cursor. */
+ sp->lno = mp->lno;
+ sp->cno = mp->cno;
+ return (0);
+}
+
+/*
+ * api_emessage --
+ * Print an error message.
+ *
+ * PUBLIC: void api_emessage __P((SCR *, char *));
+ */
+void
+api_emessage(sp, text)
+ SCR *sp;
+ char *text;
+{
+ msgq(sp, M_ERR, "%s", text);
+}
+
+/*
+ * api_imessage --
+ * Print an informational message.
+ *
+ * PUBLIC: void api_imessage __P((SCR *, char *));
+ */
+void
+api_imessage(sp, text)
+ SCR *sp;
+ char *text;
+{
+ msgq(sp, M_INFO, "%s", text);
+}
+
+/*
+ * api_edit
+ * Create a new screen and return its id
+ * or edit a new file in the current screen.
+ *
+ * PUBLIC: int api_edit __P((SCR *, char *, SCR **, int));
+ */
+int
+api_edit(sp, file, spp, newscreen)
+ SCR *sp;
+ char *file;
+ SCR **spp;
+ int newscreen;
+{
+ ARGS *ap[2], a;
+ EXCMD cmd;
+
+ if (file) {
+ ex_cinit(&cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0, ap);
+ ex_cadd(&cmd, &a, file, strlen(file));
+ } else
+ ex_cinit(&cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0, NULL);
+ if (newscreen)
+ cmd.flags |= E_NEWSCREEN; /* XXX */
+ if (cmd.cmd->fn(sp, &cmd))
+ return (1);
+ *spp = sp->nextdisp;
+ return (0);
+}
+
+/*
+ * api_escreen
+ * End a screen.
+ *
+ * PUBLIC: int api_escreen __P((SCR *));
+ */
+int
+api_escreen(sp)
+ SCR *sp;
+{
+ EXCMD cmd;
+
+ /*
+ * XXX
+ * If the interpreter exits anything other than the current
+ * screen, vi isn't going to update everything correctly.
+ */
+ ex_cinit(&cmd, C_QUIT, 0, OOBLNO, OOBLNO, 0, NULL);
+ return (cmd.cmd->fn(sp, &cmd));
+}
+
+/*
+ * api_swscreen --
+ * Switch to a new screen.
+ *
+ * PUBLIC: int api_swscreen __P((SCR *, SCR *));
+ */
+int
+api_swscreen(sp, new)
+ SCR *sp, *new;
+{
+ /*
+ * XXX
+ * If the interpreter switches from anything other than the
+ * current screen, vi isn't going to update everything correctly.
+ */
+ sp->nextdisp = new;
+ F_SET(sp, SC_SSWITCH);
+
+ return (0);
+}
+
+/*
+ * api_map --
+ * Map a key.
+ *
+ * PUBLIC: int api_map __P((SCR *, char *, char *, size_t));
+ */
+int
+api_map(sp, name, map, len)
+ SCR *sp;
+ char *name, *map;
+ size_t len;
+{
+ ARGS *ap[3], a, b;
+ EXCMD cmd;
+
+ ex_cinit(&cmd, C_MAP, 0, OOBLNO, OOBLNO, 0, ap);
+ ex_cadd(&cmd, &a, name, strlen(name));
+ ex_cadd(&cmd, &b, map, len);
+ return (cmd.cmd->fn(sp, &cmd));
+}
+
+/*
+ * api_unmap --
+ * Unmap a key.
+ *
+ * PUBLIC: int api_unmap __P((SCR *, char *));
+ */
+int
+api_unmap(sp, name)
+ SCR *sp;
+ char *name;
+{
+ ARGS *ap[2], a;
+ EXCMD cmd;
+
+ ex_cinit(&cmd, C_UNMAP, 0, OOBLNO, OOBLNO, 0, ap);
+ ex_cadd(&cmd, &a, name, strlen(name));
+ return (cmd.cmd->fn(sp, &cmd));
+}
+
+/*
+ * api_opts_get --
+ * Return a option value as a string, in allocated memory.
+ * If the option is of type boolean, boolvalue is (un)set
+ * according to the value; otherwise boolvalue is -1.
+ *
+ * PUBLIC: int api_opts_get __P((SCR *, char *, char **, int *));
+ */
+int
+api_opts_get(sp, name, value, boolvalue)
+ SCR *sp;
+ char *name, **value;
+ int *boolvalue;
+{
+ OPTLIST const *op;
+ int offset;
+
+ if ((op = opts_search(name)) == NULL) {
+ opts_nomatch(sp, name);
+ return (1);
+ }
+
+ offset = op - optlist;
+ if (boolvalue != NULL)
+ *boolvalue = -1;
+ switch (op->type) {
+ case OPT_0BOOL:
+ case OPT_1BOOL:
+ MALLOC_RET(sp, *value, char *, strlen(op->name) + 2 + 1);
+ (void)sprintf(*value,
+ "%s%s", O_ISSET(sp, offset) ? "" : "no", op->name);
+ if (boolvalue != NULL)
+ *boolvalue = O_ISSET(sp, offset);
+ break;
+ case OPT_NUM:
+ MALLOC_RET(sp, *value, char *, 20);
+ (void)sprintf(*value, "%lu", (u_long)O_VAL(sp, offset));
+ break;
+ case OPT_STR:
+ if (O_STR(sp, offset) == NULL) {
+ MALLOC_RET(sp, *value, char *, 2);
+ value[0] = '\0';
+ } else {
+ MALLOC_RET(sp,
+ *value, char *, strlen(O_STR(sp, offset)) + 1);
+ (void)sprintf(*value, "%s", O_STR(sp, offset));
+ }
+ break;
+ }
+ return (0);
+}
+
+/*
+ * api_opts_set --
+ * Set options.
+ *
+ * PUBLIC: int api_opts_set __P((SCR *, char *, char *, u_long, int));
+ */
+int
+api_opts_set(sp, name, str_value, num_value, bool_value)
+ SCR *sp;
+ char *name, *str_value;
+ u_long num_value;
+ int bool_value;
+{
+ ARGS *ap[2], a, b;
+ OPTLIST const *op;
+ int rval;
+ size_t blen;
+ char *bp;
+
+ if ((op = opts_search(name)) == NULL) {
+ opts_nomatch(sp, name);
+ return (1);
+ }
+
+ switch (op->type) {
+ case OPT_0BOOL:
+ case OPT_1BOOL:
+ GET_SPACE_RET(sp, bp, blen, 64);
+ a.len = snprintf(bp, 64, "%s%s", bool_value ? "" : "no", name);
+ break;
+ case OPT_NUM:
+ GET_SPACE_RET(sp, bp, blen, 64);
+ a.len = snprintf(bp, 64, "%s=%lu", name, num_value);
+ break;
+ case OPT_STR:
+ GET_SPACE_RET(sp, bp, blen, 1024);
+ a.len = snprintf(bp, 1024, "%s=%s", name, str_value);
+ break;
+ }
+ a.bp = bp;
+ b.len = 0;
+ b.bp = NULL;
+ ap[0] = &a;
+ ap[1] = &b;
+ rval = opts_set(sp, ap, NULL);
+
+ FREE_SPACE(sp, bp, blen);
+
+ return (rval);
+}
+
+/*
+ * api_run_str --
+ * Execute a string as an ex command.
+ *
+ * PUBLIC: int api_run_str __P((SCR *, char *));
+ */
+int
+api_run_str(sp, cmd)
+ SCR *sp;
+ char *cmd;
+{
+ return (ex_run_str(sp, NULL, cmd, strlen(cmd), 0, 0));
+}
diff --git a/contrib/nvi/common/args.h b/contrib/nvi/common/args.h
new file mode 100644
index 000000000000..e84dc2ca04c1
--- /dev/null
+++ b/contrib/nvi/common/args.h
@@ -0,0 +1,29 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)args.h 10.2 (Berkeley) 3/6/96
+ */
+
+/*
+ * Structure for building "argc/argv" vector of arguments.
+ *
+ * !!!
+ * All arguments are nul terminated as well as having an associated length.
+ * The argument vector is NOT necessarily NULL terminated. The proper way
+ * to check the number of arguments is to use the argc value in the EXCMDARG
+ * structure or to walk the array until an ARGS structure with a length of 0
+ * is found.
+ */
+typedef struct _args {
+ CHAR_T *bp; /* Argument. */
+ size_t blen; /* Buffer length. */
+ size_t len; /* Argument length. */
+
+#define A_ALLOCATED 0x01 /* If allocated space. */
+ u_int8_t flags;
+} ARGS;
diff --git a/contrib/nvi/common/common.h b/contrib/nvi/common/common.h
new file mode 100644
index 000000000000..0e13fc80b844
--- /dev/null
+++ b/contrib/nvi/common/common.h
@@ -0,0 +1,96 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)common.h 10.13 (Berkeley) 9/25/96
+ */
+
+/*
+ * Porting information built at configuration time. Included before
+ * any of nvi's include files.
+ */
+#include "port.h"
+
+/*
+ * Pseudo-local includes. These are files that are unlikely to exist
+ * on most machines to which we're porting vi, and we want to include
+ * them in a very specific order, regardless.
+ */
+#include <db.h>
+#include <regex.h>
+
+/*
+ * Forward structure declarations. Not pretty, but the include files
+ * are far too interrelated for a clean solution.
+ */
+typedef struct _cb CB;
+typedef struct _csc CSC;
+typedef struct _event EVENT;
+typedef struct _excmd EXCMD;
+typedef struct _exf EXF;
+typedef struct _fref FREF;
+typedef struct _gs GS;
+typedef struct _lmark LMARK;
+typedef struct _mark MARK;
+typedef struct _msg MSGS;
+typedef struct _option OPTION;
+typedef struct _optlist OPTLIST;
+typedef struct _scr SCR;
+typedef struct _script SCRIPT;
+typedef struct _seq SEQ;
+typedef struct _tag TAG;
+typedef struct _tagf TAGF;
+typedef struct _tagq TAGQ;
+typedef struct _text TEXT;
+
+/* Autoindent state. */
+typedef enum { C_NOTSET, C_CARATSET, C_NOCHANGE, C_ZEROSET } carat_t;
+
+/* Busy message types. */
+typedef enum { BUSY_ON = 1, BUSY_OFF, BUSY_UPDATE } busy_t;
+
+/*
+ * Routines that return a confirmation return:
+ *
+ * CONF_NO User answered no.
+ * CONF_QUIT User answered quit, eof or an error.
+ * CONF_YES User answered yes.
+ */
+typedef enum { CONF_NO, CONF_QUIT, CONF_YES } conf_t;
+
+/* Directions. */
+typedef enum { NOTSET, FORWARD, BACKWARD } dir_t;
+
+/* Line operations. */
+typedef enum { LINE_APPEND, LINE_DELETE, LINE_INSERT, LINE_RESET } lnop_t;
+
+/* Lock return values. */
+typedef enum { LOCK_FAILED, LOCK_SUCCESS, LOCK_UNAVAIL } lockr_t;
+
+/* Sequence types. */
+typedef enum { SEQ_ABBREV, SEQ_COMMAND, SEQ_INPUT } seq_t;
+
+/*
+ * Local includes.
+ */
+#include "key.h" /* Required by args.h. */
+#include "args.h" /* Required by options.h. */
+#include "options.h" /* Required by screen.h. */
+
+#include "msg.h" /* Required by gs.h. */
+#include "cut.h" /* Required by gs.h. */
+#include "seq.h" /* Required by screen.h. */
+#include "util.h" /* Required by ex.h. */
+#include "mark.h" /* Required by gs.h. */
+#include "../ex/ex.h" /* Required by gs.h. */
+#include "gs.h" /* Required by screen.h. */
+#include "screen.h" /* Required by exf.h. */
+#include "exf.h"
+#include "log.h"
+#include "mem.h"
+
+#include "com_extern.h"
diff --git a/usr.bin/vi/common/cut.c b/contrib/nvi/common/cut.c
index df86a95983b0..faceecd11166 100644
--- a/usr.bin/vi/common/cut.c
+++ b/contrib/nvi/common/cut.c
@@ -1,62 +1,33 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)cut.c 8.32 (Berkeley) 7/28/94";
+static const char sccsid[] = "@(#)cut.c 10.10 (Berkeley) 9/15/96";
#endif /* not lint */
#include <sys/types.h>
#include <sys/queue.h>
-#include <sys/time.h>
#include <bitstring.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
+#include "common.h"
-#include "vi.h"
-
-static int cb_rotate __P((SCR *));
+static void cb_rotate __P((SCR *));
/*
* cut --
@@ -89,14 +60,15 @@ static int cb_rotate __P((SCR *));
* and, in the latter case, the text was appended to the buffer instead of
* replacing the contents. Hopefully it's not worth getting right, and here
* we just treat the numeric buffers like any other named buffer.
+ *
+ * PUBLIC: int cut __P((SCR *, CHAR_T *, MARK *, MARK *, int));
*/
int
-cut(sp, ep, namep, fm, tm, flags)
+cut(sp, namep, fm, tm, flags)
SCR *sp;
- EXF *ep;
CHAR_T *namep;
- int flags;
MARK *fm, *tm;
+ int flags;
{
CB *cbp;
CHAR_T name;
@@ -128,7 +100,7 @@ cut(sp, ep, namep, fm, tm, flags)
append = copy_one = copy_def = 0;
if (namep != NULL) {
name = *namep;
- if (LF_ISSET(CUT_NUMREQ) || LF_ISSET(CUT_NUMOPT) &&
+ if (LF_ISSET(CUT_NUMREQ) || LF_ISSET(CUT_NUMOPT) &&
(LF_ISSET(CUT_LINEMODE) || fm->lno != tm->lno)) {
copy_one = 1;
cb_rotate(sp);
@@ -169,30 +141,26 @@ copyloop:
if (LF_ISSET(CUT_LINEMODE)) {
cbp->flags |= CB_LMODE;
for (lno = fm->lno; lno <= tm->lno; ++lno)
- if (cut_line(sp, ep, lno, 0, 0, cbp))
+ if (cut_line(sp, lno, 0, 0, cbp))
goto cut_line_err;
} else {
/*
* Get the first line. A length of 0 causes cut_line
* to cut from the MARK to the end of the line.
*/
- if (cut_line(sp, ep, fm->lno, fm->cno, fm->lno != tm->lno ?
+ if (cut_line(sp, fm->lno, fm->cno, fm->lno != tm->lno ?
ENTIRE_LINE : (tm->cno - fm->cno) + 1, cbp))
goto cut_line_err;
/* Get the intermediate lines. */
for (lno = fm->lno; ++lno < tm->lno;)
- if (cut_line(sp, ep, lno, 0, ENTIRE_LINE, cbp))
+ if (cut_line(sp, lno, 0, ENTIRE_LINE, cbp))
goto cut_line_err;
/* Get the last line. */
if (tm->lno != fm->lno &&
- cut_line(sp, ep, lno, 0, tm->cno + 1, cbp)) {
-cut_line_err: text_lfree(&cbp->textq);
- cbp->len = 0;
- cbp->flags = 0;
- return (1);
- }
+ cut_line(sp, lno, 0, tm->cno + 1, cbp))
+ goto cut_line_err;
}
append = 0; /* Only append to the named buffer. */
@@ -210,13 +178,19 @@ cut_line_err: text_lfree(&cbp->textq);
goto copyloop;
}
return (0);
+
+cut_line_err:
+ text_lfree(&cbp->textq);
+ cbp->len = 0;
+ cbp->flags = 0;
+ return (1);
}
/*
* cb_rotate --
* Rotate the numbered buffers up one.
*/
-static int
+static void
cb_rotate(sp)
SCR *sp;
{
@@ -256,19 +230,19 @@ cb_rotate(sp)
if (del_cbp != NULL) {
LIST_REMOVE(del_cbp, q);
text_lfree(&del_cbp->textq);
- FREE(del_cbp, sizeof(CB));
+ free(del_cbp);
}
- return (0);
}
/*
* cut_line --
* Cut a portion of a single line.
+ *
+ * PUBLIC: int cut_line __P((SCR *, recno_t, size_t, size_t, CB *));
*/
int
-cut_line(sp, ep, lno, fcno, clen, cbp)
+cut_line(sp, lno, fcno, clen, cbp)
SCR *sp;
- EXF *ep;
recno_t lno;
size_t fcno, clen;
CB *cbp;
@@ -278,10 +252,8 @@ cut_line(sp, ep, lno, fcno, clen, cbp)
char *p;
/* Get the line. */
- if ((p = file_gline(sp, ep, lno, &len)) == NULL) {
- GETLINE_ERR(sp, lno);
+ if (db_get(sp, lno, DBG_FATAL, &p, &len))
return (1);
- }
/* Create a TEXT structure that can hold the entire line. */
if ((tp = text_init(sp, NULL, 0, len)) == NULL)
@@ -294,7 +266,7 @@ cut_line(sp, ep, lno, fcno, clen, cbp)
if (len != 0) {
if (clen == 0)
clen = len - fcno;
- memmove(tp->lb, p + fcno, clen);
+ memcpy(tp->lb, p + fcno, clen);
tp->len = clen;
}
@@ -306,8 +278,36 @@ cut_line(sp, ep, lno, fcno, clen, cbp)
}
/*
+ * cut_close --
+ * Discard all cut buffers.
+ *
+ * PUBLIC: void cut_close __P((GS *));
+ */
+void
+cut_close(gp)
+ GS *gp;
+{
+ CB *cbp;
+
+ /* Free cut buffer list. */
+ while ((cbp = gp->cutq.lh_first) != NULL) {
+ if (cbp->textq.cqh_first != (void *)&cbp->textq)
+ text_lfree(&cbp->textq);
+ LIST_REMOVE(cbp, q);
+ free(cbp);
+ }
+
+ /* Free default cut storage. */
+ cbp = &gp->dcb_store;
+ if (cbp->textq.cqh_first != (void *)&cbp->textq)
+ text_lfree(&cbp->textq);
+}
+
+/*
* text_init --
* Allocate a new TEXT structure.
+ *
+ * PUBLIC: TEXT *text_init __P((SCR *, const char *, size_t, size_t));
*/
TEXT *
text_init(sp, p, len, total_len)
@@ -320,7 +320,7 @@ text_init(sp, p, len, total_len)
CALLOC(sp, tp, TEXT *, 1, sizeof(TEXT));
if (tp == NULL)
return (NULL);
- /* ANSI C doesn't define a call to malloc(2) for 0 bytes. */
+ /* ANSI C doesn't define a call to malloc(3) for 0 bytes. */
if ((tp->lb_len = total_len) != 0) {
MALLOC(sp, tp->lb, CHAR_T *, tp->lb_len);
if (tp->lb == NULL) {
@@ -328,7 +328,7 @@ text_init(sp, p, len, total_len)
return (NULL);
}
if (p != NULL && len != 0)
- memmove(tp->lb, p, len);
+ memcpy(tp->lb, p, len);
}
tp->len = len;
return (tp);
@@ -337,6 +337,8 @@ text_init(sp, p, len, total_len)
/*
* text_lfree --
* Free a chain of text structures.
+ *
+ * PUBLIC: void text_lfree __P((TEXTH *));
*/
void
text_lfree(headp)
@@ -353,14 +355,14 @@ text_lfree(headp)
/*
* text_free --
* Free a text structure.
+ *
+ * PUBLIC: void text_free __P((TEXT *));
*/
void
text_free(tp)
TEXT *tp;
{
if (tp->lb != NULL)
- FREE(tp->lb, tp->lb_len);
- if (tp->wd != NULL)
- FREE(tp->wd, tp->wd_len);
- FREE(tp, sizeof(TEXT));
+ free(tp->lb);
+ free(tp);
}
diff --git a/contrib/nvi/common/cut.h b/contrib/nvi/common/cut.h
new file mode 100644
index 000000000000..43f3ca817efd
--- /dev/null
+++ b/contrib/nvi/common/cut.h
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)cut.h 10.5 (Berkeley) 4/3/96
+ */
+
+typedef struct _texth TEXTH; /* TEXT list head structure. */
+CIRCLEQ_HEAD(_texth, _text);
+
+/* Cut buffers. */
+struct _cb {
+ LIST_ENTRY(_cb) q; /* Linked list of cut buffers. */
+ TEXTH textq; /* Linked list of TEXT structures. */
+ CHAR_T name; /* Cut buffer name. */
+ size_t len; /* Total length of cut text. */
+
+#define CB_LMODE 0x01 /* Cut was in line mode. */
+ u_int8_t flags;
+};
+
+/* Lines/blocks of text. */
+struct _text { /* Text: a linked list of lines. */
+ CIRCLEQ_ENTRY(_text) q; /* Linked list of text structures. */
+ char *lb; /* Line buffer. */
+ size_t lb_len; /* Line buffer length. */
+ size_t len; /* Line length. */
+
+ /* These fields are used by the vi text input routine. */
+ recno_t lno; /* 1-N: file line. */
+ size_t cno; /* 0-N: file character in line. */
+ size_t ai; /* 0-N: autoindent bytes. */
+ size_t insert; /* 0-N: bytes to insert (push). */
+ size_t offset; /* 0-N: initial, unerasable chars. */
+ size_t owrite; /* 0-N: chars to overwrite. */
+ size_t R_erase; /* 0-N: 'R' erase count. */
+ size_t sv_cno; /* 0-N: Saved line cursor. */
+ size_t sv_len; /* 0-N: Saved line length. */
+
+ /*
+ * These fields returns information from the vi text input routine.
+ *
+ * The termination condition. Note, this field is only valid if the
+ * text input routine returns success.
+ * TERM_BS: User backspaced over the prompt.
+ * TERM_CEDIT: User entered <edit-char>.
+ * TERM_CR: User entered <carriage-return>; no data.
+ * TERM_ESC: User entered <escape>; no data.
+ * TERM_OK: Data available.
+ * TERM_SEARCH: Incremental search.
+ */
+ enum {
+ TERM_BS, TERM_CEDIT, TERM_CR, TERM_ESC, TERM_OK, TERM_SEARCH
+ } term;
+};
+
+/*
+ * Get named buffer 'name'.
+ * Translate upper-case buffer names to lower-case buffer names.
+ */
+#define CBNAME(sp, cbp, nch) { \
+ CHAR_T L__name; \
+ L__name = isupper(nch) ? tolower(nch) : (nch); \
+ for (cbp = sp->gp->cutq.lh_first; \
+ cbp != NULL; cbp = cbp->q.le_next) \
+ if (cbp->name == L__name) \
+ break; \
+}
+
+/* Flags to the cut() routine. */
+#define CUT_LINEMODE 0x01 /* Cut in line mode. */
+#define CUT_NUMOPT 0x02 /* Numeric buffer: optional. */
+#define CUT_NUMREQ 0x04 /* Numeric buffer: required. */
diff --git a/contrib/nvi/common/delete.c b/contrib/nvi/common/delete.c
new file mode 100644
index 000000000000..001788f9bb38
--- /dev/null
+++ b/contrib/nvi/common/delete.c
@@ -0,0 +1,160 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)delete.c 10.12 (Berkeley) 10/23/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+
+/*
+ * del --
+ * Delete a range of text.
+ *
+ * PUBLIC: int del __P((SCR *, MARK *, MARK *, int));
+ */
+int
+del(sp, fm, tm, lmode)
+ SCR *sp;
+ MARK *fm, *tm;
+ int lmode;
+{
+ recno_t lno;
+ size_t blen, len, nlen, tlen;
+ char *bp, *p;
+ int eof, rval;
+
+ bp = NULL;
+
+ /* Case 1 -- delete in line mode. */
+ if (lmode) {
+ for (lno = tm->lno; lno >= fm->lno; --lno) {
+ if (db_delete(sp, lno))
+ return (1);
+ ++sp->rptlines[L_DELETED];
+ if (lno % INTERRUPT_CHECK == 0 && INTERRUPTED(sp))
+ break;
+ }
+ goto done;
+ }
+
+ /*
+ * Case 2 -- delete to EOF. This is a special case because it's
+ * easier to pick it off than try and find it in the other cases.
+ */
+ if (db_last(sp, &lno))
+ return (1);
+ if (tm->lno >= lno) {
+ if (tm->lno == lno) {
+ if (db_get(sp, lno, DBG_FATAL, &p, &len))
+ return (1);
+ eof = tm->cno >= len ? 1 : 0;
+ } else
+ eof = 1;
+ if (eof) {
+ for (lno = tm->lno; lno > fm->lno; --lno) {
+ if (db_delete(sp, lno))
+ return (1);
+ ++sp->rptlines[L_DELETED];
+ if (lno %
+ INTERRUPT_CHECK == 0 && INTERRUPTED(sp))
+ break;
+ }
+ if (db_get(sp, fm->lno, DBG_FATAL, &p, &len))
+ return (1);
+ GET_SPACE_RET(sp, bp, blen, fm->cno);
+ memcpy(bp, p, fm->cno);
+ if (db_set(sp, fm->lno, bp, fm->cno))
+ return (1);
+ goto done;
+ }
+ }
+
+ /* Case 3 -- delete within a single line. */
+ if (tm->lno == fm->lno) {
+ if (db_get(sp, fm->lno, DBG_FATAL, &p, &len))
+ return (1);
+ GET_SPACE_RET(sp, bp, blen, len);
+ if (fm->cno != 0)
+ memcpy(bp, p, fm->cno);
+ memcpy(bp + fm->cno, p + (tm->cno + 1), len - (tm->cno + 1));
+ if (db_set(sp, fm->lno,
+ bp, len - ((tm->cno - fm->cno) + 1)))
+ goto err;
+ goto done;
+ }
+
+ /*
+ * Case 4 -- delete over multiple lines.
+ *
+ * Copy the start partial line into place.
+ */
+ if ((tlen = fm->cno) != 0) {
+ if (db_get(sp, fm->lno, DBG_FATAL, &p, NULL))
+ return (1);
+ GET_SPACE_RET(sp, bp, blen, tlen + 256);
+ memcpy(bp, p, tlen);
+ }
+
+ /* Copy the end partial line into place. */
+ if (db_get(sp, tm->lno, DBG_FATAL, &p, &len))
+ goto err;
+ if (len != 0 && tm->cno != len - 1) {
+ /*
+ * XXX
+ * We can overflow memory here, if the total length is greater
+ * than SIZE_T_MAX. The only portable way I've found to test
+ * is depending on the overflow being less than the value.
+ */
+ nlen = (len - (tm->cno + 1)) + tlen;
+ if (tlen > nlen) {
+ msgq(sp, M_ERR, "002|Line length overflow");
+ goto err;
+ }
+ if (tlen == 0) {
+ GET_SPACE_RET(sp, bp, blen, nlen);
+ } else
+ ADD_SPACE_RET(sp, bp, blen, nlen);
+
+ memcpy(bp + tlen, p + (tm->cno + 1), len - (tm->cno + 1));
+ tlen += len - (tm->cno + 1);
+ }
+
+ /* Set the current line. */
+ if (db_set(sp, fm->lno, bp, tlen))
+ goto err;
+
+ /* Delete the last and intermediate lines. */
+ for (lno = tm->lno; lno > fm->lno; --lno) {
+ if (db_delete(sp, lno))
+ goto err;
+ ++sp->rptlines[L_DELETED];
+ if (lno % INTERRUPT_CHECK == 0 && INTERRUPTED(sp))
+ break;
+ }
+
+done: rval = 0;
+ if (0)
+err: rval = 1;
+ if (bp != NULL)
+ FREE_SPACE(sp, bp, blen);
+ return (rval);
+}
diff --git a/contrib/nvi/common/exf.c b/contrib/nvi/common/exf.c
new file mode 100644
index 000000000000..2993b0f4a8a5
--- /dev/null
+++ b/contrib/nvi/common/exf.c
@@ -0,0 +1,1498 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)exf.c 10.49 (Berkeley) 10/10/96";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/types.h> /* XXX: param.h may not have included types.h */
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+/*
+ * We include <sys/file.h>, because the flock(2) and open(2) #defines
+ * were found there on historical systems. We also include <fcntl.h>
+ * because the open(2) #defines are found there on newer systems.
+ */
+#include <sys/file.h>
+
+#include <bitstring.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+
+static int file_backup __P((SCR *, char *, char *));
+static void file_cinit __P((SCR *));
+static void file_comment __P((SCR *));
+static int file_spath __P((SCR *, FREF *, struct stat *, int *));
+
+/*
+ * file_add --
+ * Insert a file name into the FREF list, if it doesn't already
+ * appear in it.
+ *
+ * !!!
+ * The "if it doesn't already appear" changes vi's semantics slightly. If
+ * you do a "vi foo bar", and then execute "next bar baz", the edit of bar
+ * will reflect the line/column of the previous edit session. Historic nvi
+ * did not do this. The change is a logical extension of the change where
+ * vi now remembers the last location in any file that it has ever edited,
+ * not just the previously edited file.
+ *
+ * PUBLIC: FREF *file_add __P((SCR *, CHAR_T *));
+ */
+FREF *
+file_add(sp, name)
+ SCR *sp;
+ CHAR_T *name;
+{
+ GS *gp;
+ FREF *frp, *tfrp;
+
+ /*
+ * Return it if it already exists. Note that we test against the
+ * user's name, whatever that happens to be, including if it's a
+ * temporary file.
+ *
+ * If the user added a file but was unable to initialize it, there
+ * can be file list entries where the name field is NULL. Discard
+ * them the next time we see them.
+ */
+ gp = sp->gp;
+ if (name != NULL)
+ for (frp = gp->frefq.cqh_first;
+ frp != (FREF *)&gp->frefq; frp = frp->q.cqe_next) {
+ if (frp->name == NULL) {
+ tfrp = frp->q.cqe_next;
+ CIRCLEQ_REMOVE(&gp->frefq, frp, q);
+ if (frp->name != NULL)
+ free(frp->name);
+ free(frp);
+ frp = tfrp;
+ continue;
+ }
+ if (!strcmp(frp->name, name))
+ return (frp);
+ }
+
+ /* Allocate and initialize the FREF structure. */
+ CALLOC(sp, frp, FREF *, 1, sizeof(FREF));
+ if (frp == NULL)
+ return (NULL);
+
+ /*
+ * If no file name specified, or if the file name is a request
+ * for something temporary, file_init() will allocate the file
+ * name. Temporary files are always ignored.
+ */
+ if (name != NULL && strcmp(name, TEMPORARY_FILE_STRING) &&
+ (frp->name = strdup(name)) == NULL) {
+ free(frp);
+ msgq(sp, M_SYSERR, NULL);
+ return (NULL);
+ }
+
+ /* Append into the chain of file names. */
+ CIRCLEQ_INSERT_TAIL(&gp->frefq, frp, q);
+
+ return (frp);
+}
+
+/*
+ * file_init --
+ * Start editing a file, based on the FREF structure. If successsful,
+ * let go of any previous file. Don't release the previous file until
+ * absolutely sure we have the new one.
+ *
+ * PUBLIC: int file_init __P((SCR *, FREF *, char *, int));
+ */
+int
+file_init(sp, frp, rcv_name, flags)
+ SCR *sp;
+ FREF *frp;
+ char *rcv_name;
+ int flags;
+{
+ EXF *ep;
+ RECNOINFO oinfo;
+ struct stat sb;
+ size_t psize;
+ int fd, exists, open_err, readonly;
+ char *oname, tname[MAXPATHLEN];
+
+ open_err = readonly = 0;
+
+ /*
+ * If the file is a recovery file, let the recovery code handle it.
+ * Clear the FR_RECOVER flag first -- the recovery code does set up,
+ * and then calls us! If the recovery call fails, it's probably
+ * because the named file doesn't exist. So, move boldly forward,
+ * presuming that there's an error message the user will get to see.
+ */
+ if (F_ISSET(frp, FR_RECOVER)) {
+ F_CLR(frp, FR_RECOVER);
+ return (rcv_read(sp, frp));
+ }
+
+ /*
+ * Required FRP initialization; the only flag we keep is the
+ * cursor information.
+ */
+ F_CLR(frp, ~FR_CURSORSET);
+
+ /*
+ * Required EXF initialization:
+ * Flush the line caches.
+ * Default recover mail file fd to -1.
+ * Set initial EXF flag bits.
+ */
+ CALLOC_RET(sp, ep, EXF *, 1, sizeof(EXF));
+ ep->c_lno = ep->c_nlines = OOBLNO;
+ ep->rcv_fd = ep->fcntl_fd = -1;
+ F_SET(ep, F_FIRSTMODIFY);
+
+ /*
+ * Scan the user's path to find the file that we're going to
+ * try and open.
+ */
+ if (file_spath(sp, frp, &sb, &exists))
+ return (1);
+
+ /*
+ * If no name or backing file, for whatever reason, create a backing
+ * temporary file, saving the temp file name so we can later unlink
+ * it. If the user never named this file, copy the temporary file name
+ * to the real name (we display that until the user renames it).
+ */
+ oname = frp->name;
+ if (LF_ISSET(FS_OPENERR) || oname == NULL || !exists) {
+ if (opts_empty(sp, O_DIRECTORY, 0))
+ goto err;
+ (void)snprintf(tname, sizeof(tname),
+ "%s/vi.XXXXXX", O_STR(sp, O_DIRECTORY));
+ if ((fd = mkstemp(tname)) == -1) {
+ msgq(sp, M_SYSERR,
+ "237|Unable to create temporary file");
+ goto err;
+ }
+ (void)close(fd);
+
+ if (frp->name == NULL)
+ F_SET(frp, FR_TMPFILE);
+ if ((frp->tname = strdup(tname)) == NULL ||
+ frp->name == NULL && (frp->name = strdup(tname)) == NULL) {
+ if (frp->tname != NULL)
+ free(frp->tname);
+ msgq(sp, M_SYSERR, NULL);
+ (void)unlink(tname);
+ goto err;
+ }
+ oname = frp->tname;
+ psize = 1024;
+ if (!LF_ISSET(FS_OPENERR))
+ F_SET(frp, FR_NEWFILE);
+
+ time(&ep->mtime);
+ } else {
+ /*
+ * XXX
+ * A seat of the pants calculation: try to keep the file in
+ * 15 pages or less. Don't use a page size larger than 10K
+ * (vi should have good locality) or smaller than 1K.
+ */
+ psize = ((sb.st_size / 15) + 1023) / 1024;
+ if (psize > 10)
+ psize = 10;
+ if (psize == 0)
+ psize = 1;
+ psize *= 1024;
+
+ F_SET(ep, F_DEVSET);
+ ep->mdev = sb.st_dev;
+ ep->minode = sb.st_ino;
+
+ ep->mtime = sb.st_mtime;
+
+ if (!S_ISREG(sb.st_mode))
+ msgq_str(sp, M_ERR, oname,
+ "238|Warning: %s is not a regular file");
+ }
+
+ /* Set up recovery. */
+ memset(&oinfo, 0, sizeof(RECNOINFO));
+ oinfo.bval = '\n'; /* Always set. */
+ oinfo.psize = psize;
+ oinfo.flags = F_ISSET(sp->gp, G_SNAPSHOT) ? R_SNAPSHOT : 0;
+ if (rcv_name == NULL) {
+ if (!rcv_tmp(sp, ep, frp->name))
+ oinfo.bfname = ep->rcv_path;
+ } else {
+ if ((ep->rcv_path = strdup(rcv_name)) == NULL) {
+ msgq(sp, M_SYSERR, NULL);
+ goto err;
+ }
+ oinfo.bfname = ep->rcv_path;
+ F_SET(ep, F_MODIFIED);
+ }
+
+ /* Open a db structure. */
+ if ((ep->db = dbopen(rcv_name == NULL ? oname : NULL,
+ O_NONBLOCK | O_RDONLY,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
+ DB_RECNO, &oinfo)) == NULL) {
+ msgq_str(sp,
+ M_SYSERR, rcv_name == NULL ? oname : rcv_name, "%s");
+ /*
+ * !!!
+ * Historically, vi permitted users to edit files that couldn't
+ * be read. This isn't useful for single files from a command
+ * line, but it's quite useful for "vi *.c", since you can skip
+ * past files that you can't read.
+ */
+ open_err = 1;
+ goto oerr;
+ }
+
+ /*
+ * Do the remaining things that can cause failure of the new file,
+ * mark and logging initialization.
+ */
+ if (mark_init(sp, ep) || log_init(sp, ep))
+ goto err;
+
+ /*
+ * Set the alternate file name to be the file we're discarding.
+ *
+ * !!!
+ * Temporary files can't become alternate files, so there's no file
+ * name. This matches historical practice, although it could only
+ * happen in historical vi as the result of the initial command, i.e.
+ * if vi was executed without a file name.
+ */
+ if (LF_ISSET(FS_SETALT))
+ set_alt_name(sp, sp->frp == NULL ||
+ F_ISSET(sp->frp, FR_TMPFILE) ? NULL : sp->frp->name);
+
+ /*
+ * Close the previous file; if that fails, close the new one and run
+ * for the border.
+ *
+ * !!!
+ * There's a nasty special case. If the user edits a temporary file,
+ * and then does an ":e! %", we need to re-initialize the backing
+ * file, but we can't change the name. (It's worse -- we're dealing
+ * with *names* here, we can't even detect that it happened.) Set a
+ * flag so that the file_end routine ignores the backing information
+ * of the old file if it happens to be the same as the new one.
+ *
+ * !!!
+ * Side-effect: after the call to file_end(), sp->frp may be NULL.
+ */
+ if (sp->ep != NULL) {
+ F_SET(frp, FR_DONTDELETE);
+ if (file_end(sp, NULL, LF_ISSET(FS_FORCE))) {
+ (void)file_end(sp, ep, 1);
+ goto err;
+ }
+ F_CLR(frp, FR_DONTDELETE);
+ }
+
+ /*
+ * Lock the file; if it's a recovery file, it should already be
+ * locked. Note, we acquire the lock after the previous file
+ * has been ended, so that we don't get an "already locked" error
+ * for ":edit!".
+ *
+ * XXX
+ * While the user can't interrupt us between the open and here,
+ * there's a race between the dbopen() and the lock. Not much
+ * we can do about it.
+ *
+ * XXX
+ * We don't make a big deal of not being able to lock the file. As
+ * locking rarely works over NFS, and often fails if the file was
+ * mmap(2)'d, it's far too common to do anything like print an error
+ * message, let alone make the file readonly. At some future time,
+ * when locking is a little more reliable, this should change to be
+ * an error.
+ */
+ if (rcv_name == NULL)
+ switch (file_lock(sp, oname,
+ &ep->fcntl_fd, ep->db->fd(ep->db), 0)) {
+ case LOCK_FAILED:
+ F_SET(frp, FR_UNLOCKED);
+ break;
+ case LOCK_UNAVAIL:
+ readonly = 1;
+ msgq_str(sp, M_INFO, oname,
+ "239|%s already locked, session is read-only");
+ break;
+ case LOCK_SUCCESS:
+ break;
+ }
+
+ /*
+ * Historically, the readonly edit option was set per edit buffer in
+ * vi, unless the -R command-line option was specified or the program
+ * was executed as "view". (Well, to be truthful, if the letter 'w'
+ * occurred anywhere in the program name, but let's not get into that.)
+ * So, the persistant readonly state has to be stored in the screen
+ * structure, and the edit option value toggles with the contents of
+ * the edit buffer. If the persistant readonly flag is set, set the
+ * readonly edit option.
+ *
+ * Otherwise, try and figure out if a file is readonly. This is a
+ * dangerous thing to do. The kernel is the only arbiter of whether
+ * or not a file is writeable, and the best that a user program can
+ * do is guess. Obvious loopholes are files that are on a file system
+ * mounted readonly (access catches this one on a few systems), or
+ * alternate protection mechanisms, ACL's for example, that we can't
+ * portably check. Lots of fun, and only here because users whined.
+ *
+ * !!!
+ * Historic vi displayed the readonly message if none of the file
+ * write bits were set, or if an an access(2) call on the path
+ * failed. This seems reasonable. If the file is mode 444, root
+ * users may want to know that the owner of the file did not expect
+ * it to be written.
+ *
+ * Historic vi set the readonly bit if no write bits were set for
+ * a file, even if the access call would have succeeded. This makes
+ * the superuser force the write even when vi expects that it will
+ * succeed. I'm less supportive of this semantic, but it's historic
+ * practice and the conservative approach to vi'ing files as root.
+ *
+ * It would be nice if there was some way to update this when the user
+ * does a "^Z; chmod ...". The problem is that we'd first have to
+ * distinguish between readonly bits set because of file permissions
+ * and those set for other reasons. That's not too hard, but deciding
+ * when to reevaluate the permissions is trickier. An alternative
+ * might be to turn off the readonly bit if the user forces a write
+ * and it succeeds.
+ *
+ * XXX
+ * Access(2) doesn't consider the effective uid/gid values. This
+ * probably isn't a problem for vi when it's running standalone.
+ */
+ if (readonly || F_ISSET(sp, SC_READONLY) ||
+ !F_ISSET(frp, FR_NEWFILE) &&
+ (!(sb.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) ||
+ access(frp->name, W_OK)))
+ O_SET(sp, O_READONLY);
+ else
+ O_CLR(sp, O_READONLY);
+
+ /* Switch... */
+ ++ep->refcnt;
+ sp->ep = ep;
+ sp->frp = frp;
+
+ /* Set the initial cursor position, queue initial command. */
+ file_cinit(sp);
+
+ /* Redraw the screen from scratch, schedule a welcome message. */
+ F_SET(sp, SC_SCR_REFORMAT | SC_STATUS);
+
+ return (0);
+
+err: if (frp->name != NULL) {
+ free(frp->name);
+ frp->name = NULL;
+ }
+ if (frp->tname != NULL) {
+ (void)unlink(frp->tname);
+ free(frp->tname);
+ frp->tname = NULL;
+ }
+
+oerr: if (F_ISSET(ep, F_RCV_ON))
+ (void)unlink(ep->rcv_path);
+ if (ep->rcv_path != NULL) {
+ free(ep->rcv_path);
+ ep->rcv_path = NULL;
+ }
+ if (ep->db != NULL)
+ (void)ep->db->close(ep->db);
+ free(ep);
+
+ return (open_err ?
+ file_init(sp, frp, rcv_name, flags | FS_OPENERR) : 1);
+}
+
+/*
+ * file_spath --
+ * Scan the user's path to find the file that we're going to
+ * try and open.
+ */
+static int
+file_spath(sp, frp, sbp, existsp)
+ SCR *sp;
+ FREF *frp;
+ struct stat *sbp;
+ int *existsp;
+{
+ CHAR_T savech;
+ size_t len;
+ int found;
+ char *name, *p, *t, path[MAXPATHLEN];
+
+ /*
+ * If the name is NULL or an explicit reference (i.e., the first
+ * component is . or ..) ignore the O_PATH option.
+ */
+ name = frp->name;
+ if (name == NULL) {
+ *existsp = 0;
+ return (0);
+ }
+ if (name[0] == '/' || name[0] == '.' &&
+ (name[1] == '/' || name[1] == '.' && name[2] == '/')) {
+ *existsp = !stat(name, sbp);
+ return (0);
+ }
+
+ /* Try . */
+ if (!stat(name, sbp)) {
+ *existsp = 1;
+ return (0);
+ }
+
+ /* Try the O_PATH option values. */
+ for (found = 0, p = t = O_STR(sp, O_PATH);; ++p)
+ if (*p == ':' || *p == '\0') {
+ if (t < p - 1) {
+ savech = *p;
+ *p = '\0';
+ len = snprintf(path,
+ sizeof(path), "%s/%s", t, name);
+ *p = savech;
+ if (!stat(path, sbp)) {
+ found = 1;
+ break;
+ }
+ }
+ t = p + 1;
+ if (*p == '\0')
+ break;
+ }
+
+ /* If we found it, build a new pathname and discard the old one. */
+ if (found) {
+ MALLOC_RET(sp, p, char *, len + 1);
+ memcpy(p, path, len + 1);
+ free(frp->name);
+ frp->name = p;
+ }
+ *existsp = found;
+ return (0);
+}
+
+/*
+ * file_cinit --
+ * Set up the initial cursor position.
+ */
+static void
+file_cinit(sp)
+ SCR *sp;
+{
+ GS *gp;
+ MARK m;
+ size_t len;
+ int nb;
+
+ /* Set some basic defaults. */
+ sp->lno = 1;
+ sp->cno = 0;
+
+ /*
+ * Historically, initial commands (the -c option) weren't executed
+ * until a file was loaded, e.g. "vi +10 nofile", followed by an
+ * :edit or :tag command, would execute the +10 on the file loaded
+ * by the subsequent command, (assuming that it existed). This
+ * applied as well to files loaded using the tag commands, and we
+ * follow that historic practice. Also, all initial commands were
+ * ex commands and were always executed on the last line of the file.
+ *
+ * Otherwise, if no initial command for this file:
+ * If in ex mode, move to the last line, first nonblank character.
+ * If the file has previously been edited, move to the last known
+ * position, and check it for validity.
+ * Otherwise, move to the first line, first nonblank.
+ *
+ * This gets called by the file init code, because we may be in a
+ * file of ex commands and we want to execute them from the right
+ * location in the file.
+ */
+ nb = 0;
+ gp = sp->gp;
+ if (gp->c_option != NULL && !F_ISSET(sp->frp, FR_NEWFILE)) {
+ if (db_last(sp, &sp->lno))
+ return;
+ if (sp->lno == 0) {
+ sp->lno = 1;
+ sp->cno = 0;
+ }
+ if (ex_run_str(sp,
+ "-c option", gp->c_option, strlen(gp->c_option), 1, 1))
+ return;
+ gp->c_option = NULL;
+ } else if (F_ISSET(sp, SC_EX)) {
+ if (db_last(sp, &sp->lno))
+ return;
+ if (sp->lno == 0) {
+ sp->lno = 1;
+ sp->cno = 0;
+ return;
+ }
+ nb = 1;
+ } else {
+ if (F_ISSET(sp->frp, FR_CURSORSET)) {
+ sp->lno = sp->frp->lno;
+ sp->cno = sp->frp->cno;
+
+ /* If returning to a file in vi, center the line. */
+ F_SET(sp, SC_SCR_CENTER);
+ } else {
+ if (O_ISSET(sp, O_COMMENT))
+ file_comment(sp);
+ else
+ sp->lno = 1;
+ nb = 1;
+ }
+ if (db_get(sp, sp->lno, 0, NULL, &len)) {
+ sp->lno = 1;
+ sp->cno = 0;
+ return;
+ }
+ if (!nb && sp->cno > len)
+ nb = 1;
+ }
+ if (nb) {
+ sp->cno = 0;
+ (void)nonblank(sp, sp->lno, &sp->cno);
+ }
+
+ /*
+ * !!!
+ * The initial column is also the most attractive column.
+ */
+ sp->rcm = sp->cno;
+
+ /*
+ * !!!
+ * Historically, vi initialized the absolute mark, but ex did not.
+ * Which meant, that if the first command in ex mode was "visual",
+ * or if an ex command was executed first (e.g. vi +10 file) vi was
+ * entered without the mark being initialized. For consistency, if
+ * the file isn't empty, we initialize it for everyone, believing
+ * that it can't hurt, and is generally useful. Not initializing it
+ * if the file is empty is historic practice, although it has always
+ * been possible to set (and use) marks in empty vi files.
+ */
+ m.lno = sp->lno;
+ m.cno = sp->cno;
+ (void)mark_set(sp, ABSMARK1, &m, 0);
+}
+
+/*
+ * file_end --
+ * Stop editing a file.
+ *
+ * PUBLIC: int file_end __P((SCR *, EXF *, int));
+ */
+int
+file_end(sp, ep, force)
+ SCR *sp;
+ EXF *ep;
+ int force;
+{
+ FREF *frp;
+
+ /*
+ * !!!
+ * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+ * (If argument ep is NULL, use sp->ep.)
+ *
+ * If multiply referenced, just decrement the count and return.
+ */
+ if (ep == NULL)
+ ep = sp->ep;
+ if (--ep->refcnt != 0)
+ return (0);
+
+ /*
+ *
+ * Clean up the FREF structure.
+ *
+ * Save the cursor location.
+ *
+ * XXX
+ * It would be cleaner to do this somewhere else, but by the time
+ * ex or vi knows that we're changing files it's already happened.
+ */
+ frp = sp->frp;
+ frp->lno = sp->lno;
+ frp->cno = sp->cno;
+ F_SET(frp, FR_CURSORSET);
+
+ /*
+ * We may no longer need the temporary backing file, so clean it
+ * up. We don't need the FREF structure either, if the file was
+ * never named, so lose it.
+ *
+ * !!!
+ * Re: FR_DONTDELETE, see the comment above in file_init().
+ */
+ if (!F_ISSET(frp, FR_DONTDELETE) && frp->tname != NULL) {
+ if (unlink(frp->tname))
+ msgq_str(sp, M_SYSERR, frp->tname, "240|%s: remove");
+ free(frp->tname);
+ frp->tname = NULL;
+ if (F_ISSET(frp, FR_TMPFILE)) {
+ CIRCLEQ_REMOVE(&sp->gp->frefq, frp, q);
+ if (frp->name != NULL)
+ free(frp->name);
+ free(frp);
+ }
+ sp->frp = NULL;
+ }
+
+ /*
+ * Clean up the EXF structure.
+ *
+ * Close the db structure.
+ */
+ if (ep->db->close != NULL && ep->db->close(ep->db) && !force) {
+ msgq_str(sp, M_SYSERR, frp->name, "241|%s: close");
+ ++ep->refcnt;
+ return (1);
+ }
+
+ /* COMMITTED TO THE CLOSE. THERE'S NO GOING BACK... */
+
+ /* Stop logging. */
+ (void)log_end(sp, ep);
+
+ /* Free up any marks. */
+ (void)mark_end(sp, ep);
+
+ /*
+ * Delete recovery files, close the open descriptor, free recovery
+ * memory. See recover.c for a description of the protocol.
+ *
+ * XXX
+ * Unlink backup file first, we can detect that the recovery file
+ * doesn't reference anything when the user tries to recover it.
+ * There's a race, here, obviously, but it's fairly small.
+ */
+ if (!F_ISSET(ep, F_RCV_NORM)) {
+ if (ep->rcv_path != NULL && unlink(ep->rcv_path))
+ msgq_str(sp, M_SYSERR, ep->rcv_path, "242|%s: remove");
+ if (ep->rcv_mpath != NULL && unlink(ep->rcv_mpath))
+ msgq_str(sp, M_SYSERR, ep->rcv_mpath, "243|%s: remove");
+ }
+ if (ep->fcntl_fd != -1)
+ (void)close(ep->fcntl_fd);
+ if (ep->rcv_fd != -1)
+ (void)close(ep->rcv_fd);
+ if (ep->rcv_path != NULL)
+ free(ep->rcv_path);
+ if (ep->rcv_mpath != NULL)
+ free(ep->rcv_mpath);
+
+ free(ep);
+ return (0);
+}
+
+/*
+ * file_write --
+ * Write the file to disk. Historic vi had fairly convoluted
+ * semantics for whether or not writes would happen. That's
+ * why all the flags.
+ *
+ * PUBLIC: int file_write __P((SCR *, MARK *, MARK *, char *, int));
+ */
+int
+file_write(sp, fm, tm, name, flags)
+ SCR *sp;
+ MARK *fm, *tm;
+ char *name;
+ int flags;
+{
+ enum { NEWFILE, OLDFILE } mtype;
+ struct stat sb;
+ EXF *ep;
+ FILE *fp;
+ FREF *frp;
+ MARK from, to;
+ size_t len;
+ u_long nlno, nch;
+ int fd, nf, noname, oflags, rval;
+ char *p, *s, *t, buf[MAXPATHLEN + 64];
+ const char *msgstr;
+
+ ep = sp->ep;
+ frp = sp->frp;
+
+ /*
+ * Writing '%', or naming the current file explicitly, has the
+ * same semantics as writing without a name.
+ */
+ if (name == NULL || !strcmp(name, frp->name)) {
+ noname = 1;
+ name = frp->name;
+ } else
+ noname = 0;
+
+ /* Can't write files marked read-only, unless forced. */
+ if (!LF_ISSET(FS_FORCE) && noname && O_ISSET(sp, O_READONLY)) {
+ msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ?
+ "244|Read-only file, not written; use ! to override" :
+ "245|Read-only file, not written");
+ return (1);
+ }
+
+ /* If not forced, not appending, and "writeany" not set ... */
+ if (!LF_ISSET(FS_FORCE | FS_APPEND) && !O_ISSET(sp, O_WRITEANY)) {
+ /* Don't overwrite anything but the original file. */
+ if ((!noname || F_ISSET(frp, FR_NAMECHANGE)) &&
+ !stat(name, &sb)) {
+ msgq_str(sp, M_ERR, name,
+ LF_ISSET(FS_POSSIBLE) ?
+ "246|%s exists, not written; use ! to override" :
+ "247|%s exists, not written");
+ return (1);
+ }
+
+ /*
+ * Don't write part of any existing file. Only test for the
+ * original file, the previous test catches anything else.
+ */
+ if (!LF_ISSET(FS_ALL) && noname && !stat(name, &sb)) {
+ msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ?
+ "248|Partial file, not written; use ! to override" :
+ "249|Partial file, not written");
+ return (1);
+ }
+ }
+
+ /*
+ * Figure out if the file already exists -- if it doesn't, we display
+ * the "new file" message. The stat might not be necessary, but we
+ * just repeat it because it's easier than hacking the previous tests.
+ * The information is only used for the user message and modification
+ * time test, so we can ignore the obvious race condition.
+ *
+ * One final test. If we're not forcing or appending the current file,
+ * and we have a saved modification time, object if the file changed
+ * since we last edited or wrote it, and make them force it.
+ */
+ if (stat(name, &sb))
+ mtype = NEWFILE;
+ else {
+ if (noname && !LF_ISSET(FS_FORCE | FS_APPEND) &&
+ (F_ISSET(ep, F_DEVSET) &&
+ (sb.st_dev != ep->mdev || sb.st_ino != ep->minode) ||
+ sb.st_mtime != ep->mtime)) {
+ msgq_str(sp, M_ERR, name, LF_ISSET(FS_POSSIBLE) ?
+"250|%s: file modified more recently than this copy; use ! to override" :
+"251|%s: file modified more recently than this copy");
+ return (1);
+ }
+
+ mtype = OLDFILE;
+ }
+
+ /* Set flags to create, write, and either append or truncate. */
+ oflags = O_CREAT | O_WRONLY |
+ (LF_ISSET(FS_APPEND) ? O_APPEND : O_TRUNC);
+
+ /* Backup the file if requested. */
+ if (!opts_empty(sp, O_BACKUP, 1) &&
+ file_backup(sp, name, O_STR(sp, O_BACKUP)) && !LF_ISSET(FS_FORCE))
+ return (1);
+
+ /* Open the file. */
+ SIGBLOCK;
+ if ((fd = open(name, oflags,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) < 0) {
+ msgq_str(sp, M_SYSERR, name, "%s");
+ SIGUNBLOCK;
+ return (1);
+ }
+ SIGUNBLOCK;
+
+ /* Try and get a lock. */
+ if (!noname && file_lock(sp, NULL, NULL, fd, 0) == LOCK_UNAVAIL)
+ msgq_str(sp, M_ERR, name,
+ "252|%s: write lock was unavailable");
+
+#if __linux__
+ /*
+ * XXX
+ * In libc 4.5.x, fdopen(fd, "w") clears the O_APPEND flag (if set).
+ * This bug is fixed in libc 4.6.x.
+ *
+ * This code works around this problem for libc 4.5.x users.
+ * Note that this code is harmless if you're using libc 4.6.x.
+ */
+ if (LF_ISSET(FS_APPEND) && lseek(fd, (off_t)0, SEEK_END) < 0) {
+ msgq(sp, M_SYSERR, name);
+ return (1);
+ }
+#endif
+
+ /*
+ * Use stdio for buffering.
+ *
+ * XXX
+ * SVR4.2 requires the fdopen mode exactly match the original open
+ * mode, i.e. you have to open with "a" if appending.
+ */
+ if ((fp = fdopen(fd, LF_ISSET(FS_APPEND) ? "a" : "w")) == NULL) {
+ msgq_str(sp, M_SYSERR, name, "%s");
+ (void)close(fd);
+ return (1);
+ }
+
+ /* Build fake addresses, if necessary. */
+ if (fm == NULL) {
+ from.lno = 1;
+ from.cno = 0;
+ fm = &from;
+ if (db_last(sp, &to.lno))
+ return (1);
+ to.cno = 0;
+ tm = &to;
+ }
+
+ rval = ex_writefp(sp, name, fp, fm, tm, &nlno, &nch, 0);
+
+ /*
+ * Save the new last modification time -- even if the write fails
+ * we re-init the time. That way the user can clean up the disk
+ * and rewrite without having to force it.
+ */
+ if (noname)
+ if (stat(name, &sb))
+ time(&ep->mtime);
+ else {
+ F_SET(ep, F_DEVSET);
+ ep->mdev = sb.st_dev;
+ ep->minode = sb.st_ino;
+
+ ep->mtime = sb.st_mtime;
+ }
+
+ /*
+ * If the write failed, complain loudly. ex_writefp() has already
+ * complained about the actual error, reinforce it if data was lost.
+ */
+ if (rval) {
+ if (!LF_ISSET(FS_APPEND))
+ msgq_str(sp, M_ERR, name,
+ "254|%s: WARNING: FILE TRUNCATED");
+ return (1);
+ }
+
+ /*
+ * Once we've actually written the file, it doesn't matter that the
+ * file name was changed -- if it was, we've already whacked it.
+ */
+ F_CLR(frp, FR_NAMECHANGE);
+
+ /*
+ * If wrote the entire file, and it wasn't by appending it to a file,
+ * clear the modified bit. If the file was written to the original
+ * file name and the file is a temporary, set the "no exit" bit. This
+ * permits the user to write the file and use it in the context of the
+ * filesystem, but still keeps them from discarding their changes by
+ * exiting.
+ */
+ if (LF_ISSET(FS_ALL) && !LF_ISSET(FS_APPEND)) {
+ F_CLR(ep, F_MODIFIED);
+ if (F_ISSET(frp, FR_TMPFILE))
+ if (noname)
+ F_SET(frp, FR_TMPEXIT);
+ else
+ F_CLR(frp, FR_TMPEXIT);
+ }
+
+ p = msg_print(sp, name, &nf);
+ switch (mtype) {
+ case NEWFILE:
+ msgstr = msg_cat(sp,
+ "256|%s: new file: %lu lines, %lu characters", NULL);
+ len = snprintf(buf, sizeof(buf), msgstr, p, nlno, nch);
+ break;
+ case OLDFILE:
+ msgstr = msg_cat(sp, LF_ISSET(FS_APPEND) ?
+ "315|%s: appended: %lu lines, %lu characters" :
+ "257|%s: %lu lines, %lu characters", NULL);
+ len = snprintf(buf, sizeof(buf), msgstr, p, nlno, nch);
+ break;
+ default:
+ abort();
+ }
+
+ /*
+ * There's a nasty problem with long path names. Cscope and tags files
+ * can result in long paths and vi will request a continuation key from
+ * the user. Unfortunately, the user has typed ahead, and chaos will
+ * result. If we assume that the characters in the filenames only take
+ * a single screen column each, we can trim the filename.
+ */
+ s = buf;
+ if (len >= sp->cols) {
+ for (s = buf, t = buf + strlen(p); s < t &&
+ (*s != '/' || len >= sp->cols - 3); ++s, --len);
+ if (s == t)
+ s = buf;
+ else {
+ *--s = '.'; /* Leading ellipses. */
+ *--s = '.';
+ *--s = '.';
+ }
+ }
+ msgq(sp, M_INFO, s);
+ if (nf)
+ FREE_SPACE(sp, p, 0);
+ return (0);
+}
+
+/*
+ * file_backup --
+ * Backup the about-to-be-written file.
+ *
+ * XXX
+ * We do the backup by copying the entire file. It would be nice to do
+ * a rename instead, but: (1) both files may not fit and we want to fail
+ * before doing the rename; (2) the backup file may not be on the same
+ * disk partition as the file being written; (3) there may be optional
+ * file information (MACs, DACs, whatever) that we won't get right if we
+ * recreate the file. So, let's not risk it.
+ */
+static int
+file_backup(sp, name, bname)
+ SCR *sp;
+ char *name, *bname;
+{
+ struct dirent *dp;
+ struct stat sb;
+ DIR *dirp;
+ EXCMD cmd;
+ off_t off;
+ size_t blen;
+ int flags, maxnum, nr, num, nw, rfd, wfd, version;
+ char *bp, *estr, *p, *pct, *slash, *t, *wfname, buf[8192];
+
+ rfd = wfd = -1;
+ bp = estr = wfname = NULL;
+
+ /*
+ * Open the current file for reading. Do this first, so that
+ * we don't exec a shell before the most likely failure point.
+ * If it doesn't exist, it's okay, there's just nothing to back
+ * up.
+ */
+ errno = 0;
+ if ((rfd = open(name, O_RDONLY, 0)) < 0) {
+ if (errno == ENOENT)
+ return (0);
+ estr = name;
+ goto err;
+ }
+
+ /*
+ * If the name starts with an 'N' character, add a version number
+ * to the name. Strip the leading N from the string passed to the
+ * expansion routines, for no particular reason. It would be nice
+ * to permit users to put the version number anywhere in the backup
+ * name, but there isn't a special character that we can use in the
+ * name, and giving a new character a special meaning leads to ugly
+ * hacks both here and in the supporting ex routines.
+ *
+ * Shell and file name expand the option's value.
+ */
+ argv_init(sp, &cmd);
+ ex_cinit(&cmd, 0, 0, 0, 0, 0, NULL);
+ if (bname[0] == 'N') {
+ version = 1;
+ ++bname;
+ } else
+ version = 0;
+ if (argv_exp2(sp, &cmd, bname, strlen(bname)))
+ return (1);
+
+ /*
+ * 0 args: impossible.
+ * 1 args: use it.
+ * >1 args: object, too many args.
+ */
+ if (cmd.argc != 1) {
+ msgq_str(sp, M_ERR, bname,
+ "258|%s expanded into too many file names");
+ (void)close(rfd);
+ return (1);
+ }
+
+ /*
+ * If appending a version number, read through the directory, looking
+ * for file names that match the name followed by a number. Make all
+ * of the other % characters in name literal, so the user doesn't get
+ * surprised and sscanf doesn't drop core indirecting through pointers
+ * that don't exist. If any such files are found, increment its number
+ * by one.
+ */
+ if (version) {
+ GET_SPACE_GOTO(sp, bp, blen, cmd.argv[0]->len * 2 + 50);
+ for (t = bp, slash = NULL,
+ p = cmd.argv[0]->bp; p[0] != '\0'; *t++ = *p++)
+ if (p[0] == '%') {
+ if (p[1] != '%')
+ *t++ = '%';
+ } else if (p[0] == '/')
+ slash = t;
+ pct = t;
+ *t++ = '%';
+ *t++ = 'd';
+ *t = '\0';
+
+ if (slash == NULL) {
+ dirp = opendir(".");
+ p = bp;
+ } else {
+ *slash = '\0';
+ dirp = opendir(bp);
+ *slash = '/';
+ p = slash + 1;
+ }
+ if (dirp == NULL) {
+ estr = cmd.argv[0]->bp;
+ goto err;
+ }
+
+ for (maxnum = 0; (dp = readdir(dirp)) != NULL;)
+ if (sscanf(dp->d_name, p, &num) == 1 && num > maxnum)
+ maxnum = num;
+ (void)closedir(dirp);
+
+ /* Format the backup file name. */
+ (void)snprintf(pct, blen - (pct - bp), "%d", maxnum + 1);
+ wfname = bp;
+ } else {
+ bp = NULL;
+ wfname = cmd.argv[0]->bp;
+ }
+
+ /* Open the backup file, avoiding lurkers. */
+ if (stat(wfname, &sb) == 0) {
+ if (!S_ISREG(sb.st_mode)) {
+ msgq_str(sp, M_ERR, bname,
+ "259|%s: not a regular file");
+ goto err;
+ }
+ if (sb.st_uid != getuid()) {
+ msgq_str(sp, M_ERR, bname, "260|%s: not owned by you");
+ goto err;
+ }
+ if (sb.st_mode & (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) {
+ msgq_str(sp, M_ERR, bname,
+ "261|%s: accessible by a user other than the owner");
+ goto err;
+ }
+ flags = O_TRUNC;
+ } else
+ flags = O_CREAT | O_EXCL;
+ if ((wfd = open(wfname, flags | O_WRONLY, S_IRUSR | S_IWUSR)) < 0) {
+ estr = bname;
+ goto err;
+ }
+
+ /* Copy the file's current contents to its backup value. */
+ while ((nr = read(rfd, buf, sizeof(buf))) > 0)
+ for (off = 0; nr != 0; nr -= nw, off += nw)
+ if ((nw = write(wfd, buf + off, nr)) < 0) {
+ estr = wfname;
+ goto err;
+ }
+ if (nr < 0) {
+ estr = name;
+ goto err;
+ }
+
+ if (close(rfd)) {
+ estr = name;
+ goto err;
+ }
+ if (close(wfd)) {
+ estr = wfname;
+ goto err;
+ }
+ if (bp != NULL)
+ FREE_SPACE(sp, bp, blen);
+ return (0);
+
+alloc_err:
+err: if (rfd != -1)
+ (void)close(rfd);
+ if (wfd != -1) {
+ (void)unlink(wfname);
+ (void)close(wfd);
+ }
+ if (estr)
+ msgq_str(sp, M_SYSERR, estr, "%s");
+ if (bp != NULL)
+ FREE_SPACE(sp, bp, blen);
+ return (1);
+}
+
+/*
+ * file_comment --
+ * Skip the first comment.
+ */
+static void
+file_comment(sp)
+ SCR *sp;
+{
+ recno_t lno;
+ size_t len;
+ char *p;
+
+ for (lno = 1; !db_get(sp, lno, 0, &p, &len) && len == 0; ++lno);
+ if (p == NULL)
+ return;
+ if (p[0] == '#') {
+ F_SET(sp, SC_SCR_TOP);
+ while (!db_get(sp, ++lno, 0, &p, &len))
+ if (len < 1 || p[0] != '#') {
+ sp->lno = lno;
+ return;
+ }
+ } else if (len > 1 && p[0] == '/' && p[1] == '*') {
+ F_SET(sp, SC_SCR_TOP);
+ do {
+ for (; len > 1; --len, ++p)
+ if (p[0] == '*' && p[1] == '/') {
+ sp->lno = lno;
+ return;
+ }
+ } while (!db_get(sp, ++lno, 0, &p, &len));
+ } else if (len > 1 && p[0] == '/' && p[1] == '/') {
+ F_SET(sp, SC_SCR_TOP);
+ p += 2;
+ len -= 2;
+ do {
+ for (; len > 1; --len, ++p)
+ if (p[0] == '/' && p[1] == '/') {
+ sp->lno = lno;
+ return;
+ }
+ } while (!db_get(sp, ++lno, 0, &p, &len));
+ }
+}
+
+/*
+ * file_m1 --
+ * First modification check routine. The :next, :prev, :rewind, :tag,
+ * :tagpush, :tagpop, ^^ modifications check.
+ *
+ * PUBLIC: int file_m1 __P((SCR *, int, int));
+ */
+int
+file_m1(sp, force, flags)
+ SCR *sp;
+ int force, flags;
+{
+ EXF *ep;
+
+ ep = sp->ep;
+
+ /* If no file loaded, return no modifications. */
+ if (ep == NULL)
+ return (0);
+
+ /*
+ * If the file has been modified, we'll want to write it back or
+ * fail. If autowrite is set, we'll write it back automatically,
+ * unless force is also set. Otherwise, we fail unless forced or
+ * there's another open screen on this file.
+ */
+ if (F_ISSET(ep, F_MODIFIED))
+ if (O_ISSET(sp, O_AUTOWRITE)) {
+ if (!force && file_aw(sp, flags))
+ return (1);
+ } else if (ep->refcnt <= 1 && !force) {
+ msgq(sp, M_ERR, LF_ISSET(FS_POSSIBLE) ?
+"262|File modified since last complete write; write or use ! to override" :
+"263|File modified since last complete write; write or use :edit! to override");
+ return (1);
+ }
+
+ return (file_m3(sp, force));
+}
+
+/*
+ * file_m2 --
+ * Second modification check routine. The :edit, :quit, :recover
+ * modifications check.
+ *
+ * PUBLIC: int file_m2 __P((SCR *, int));
+ */
+int
+file_m2(sp, force)
+ SCR *sp;
+ int force;
+{
+ EXF *ep;
+
+ ep = sp->ep;
+
+ /* If no file loaded, return no modifications. */
+ if (ep == NULL)
+ return (0);
+
+ /*
+ * If the file has been modified, we'll want to fail, unless forced
+ * or there's another open screen on this file.
+ */
+ if (F_ISSET(ep, F_MODIFIED) && ep->refcnt <= 1 && !force) {
+ msgq(sp, M_ERR,
+"264|File modified since last complete write; write or use ! to override");
+ return (1);
+ }
+
+ return (file_m3(sp, force));
+}
+
+/*
+ * file_m3 --
+ * Third modification check routine.
+ *
+ * PUBLIC: int file_m3 __P((SCR *, int));
+ */
+int
+file_m3(sp, force)
+ SCR *sp;
+ int force;
+{
+ EXF *ep;
+
+ ep = sp->ep;
+
+ /* If no file loaded, return no modifications. */
+ if (ep == NULL)
+ return (0);
+
+ /*
+ * Don't exit while in a temporary files if the file was ever modified.
+ * The problem is that if the user does a ":wq", we write and quit,
+ * unlinking the temporary file. Not what the user had in mind at all.
+ * We permit writing to temporary files, so that user maps using file
+ * system names work with temporary files.
+ */
+ if (F_ISSET(sp->frp, FR_TMPEXIT) && ep->refcnt <= 1 && !force) {
+ msgq(sp, M_ERR,
+ "265|File is a temporary; exit will discard modifications");
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * file_aw --
+ * Autowrite routine. If modified, autowrite is set and the readonly bit
+ * is not set, write the file. A routine so there's a place to put the
+ * comment.
+ *
+ * PUBLIC: int file_aw __P((SCR *, int));
+ */
+int
+file_aw(sp, flags)
+ SCR *sp;
+ int flags;
+{
+ if (!F_ISSET(sp->ep, F_MODIFIED))
+ return (0);
+ if (!O_ISSET(sp, O_AUTOWRITE))
+ return (0);
+
+ /*
+ * !!!
+ * Historic 4BSD vi attempted to write the file if autowrite was set,
+ * regardless of the writeability of the file (as defined by the file
+ * readonly flag). System V changed this as some point, not attempting
+ * autowrite if the file was readonly. This feels like a bug fix to
+ * me (e.g. the principle of least surprise is violated if readonly is
+ * set and vi writes the file), so I'm compatible with System V.
+ */
+ if (O_ISSET(sp, O_READONLY)) {
+ msgq(sp, M_INFO,
+ "266|File readonly, modifications not auto-written");
+ return (1);
+ }
+ return (file_write(sp, NULL, NULL, NULL, flags));
+}
+
+/*
+ * set_alt_name --
+ * Set the alternate pathname.
+ *
+ * Set the alternate pathname. It's a routine because I wanted some place
+ * to hang this comment. The alternate pathname (normally referenced using
+ * the special character '#' during file expansion and in the vi ^^ command)
+ * is set by almost all ex commands that take file names as arguments. The
+ * rules go something like this:
+ *
+ * 1: If any ex command takes a file name as an argument (except for the
+ * :next command), the alternate pathname is set to that file name.
+ * This excludes the command ":e" and ":w !command" as no file name
+ * was specified. Note, historically, the :source command did not set
+ * the alternate pathname. It does in nvi, for consistency.
+ *
+ * 2: However, if any ex command sets the current pathname, e.g. the
+ * ":e file" or ":rew" commands succeed, then the alternate pathname
+ * is set to the previous file's current pathname, if it had one.
+ * This includes the ":file" command and excludes the ":e" command.
+ * So, by rule #1 and rule #2, if ":edit foo" fails, the alternate
+ * pathname will be "foo", if it succeeds, the alternate pathname will
+ * be the previous current pathname. The ":e" command will not set
+ * the alternate or current pathnames regardless.
+ *
+ * 3: However, if it's a read or write command with a file argument and
+ * the current pathname has not yet been set, the file name becomes
+ * the current pathname, and the alternate pathname is unchanged.
+ *
+ * If the user edits a temporary file, there may be times when there is no
+ * alternative file name. A name argument of NULL turns it off.
+ *
+ * PUBLIC: void set_alt_name __P((SCR *, char *));
+ */
+void
+set_alt_name(sp, name)
+ SCR *sp;
+ char *name;
+{
+ if (sp->alt_name != NULL)
+ free(sp->alt_name);
+ if (name == NULL)
+ sp->alt_name = NULL;
+ else if ((sp->alt_name = strdup(name)) == NULL)
+ msgq(sp, M_SYSERR, NULL);
+}
+
+/*
+ * file_lock --
+ * Get an exclusive lock on a file.
+ *
+ * XXX
+ * The default locking is flock(2) style, not fcntl(2). The latter is
+ * known to fail badly on some systems, and its only advantage is that
+ * it occasionally works over NFS.
+ *
+ * Furthermore, the semantics of fcntl(2) are wrong. The problems are
+ * two-fold: you can't close any file descriptor associated with the file
+ * without losing all of the locks, and you can't get an exclusive lock
+ * unless you have the file open for writing. Someone ought to be shot,
+ * but it's probably too late, they may already have reproduced. To get
+ * around these problems, nvi opens the files for writing when it can and
+ * acquires a second file descriptor when it can't. The recovery files
+ * are examples of the former, they're always opened for writing. The DB
+ * files can't be opened for writing because the semantics of DB are that
+ * files opened for writing are flushed back to disk when the DB session
+ * is ended. So, in that case we have to acquire an extra file descriptor.
+ *
+ * PUBLIC: lockr_t file_lock __P((SCR *, char *, int *, int, int));
+ */
+lockr_t
+file_lock(sp, name, fdp, fd, iswrite)
+ SCR *sp;
+ char *name;
+ int *fdp, fd, iswrite;
+{
+ if (!O_ISSET(sp, O_LOCKFILES))
+ return (LOCK_SUCCESS);
+
+#ifdef HAVE_LOCK_FLOCK /* Hurrah! We've got flock(2). */
+ /*
+ * !!!
+ * We need to distinguish a lock not being available for the file
+ * from the file system not supporting locking. Flock is documented
+ * as returning EWOULDBLOCK; add EAGAIN for good measure, and assume
+ * they are the former. There's no portable way to do this.
+ */
+ errno = 0;
+ return (flock(fd, LOCK_EX | LOCK_NB) ? errno == EAGAIN
+#ifdef EWOULDBLOCK
+ || errno == EWOULDBLOCK
+#endif
+ ? LOCK_UNAVAIL : LOCK_FAILED : LOCK_SUCCESS);
+#endif
+#ifdef HAVE_LOCK_FCNTL /* Gag me. We've got fcntl(2). */
+{
+ struct flock arg;
+ int didopen, sverrno;
+
+ arg.l_type = F_WRLCK;
+ arg.l_whence = 0; /* SEEK_SET */
+ arg.l_start = arg.l_len = 0;
+ arg.l_pid = 0;
+
+ /*
+ * If the file descriptor isn't opened for writing, it must fail.
+ * If we fail because we can't get a read/write file descriptor,
+ * we return LOCK_SUCCESS, believing that the file is readonly
+ * and that will be sufficient to warn the user.
+ */
+ if (!iswrite) {
+ if (name == NULL || fdp == NULL)
+ return (LOCK_FAILED);
+ if ((fd = open(name, O_RDWR, 0)) == -1)
+ return (LOCK_SUCCESS);
+ *fdp = fd;
+ didopen = 1;
+ }
+
+ errno = 0;
+ if (!fcntl(fd, F_SETLK, &arg))
+ return (LOCK_SUCCESS);
+ if (didopen) {
+ sverrno = errno;
+ (void)close(fd);
+ errno = sverrno;
+ }
+
+ /*
+ * !!!
+ * We need to distinguish a lock not being available for the file
+ * from the file system not supporting locking. Fcntl is documented
+ * as returning EACCESS and EAGAIN; add EWOULDBLOCK for good measure,
+ * and assume they are the former. There's no portable way to do this.
+ */
+ return (errno == EACCES || errno == EAGAIN
+#ifdef EWOULDBLOCK
+ || errno == EWOULDBLOCK
+#endif
+ ? LOCK_UNAVAIL : LOCK_FAILED);
+}
+#endif
+#if !defined(HAVE_LOCK_FLOCK) && !defined(HAVE_LOCK_FCNTL)
+ return (LOCK_SUCCESS);
+#endif
+}
diff --git a/contrib/nvi/common/exf.h b/contrib/nvi/common/exf.h
new file mode 100644
index 000000000000..cdfaa8294485
--- /dev/null
+++ b/contrib/nvi/common/exf.h
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)exf.h 10.7 (Berkeley) 7/9/96
+ */
+ /* Undo direction. */
+/*
+ * exf --
+ * The file structure.
+ */
+struct _exf {
+ int refcnt; /* Reference count. */
+
+ /* Underlying database state. */
+ DB *db; /* File db structure. */
+ char *c_lp; /* Cached line. */
+ size_t c_len; /* Cached line length. */
+ recno_t c_lno; /* Cached line number. */
+ recno_t c_nlines; /* Cached lines in the file. */
+
+ DB *log; /* Log db structure. */
+ char *l_lp; /* Log buffer. */
+ size_t l_len; /* Log buffer length. */
+ recno_t l_high; /* Log last + 1 record number. */
+ recno_t l_cur; /* Log current record number. */
+ MARK l_cursor; /* Log cursor position. */
+ dir_t lundo; /* Last undo direction. */
+
+ LIST_HEAD(_markh, _lmark) marks;/* Linked list of file MARK's. */
+
+ /*
+ * XXX
+ * Mtime should be a struct timespec, but time_t is more portable.
+ */
+ dev_t mdev; /* Device. */
+ ino_t minode; /* Inode. */
+ time_t mtime; /* Last modification time. */
+
+ int fcntl_fd; /* Fcntl locking fd; see exf.c. */
+
+ /*
+ * Recovery in general, and these fields specifically, are described
+ * in recover.c.
+ */
+#define RCV_PERIOD 120 /* Sync every two minutes. */
+ char *rcv_path; /* Recover file name. */
+ char *rcv_mpath; /* Recover mail file name. */
+ int rcv_fd; /* Locked mail file descriptor. */
+
+#define F_DEVSET 0x001 /* mdev/minode fields initialized. */
+#define F_FIRSTMODIFY 0x002 /* File not yet modified. */
+#define F_MODIFIED 0x004 /* File is currently dirty. */
+#define F_MULTILOCK 0x008 /* Multiple processes running, lock. */
+#define F_NOLOG 0x010 /* Logging turned off. */
+#define F_RCV_NORM 0x020 /* Don't delete recovery files. */
+#define F_RCV_ON 0x040 /* Recovery is possible. */
+#define F_UNDO 0x080 /* No change since last undo. */
+ u_int8_t flags;
+};
+
+/* Flags to db_get(). */
+#define DBG_FATAL 0x001 /* If DNE, error message. */
+#define DBG_NOCACHE 0x002 /* Ignore the front-end cache. */
+
+/* Flags to file_init() and file_write(). */
+#define FS_ALL 0x001 /* Write the entire file. */
+#define FS_APPEND 0x002 /* Append to the file. */
+#define FS_FORCE 0x004 /* Force is set. */
+#define FS_OPENERR 0x008 /* Open failed, try it again. */
+#define FS_POSSIBLE 0x010 /* Force could have been set. */
+#define FS_SETALT 0x020 /* Set alternate file name. */
+
+/* Flags to rcv_sync(). */
+#define RCV_EMAIL 0x01 /* Send the user email, IFF file modified. */
+#define RCV_ENDSESSION 0x02 /* End the file session. */
+#define RCV_PRESERVE 0x04 /* Preserve backup file, IFF file modified. */
+#define RCV_SNAPSHOT 0x08 /* Snapshot the recovery, and send email. */
diff --git a/contrib/nvi/common/gs.h b/contrib/nvi/common/gs.h
new file mode 100644
index 000000000000..e5a43a656ac2
--- /dev/null
+++ b/contrib/nvi/common/gs.h
@@ -0,0 +1,210 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)gs.h 10.34 (Berkeley) 9/24/96
+ */
+
+#define TEMPORARY_FILE_STRING "/tmp" /* Default temporary file name. */
+
+/*
+ * File reference structure (FREF). The structure contains the name of the
+ * file, along with the information that follows the name.
+ *
+ * !!!
+ * The read-only bit follows the file name, not the file itself.
+ */
+struct _fref {
+ CIRCLEQ_ENTRY(_fref) q; /* Linked list of file references. */
+ char *name; /* File name. */
+ char *tname; /* Backing temporary file name. */
+
+ recno_t lno; /* 1-N: file cursor line. */
+ size_t cno; /* 0-N: file cursor column. */
+
+#define FR_CURSORSET 0x0001 /* If lno/cno values valid. */
+#define FR_DONTDELETE 0x0002 /* Don't delete the temporary file. */
+#define FR_EXNAMED 0x0004 /* Read/write renamed the file. */
+#define FR_NAMECHANGE 0x0008 /* If the name changed. */
+#define FR_NEWFILE 0x0010 /* File doesn't really exist yet. */
+#define FR_RECOVER 0x0020 /* File is being recovered. */
+#define FR_TMPEXIT 0x0040 /* Modified temporary file, no exit. */
+#define FR_TMPFILE 0x0080 /* If file has no name. */
+#define FR_UNLOCKED 0x0100 /* File couldn't be locked. */
+ u_int16_t flags;
+};
+
+/* Action arguments to scr_exadjust(). */
+typedef enum { EX_TERM_CE, EX_TERM_SCROLL } exadj_t;
+
+/* Screen attribute arguments to scr_attr(). */
+typedef enum { SA_ALTERNATE, SA_INVERSE } scr_attr_t;
+
+/* Key type arguments to scr_keyval(). */
+typedef enum { KEY_VEOF, KEY_VERASE, KEY_VKILL, KEY_VWERASE } scr_keyval_t;
+
+/*
+ * GS:
+ *
+ * Structure that describes global state of the running program.
+ */
+struct _gs {
+ char *progname; /* Programe name. */
+
+ int id; /* Last allocated screen id. */
+ CIRCLEQ_HEAD(_dqh, _scr) dq; /* Displayed screens. */
+ CIRCLEQ_HEAD(_hqh, _scr) hq; /* Hidden screens. */
+
+ SCR *ccl_sp; /* Colon command-line screen. */
+
+ void *perl_interp; /* Perl interpreter. */
+ void *tcl_interp; /* Tcl_Interp *: Tcl interpreter. */
+
+ void *cl_private; /* Curses support private area. */
+ void *ip_private; /* IP support private area. */
+ void *tk_private; /* Tk/Tcl support private area. */
+
+ /* File references. */
+ CIRCLEQ_HEAD(_frefh, _fref) frefq;
+
+#define GO_COLUMNS 0 /* Global options: columns. */
+#define GO_LINES 1 /* Global options: lines. */
+#define GO_SECURE 2 /* Global options: secure. */
+#define GO_TERM 3 /* Global options: terminal type. */
+ OPTION opts[GO_TERM + 1];
+
+ DB *msg; /* Message catalog DB. */
+ MSGH msgq; /* User message list. */
+#define DEFAULT_NOPRINT '\1' /* Emergency non-printable character. */
+ CHAR_T noprint; /* Cached, unprintable character. */
+
+ char *tmp_bp; /* Temporary buffer. */
+ size_t tmp_blen; /* Temporary buffer size. */
+
+ /*
+ * Ex command structures (EXCMD). Defined here because ex commands
+ * exist outside of any particular screen or file.
+ */
+#define EXCMD_RUNNING(gp) ((gp)->ecq.lh_first->clen != 0)
+ LIST_HEAD(_excmdh, _excmd) ecq; /* Ex command linked list. */
+ EXCMD excmd; /* Default ex command structure. */
+ char *if_name; /* Current associated file. */
+ recno_t if_lno; /* Current associated line number. */
+
+ char *c_option; /* Ex initial, command-line command. */
+
+#ifdef DEBUG
+ FILE *tracefp; /* Trace file pointer. */
+#endif
+
+ EVENT *i_event; /* Array of input events. */
+ size_t i_nelem; /* Number of array elements. */
+ size_t i_cnt; /* Count of events. */
+ size_t i_next; /* Offset of next event. */
+
+ CB *dcbp; /* Default cut buffer pointer. */
+ CB dcb_store; /* Default cut buffer storage. */
+ LIST_HEAD(_cuth, _cb) cutq; /* Linked list of cut buffers. */
+
+#define MAX_BIT_SEQ 128 /* Max + 1 fast check character. */
+ LIST_HEAD(_seqh, _seq) seqq; /* Linked list of maps, abbrevs. */
+ bitstr_t bit_decl(seqb, MAX_BIT_SEQ);
+
+#define MAX_FAST_KEY 254 /* Max fast check character.*/
+#define KEY_LEN(sp, ch) \
+ ((unsigned char)(ch) <= MAX_FAST_KEY ? \
+ sp->gp->cname[(unsigned char)ch].len : v_key_len(sp, ch))
+#define KEY_NAME(sp, ch) \
+ ((unsigned char)(ch) <= MAX_FAST_KEY ? \
+ sp->gp->cname[(unsigned char)ch].name : v_key_name(sp, ch))
+ struct {
+ CHAR_T name[MAX_CHARACTER_COLUMNS + 1];
+ u_int8_t len;
+ } cname[MAX_FAST_KEY + 1]; /* Fast lookup table. */
+
+#define KEY_VAL(sp, ch) \
+ ((unsigned char)(ch) <= MAX_FAST_KEY ? \
+ sp->gp->special_key[(unsigned char)ch] : \
+ (unsigned char)(ch) > sp->gp->max_special ? 0 : v_key_val(sp,ch))
+ CHAR_T max_special; /* Max special character. */
+ u_char /* Fast lookup table. */
+ special_key[MAX_FAST_KEY + 1];
+
+/* Flags. */
+#define G_ABBREV 0x0001 /* If have abbreviations. */
+#define G_BELLSCHED 0x0002 /* Bell scheduled. */
+#define G_INTERRUPTED 0x0004 /* Interrupted. */
+#define G_RECOVER_SET 0x0008 /* Recover system initialized. */
+#define G_SCRIPTED 0x0010 /* Ex script session. */
+#define G_SCRWIN 0x0020 /* Scripting windows running. */
+#define G_SNAPSHOT 0x0040 /* Always snapshot files. */
+#define G_SRESTART 0x0080 /* Screen restarted. */
+#define G_TMP_INUSE 0x0100 /* Temporary buffer in use. */
+ u_int32_t flags;
+
+ /* Screen interface functions. */
+ /* Add a string to the screen. */
+ int (*scr_addstr) __P((SCR *, const char *, size_t));
+ /* Toggle a screen attribute. */
+ int (*scr_attr) __P((SCR *, scr_attr_t, int));
+ /* Terminal baud rate. */
+ int (*scr_baud) __P((SCR *, u_long *));
+ /* Beep/bell/flash the terminal. */
+ int (*scr_bell) __P((SCR *));
+ /* Display a busy message. */
+ void (*scr_busy) __P((SCR *, const char *, busy_t));
+ /* Clear to the end of the line. */
+ int (*scr_clrtoeol) __P((SCR *));
+ /* Return the cursor location. */
+ int (*scr_cursor) __P((SCR *, size_t *, size_t *));
+ /* Delete a line. */
+ int (*scr_deleteln) __P((SCR *));
+ /* Get a keyboard event. */
+ int (*scr_event) __P((SCR *, EVENT *, u_int32_t, int));
+ /* Ex: screen adjustment routine. */
+ int (*scr_ex_adjust) __P((SCR *, exadj_t));
+ int (*scr_fmap) /* Set a function key. */
+ __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
+ /* Get terminal key value. */
+ int (*scr_keyval) __P((SCR *, scr_keyval_t, CHAR_T *, int *));
+ /* Insert a line. */
+ int (*scr_insertln) __P((SCR *));
+ /* Handle an option change. */
+ int (*scr_optchange) __P((SCR *, int, char *, u_long *));
+ /* Move the cursor. */
+ int (*scr_move) __P((SCR *, size_t, size_t));
+ /* Message or ex output. */
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ /* Refresh the screen. */
+ int (*scr_refresh) __P((SCR *, int));
+ /* Rename the file. */
+ int (*scr_rename) __P((SCR *, char *, int));
+ /* Set the screen type. */
+ int (*scr_screen) __P((SCR *, u_int32_t));
+ /* Suspend the editor. */
+ int (*scr_suspend) __P((SCR *, int *));
+ /* Print usage message. */
+ void (*scr_usage) __P((void));
+};
+
+/*
+ * XXX
+ * Block signals if there are asynchronous events. Used to keep DB system calls
+ * from being interrupted and not restarted, as that will result in consistency
+ * problems. This should be handled by DB.
+ */
+#ifdef BLOCK_SIGNALS
+#include <signal.h>
+extern sigset_t __sigblockset;
+#define SIGBLOCK \
+ (void)sigprocmask(SIG_BLOCK, &__sigblockset, NULL)
+#define SIGUNBLOCK \
+ (void)sigprocmask(SIG_UNBLOCK, &__sigblockset, NULL);
+#else
+#define SIGBLOCK
+#define SIGUNBLOCK
+#endif
diff --git a/contrib/nvi/common/key.c b/contrib/nvi/common/key.c
new file mode 100644
index 000000000000..e1311ab571b0
--- /dev/null
+++ b/contrib/nvi/common/key.c
@@ -0,0 +1,865 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)key.c 10.33 (Berkeley) 9/24/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "../vi/vi.h"
+
+static int v_event_append __P((SCR *, EVENT *));
+static int v_event_grow __P((SCR *, int));
+static int v_key_cmp __P((const void *, const void *));
+static void v_keyval __P((SCR *, int, scr_keyval_t));
+static void v_sync __P((SCR *, int));
+
+/*
+ * !!!
+ * Historic vi always used:
+ *
+ * ^D: autoindent deletion
+ * ^H: last character deletion
+ * ^W: last word deletion
+ * ^Q: quote the next character (if not used in flow control).
+ * ^V: quote the next character
+ *
+ * regardless of the user's choices for these characters. The user's erase
+ * and kill characters worked in addition to these characters. Nvi wires
+ * down the above characters, but in addition permits the VEOF, VERASE, VKILL
+ * and VWERASE characters described by the user's termios structure.
+ *
+ * Ex was not consistent with this scheme, as it historically ran in tty
+ * cooked mode. This meant that the scroll command and autoindent erase
+ * characters were mapped to the user's EOF character, and the character
+ * and word deletion characters were the user's tty character and word
+ * deletion characters. This implementation makes it all consistent, as
+ * described above for vi.
+ *
+ * !!!
+ * This means that all screens share a special key set.
+ */
+KEYLIST keylist[] = {
+ {K_BACKSLASH, '\\'}, /* \ */
+ {K_CARAT, '^'}, /* ^ */
+ {K_CNTRLD, '\004'}, /* ^D */
+ {K_CNTRLR, '\022'}, /* ^R */
+ {K_CNTRLT, '\024'}, /* ^T */
+ {K_CNTRLZ, '\032'}, /* ^Z */
+ {K_COLON, ':'}, /* : */
+ {K_CR, '\r'}, /* \r */
+ {K_ESCAPE, '\033'}, /* ^[ */
+ {K_FORMFEED, '\f'}, /* \f */
+ {K_HEXCHAR, '\030'}, /* ^X */
+ {K_NL, '\n'}, /* \n */
+ {K_RIGHTBRACE, '}'}, /* } */
+ {K_RIGHTPAREN, ')'}, /* ) */
+ {K_TAB, '\t'}, /* \t */
+ {K_VERASE, '\b'}, /* \b */
+ {K_VKILL, '\025'}, /* ^U */
+ {K_VLNEXT, '\021'}, /* ^Q */
+ {K_VLNEXT, '\026'}, /* ^V */
+ {K_VWERASE, '\027'}, /* ^W */
+ {K_ZERO, '0'}, /* 0 */
+
+#define ADDITIONAL_CHARACTERS 4
+ {K_NOTUSED, 0}, /* VEOF, VERASE, VKILL, VWERASE */
+ {K_NOTUSED, 0},
+ {K_NOTUSED, 0},
+ {K_NOTUSED, 0},
+};
+static int nkeylist =
+ (sizeof(keylist) / sizeof(keylist[0])) - ADDITIONAL_CHARACTERS;
+
+/*
+ * v_key_init --
+ * Initialize the special key lookup table.
+ *
+ * PUBLIC: int v_key_init __P((SCR *));
+ */
+int
+v_key_init(sp)
+ SCR *sp;
+{
+ CHAR_T ch;
+ GS *gp;
+ KEYLIST *kp;
+ int cnt;
+
+ gp = sp->gp;
+
+ /*
+ * XXX
+ * 8-bit only, for now. Recompilation should get you any 8-bit
+ * character set, as long as nul isn't a character.
+ */
+ (void)setlocale(LC_ALL, "");
+#if __linux__
+ /*
+ * In libc 4.5.26, setlocale(LC_ALL, ""), doesn't setup the table
+ * for ctype(3c) correctly. This bug is fixed in libc 4.6.x.
+ *
+ * This code works around this problem for libc 4.5.x users.
+ * Note that this code is harmless if you're using libc 4.6.x.
+ */
+ (void)setlocale(LC_CTYPE, "");
+#endif
+ v_key_ilookup(sp);
+
+ v_keyval(sp, K_CNTRLD, KEY_VEOF);
+ v_keyval(sp, K_VERASE, KEY_VERASE);
+ v_keyval(sp, K_VKILL, KEY_VKILL);
+ v_keyval(sp, K_VWERASE, KEY_VWERASE);
+
+ /* Sort the special key list. */
+ qsort(keylist, nkeylist, sizeof(keylist[0]), v_key_cmp);
+
+ /* Initialize the fast lookup table. */
+ for (gp->max_special = 0, kp = keylist, cnt = nkeylist; cnt--; ++kp) {
+ if (gp->max_special < kp->value)
+ gp->max_special = kp->value;
+ if (kp->ch <= MAX_FAST_KEY)
+ gp->special_key[kp->ch] = kp->value;
+ }
+
+ /* Find a non-printable character to use as a message separator. */
+ for (ch = 1; ch <= MAX_CHAR_T; ++ch)
+ if (!isprint(ch)) {
+ gp->noprint = ch;
+ break;
+ }
+ if (ch != gp->noprint) {
+ msgq(sp, M_ERR, "079|No non-printable character found");
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * v_keyval --
+ * Set key values.
+ *
+ * We've left some open slots in the keylist table, and if these values exist,
+ * we put them into place. Note, they may reset (or duplicate) values already
+ * in the table, so we check for that first.
+ */
+static void
+v_keyval(sp, val, name)
+ SCR *sp;
+ int val;
+ scr_keyval_t name;
+{
+ KEYLIST *kp;
+ CHAR_T ch;
+ int dne;
+
+ /* Get the key's value from the screen. */
+ if (sp->gp->scr_keyval(sp, name, &ch, &dne))
+ return;
+ if (dne)
+ return;
+
+ /* Check for duplication. */
+ for (kp = keylist; kp->value != K_NOTUSED; ++kp)
+ if (kp->ch == ch) {
+ kp->value = val;
+ return;
+ }
+
+ /* Add a new entry. */
+ if (kp->value == K_NOTUSED) {
+ keylist[nkeylist].ch = ch;
+ keylist[nkeylist].value = val;
+ ++nkeylist;
+ }
+}
+
+/*
+ * v_key_ilookup --
+ * Build the fast-lookup key display array.
+ *
+ * PUBLIC: void v_key_ilookup __P((SCR *));
+ */
+void
+v_key_ilookup(sp)
+ SCR *sp;
+{
+ CHAR_T ch, *p, *t;
+ GS *gp;
+ size_t len;
+
+ for (gp = sp->gp, ch = 0; ch <= MAX_FAST_KEY; ++ch)
+ for (p = gp->cname[ch].name, t = v_key_name(sp, ch),
+ len = gp->cname[ch].len = sp->clen; len--;)
+ *p++ = *t++;
+}
+
+/*
+ * v_key_len --
+ * Return the length of the string that will display the key.
+ * This routine is the backup for the KEY_LEN() macro.
+ *
+ * PUBLIC: size_t v_key_len __P((SCR *, ARG_CHAR_T));
+ */
+size_t
+v_key_len(sp, ch)
+ SCR *sp;
+ ARG_CHAR_T ch;
+{
+ (void)v_key_name(sp, ch);
+ return (sp->clen);
+}
+
+/*
+ * v_key_name --
+ * Return the string that will display the key. This routine
+ * is the backup for the KEY_NAME() macro.
+ *
+ * PUBLIC: CHAR_T *v_key_name __P((SCR *, ARG_CHAR_T));
+ */
+CHAR_T *
+v_key_name(sp, ach)
+ SCR *sp;
+ ARG_CHAR_T ach;
+{
+ static const CHAR_T hexdigit[] = "0123456789abcdef";
+ static const CHAR_T octdigit[] = "01234567";
+ CHAR_T ch, *chp, mask;
+ size_t len;
+ int cnt, shift;
+
+ ch = ach;
+
+ /* See if the character was explicitly declared printable or not. */
+ if ((chp = O_STR(sp, O_PRINT)) != NULL)
+ for (; *chp != '\0'; ++chp)
+ if (*chp == ch)
+ goto pr;
+ if ((chp = O_STR(sp, O_NOPRINT)) != NULL)
+ for (; *chp != '\0'; ++chp)
+ if (*chp == ch)
+ goto nopr;
+
+ /*
+ * Historical (ARPA standard) mappings. Printable characters are left
+ * alone. Control characters less than 0x20 are represented as '^'
+ * followed by the character offset from the '@' character in the ASCII
+ * character set. Del (0x7f) is represented as '^' followed by '?'.
+ *
+ * XXX
+ * The following code depends on the current locale being identical to
+ * the ASCII map from 0x40 to 0x5f (since 0x1f + 0x40 == 0x5f). I'm
+ * told that this is a reasonable assumption...
+ *
+ * XXX
+ * This code will only work with CHAR_T's that are multiples of 8-bit
+ * bytes.
+ *
+ * XXX
+ * NB: There's an assumption here that all printable characters take
+ * up a single column on the screen. This is not always correct.
+ */
+ if (isprint(ch)) {
+pr: sp->cname[0] = ch;
+ len = 1;
+ goto done;
+ }
+nopr: if (iscntrl(ch) && (ch < 0x20 || ch == 0x7f)) {
+ sp->cname[0] = '^';
+ sp->cname[1] = ch == 0x7f ? '?' : '@' + ch;
+ len = 2;
+ } else if (O_ISSET(sp, O_OCTAL)) {
+#define BITS (sizeof(CHAR_T) * 8)
+#define SHIFT (BITS - BITS % 3)
+#define TOPMASK (BITS % 3 == 2 ? 3 : 1) << (BITS - BITS % 3)
+ sp->cname[0] = '\\';
+ sp->cname[1] = octdigit[(ch & TOPMASK) >> SHIFT];
+ shift = SHIFT - 3;
+ for (len = 2, mask = 7 << (SHIFT - 3),
+ cnt = BITS / 3; cnt-- > 0; mask >>= 3, shift -= 3)
+ sp->cname[len++] = octdigit[(ch & mask) >> shift];
+ } else {
+ sp->cname[0] = '\\';
+ sp->cname[1] = 'x';
+ for (len = 2, chp = (u_int8_t *)&ch,
+ cnt = sizeof(CHAR_T); cnt-- > 0; ++chp) {
+ sp->cname[len++] = hexdigit[(*chp & 0xf0) >> 4];
+ sp->cname[len++] = hexdigit[*chp & 0x0f];
+ }
+ }
+done: sp->cname[sp->clen = len] = '\0';
+ return (sp->cname);
+}
+
+/*
+ * v_key_val --
+ * Fill in the value for a key. This routine is the backup
+ * for the KEY_VAL() macro.
+ *
+ * PUBLIC: int v_key_val __P((SCR *, ARG_CHAR_T));
+ */
+int
+v_key_val(sp, ch)
+ SCR *sp;
+ ARG_CHAR_T ch;
+{
+ KEYLIST k, *kp;
+
+ k.ch = ch;
+ kp = bsearch(&k, keylist, nkeylist, sizeof(keylist[0]), v_key_cmp);
+ return (kp == NULL ? K_NOTUSED : kp->value);
+}
+
+/*
+ * v_event_push --
+ * Push events/keys onto the front of the buffer.
+ *
+ * There is a single input buffer in ex/vi. Characters are put onto the
+ * end of the buffer by the terminal input routines, and pushed onto the
+ * front of the buffer by various other functions in ex/vi. Each key has
+ * an associated flag value, which indicates if it has already been quoted,
+ * and if it is the result of a mapping or an abbreviation.
+ *
+ * PUBLIC: int v_event_push __P((SCR *, EVENT *, CHAR_T *, size_t, u_int));
+ */
+int
+v_event_push(sp, p_evp, p_s, nitems, flags)
+ SCR *sp;
+ EVENT *p_evp; /* Push event. */
+ CHAR_T *p_s; /* Push characters. */
+ size_t nitems; /* Number of items to push. */
+ u_int flags; /* CH_* flags. */
+{
+ EVENT *evp;
+ GS *gp;
+ size_t total;
+
+ /* If we have room, stuff the items into the buffer. */
+ gp = sp->gp;
+ if (nitems <= gp->i_next ||
+ (gp->i_event != NULL && gp->i_cnt == 0 && nitems <= gp->i_nelem)) {
+ if (gp->i_cnt != 0)
+ gp->i_next -= nitems;
+ goto copy;
+ }
+
+ /*
+ * If there are currently items in the queue, shift them up,
+ * leaving some extra room. Get enough space plus a little
+ * extra.
+ */
+#define TERM_PUSH_SHIFT 30
+ total = gp->i_cnt + gp->i_next + nitems + TERM_PUSH_SHIFT;
+ if (total >= gp->i_nelem && v_event_grow(sp, MAX(total, 64)))
+ return (1);
+ if (gp->i_cnt)
+ MEMMOVE(gp->i_event + TERM_PUSH_SHIFT + nitems,
+ gp->i_event + gp->i_next, gp->i_cnt);
+ gp->i_next = TERM_PUSH_SHIFT;
+
+ /* Put the new items into the queue. */
+copy: gp->i_cnt += nitems;
+ for (evp = gp->i_event + gp->i_next; nitems--; ++evp) {
+ if (p_evp != NULL)
+ *evp = *p_evp++;
+ else {
+ evp->e_event = E_CHARACTER;
+ evp->e_c = *p_s++;
+ evp->e_value = KEY_VAL(sp, evp->e_c);
+ F_INIT(&evp->e_ch, flags);
+ }
+ }
+ return (0);
+}
+
+/*
+ * v_event_append --
+ * Append events onto the tail of the buffer.
+ */
+static int
+v_event_append(sp, argp)
+ SCR *sp;
+ EVENT *argp;
+{
+ CHAR_T *s; /* Characters. */
+ EVENT *evp;
+ GS *gp;
+ size_t nevents; /* Number of events. */
+
+ /* Grow the buffer as necessary. */
+ nevents = argp->e_event == E_STRING ? argp->e_len : 1;
+ gp = sp->gp;
+ if (gp->i_event == NULL ||
+ nevents > gp->i_nelem - (gp->i_next + gp->i_cnt))
+ v_event_grow(sp, MAX(nevents, 64));
+ evp = gp->i_event + gp->i_next + gp->i_cnt;
+ gp->i_cnt += nevents;
+
+ /* Transform strings of characters into single events. */
+ if (argp->e_event == E_STRING)
+ for (s = argp->e_csp; nevents--; ++evp) {
+ evp->e_event = E_CHARACTER;
+ evp->e_c = *s++;
+ evp->e_value = KEY_VAL(sp, evp->e_c);
+ evp->e_flags = 0;
+ }
+ else
+ *evp = *argp;
+ return (0);
+}
+
+/* Remove events from the queue. */
+#define QREM(len) { \
+ if ((gp->i_cnt -= len) == 0) \
+ gp->i_next = 0; \
+ else \
+ gp->i_next += len; \
+}
+
+/*
+ * v_event_get --
+ * Return the next event.
+ *
+ * !!!
+ * The flag EC_NODIGIT probably needs some explanation. First, the idea of
+ * mapping keys is that one or more keystrokes act like a function key.
+ * What's going on is that vi is reading a number, and the character following
+ * the number may or may not be mapped (EC_MAPCOMMAND). For example, if the
+ * user is entering the z command, a valid command is "z40+", and we don't want
+ * to map the '+', i.e. if '+' is mapped to "xxx", we don't want to change it
+ * into "z40xxx". However, if the user enters "35x", we want to put all of the
+ * characters through the mapping code.
+ *
+ * Historical practice is a bit muddled here. (Surprise!) It always permitted
+ * mapping digits as long as they weren't the first character of the map, e.g.
+ * ":map ^A1 xxx" was okay. It also permitted the mapping of the digits 1-9
+ * (the digit 0 was a special case as it doesn't indicate the start of a count)
+ * as the first character of the map, but then ignored those mappings. While
+ * it's probably stupid to map digits, vi isn't your mother.
+ *
+ * The way this works is that the EC_MAPNODIGIT causes term_key to return the
+ * end-of-digit without "looking" at the next character, i.e. leaving it as the
+ * user entered it. Presumably, the next term_key call will tell us how the
+ * user wants it handled.
+ *
+ * There is one more complication. Users might map keys to digits, and, as
+ * it's described above, the commands:
+ *
+ * :map g 1G
+ * d2g
+ *
+ * would return the keys "d2<end-of-digits>1G", when the user probably wanted
+ * "d21<end-of-digits>G". So, if a map starts off with a digit we continue as
+ * before, otherwise, we pretend we haven't mapped the character, and return
+ * <end-of-digits>.
+ *
+ * Now that that's out of the way, let's talk about Energizer Bunny macros.
+ * It's easy to create macros that expand to a loop, e.g. map x 3x. It's
+ * fairly easy to detect this example, because it's all internal to term_key.
+ * If we're expanding a macro and it gets big enough, at some point we can
+ * assume it's looping and kill it. The examples that are tough are the ones
+ * where the parser is involved, e.g. map x "ayyx"byy. We do an expansion
+ * on 'x', and get "ayyx"byy. We then return the first 4 characters, and then
+ * find the looping macro again. There is no way that we can detect this
+ * without doing a full parse of the command, because the character that might
+ * cause the loop (in this case 'x') may be a literal character, e.g. the map
+ * map x "ayy"xyy"byy is perfectly legal and won't cause a loop.
+ *
+ * Historic vi tried to detect looping macros by disallowing obvious cases in
+ * the map command, maps that that ended with the same letter as they started
+ * (which wrongly disallowed "map x 'x"), and detecting macros that expanded
+ * too many times before keys were returned to the command parser. It didn't
+ * get many (most?) of the tricky cases right, however, and it was certainly
+ * possible to create macros that ran forever. And, even if it did figure out
+ * what was going on, the user was usually tossed into ex mode. Finally, any
+ * changes made before vi realized that the macro was recursing were left in
+ * place. We recover gracefully, but the only recourse the user has in an
+ * infinite macro loop is to interrupt.
+ *
+ * !!!
+ * It is historic practice that mapping characters to themselves as the first
+ * part of the mapped string was legal, and did not cause infinite loops, i.e.
+ * ":map! { {^M^T" and ":map n nz." were known to work. The initial, matching
+ * characters were returned instead of being remapped.
+ *
+ * !!!
+ * It is also historic practice that the macro "map ] ]]^" caused a single ]
+ * keypress to behave as the command ]] (the ^ got the map past the vi check
+ * for "tail recursion"). Conversely, the mapping "map n nn^" went recursive.
+ * What happened was that, in the historic vi, maps were expanded as the keys
+ * were retrieved, but not all at once and not centrally. So, the keypress ]
+ * pushed ]]^ on the stack, and then the first ] from the stack was passed to
+ * the ]] command code. The ]] command then retrieved a key without entering
+ * the mapping code. This could bite us anytime a user has a map that depends
+ * on secondary keys NOT being mapped. I can't see any possible way to make
+ * this work in here without the complete abandonment of Rationality Itself.
+ *
+ * XXX
+ * The final issue is recovery. It would be possible to undo all of the work
+ * that was done by the macro if we entered a record into the log so that we
+ * knew when the macro started, and, in fact, this might be worth doing at some
+ * point. Given that this might make the log grow unacceptably (consider that
+ * cursor keys are done with maps), for now we leave any changes made in place.
+ *
+ * PUBLIC: int v_event_get __P((SCR *, EVENT *, int, u_int32_t));
+ */
+int
+v_event_get(sp, argp, timeout, flags)
+ SCR *sp;
+ EVENT *argp;
+ int timeout;
+ u_int32_t flags;
+{
+ EVENT *evp, ev;
+ GS *gp;
+ SEQ *qp;
+ int init_nomap, ispartial, istimeout, remap_cnt;
+
+ gp = sp->gp;
+
+ /* If simply checking for interrupts, argp may be NULL. */
+ if (argp == NULL)
+ argp = &ev;
+
+retry: istimeout = remap_cnt = 0;
+
+ /*
+ * If the queue isn't empty and we're timing out for characters,
+ * return immediately.
+ */
+ if (gp->i_cnt != 0 && LF_ISSET(EC_TIMEOUT))
+ return (0);
+
+ /*
+ * If the queue is empty, we're checking for interrupts, or we're
+ * timing out for characters, get more events.
+ */
+ if (gp->i_cnt == 0 || LF_ISSET(EC_INTERRUPT | EC_TIMEOUT)) {
+ /*
+ * If we're reading new characters, check any scripting
+ * windows for input.
+ */
+ if (F_ISSET(gp, G_SCRWIN) && sscr_input(sp))
+ return (1);
+loop: if (gp->scr_event(sp, argp,
+ LF_ISSET(EC_INTERRUPT | EC_QUOTED | EC_RAW), timeout))
+ return (1);
+ switch (argp->e_event) {
+ case E_ERR:
+ case E_SIGHUP:
+ case E_SIGTERM:
+ /*
+ * Fatal conditions cause the file to be synced to
+ * disk immediately.
+ */
+ v_sync(sp, RCV_ENDSESSION | RCV_PRESERVE |
+ (argp->e_event == E_SIGTERM ? 0: RCV_EMAIL));
+ return (1);
+ case E_TIMEOUT:
+ istimeout = 1;
+ break;
+ case E_INTERRUPT:
+ /* Set the global interrupt flag. */
+ F_SET(sp->gp, G_INTERRUPTED);
+
+ /*
+ * If the caller was interested in interrupts, return
+ * immediately.
+ */
+ if (LF_ISSET(EC_INTERRUPT))
+ return (0);
+ goto append;
+ default:
+append: if (v_event_append(sp, argp))
+ return (1);
+ break;
+ }
+ }
+
+ /*
+ * If the caller was only interested in interrupts or timeouts, return
+ * immediately. (We may have gotten characters, and that's okay, they
+ * were queued up for later use.)
+ */
+ if (LF_ISSET(EC_INTERRUPT | EC_TIMEOUT))
+ return (0);
+
+newmap: evp = &gp->i_event[gp->i_next];
+
+ /*
+ * If the next event in the queue isn't a character event, return
+ * it, we're done.
+ */
+ if (evp->e_event != E_CHARACTER) {
+ *argp = *evp;
+ QREM(1);
+ return (0);
+ }
+
+ /*
+ * If the key isn't mappable because:
+ *
+ * + ... the timeout has expired
+ * + ... it's not a mappable key
+ * + ... neither the command or input map flags are set
+ * + ... there are no maps that can apply to it
+ *
+ * return it forthwith.
+ */
+ if (istimeout || F_ISSET(&evp->e_ch, CH_NOMAP) ||
+ !LF_ISSET(EC_MAPCOMMAND | EC_MAPINPUT) ||
+ evp->e_c < MAX_BIT_SEQ && !bit_test(gp->seqb, evp->e_c))
+ goto nomap;
+
+ /* Search the map. */
+ qp = seq_find(sp, NULL, evp, NULL, gp->i_cnt,
+ LF_ISSET(EC_MAPCOMMAND) ? SEQ_COMMAND : SEQ_INPUT, &ispartial);
+
+ /*
+ * If get a partial match, get more characters and retry the map.
+ * If time out without further characters, return the characters
+ * unmapped.
+ *
+ * !!!
+ * <escape> characters are a problem. Cursor keys start with <escape>
+ * characters, so there's almost always a map in place that begins with
+ * an <escape> character. If we timeout <escape> keys in the same way
+ * that we timeout other keys, the user will get a noticeable pause as
+ * they enter <escape> to terminate input mode. If key timeout is set
+ * for a slow link, users will get an even longer pause. Nvi used to
+ * simply timeout <escape> characters at 1/10th of a second, but this
+ * loses over PPP links where the latency is greater than 100Ms.
+ */
+ if (ispartial) {
+ if (O_ISSET(sp, O_TIMEOUT))
+ timeout = (evp->e_value == K_ESCAPE ?
+ O_VAL(sp, O_ESCAPETIME) :
+ O_VAL(sp, O_KEYTIME)) * 100;
+ else
+ timeout = 0;
+ goto loop;
+ }
+
+ /* If no map, return the character. */
+ if (qp == NULL) {
+nomap: if (!isdigit(evp->e_c) && LF_ISSET(EC_MAPNODIGIT))
+ goto not_digit;
+ *argp = *evp;
+ QREM(1);
+ return (0);
+ }
+
+ /*
+ * If looking for the end of a digit string, and the first character
+ * of the map is it, pretend we haven't seen the character.
+ */
+ if (LF_ISSET(EC_MAPNODIGIT) &&
+ qp->output != NULL && !isdigit(qp->output[0])) {
+not_digit: argp->e_c = CH_NOT_DIGIT;
+ argp->e_value = K_NOTUSED;
+ argp->e_event = E_CHARACTER;
+ F_INIT(&argp->e_ch, 0);
+ return (0);
+ }
+
+ /* Find out if the initial segments are identical. */
+ init_nomap = !e_memcmp(qp->output, &gp->i_event[gp->i_next], qp->ilen);
+
+ /* Delete the mapped characters from the queue. */
+ QREM(qp->ilen);
+
+ /* If keys mapped to nothing, go get more. */
+ if (qp->output == NULL)
+ goto retry;
+
+ /* If remapping characters... */
+ if (O_ISSET(sp, O_REMAP)) {
+ /*
+ * Periodically check for interrupts. Always check the first
+ * time through, because it's possible to set up a map that
+ * will return a character every time, but will expand to more,
+ * e.g. "map! a aaaa" will always return a 'a', but we'll never
+ * get anywhere useful.
+ */
+ if ((++remap_cnt == 1 || remap_cnt % 10 == 0) &&
+ (gp->scr_event(sp, &ev,
+ EC_INTERRUPT, 0) || ev.e_event == E_INTERRUPT)) {
+ F_SET(sp->gp, G_INTERRUPTED);
+ argp->e_event = E_INTERRUPT;
+ return (0);
+ }
+
+ /*
+ * If an initial part of the characters mapped, they are not
+ * further remapped -- return the first one. Push the rest
+ * of the characters, or all of the characters if no initial
+ * part mapped, back on the queue.
+ */
+ if (init_nomap) {
+ if (v_event_push(sp, NULL, qp->output + qp->ilen,
+ qp->olen - qp->ilen, CH_MAPPED))
+ return (1);
+ if (v_event_push(sp, NULL,
+ qp->output, qp->ilen, CH_NOMAP | CH_MAPPED))
+ return (1);
+ evp = &gp->i_event[gp->i_next];
+ goto nomap;
+ }
+ if (v_event_push(sp, NULL, qp->output, qp->olen, CH_MAPPED))
+ return (1);
+ goto newmap;
+ }
+
+ /* Else, push the characters on the queue and return one. */
+ if (v_event_push(sp, NULL, qp->output, qp->olen, CH_MAPPED | CH_NOMAP))
+ return (1);
+
+ goto nomap;
+}
+
+/*
+ * v_sync --
+ * Walk the screen lists, sync'ing files to their backup copies.
+ */
+static void
+v_sync(sp, flags)
+ SCR *sp;
+ int flags;
+{
+ GS *gp;
+
+ gp = sp->gp;
+ for (sp = gp->dq.cqh_first; sp != (void *)&gp->dq; sp = sp->q.cqe_next)
+ rcv_sync(sp, flags);
+ for (sp = gp->hq.cqh_first; sp != (void *)&gp->hq; sp = sp->q.cqe_next)
+ rcv_sync(sp, flags);
+}
+
+/*
+ * v_event_err --
+ * Unexpected event.
+ *
+ * PUBLIC: void v_event_err __P((SCR *, EVENT *));
+ */
+void
+v_event_err(sp, evp)
+ SCR *sp;
+ EVENT *evp;
+{
+ switch (evp->e_event) {
+ case E_CHARACTER:
+ msgq(sp, M_ERR, "276|Unexpected character event");
+ break;
+ case E_EOF:
+ msgq(sp, M_ERR, "277|Unexpected end-of-file event");
+ break;
+ case E_INTERRUPT:
+ msgq(sp, M_ERR, "279|Unexpected interrupt event");
+ break;
+ case E_QUIT:
+ msgq(sp, M_ERR, "280|Unexpected quit event");
+ break;
+ case E_REPAINT:
+ msgq(sp, M_ERR, "281|Unexpected repaint event");
+ break;
+ case E_STRING:
+ msgq(sp, M_ERR, "285|Unexpected string event");
+ break;
+ case E_TIMEOUT:
+ msgq(sp, M_ERR, "286|Unexpected timeout event");
+ break;
+ case E_WRESIZE:
+ msgq(sp, M_ERR, "316|Unexpected resize event");
+ break;
+ case E_WRITE:
+ msgq(sp, M_ERR, "287|Unexpected write event");
+ break;
+
+ /*
+ * Theoretically, none of these can occur, as they're handled at the
+ * top editor level.
+ */
+ case E_ERR:
+ case E_SIGHUP:
+ case E_SIGTERM:
+ default:
+ abort();
+ }
+
+ /* Free any allocated memory. */
+ if (evp->e_asp != NULL)
+ free(evp->e_asp);
+}
+
+/*
+ * v_event_flush --
+ * Flush any flagged keys, returning if any keys were flushed.
+ *
+ * PUBLIC: int v_event_flush __P((SCR *, u_int));
+ */
+int
+v_event_flush(sp, flags)
+ SCR *sp;
+ u_int flags;
+{
+ GS *gp;
+ int rval;
+
+ for (rval = 0, gp = sp->gp; gp->i_cnt != 0 &&
+ F_ISSET(&gp->i_event[gp->i_next].e_ch, flags); rval = 1)
+ QREM(1);
+ return (rval);
+}
+
+/*
+ * v_event_grow --
+ * Grow the terminal queue.
+ */
+static int
+v_event_grow(sp, add)
+ SCR *sp;
+ int add;
+{
+ GS *gp;
+ size_t new_nelem, olen;
+
+ gp = sp->gp;
+ new_nelem = gp->i_nelem + add;
+ olen = gp->i_nelem * sizeof(gp->i_event[0]);
+ BINC_RET(sp, gp->i_event, olen, new_nelem * sizeof(gp->i_event[0]));
+ gp->i_nelem = olen / sizeof(gp->i_event[0]);
+ return (0);
+}
+
+/*
+ * v_key_cmp --
+ * Compare two keys for sorting.
+ */
+static int
+v_key_cmp(ap, bp)
+ const void *ap, *bp;
+{
+ return (((KEYLIST *)ap)->ch - ((KEYLIST *)bp)->ch);
+}
diff --git a/contrib/nvi/common/key.h b/contrib/nvi/common/key.h
new file mode 100644
index 000000000000..76fb64f8e1ec
--- /dev/null
+++ b/contrib/nvi/common/key.h
@@ -0,0 +1,222 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)key.h 10.18 (Berkeley) 6/30/96
+ */
+
+/*
+ * Fundamental character types.
+ *
+ * CHAR_T An integral type that can hold any character.
+ * ARG_CHAR_T The type of a CHAR_T when passed as an argument using
+ * traditional promotion rules. It should also be able
+ * to be compared against any CHAR_T for equality without
+ * problems.
+ * MAX_CHAR_T The maximum value of any character.
+ *
+ * If no integral type can hold a character, don't even try the port.
+ */
+typedef u_char CHAR_T;
+typedef u_int ARG_CHAR_T;
+#define MAX_CHAR_T 0xff
+
+/* The maximum number of columns any character can take up on a screen. */
+#define MAX_CHARACTER_COLUMNS 4
+
+/*
+ * Event types.
+ *
+ * The program structure depends on the event loop being able to return
+ * E_EOF/E_ERR multiple times -- eventually enough things will end due
+ * to the events that vi will reach the command level for the screen, at
+ * which point the exit flags will be set and vi will exit.
+ */
+typedef enum {
+ E_NOTUSED = 0, /* Not set. */
+ E_CHARACTER, /* Input character: e_c set. */
+ E_EOF, /* End of input (NOT ^D). */
+ E_ERR, /* Input error. */
+ E_INTERRUPT, /* Interrupt. */
+ E_QUIT, /* Quit. */
+ E_REPAINT, /* Repaint: e_flno, e_tlno set. */
+ E_SIGHUP, /* SIGHUP. */
+ E_SIGTERM, /* SIGTERM. */
+ E_STRING, /* Input string: e_csp, e_len set. */
+ E_TIMEOUT, /* Timeout. */
+ E_WRESIZE, /* Window resize. */
+ E_WRITE /* Write. */
+} e_event_t;
+
+/*
+ * Character values.
+ */
+typedef enum {
+ K_NOTUSED = 0, /* Not set. */
+ K_BACKSLASH, /* \ */
+ K_CARAT, /* ^ */
+ K_CNTRLD, /* ^D */
+ K_CNTRLR, /* ^R */
+ K_CNTRLT, /* ^T */
+ K_CNTRLZ, /* ^Z */
+ K_COLON, /* : */
+ K_CR, /* \r */
+ K_ESCAPE, /* ^[ */
+ K_FORMFEED, /* \f */
+ K_HEXCHAR, /* ^X */
+ K_NL, /* \n */
+ K_RIGHTBRACE, /* } */
+ K_RIGHTPAREN, /* ) */
+ K_TAB, /* \t */
+ K_VERASE, /* set from tty: default ^H */
+ K_VKILL, /* set from tty: default ^U */
+ K_VLNEXT, /* set from tty: default ^V */
+ K_VWERASE, /* set from tty: default ^W */
+ K_ZERO /* 0 */
+} e_key_t;
+
+struct _event {
+ TAILQ_ENTRY(_event) q; /* Linked list of events. */
+ e_event_t e_event; /* Event type. */
+ union {
+ struct { /* Input character. */
+ CHAR_T c; /* Character. */
+ e_key_t value; /* Key type. */
+
+#define CH_ABBREVIATED 0x01 /* Character is from an abbreviation. */
+#define CH_MAPPED 0x02 /* Character is from a map. */
+#define CH_NOMAP 0x04 /* Do not map the character. */
+#define CH_QUOTED 0x08 /* Character is already quoted. */
+ u_int8_t flags;
+ } _e_ch;
+#define e_ch _u_event._e_ch /* !!! The structure, not the char. */
+#define e_c _u_event._e_ch.c
+#define e_value _u_event._e_ch.value
+#define e_flags _u_event._e_ch.flags
+
+ struct { /* Screen position, size. */
+ size_t lno1; /* Line number. */
+ size_t cno1; /* Column number. */
+ size_t lno2; /* Line number. */
+ size_t cno2; /* Column number. */
+ } _e_mark;
+#define e_lno _u_event._e_mark.lno1 /* Single location. */
+#define e_cno _u_event._e_mark.cno1
+#define e_flno _u_event._e_mark.lno1 /* Text region. */
+#define e_fcno _u_event._e_mark.cno1
+#define e_tlno _u_event._e_mark.lno2
+#define e_tcno _u_event._e_mark.cno2
+
+ struct { /* Input string. */
+ CHAR_T *asp; /* Allocated string. */
+ CHAR_T *csp; /* String. */
+ size_t len; /* String length. */
+ } _e_str;
+#define e_asp _u_event._e_str.asp
+#define e_csp _u_event._e_str.csp
+#define e_len _u_event._e_str.len
+ } _u_event;
+};
+
+typedef struct _keylist {
+ e_key_t value; /* Special value. */
+ CHAR_T ch; /* Key. */
+} KEYLIST;
+extern KEYLIST keylist[];
+
+ /* Return if more keys in queue. */
+#define KEYS_WAITING(sp) ((sp)->gp->i_cnt != 0)
+#define MAPPED_KEYS_WAITING(sp) \
+ (KEYS_WAITING(sp) && \
+ F_ISSET(&sp->gp->i_event[sp->gp->i_next].e_ch, CH_MAPPED))
+
+/*
+ * Ex/vi commands are generally separated by whitespace characters. We
+ * can't use the standard isspace(3) macro because it returns true for
+ * characters like ^K in the ASCII character set. The 4.4BSD isblank(3)
+ * macro does exactly what we want, but it's not portable yet.
+ *
+ * XXX
+ * Note side effect, ch is evaluated multiple times.
+ */
+#ifndef isblank
+#define isblank(ch) ((ch) == ' ' || (ch) == '\t')
+#endif
+
+/* The "standard" tab width, for displaying things to users. */
+#define STANDARD_TAB 6
+
+/* Various special characters, messages. */
+#define CH_BSEARCH '?' /* Backward search prompt. */
+#define CH_CURSOR ' ' /* Cursor character. */
+#define CH_ENDMARK '$' /* End of a range. */
+#define CH_EXPROMPT ':' /* Ex prompt. */
+#define CH_FSEARCH '/' /* Forward search prompt. */
+#define CH_HEX '\030' /* Leading hex character. */
+#define CH_LITERAL '\026' /* ASCII ^V. */
+#define CH_NO 'n' /* No. */
+#define CH_NOT_DIGIT 'a' /* A non-isdigit() character. */
+#define CH_QUIT 'q' /* Quit. */
+#define CH_YES 'y' /* Yes. */
+
+/*
+ * Checking for interrupts means that we look at the bit that gets set if the
+ * screen code supports asynchronous events, and call back into the event code
+ * so that non-asynchronous screens get a chance to post the interrupt.
+ *
+ * INTERRUPT_CHECK is the number of lines "operated" on before checking for
+ * interrupts.
+ */
+#define INTERRUPT_CHECK 100
+#define INTERRUPTED(sp) \
+ (F_ISSET((sp)->gp, G_INTERRUPTED) || \
+ (!v_event_get(sp, NULL, 0, EC_INTERRUPT) && \
+ F_ISSET((sp)->gp, G_INTERRUPTED)))
+#define CLR_INTERRUPT(sp) \
+ F_CLR((sp)->gp, G_INTERRUPTED)
+
+/* Flags describing types of characters being requested. */
+#define EC_INTERRUPT 0x001 /* Checking for interrupts. */
+#define EC_MAPCOMMAND 0x002 /* Apply the command map. */
+#define EC_MAPINPUT 0x004 /* Apply the input map. */
+#define EC_MAPNODIGIT 0x008 /* Return to a digit. */
+#define EC_QUOTED 0x010 /* Try to quote next character */
+#define EC_RAW 0x020 /* Any next character. XXX: not used. */
+#define EC_TIMEOUT 0x040 /* Timeout to next character. */
+
+/* Flags describing text input special cases. */
+#define TXT_ADDNEWLINE 0x00000001 /* Replay starts on a new line. */
+#define TXT_AICHARS 0x00000002 /* Leading autoindent chars. */
+#define TXT_ALTWERASE 0x00000004 /* Option: altwerase. */
+#define TXT_APPENDEOL 0x00000008 /* Appending after EOL. */
+#define TXT_AUTOINDENT 0x00000010 /* Autoindent set this line. */
+#define TXT_BACKSLASH 0x00000020 /* Backslashes escape characters. */
+#define TXT_BEAUTIFY 0x00000040 /* Only printable characters. */
+#define TXT_BS 0x00000080 /* Backspace returns the buffer. */
+#define TXT_CEDIT 0x00000100 /* Can return TERM_CEDIT. */
+#define TXT_CNTRLD 0x00000200 /* Control-D is a command. */
+#define TXT_CNTRLT 0x00000400 /* Control-T is an indent special. */
+#define TXT_CR 0x00000800 /* CR returns the buffer. */
+#define TXT_DOTTERM 0x00001000 /* Leading '.' terminates the input. */
+#define TXT_EMARK 0x00002000 /* End of replacement mark. */
+#define TXT_EOFCHAR 0x00004000 /* ICANON set, return EOF character. */
+#define TXT_ESCAPE 0x00008000 /* Escape returns the buffer. */
+#define TXT_FILEC 0x00010000 /* Option: filec. */
+#define TXT_INFOLINE 0x00020000 /* Editing the info line. */
+#define TXT_MAPINPUT 0x00040000 /* Apply the input map. */
+#define TXT_NLECHO 0x00080000 /* Echo the newline. */
+#define TXT_NUMBER 0x00100000 /* Number the line. */
+#define TXT_OVERWRITE 0x00200000 /* Overwrite characters. */
+#define TXT_PROMPT 0x00400000 /* Display a prompt. */
+#define TXT_RECORD 0x00800000 /* Record for replay. */
+#define TXT_REPLACE 0x01000000 /* Replace; don't delete overwrite. */
+#define TXT_REPLAY 0x02000000 /* Replay the last input. */
+#define TXT_RESOLVE 0x04000000 /* Resolve the text into the file. */
+#define TXT_SEARCHINCR 0x08000000 /* Incremental search. */
+#define TXT_SHOWMATCH 0x10000000 /* Option: showmatch. */
+#define TXT_TTYWERASE 0x20000000 /* Option: ttywerase. */
+#define TXT_WRAPMARGIN 0x40000000 /* Option: wrapmargin. */
diff --git a/contrib/nvi/common/line.c b/contrib/nvi/common/line.c
new file mode 100644
index 000000000000..bcb9e0c86bcb
--- /dev/null
+++ b/contrib/nvi/common/line.c
@@ -0,0 +1,576 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)line.c 10.21 (Berkeley) 9/15/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "common.h"
+#include "../vi/vi.h"
+
+static int scr_update __P((SCR *, recno_t, lnop_t, int));
+
+/*
+ * db_eget --
+ * Front-end to db_get, special case handling for empty files.
+ *
+ * PUBLIC: int db_eget __P((SCR *, recno_t, char **, size_t *, int *));
+ */
+int
+db_eget(sp, lno, pp, lenp, isemptyp)
+ SCR *sp;
+ recno_t lno; /* Line number. */
+ char **pp; /* Pointer store. */
+ size_t *lenp; /* Length store. */
+ int *isemptyp;
+{
+ recno_t l1;
+
+ if (isemptyp != NULL)
+ *isemptyp = 0;
+
+ /* If the line exists, simply return it. */
+ if (!db_get(sp, lno, 0, pp, lenp))
+ return (0);
+
+ /*
+ * If the user asked for line 0 or line 1, i.e. the only possible
+ * line in an empty file, find the last line of the file; db_last
+ * fails loudly.
+ */
+ if ((lno == 0 || lno == 1) && db_last(sp, &l1))
+ return (1);
+
+ /* If the file isn't empty, fail loudly. */
+ if (lno != 0 && lno != 1 || l1 != 0) {
+ db_err(sp, lno);
+ return (1);
+ }
+
+ if (isemptyp != NULL)
+ *isemptyp = 1;
+
+ return (1);
+}
+
+/*
+ * db_get --
+ * Look in the text buffers for a line, followed by the cache, followed
+ * by the database.
+ *
+ * PUBLIC: int db_get __P((SCR *, recno_t, u_int32_t, char **, size_t *));
+ */
+int
+db_get(sp, lno, flags, pp, lenp)
+ SCR *sp;
+ recno_t lno; /* Line number. */
+ u_int32_t flags;
+ char **pp; /* Pointer store. */
+ size_t *lenp; /* Length store. */
+{
+ DBT data, key;
+ EXF *ep;
+ TEXT *tp;
+ recno_t l1, l2;
+
+ /*
+ * The underlying recno stuff handles zero by returning NULL, but
+ * have to have an OOB condition for the look-aside into the input
+ * buffer anyway.
+ */
+ if (lno == 0)
+ goto err1;
+
+ /* Check for no underlying file. */
+ if ((ep = sp->ep) == NULL) {
+ ex_emsg(sp, NULL, EXM_NOFILEYET);
+ goto err3;
+ }
+
+ if (LF_ISSET(DBG_NOCACHE))
+ goto nocache;
+
+ /*
+ * Look-aside into the TEXT buffers and see if the line we want
+ * is there.
+ */
+ if (F_ISSET(sp, SC_TINPUT)) {
+ l1 = ((TEXT *)sp->tiq.cqh_first)->lno;
+ l2 = ((TEXT *)sp->tiq.cqh_last)->lno;
+ if (l1 <= lno && l2 >= lno) {
+#if defined(DEBUG) && 0
+ TRACE(sp, "retrieve TEXT buffer line %lu\n", (u_long)lno);
+#endif
+ for (tp = sp->tiq.cqh_first;
+ tp->lno != lno; tp = tp->q.cqe_next);
+ if (lenp != NULL)
+ *lenp = tp->len;
+ if (pp != NULL)
+ *pp = tp->lb;
+ return (0);
+ }
+ /*
+ * Adjust the line number for the number of lines used
+ * by the text input buffers.
+ */
+ if (lno > l2)
+ lno -= l2 - l1;
+ }
+
+ /* Look-aside into the cache, and see if the line we want is there. */
+ if (lno == ep->c_lno) {
+#if defined(DEBUG) && 0
+ TRACE(sp, "retrieve cached line %lu\n", (u_long)lno);
+#endif
+ if (lenp != NULL)
+ *lenp = ep->c_len;
+ if (pp != NULL)
+ *pp = ep->c_lp;
+ return (0);
+ }
+ ep->c_lno = OOBLNO;
+
+nocache:
+ /* Get the line from the underlying database. */
+ key.data = &lno;
+ key.size = sizeof(lno);
+ switch (ep->db->get(ep->db, &key, &data, 0)) {
+ case -1:
+ goto err2;
+ case 1:
+err1: if (LF_ISSET(DBG_FATAL))
+err2: db_err(sp, lno);
+err3: if (lenp != NULL)
+ *lenp = 0;
+ if (pp != NULL)
+ *pp = NULL;
+ return (1);
+ }
+
+ /* Reset the cache. */
+ ep->c_lno = lno;
+ ep->c_len = data.size;
+ ep->c_lp = data.data;
+
+#if defined(DEBUG) && 0
+ TRACE(sp, "retrieve DB line %lu\n", (u_long)lno);
+#endif
+ if (lenp != NULL)
+ *lenp = data.size;
+ if (pp != NULL)
+ *pp = ep->c_lp;
+ return (0);
+}
+
+/*
+ * db_delete --
+ * Delete a line from the file.
+ *
+ * PUBLIC: int db_delete __P((SCR *, recno_t));
+ */
+int
+db_delete(sp, lno)
+ SCR *sp;
+ recno_t lno;
+{
+ DBT key;
+ EXF *ep;
+
+#if defined(DEBUG) && 0
+ TRACE(sp, "delete line %lu\n", (u_long)lno);
+#endif
+ /* Check for no underlying file. */
+ if ((ep = sp->ep) == NULL) {
+ ex_emsg(sp, NULL, EXM_NOFILEYET);
+ return (1);
+ }
+
+ /* Update marks, @ and global commands. */
+ if (mark_insdel(sp, LINE_DELETE, lno))
+ return (1);
+ if (ex_g_insdel(sp, LINE_DELETE, lno))
+ return (1);
+
+ /* Log change. */
+ log_line(sp, lno, LOG_LINE_DELETE);
+
+ /* Update file. */
+ key.data = &lno;
+ key.size = sizeof(lno);
+ SIGBLOCK;
+ if (ep->db->del(ep->db, &key, 0) == 1) {
+ msgq(sp, M_SYSERR,
+ "003|unable to delete line %lu", (u_long)lno);
+ return (1);
+ }
+ SIGUNBLOCK;
+
+ /* Flush the cache, update line count, before screen update. */
+ if (lno <= ep->c_lno)
+ ep->c_lno = OOBLNO;
+ if (ep->c_nlines != OOBLNO)
+ --ep->c_nlines;
+
+ /* File now modified. */
+ if (F_ISSET(ep, F_FIRSTMODIFY))
+ (void)rcv_init(sp);
+ F_SET(ep, F_MODIFIED);
+
+ /* Update screen. */
+ return (scr_update(sp, lno, LINE_DELETE, 1));
+}
+
+/*
+ * db_append --
+ * Append a line into the file.
+ *
+ * PUBLIC: int db_append __P((SCR *, int, recno_t, char *, size_t));
+ */
+int
+db_append(sp, update, lno, p, len)
+ SCR *sp;
+ int update;
+ recno_t lno;
+ char *p;
+ size_t len;
+{
+ DBT data, key;
+ EXF *ep;
+ int rval;
+
+#if defined(DEBUG) && 0
+ TRACE(sp, "append to %lu: len %u {%.*s}\n", lno, len, MIN(len, 20), p);
+#endif
+ /* Check for no underlying file. */
+ if ((ep = sp->ep) == NULL) {
+ ex_emsg(sp, NULL, EXM_NOFILEYET);
+ return (1);
+ }
+
+ /* Update file. */
+ key.data = &lno;
+ key.size = sizeof(lno);
+ data.data = p;
+ data.size = len;
+ SIGBLOCK;
+ if (ep->db->put(ep->db, &key, &data, R_IAFTER) == -1) {
+ msgq(sp, M_SYSERR,
+ "004|unable to append to line %lu", (u_long)lno);
+ return (1);
+ }
+ SIGUNBLOCK;
+
+ /* Flush the cache, update line count, before screen update. */
+ if (lno < ep->c_lno)
+ ep->c_lno = OOBLNO;
+ if (ep->c_nlines != OOBLNO)
+ ++ep->c_nlines;
+
+ /* File now dirty. */
+ if (F_ISSET(ep, F_FIRSTMODIFY))
+ (void)rcv_init(sp);
+ F_SET(ep, F_MODIFIED);
+
+ /* Log change. */
+ log_line(sp, lno + 1, LOG_LINE_APPEND);
+
+ /* Update marks, @ and global commands. */
+ rval = 0;
+ if (mark_insdel(sp, LINE_INSERT, lno + 1))
+ rval = 1;
+ if (ex_g_insdel(sp, LINE_INSERT, lno + 1))
+ rval = 1;
+
+ /*
+ * Update screen.
+ *
+ * XXX
+ * Nasty hack. If multiple lines are input by the user, they aren't
+ * committed until an <ESC> is entered. The problem is the screen was
+ * updated/scrolled as each line was entered. So, when this routine
+ * is called to copy the new lines from the cut buffer into the file,
+ * it has to know not to update the screen again.
+ */
+ return (scr_update(sp, lno, LINE_APPEND, update) || rval);
+}
+
+/*
+ * db_insert --
+ * Insert a line into the file.
+ *
+ * PUBLIC: int db_insert __P((SCR *, recno_t, char *, size_t));
+ */
+int
+db_insert(sp, lno, p, len)
+ SCR *sp;
+ recno_t lno;
+ char *p;
+ size_t len;
+{
+ DBT data, key;
+ EXF *ep;
+ int rval;
+
+#if defined(DEBUG) && 0
+ TRACE(sp, "insert before %lu: len %lu {%.*s}\n",
+ (u_long)lno, (u_long)len, MIN(len, 20), p);
+#endif
+ /* Check for no underlying file. */
+ if ((ep = sp->ep) == NULL) {
+ ex_emsg(sp, NULL, EXM_NOFILEYET);
+ return (1);
+ }
+
+ /* Update file. */
+ key.data = &lno;
+ key.size = sizeof(lno);
+ data.data = p;
+ data.size = len;
+ SIGBLOCK;
+ if (ep->db->put(ep->db, &key, &data, R_IBEFORE) == -1) {
+ msgq(sp, M_SYSERR,
+ "005|unable to insert at line %lu", (u_long)lno);
+ return (1);
+ }
+ SIGUNBLOCK;
+
+ /* Flush the cache, update line count, before screen update. */
+ if (lno >= ep->c_lno)
+ ep->c_lno = OOBLNO;
+ if (ep->c_nlines != OOBLNO)
+ ++ep->c_nlines;
+
+ /* File now dirty. */
+ if (F_ISSET(ep, F_FIRSTMODIFY))
+ (void)rcv_init(sp);
+ F_SET(ep, F_MODIFIED);
+
+ /* Log change. */
+ log_line(sp, lno, LOG_LINE_INSERT);
+
+ /* Update marks, @ and global commands. */
+ rval = 0;
+ if (mark_insdel(sp, LINE_INSERT, lno))
+ rval = 1;
+ if (ex_g_insdel(sp, LINE_INSERT, lno))
+ rval = 1;
+
+ /* Update screen. */
+ return (scr_update(sp, lno, LINE_INSERT, 1) || rval);
+}
+
+/*
+ * db_set --
+ * Store a line in the file.
+ *
+ * PUBLIC: int db_set __P((SCR *, recno_t, char *, size_t));
+ */
+int
+db_set(sp, lno, p, len)
+ SCR *sp;
+ recno_t lno;
+ char *p;
+ size_t len;
+{
+ DBT data, key;
+ EXF *ep;
+
+#if defined(DEBUG) && 0
+ TRACE(sp, "replace line %lu: len %lu {%.*s}\n",
+ (u_long)lno, (u_long)len, MIN(len, 20), p);
+#endif
+
+ /* Check for no underlying file. */
+ if ((ep = sp->ep) == NULL) {
+ ex_emsg(sp, NULL, EXM_NOFILEYET);
+ return (1);
+ }
+
+ /* Log before change. */
+ log_line(sp, lno, LOG_LINE_RESET_B);
+
+ /* Update file. */
+ key.data = &lno;
+ key.size = sizeof(lno);
+ data.data = p;
+ data.size = len;
+ SIGBLOCK;
+ if (ep->db->put(ep->db, &key, &data, 0) == -1) {
+ msgq(sp, M_SYSERR,
+ "006|unable to store line %lu", (u_long)lno);
+ return (1);
+ }
+ SIGUNBLOCK;
+
+ /* Flush the cache, before logging or screen update. */
+ if (lno == ep->c_lno)
+ ep->c_lno = OOBLNO;
+
+ /* File now dirty. */
+ if (F_ISSET(ep, F_FIRSTMODIFY))
+ (void)rcv_init(sp);
+ F_SET(ep, F_MODIFIED);
+
+ /* Log after change. */
+ log_line(sp, lno, LOG_LINE_RESET_F);
+
+ /* Update screen. */
+ return (scr_update(sp, lno, LINE_RESET, 1));
+}
+
+/*
+ * db_exist --
+ * Return if a line exists.
+ *
+ * PUBLIC: int db_exist __P((SCR *, recno_t));
+ */
+int
+db_exist(sp, lno)
+ SCR *sp;
+ recno_t lno;
+{
+ EXF *ep;
+
+ /* Check for no underlying file. */
+ if ((ep = sp->ep) == NULL) {
+ ex_emsg(sp, NULL, EXM_NOFILEYET);
+ return (1);
+ }
+
+ if (lno == OOBLNO)
+ return (0);
+
+ /*
+ * Check the last-line number cache. Adjust the cached line
+ * number for the lines used by the text input buffers.
+ */
+ if (ep->c_nlines != OOBLNO)
+ return (lno <= (F_ISSET(sp, SC_TINPUT) ?
+ ep->c_nlines + (((TEXT *)sp->tiq.cqh_last)->lno -
+ ((TEXT *)sp->tiq.cqh_first)->lno) : ep->c_nlines));
+
+ /* Go get the line. */
+ return (!db_get(sp, lno, 0, NULL, NULL));
+}
+
+/*
+ * db_last --
+ * Return the number of lines in the file.
+ *
+ * PUBLIC: int db_last __P((SCR *, recno_t *));
+ */
+int
+db_last(sp, lnop)
+ SCR *sp;
+ recno_t *lnop;
+{
+ DBT data, key;
+ EXF *ep;
+ recno_t lno;
+
+ /* Check for no underlying file. */
+ if ((ep = sp->ep) == NULL) {
+ ex_emsg(sp, NULL, EXM_NOFILEYET);
+ return (1);
+ }
+
+ /*
+ * Check the last-line number cache. Adjust the cached line
+ * number for the lines used by the text input buffers.
+ */
+ if (ep->c_nlines != OOBLNO) {
+ *lnop = ep->c_nlines;
+ if (F_ISSET(sp, SC_TINPUT))
+ *lnop += ((TEXT *)sp->tiq.cqh_last)->lno -
+ ((TEXT *)sp->tiq.cqh_first)->lno;
+ return (0);
+ }
+
+ key.data = &lno;
+ key.size = sizeof(lno);
+
+ switch (ep->db->seq(ep->db, &key, &data, R_LAST)) {
+ case -1:
+ msgq(sp, M_SYSERR, "007|unable to get last line");
+ *lnop = 0;
+ return (1);
+ case 1:
+ *lnop = 0;
+ return (0);
+ default:
+ break;
+ }
+
+ /* Fill the cache. */
+ memcpy(&lno, key.data, sizeof(lno));
+ ep->c_nlines = ep->c_lno = lno;
+ ep->c_len = data.size;
+ ep->c_lp = data.data;
+
+ /* Return the value. */
+ *lnop = (F_ISSET(sp, SC_TINPUT) &&
+ ((TEXT *)sp->tiq.cqh_last)->lno > lno ?
+ ((TEXT *)sp->tiq.cqh_last)->lno : lno);
+ return (0);
+}
+
+/*
+ * db_err --
+ * Report a line error.
+ *
+ * PUBLIC: void db_err __P((SCR *, recno_t));
+ */
+void
+db_err(sp, lno)
+ SCR *sp;
+ recno_t lno;
+{
+ msgq(sp, M_ERR,
+ "008|Error: unable to retrieve line %lu", (u_long)lno);
+}
+
+/*
+ * scr_update --
+ * Update all of the screens that are backed by the file that
+ * just changed.
+ */
+static int
+scr_update(sp, lno, op, current)
+ SCR *sp;
+ recno_t lno;
+ lnop_t op;
+ int current;
+{
+ EXF *ep;
+ SCR *tsp;
+
+ if (F_ISSET(sp, SC_EX))
+ return (0);
+
+ ep = sp->ep;
+ if (ep->refcnt != 1)
+ for (tsp = sp->gp->dq.cqh_first;
+ tsp != (void *)&sp->gp->dq; tsp = tsp->q.cqe_next)
+ if (sp != tsp && tsp->ep == ep)
+ if (vs_change(tsp, lno, op))
+ return (1);
+ return (current ? vs_change(sp, lno, op) : 0);
+}
diff --git a/usr.bin/vi/common/log.c b/contrib/nvi/common/log.c
index 09f0c27fe0f4..9a9fe793ffb8 100644
--- a/usr.bin/vi/common/log.c
+++ b/contrib/nvi/common/log.c
@@ -1,60 +1,31 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)log.c 8.16 (Berkeley) 5/21/94";
+static const char sccsid[] = "@(#)log.c 10.8 (Berkeley) 3/6/96";
#endif /* not lint */
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/stat.h>
-#include <sys/time.h>
#include <bitstring.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-#include "vi.h"
+#include "common.h"
/*
* The log consists of records, each containing a type byte and a variable
@@ -91,24 +62,23 @@ static char sccsid[] = "@(#)log.c 8.16 (Berkeley) 5/21/94";
* behaved that way.
*/
-static int log_cursor1 __P((SCR *, EXF *, int));
+static int log_cursor1 __P((SCR *, int));
+static void log_err __P((SCR *, char *, int));
#if defined(DEBUG) && 0
static void log_trace __P((SCR *, char *, recno_t, u_char *));
#endif
/* Try and restart the log on failure, i.e. if we run out of memory. */
#define LOG_ERR { \
- msgq(sp, M_ERR, "Error: %s/%d: put log error: %s", \
- tail(__FILE__), __LINE__, strerror(errno)); \
- (void)ep->log->close(ep->log); \
- if (!log_init(sp, ep)) \
- msgq(sp, M_ERR, "Log restarted"); \
+ log_err(sp, __FILE__, __LINE__); \
return (1); \
}
/*
* log_init --
* Initialize the logging subsystem.
+ *
+ * PUBLIC: int log_init __P((SCR *, EXF *));
*/
int
log_init(sp, ep)
@@ -116,6 +86,9 @@ log_init(sp, ep)
EXF *ep;
{
/*
+ * !!!
+ * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+ *
* Initialize the buffer. The logging subsystem has its own
* buffers because the global ones are almost by definition
* going to be in use when the log runs.
@@ -129,7 +102,7 @@ log_init(sp, ep)
ep->log = dbopen(NULL, O_CREAT | O_NONBLOCK | O_RDWR,
S_IRUSR | S_IWUSR, DB_RECNO, NULL);
if (ep->log == NULL) {
- msgq(sp, M_ERR, "log db: %s", strerror(errno));
+ msgq(sp, M_SYSERR, "009|Log file");
F_SET(ep, F_NOLOG);
return (1);
}
@@ -140,12 +113,18 @@ log_init(sp, ep)
/*
* log_end --
* Close the logging subsystem.
+ *
+ * PUBLIC: int log_end __P((SCR *, EXF *));
*/
int
log_end(sp, ep)
SCR *sp;
EXF *ep;
{
+ /*
+ * !!!
+ * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+ */
if (ep->log != NULL) {
(void)(ep->log->close)(ep->log);
ep->log = NULL;
@@ -164,12 +143,19 @@ log_end(sp, ep)
/*
* log_cursor --
* Log the current cursor position, starting an event.
+ *
+ * PUBLIC: int log_cursor __P((SCR *));
*/
int
-log_cursor(sp, ep)
+log_cursor(sp)
SCR *sp;
- EXF *ep;
{
+ EXF *ep;
+
+ ep = sp->ep;
+ if (F_ISSET(ep, F_NOLOG))
+ return (0);
+
/*
* If any changes were made since the last cursor init,
* put out the ending cursor record.
@@ -177,7 +163,7 @@ log_cursor(sp, ep)
if (ep->l_cursor.lno == OOBLNO) {
ep->l_cursor.lno = sp->lno;
ep->l_cursor.cno = sp->cno;
- return (log_cursor1(sp, ep, LOG_CURSOR_END));
+ return (log_cursor1(sp, LOG_CURSOR_END));
}
ep->l_cursor.lno = sp->lno;
ep->l_cursor.cno = sp->cno;
@@ -189,13 +175,14 @@ log_cursor(sp, ep)
* Actually push a cursor record out.
*/
static int
-log_cursor1(sp, ep, type)
+log_cursor1(sp, type)
SCR *sp;
- EXF *ep;
int type;
{
DBT data, key;
+ EXF *ep;
+ ep = sp->ep;
BINC_RET(sp, ep->l_lp, ep->l_len, sizeof(u_char) + sizeof(MARK));
ep->l_lp[0] = type;
memmove(ep->l_lp + sizeof(u_char), &ep->l_cursor, sizeof(MARK));
@@ -221,18 +208,21 @@ log_cursor1(sp, ep, type)
/*
* log_line --
* Log a line change.
+ *
+ * PUBLIC: int log_line __P((SCR *, recno_t, u_int));
*/
int
-log_line(sp, ep, lno, action)
+log_line(sp, lno, action)
SCR *sp;
- EXF *ep;
recno_t lno;
u_int action;
{
DBT data, key;
+ EXF *ep;
size_t len;
char *lp;
+ ep = sp->ep;
if (F_ISSET(ep, F_NOLOG))
return (0);
@@ -246,7 +236,7 @@ log_line(sp, ep, lno, action)
/* Put out one initial cursor record per set of changes. */
if (ep->l_cursor.lno != OOBLNO) {
- if (log_cursor1(sp, ep, LOG_CURSOR_INIT))
+ if (log_cursor1(sp, LOG_CURSOR_INIT))
return (1);
ep->l_cursor.lno = OOBLNO;
}
@@ -258,19 +248,17 @@ log_line(sp, ep, lno, action)
* so fake an empty length line.
*/
if (action == LOG_LINE_RESET_B) {
- if ((lp = file_rline(sp, ep, lno, &len)) == NULL) {
+ if (db_get(sp, lno, DBG_NOCACHE, &lp, &len)) {
if (lno != 1) {
- GETLINE_ERR(sp, lno);
+ db_err(sp, lno);
return (1);
}
len = 0;
lp = "";
}
} else
- if ((lp = file_gline(sp, ep, lno, &len)) == NULL) {
- GETLINE_ERR(sp, lno);
+ if (db_get(sp, lno, DBG_FATAL, &lp, &len))
return (1);
- }
BINC_RET(sp,
ep->l_lp, ep->l_len, len + sizeof(u_char) + sizeof(recno_t));
ep->l_lp[0] = action;
@@ -320,21 +308,24 @@ log_line(sp, ep, lno, action)
* aren't any operations that just put out a log record -- this
* would mean that undo operations would only reset marks, and not
* cause any other change.
+ *
+ * PUBLIC: int log_mark __P((SCR *, LMARK *));
*/
int
-log_mark(sp, ep, lmp)
+log_mark(sp, lmp)
SCR *sp;
- EXF *ep;
LMARK *lmp;
{
DBT data, key;
+ EXF *ep;
+ ep = sp->ep;
if (F_ISSET(ep, F_NOLOG))
return (0);
/* Put out one initial cursor record per set of changes. */
if (ep->l_cursor.lno != OOBLNO) {
- if (log_cursor1(sp, ep, LOG_CURSOR_INIT))
+ if (log_cursor1(sp, LOG_CURSOR_INIT))
return (1);
ep->l_cursor.lno = OOBLNO;
}
@@ -363,28 +354,31 @@ log_mark(sp, ep, lmp)
/*
* Log_backward --
* Roll the log backward one operation.
+ *
+ * PUBLIC: int log_backward __P((SCR *, MARK *));
*/
int
-log_backward(sp, ep, rp)
+log_backward(sp, rp)
SCR *sp;
- EXF *ep;
MARK *rp;
{
DBT key, data;
+ EXF *ep;
LMARK lm;
MARK m;
recno_t lno;
int didop;
u_char *p;
+ ep = sp->ep;
if (F_ISSET(ep, F_NOLOG)) {
msgq(sp, M_ERR,
- "Logging not being performed, undo not possible");
+ "010|Logging not being performed, undo not possible");
return (1);
}
if (ep->l_cur == 1) {
- msgq(sp, M_BERR, "No changes to undo");
+ msgq(sp, M_BERR, "011|No changes to undo");
return (1);
}
@@ -413,14 +407,14 @@ log_backward(sp, ep, rp)
case LOG_LINE_INSERT:
didop = 1;
memmove(&lno, p + sizeof(u_char), sizeof(recno_t));
- if (file_dline(sp, ep, lno))
+ if (db_delete(sp, lno))
goto err;
++sp->rptlines[L_DELETED];
break;
case LOG_LINE_DELETE:
didop = 1;
memmove(&lno, p + sizeof(u_char), sizeof(recno_t));
- if (file_iline(sp, ep, lno, p + sizeof(u_char) +
+ if (db_insert(sp, lno, p + sizeof(u_char) +
sizeof(recno_t), data.size - sizeof(u_char) -
sizeof(recno_t)))
goto err;
@@ -431,7 +425,7 @@ log_backward(sp, ep, rp)
case LOG_LINE_RESET_B:
didop = 1;
memmove(&lno, p + sizeof(u_char), sizeof(recno_t));
- if (file_sline(sp, ep, lno, p + sizeof(u_char) +
+ if (db_set(sp, lno, p + sizeof(u_char) +
sizeof(recno_t), data.size - sizeof(u_char) -
sizeof(recno_t)))
goto err;
@@ -445,7 +439,7 @@ log_backward(sp, ep, rp)
memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
m.lno = lm.lno;
m.cno = lm.cno;
- if (mark_set(sp, ep, lm.name, &m, 0))
+ if (mark_set(sp, lm.name, &m, 0))
goto err;
break;
default:
@@ -466,21 +460,24 @@ err: F_CLR(ep, F_NOLOG);
* unless a change was made. If you do a change, move off the line,
* then move back on and do a 'U', the line will be restored to the way
* it was before the original change.
+ *
+ * PUBLIC: int log_setline __P((SCR *));
*/
int
-log_setline(sp, ep)
+log_setline(sp)
SCR *sp;
- EXF *ep;
{
DBT key, data;
+ EXF *ep;
LMARK lm;
MARK m;
recno_t lno;
u_char *p;
+ ep = sp->ep;
if (F_ISSET(ep, F_NOLOG)) {
msgq(sp, M_ERR,
- "Logging not being performed, undo not possible");
+ "012|Logging not being performed, undo not possible");
return (1);
}
@@ -523,7 +520,7 @@ log_setline(sp, ep)
case LOG_LINE_RESET_B:
memmove(&lno, p + sizeof(u_char), sizeof(recno_t));
if (lno == sp->lno &&
- file_sline(sp, ep, lno, p + sizeof(u_char) +
+ db_set(sp, lno, p + sizeof(u_char) +
sizeof(recno_t), data.size - sizeof(u_char) -
sizeof(recno_t)))
goto err;
@@ -535,7 +532,7 @@ log_setline(sp, ep)
memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
m.lno = lm.lno;
m.cno = lm.cno;
- if (mark_set(sp, ep, lm.name, &m, 0))
+ if (mark_set(sp, lm.name, &m, 0))
goto err;
break;
default:
@@ -550,28 +547,31 @@ err: F_CLR(ep, F_NOLOG);
/*
* Log_forward --
* Roll the log forward one operation.
+ *
+ * PUBLIC: int log_forward __P((SCR *, MARK *));
*/
int
-log_forward(sp, ep, rp)
+log_forward(sp, rp)
SCR *sp;
- EXF *ep;
MARK *rp;
{
DBT key, data;
+ EXF *ep;
LMARK lm;
MARK m;
recno_t lno;
int didop;
u_char *p;
+ ep = sp->ep;
if (F_ISSET(ep, F_NOLOG)) {
msgq(sp, M_ERR,
- "Logging not being performed, roll-forward not possible");
+ "013|Logging not being performed, roll-forward not possible");
return (1);
}
if (ep->l_cur == ep->l_high) {
- msgq(sp, M_BERR, "No changes to re-do");
+ msgq(sp, M_BERR, "014|No changes to re-do");
return (1);
}
@@ -601,7 +601,7 @@ log_forward(sp, ep, rp)
case LOG_LINE_INSERT:
didop = 1;
memmove(&lno, p + sizeof(u_char), sizeof(recno_t));
- if (file_iline(sp, ep, lno, p + sizeof(u_char) +
+ if (db_insert(sp, lno, p + sizeof(u_char) +
sizeof(recno_t), data.size - sizeof(u_char) -
sizeof(recno_t)))
goto err;
@@ -610,7 +610,7 @@ log_forward(sp, ep, rp)
case LOG_LINE_DELETE:
didop = 1;
memmove(&lno, p + sizeof(u_char), sizeof(recno_t));
- if (file_dline(sp, ep, lno))
+ if (db_delete(sp, lno))
goto err;
++sp->rptlines[L_DELETED];
break;
@@ -619,7 +619,7 @@ log_forward(sp, ep, rp)
case LOG_LINE_RESET_F:
didop = 1;
memmove(&lno, p + sizeof(u_char), sizeof(recno_t));
- if (file_sline(sp, ep, lno, p + sizeof(u_char) +
+ if (db_set(sp, lno, p + sizeof(u_char) +
sizeof(recno_t), data.size - sizeof(u_char) -
sizeof(recno_t)))
goto err;
@@ -633,7 +633,7 @@ log_forward(sp, ep, rp)
memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
m.lno = lm.lno;
m.cno = lm.cno;
- if (mark_set(sp, ep, lm.name, &m, 0))
+ if (mark_set(sp, lm.name, &m, 0))
goto err;
break;
default:
@@ -645,6 +645,25 @@ err: F_CLR(ep, F_NOLOG);
return (1);
}
+/*
+ * log_err --
+ * Try and restart the log on failure, i.e. if we run out of memory.
+ */
+static void
+log_err(sp, file, line)
+ SCR *sp;
+ char *file;
+ int line;
+{
+ EXF *ep;
+
+ msgq(sp, M_SYSERR, "015|%s/%d: log put error", tail(file), line);
+ ep = sp->ep;
+ (void)ep->log->close(ep->log);
+ if (!log_init(sp, ep))
+ msgq(sp, M_ERR, "267|Log restarted");
+}
+
#if defined(DEBUG) && 0
static void
log_trace(sp, msg, rno, p)
diff --git a/contrib/nvi/common/log.h b/contrib/nvi/common/log.h
new file mode 100644
index 000000000000..df307319b1d3
--- /dev/null
+++ b/contrib/nvi/common/log.h
@@ -0,0 +1,20 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)log.h 10.2 (Berkeley) 3/6/96
+ */
+
+#define LOG_NOTYPE 0
+#define LOG_CURSOR_INIT 1
+#define LOG_CURSOR_END 2
+#define LOG_LINE_APPEND 3
+#define LOG_LINE_DELETE 4
+#define LOG_LINE_INSERT 5
+#define LOG_LINE_RESET_F 6
+#define LOG_LINE_RESET_B 7
+#define LOG_MARK 8
diff --git a/contrib/nvi/common/main.c b/contrib/nvi/common/main.c
new file mode 100644
index 000000000000..6fb2ed1fe2f0
--- /dev/null
+++ b/contrib/nvi/common/main.c
@@ -0,0 +1,617 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1992, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n\
+@(#) Copyright (c) 1992, 1993, 1994, 1995, 1996\n\
+ Keith Bostic. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static const char sccsid[] = "@(#)main.c 10.48 (Berkeley) 10/11/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "../vi/vi.h"
+#include "pathnames.h"
+
+static void attach __P((GS *));
+static void v_estr __P((char *, int, char *));
+static int v_obsolete __P((char *, char *[]));
+
+/*
+ * editor --
+ * Main editor routine.
+ *
+ * PUBLIC: int editor __P((GS *, int, char *[]));
+ */
+int
+editor(gp, argc, argv)
+ GS *gp;
+ int argc;
+ char *argv[];
+{
+ extern int optind;
+ extern char *optarg;
+ const char *p;
+ EVENT ev;
+ FREF *frp;
+ SCR *sp;
+ size_t len;
+ u_int flags;
+ int ch, flagchk, lflag, secure, startup, readonly, rval, silent;
+ char *tag_f, *wsizearg, path[256];
+
+ /* Initialize the busy routine, if not defined by the screen. */
+ if (gp->scr_busy == NULL)
+ gp->scr_busy = vs_busy;
+ /* Initialize the message routine, if not defined by the screen. */
+ if (gp->scr_msg == NULL)
+ gp->scr_msg = vs_msg;
+
+ /* Common global structure initialization. */
+ CIRCLEQ_INIT(&gp->dq);
+ CIRCLEQ_INIT(&gp->hq);
+ LIST_INIT(&gp->ecq);
+ LIST_INSERT_HEAD(&gp->ecq, &gp->excmd, q);
+ gp->noprint = DEFAULT_NOPRINT;
+
+ /* Structures shared by screens so stored in the GS structure. */
+ CIRCLEQ_INIT(&gp->frefq);
+ CIRCLEQ_INIT(&gp->dcb_store.textq);
+ LIST_INIT(&gp->cutq);
+ LIST_INIT(&gp->seqq);
+
+ /* Set initial screen type and mode based on the program name. */
+ readonly = 0;
+ if (!strcmp(gp->progname, "ex") || !strcmp(gp->progname, "nex"))
+ LF_INIT(SC_EX);
+ else {
+ /* Nview, view are readonly. */
+ if (!strcmp(gp->progname, "nview") ||
+ !strcmp(gp->progname, "view"))
+ readonly = 1;
+
+ /* Vi is the default. */
+ LF_INIT(SC_VI);
+ }
+
+ /* Convert old-style arguments into new-style ones. */
+ if (v_obsolete(gp->progname, argv))
+ return (1);
+
+ /* Parse the arguments. */
+ flagchk = '\0';
+ tag_f = wsizearg = NULL;
+ lflag = secure = silent = 0;
+ startup = 1;
+
+ /* Set the file snapshot flag. */
+ F_SET(gp, G_SNAPSHOT);
+
+#ifdef DEBUG
+ while ((ch = getopt(argc, argv, "c:D:eFlRrSsT:t:vw:")) != EOF)
+#else
+ while ((ch = getopt(argc, argv, "c:eFlRrSst:vw:")) != EOF)
+#endif
+ switch (ch) {
+ case 'c': /* Run the command. */
+ /*
+ * XXX
+ * We should support multiple -c options.
+ */
+ if (gp->c_option != NULL) {
+ v_estr(gp->progname, 0,
+ "only one -c command may be specified.");
+ return (1);
+ }
+ gp->c_option = optarg;
+ break;
+#ifdef DEBUG
+ case 'D':
+ switch (optarg[0]) {
+ case 's':
+ startup = 0;
+ break;
+ case 'w':
+ attach(gp);
+ break;
+ default:
+ v_estr(gp->progname, 0,
+ "usage: -D requires s or w argument.");
+ return (1);
+ }
+ break;
+#endif
+ case 'e': /* Ex mode. */
+ LF_CLR(SC_VI);
+ LF_SET(SC_EX);
+ break;
+ case 'F': /* No snapshot. */
+ F_CLR(gp, G_SNAPSHOT);
+ break;
+ case 'l': /* Set lisp, showmatch options. */
+ lflag = 1;
+ break;
+ case 'R': /* Readonly. */
+ readonly = 1;
+ break;
+ case 'r': /* Recover. */
+ if (flagchk == 't') {
+ v_estr(gp->progname, 0,
+ "only one of -r and -t may be specified.");
+ return (1);
+ }
+ flagchk = 'r';
+ break;
+ case 'S':
+ secure = 1;
+ break;
+ case 's':
+ silent = 1;
+ break;
+#ifdef DEBUG
+ case 'T': /* Trace. */
+ if ((gp->tracefp = fopen(optarg, "w")) == NULL) {
+ v_estr(gp->progname, errno, optarg);
+ goto err;
+ }
+ (void)fprintf(gp->tracefp,
+ "\n===\ntrace: open %s\n", optarg);
+ break;
+#endif
+ case 't': /* Tag. */
+ if (flagchk == 'r') {
+ v_estr(gp->progname, 0,
+ "only one of -r and -t may be specified.");
+ return (1);
+ }
+ if (flagchk == 't') {
+ v_estr(gp->progname, 0,
+ "only one tag file may be specified.");
+ return (1);
+ }
+ flagchk = 't';
+ tag_f = optarg;
+ break;
+ case 'v': /* Vi mode. */
+ LF_CLR(SC_EX);
+ LF_SET(SC_VI);
+ break;
+ case 'w':
+ wsizearg = optarg;
+ break;
+ case '?':
+ default:
+ (void)gp->scr_usage();
+ return (1);
+ }
+ argc -= optind;
+ argv += optind;
+
+ /*
+ * -s option is only meaningful to ex.
+ *
+ * If not reading from a terminal, it's like -s was specified.
+ */
+ if (silent && !LF_ISSET(SC_EX)) {
+ v_estr(gp->progname, 0, "-s option is only applicable to ex.");
+ goto err;
+ }
+ if (LF_ISSET(SC_EX) && F_ISSET(gp, G_SCRIPTED))
+ silent = 1;
+
+ /*
+ * Build and initialize the first/current screen. This is a bit
+ * tricky. If an error is returned, we may or may not have a
+ * screen structure. If we have a screen structure, put it on a
+ * display queue so that the error messages get displayed.
+ *
+ * !!!
+ * Everything we do until we go interactive is done in ex mode.
+ */
+ if (screen_init(gp, NULL, &sp)) {
+ if (sp != NULL)
+ CIRCLEQ_INSERT_HEAD(&gp->dq, sp, q);
+ goto err;
+ }
+ F_SET(sp, SC_EX);
+ CIRCLEQ_INSERT_HEAD(&gp->dq, sp, q);
+
+ if (v_key_init(sp)) /* Special key initialization. */
+ goto err;
+
+ { int oargs[5], *oargp = oargs;
+ if (lflag) { /* Command-line options. */
+ *oargp++ = O_LISP;
+ *oargp++ = O_SHOWMATCH;
+ }
+ if (readonly)
+ *oargp++ = O_READONLY;
+ if (secure)
+ *oargp++ = O_SECURE;
+ *oargp = -1; /* Options initialization. */
+ if (opts_init(sp, oargs))
+ goto err;
+ }
+ if (wsizearg != NULL) {
+ ARGS *av[2], a, b;
+ (void)snprintf(path, sizeof(path), "window=%s", wsizearg);
+ a.bp = (CHAR_T *)path;
+ a.len = strlen(path);
+ b.bp = NULL;
+ b.len = 0;
+ av[0] = &a;
+ av[1] = &b;
+ (void)opts_set(sp, av, NULL);
+ }
+ if (silent) { /* Ex batch mode option values. */
+ O_CLR(sp, O_AUTOPRINT);
+ O_CLR(sp, O_PROMPT);
+ O_CLR(sp, O_VERBOSE);
+ O_CLR(sp, O_WARN);
+ F_SET(sp, SC_EX_SILENT);
+ }
+
+ sp->rows = O_VAL(sp, O_LINES); /* Make ex formatting work. */
+ sp->cols = O_VAL(sp, O_COLUMNS);
+
+ if (!silent && startup) { /* Read EXINIT, exrc files. */
+ if (ex_exrc(sp))
+ goto err;
+ if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) {
+ if (screen_end(sp))
+ goto err;
+ goto done;
+ }
+ }
+
+ /*
+ * List recovery files if -r specified without file arguments.
+ * Note, options must be initialized and startup information
+ * read before doing this.
+ */
+ if (flagchk == 'r' && argv[0] == NULL) {
+ if (rcv_list(sp))
+ goto err;
+ if (screen_end(sp))
+ goto err;
+ goto done;
+ }
+
+ /*
+ * !!!
+ * Initialize the default ^D, ^U scrolling value here, after the
+ * user has had every opportunity to set the window option.
+ *
+ * It's historic practice that changing the value of the window
+ * option did not alter the default scrolling value, only giving
+ * a count to ^D/^U did that.
+ */
+ sp->defscroll = (O_VAL(sp, O_WINDOW) + 1) / 2;
+
+ /*
+ * If we don't have a command-line option, switch into the right
+ * editor now, so that we position default files correctly, and
+ * so that any tags file file-already-locked messages are in the
+ * vi screen, not the ex screen.
+ *
+ * XXX
+ * If we have a command-line option, the error message can end
+ * up in the wrong place, but I think that the combination is
+ * unlikely.
+ */
+ if (gp->c_option == NULL) {
+ F_CLR(sp, SC_EX | SC_VI);
+ F_SET(sp, LF_ISSET(SC_EX | SC_VI));
+ }
+
+ /* Open a tag file if specified. */
+ if (tag_f != NULL && ex_tag_first(sp, tag_f))
+ goto err;
+
+ /*
+ * Append any remaining arguments as file names. Files are recovery
+ * files if -r specified. If the tag option or ex startup commands
+ * loaded a file, then any file arguments are going to come after it.
+ */
+ if (*argv != NULL) {
+ if (sp->frp != NULL) {
+ /* Cheat -- we know we have an extra argv slot. */
+ MALLOC_NOMSG(sp,
+ *--argv, char *, strlen(sp->frp->name) + 1);
+ if (*argv == NULL) {
+ v_estr(gp->progname, errno, NULL);
+ goto err;
+ }
+ (void)strcpy(*argv, sp->frp->name);
+ }
+ sp->argv = sp->cargv = argv;
+ F_SET(sp, SC_ARGNOFREE);
+ if (flagchk == 'r')
+ F_SET(sp, SC_ARGRECOVER);
+ }
+
+ /*
+ * If the ex startup commands and or/the tag option haven't already
+ * created a file, create one. If no command-line files were given,
+ * use a temporary file.
+ */
+ if (sp->frp == NULL) {
+ if (sp->argv == NULL) {
+ if ((frp = file_add(sp, NULL)) == NULL)
+ goto err;
+ } else {
+ if ((frp = file_add(sp, (CHAR_T *)sp->argv[0])) == NULL)
+ goto err;
+ if (F_ISSET(sp, SC_ARGRECOVER))
+ F_SET(frp, FR_RECOVER);
+ }
+
+ if (file_init(sp, frp, NULL, 0))
+ goto err;
+ if (EXCMD_RUNNING(gp)) {
+ (void)ex_cmd(sp);
+ if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) {
+ if (screen_end(sp))
+ goto err;
+ goto done;
+ }
+ }
+ }
+
+ /*
+ * Check to see if we need to wait for ex. If SC_SCR_EX is set, ex
+ * was forced to initialize the screen during startup. We'd like to
+ * wait for a single character from the user, but we can't because
+ * we're not in raw mode. We can't switch to raw mode because the
+ * vi initialization will switch to xterm's alternate screen, causing
+ * us to lose the messages we're pausing to make sure the user read.
+ * So, wait for a complete line.
+ */
+ if (F_ISSET(sp, SC_SCR_EX)) {
+ p = msg_cmsg(sp, CMSG_CONT_R, &len);
+ (void)write(STDOUT_FILENO, p, len);
+ for (;;) {
+ if (v_event_get(sp, &ev, 0, 0))
+ goto err;
+ if (ev.e_event == E_INTERRUPT ||
+ ev.e_event == E_CHARACTER &&
+ (ev.e_value == K_CR || ev.e_value == K_NL))
+ break;
+ (void)gp->scr_bell(sp);
+ }
+ }
+
+ /* Switch into the right editor, regardless. */
+ F_CLR(sp, SC_EX | SC_VI);
+ F_SET(sp, LF_ISSET(SC_EX | SC_VI) | SC_STATUS_CNT);
+
+ /*
+ * Main edit loop. Vi handles split screens itself, we only return
+ * here when switching editor modes or restarting the screen.
+ */
+ while (sp != NULL)
+ if (F_ISSET(sp, SC_EX) ? ex(&sp) : vi(&sp))
+ goto err;
+
+done: rval = 0;
+ if (0)
+err: rval = 1;
+
+ /* Clean out the global structure. */
+ v_end(gp);
+
+ return (rval);
+}
+
+/*
+ * v_end --
+ * End the program, discarding screens and most of the global area.
+ *
+ * PUBLIC: void v_end __P((GS *));
+ */
+void
+v_end(gp)
+ GS *gp;
+{
+ MSGS *mp;
+ SCR *sp;
+
+ /* If there are any remaining screens, kill them off. */
+ if (gp->ccl_sp != NULL) {
+ (void)file_end(gp->ccl_sp, NULL, 1);
+ (void)screen_end(gp->ccl_sp);
+ }
+ while ((sp = gp->dq.cqh_first) != (void *)&gp->dq)
+ (void)screen_end(sp);
+ while ((sp = gp->hq.cqh_first) != (void *)&gp->hq)
+ (void)screen_end(sp);
+
+#ifdef HAVE_PERL_INTERP
+ perl_end(gp);
+#endif
+
+#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
+ { FREF *frp;
+ /* Free FREF's. */
+ while ((frp = gp->frefq.cqh_first) != (FREF *)&gp->frefq) {
+ CIRCLEQ_REMOVE(&gp->frefq, frp, q);
+ if (frp->name != NULL)
+ free(frp->name);
+ if (frp->tname != NULL)
+ free(frp->tname);
+ free(frp);
+ }
+ }
+
+ /* Free key input queue. */
+ if (gp->i_event != NULL)
+ free(gp->i_event);
+
+ /* Free cut buffers. */
+ cut_close(gp);
+
+ /* Free map sequences. */
+ seq_close(gp);
+
+ /* Free default buffer storage. */
+ (void)text_lfree(&gp->dcb_store.textq);
+
+ /* Close message catalogs. */
+ msg_close(gp);
+#endif
+
+ /* Ring the bell if scheduled. */
+ if (F_ISSET(gp, G_BELLSCHED))
+ (void)fprintf(stderr, "\07"); /* \a */
+
+ /*
+ * Flush any remaining messages. If a message is here, it's almost
+ * certainly the message about the event that killed us (although
+ * it's possible that the user is sourcing a file that exits from the
+ * editor).
+ */
+ while ((mp = gp->msgq.lh_first) != NULL) {
+ (void)fprintf(stderr, "%s%.*s",
+ mp->mtype == M_ERR ? "ex/vi: " : "", (int)mp->len, mp->buf);
+ LIST_REMOVE(mp, q);
+#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
+ free(mp->buf);
+ free(mp);
+#endif
+ }
+
+#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
+ /* Free any temporary space. */
+ if (gp->tmp_bp != NULL)
+ free(gp->tmp_bp);
+
+#if defined(DEBUG)
+ /* Close debugging file descriptor. */
+ if (gp->tracefp != NULL)
+ (void)fclose(gp->tracefp);
+#endif
+#endif
+}
+
+/*
+ * v_obsolete --
+ * Convert historic arguments into something getopt(3) will like.
+ */
+static int
+v_obsolete(name, argv)
+ char *name, *argv[];
+{
+ size_t len;
+ char *p;
+
+ /*
+ * Translate old style arguments into something getopt will like.
+ * Make sure it's not text space memory, because ex modifies the
+ * strings.
+ * Change "+" into "-c$".
+ * Change "+<anything else>" into "-c<anything else>".
+ * Change "-" into "-s"
+ * The c, T, t and w options take arguments so they can't be
+ * special arguments.
+ *
+ * Stop if we find "--" as an argument, the user may want to edit
+ * a file named "+foo".
+ */
+ while (*++argv && strcmp(argv[0], "--"))
+ if (argv[0][0] == '+') {
+ if (argv[0][1] == '\0') {
+ MALLOC_NOMSG(NULL, argv[0], char *, 4);
+ if (argv[0] == NULL)
+ goto nomem;
+ (void)strcpy(argv[0], "-c$");
+ } else {
+ p = argv[0];
+ len = strlen(argv[0]);
+ MALLOC_NOMSG(NULL, argv[0], char *, len + 2);
+ if (argv[0] == NULL)
+ goto nomem;
+ argv[0][0] = '-';
+ argv[0][1] = 'c';
+ (void)strcpy(argv[0] + 2, p + 1);
+ }
+ } else if (argv[0][0] == '-')
+ if (argv[0][1] == '\0') {
+ MALLOC_NOMSG(NULL, argv[0], char *, 3);
+ if (argv[0] == NULL) {
+nomem: v_estr(name, errno, NULL);
+ return (1);
+ }
+ (void)strcpy(argv[0], "-s");
+ } else
+ if ((argv[0][1] == 'c' || argv[0][1] == 'T' ||
+ argv[0][1] == 't' || argv[0][1] == 'w') &&
+ argv[0][2] == '\0')
+ ++argv;
+ return (0);
+}
+
+#ifdef DEBUG
+static void
+attach(gp)
+ GS *gp;
+{
+ int fd;
+ char ch;
+
+ if ((fd = open(_PATH_TTY, O_RDONLY, 0)) < 0) {
+ v_estr(gp->progname, errno, _PATH_TTY);
+ return;
+ }
+
+ (void)printf("process %lu waiting, enter <CR> to continue: ",
+ (u_long)getpid());
+ (void)fflush(stdout);
+
+ do {
+ if (read(fd, &ch, 1) != 1) {
+ (void)close(fd);
+ return;
+ }
+ } while (ch != '\n' && ch != '\r');
+ (void)close(fd);
+}
+#endif
+
+static void
+v_estr(name, eno, msg)
+ char *name, *msg;
+ int eno;
+{
+ (void)fprintf(stderr, "%s", name);
+ if (msg != NULL)
+ (void)fprintf(stderr, ": %s", msg);
+ if (eno)
+ (void)fprintf(stderr, ": %s", strerror(errno));
+ (void)fprintf(stderr, "\n");
+}
diff --git a/usr.bin/vi/common/mark.c b/contrib/nvi/common/mark.c
index 15b04974fc0f..0ac1fc28bf9c 100644
--- a/usr.bin/vi/common/mark.c
+++ b/contrib/nvi/common/mark.c
@@ -1,60 +1,31 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)mark.c 8.19 (Berkeley) 5/21/94";
+static const char sccsid[] = "@(#)mark.c 10.13 (Berkeley) 7/19/96";
#endif /* not lint */
#include <sys/types.h>
#include <sys/queue.h>
-#include <sys/time.h>
#include <bitstring.h>
#include <errno.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-#include "vi.h"
+#include "common.h"
-static LMARK *mark_find __P((SCR *, EXF *, ARG_CHAR_T));
+static LMARK *mark_find __P((SCR *, ARG_CHAR_T));
/*
* Marks are maintained in a key sorted doubly linked list. We can't
@@ -70,7 +41,7 @@ static LMARK *mark_find __P((SCR *, EXF *, ARG_CHAR_T));
* if we've given the line to v_ntext.c:v_ntext() for editing. Historic vi
* would move to the first non-blank on the line when the mark location was
* past the end of the line. This can be complicated by deleting to a mark
- * that has disappeared using the ` command. Historic vi vi treated this as
+ * that has disappeared using the ` command. Historic vi treated this as
* a line-mode motion and deleted the line. This implementation complains to
* the user.
*
@@ -90,30 +61,29 @@ static LMARK *mark_find __P((SCR *, EXF *, ARG_CHAR_T));
/*
* mark_init --
* Set up the marks.
+ *
+ * PUBLIC: int mark_init __P((SCR *, EXF *));
*/
int
mark_init(sp, ep)
SCR *sp;
EXF *ep;
{
- LMARK *lmp;
-
/*
- * Make sure the marks have been set up. If they
- * haven't, do so, and create the absolute mark.
+ * !!!
+ * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+ *
+ * Set up the marks.
*/
- MALLOC_RET(sp, lmp, LMARK *, sizeof(LMARK));
- lmp->lno = 1;
- lmp->cno = 0;
- lmp->name = ABSMARK1;
- lmp->flags = 0;
- LIST_INSERT_HEAD(&ep->marks, lmp, q);
+ LIST_INIT(&ep->marks);
return (0);
}
/*
* mark_end --
* Free up the marks.
+ *
+ * PUBLIC: int mark_end __P((SCR *, EXF *));
*/
int
mark_end(sp, ep)
@@ -122,9 +92,13 @@ mark_end(sp, ep)
{
LMARK *lmp;
+ /*
+ * !!!
+ * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+ */
while ((lmp = ep->marks.lh_first) != NULL) {
LIST_REMOVE(lmp, q);
- FREE(lmp, sizeof(LMARK));
+ free(lmp);
}
return (0);
}
@@ -132,33 +106,40 @@ mark_end(sp, ep)
/*
* mark_get --
* Get the location referenced by a mark.
+ *
+ * PUBLIC: int mark_get __P((SCR *, ARG_CHAR_T, MARK *, mtype_t));
*/
int
-mark_get(sp, ep, key, mp)
+mark_get(sp, key, mp, mtype)
SCR *sp;
- EXF *ep;
ARG_CHAR_T key;
MARK *mp;
+ mtype_t mtype;
{
LMARK *lmp;
- size_t len;
if (key == ABSMARK2)
key = ABSMARK1;
- lmp = mark_find(sp, ep, key);
+ lmp = mark_find(sp, key);
if (lmp == NULL || lmp->name != key) {
- msgq(sp, M_BERR, "Mark %s: not set", KEY_NAME(sp, key));
+ msgq(sp, mtype, "017|Mark %s: not set", KEY_NAME(sp, key));
return (1);
}
if (F_ISSET(lmp, MARK_DELETED)) {
- msgq(sp, M_BERR,
- "Mark %s: the line was deleted", KEY_NAME(sp, key));
+ msgq(sp, mtype,
+ "018|Mark %s: the line was deleted", KEY_NAME(sp, key));
return (1);
}
- if (file_gline(sp, ep, lmp->lno, &len) == NULL ||
- lmp->cno > len || lmp->cno == len && len != 0) {
- msgq(sp, M_BERR, "Mark %s: cursor position no longer exists",
+
+ /*
+ * !!!
+ * The absolute mark is initialized to lno 1/cno 0, and historically
+ * you could use it in an empty file. Make such a mark always work.
+ */
+ if ((lmp->lno != 1 || lmp->cno != 0) && !db_exist(sp, lmp->lno)) {
+ msgq(sp, mtype,
+ "019|Mark %s: cursor position no longer exists",
KEY_NAME(sp, key));
return (1);
}
@@ -170,11 +151,12 @@ mark_get(sp, ep, key, mp)
/*
* mark_set --
* Set the location referenced by a mark.
+ *
+ * PUBLIC: int mark_set __P((SCR *, ARG_CHAR_T, MARK *, int));
*/
int
-mark_set(sp, ep, key, value, userset)
+mark_set(sp, key, value, userset)
SCR *sp;
- EXF *ep;
ARG_CHAR_T key;
MARK *value;
int userset;
@@ -190,11 +172,11 @@ mark_set(sp, ep, key, value, userset)
* an undo, and we set it if it's not already set or if it was set
* by a previous undo.
*/
- lmp = mark_find(sp, ep, key);
+ lmp = mark_find(sp, key);
if (lmp == NULL || lmp->name != key) {
MALLOC_RET(sp, lmt, LMARK *, sizeof(LMARK));
if (lmp == NULL) {
- LIST_INSERT_HEAD(&ep->marks, lmt, q);
+ LIST_INSERT_HEAD(&sp->ep->marks, lmt, q);
} else
LIST_INSERT_AFTER(lmp, lmt, q);
lmp = lmt;
@@ -215,9 +197,8 @@ mark_set(sp, ep, key, value, userset)
* where it would go.
*/
static LMARK *
-mark_find(sp, ep, key)
+mark_find(sp, key)
SCR *sp;
- EXF *ep;
ARG_CHAR_T key;
{
LMARK *lmp, *lastlmp;
@@ -226,7 +207,7 @@ mark_find(sp, ep, key)
* Return the requested mark or the slot immediately before
* where it should go.
*/
- for (lastlmp = NULL, lmp = ep->marks.lh_first;
+ for (lastlmp = NULL, lmp = sp->ep->marks.lh_first;
lmp != NULL; lastlmp = lmp, lmp = lmp->q.le_next)
if (lmp->name >= key)
return (lmp->name == key ? lmp : lastlmp);
@@ -236,37 +217,61 @@ mark_find(sp, ep, key)
/*
* mark_insdel --
* Update the marks based on an insertion or deletion.
+ *
+ * PUBLIC: int mark_insdel __P((SCR *, lnop_t, recno_t));
*/
-void
-mark_insdel(sp, ep, op, lno)
+int
+mark_insdel(sp, op, lno)
SCR *sp;
- EXF *ep;
- enum operation op;
+ lnop_t op;
recno_t lno;
{
LMARK *lmp;
+ recno_t lline;
switch (op) {
case LINE_APPEND:
- return;
+ /* All insert/append operations are done as inserts. */
+ abort();
case LINE_DELETE:
- for (lmp = ep->marks.lh_first;
+ for (lmp = sp->ep->marks.lh_first;
lmp != NULL; lmp = lmp->q.le_next)
if (lmp->lno >= lno)
if (lmp->lno == lno) {
F_SET(lmp, MARK_DELETED);
- (void)log_mark(sp, ep, lmp);
+ (void)log_mark(sp, lmp);
} else
--lmp->lno;
- return;
+ break;
case LINE_INSERT:
- for (lmp = ep->marks.lh_first;
+ /*
+ * XXX
+ * Very nasty special case. If the file was empty, then we're
+ * adding the first line, which is a replacement. So, we don't
+ * modify the marks. This is a hack to make:
+ *
+ * mz:r!echo foo<carriage-return>'z
+ *
+ * work, i.e. historically you could mark the "line" in an empty
+ * file and replace it, and continue to use the mark. Insane,
+ * well, yes, I know, but someone complained.
+ *
+ * Check for line #2 before going to the end of the file.
+ */
+ if (!db_exist(sp, 2)) {
+ if (db_last(sp, &lline))
+ return (1);
+ if (lline == 1)
+ return (0);
+ }
+
+ for (lmp = sp->ep->marks.lh_first;
lmp != NULL; lmp = lmp->q.le_next)
if (lmp->lno >= lno)
++lmp->lno;
- return;
+ break;
case LINE_RESET:
- return;
+ break;
}
- /* NOTREACHED */
+ return (0);
}
diff --git a/contrib/nvi/common/mark.h b/contrib/nvi/common/mark.h
new file mode 100644
index 000000000000..9c63e183e83f
--- /dev/null
+++ b/contrib/nvi/common/mark.h
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)mark.h 10.3 (Berkeley) 3/6/96
+ */
+
+/*
+ * The MARK and LMARK structures define positions in the file. There are
+ * two structures because the mark subroutines are the only places where
+ * anything cares about something other than line and column.
+ *
+ * Because of the different interfaces used by the db(3) package, curses,
+ * and users, the line number is 1 based and the column number is 0 based.
+ * Additionally, it is known that the out-of-band line number is less than
+ * any legal line number. The line number is of type recno_t, as that's
+ * the underlying type of the database. The column number is of type size_t,
+ * guaranteeing that we can malloc a line.
+ */
+struct _mark {
+#define OOBLNO 0 /* Out-of-band line number. */
+ recno_t lno; /* Line number. */
+ size_t cno; /* Column number. */
+};
+
+struct _lmark {
+ LIST_ENTRY(_lmark) q; /* Linked list of marks. */
+ recno_t lno; /* Line number. */
+ size_t cno; /* Column number. */
+ CHAR_T name; /* Mark name. */
+
+#define MARK_DELETED 0x01 /* Mark was deleted. */
+#define MARK_USERSET 0x02 /* User set this mark. */
+ u_int8_t flags;
+};
+
+#define ABSMARK1 '\'' /* Absolute mark name. */
+#define ABSMARK2 '`' /* Absolute mark name. */
diff --git a/contrib/nvi/common/mem.h b/contrib/nvi/common/mem.h
new file mode 100644
index 000000000000..af42e6bcd1de
--- /dev/null
+++ b/contrib/nvi/common/mem.h
@@ -0,0 +1,168 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)mem.h 10.7 (Berkeley) 3/30/96
+ */
+
+/* Increase the size of a malloc'd buffer. Two versions, one that
+ * returns, one that jumps to an error label.
+ */
+#define BINC_GOTO(sp, lp, llen, nlen) { \
+ void *L__bincp; \
+ if ((nlen) > llen) { \
+ if ((L__bincp = binc(sp, lp, &(llen), nlen)) == NULL) \
+ goto alloc_err; \
+ /* \
+ * !!! \
+ * Possible pointer conversion. \
+ */ \
+ lp = L__bincp; \
+ } \
+}
+#define BINC_RET(sp, lp, llen, nlen) { \
+ void *L__bincp; \
+ if ((nlen) > llen) { \
+ if ((L__bincp = binc(sp, lp, &(llen), nlen)) == NULL) \
+ return (1); \
+ /* \
+ * !!! \
+ * Possible pointer conversion. \
+ */ \
+ lp = L__bincp; \
+ } \
+}
+
+/*
+ * Get some temporary space, preferably from the global temporary buffer,
+ * from a malloc'd buffer otherwise. Two versions, one that returns, one
+ * that jumps to an error label.
+ */
+#define GET_SPACE_GOTO(sp, bp, blen, nlen) { \
+ GS *L__gp = (sp) == NULL ? NULL : (sp)->gp; \
+ if (L__gp == NULL || F_ISSET(L__gp, G_TMP_INUSE)) { \
+ bp = NULL; \
+ blen = 0; \
+ BINC_GOTO(sp, bp, blen, nlen); \
+ } else { \
+ BINC_GOTO(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen); \
+ bp = L__gp->tmp_bp; \
+ blen = L__gp->tmp_blen; \
+ F_SET(L__gp, G_TMP_INUSE); \
+ } \
+}
+#define GET_SPACE_RET(sp, bp, blen, nlen) { \
+ GS *L__gp = (sp) == NULL ? NULL : (sp)->gp; \
+ if (L__gp == NULL || F_ISSET(L__gp, G_TMP_INUSE)) { \
+ bp = NULL; \
+ blen = 0; \
+ BINC_RET(sp, bp, blen, nlen); \
+ } else { \
+ BINC_RET(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen); \
+ bp = L__gp->tmp_bp; \
+ blen = L__gp->tmp_blen; \
+ F_SET(L__gp, G_TMP_INUSE); \
+ } \
+}
+
+/*
+ * Add space to a GET_SPACE returned buffer. Two versions, one that
+ * returns, one that jumps to an error label.
+ */
+#define ADD_SPACE_GOTO(sp, bp, blen, nlen) { \
+ GS *L__gp = (sp) == NULL ? NULL : (sp)->gp; \
+ if (L__gp == NULL || bp == L__gp->tmp_bp) { \
+ F_CLR(L__gp, G_TMP_INUSE); \
+ BINC_GOTO(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen); \
+ bp = L__gp->tmp_bp; \
+ blen = L__gp->tmp_blen; \
+ F_SET(L__gp, G_TMP_INUSE); \
+ } else \
+ BINC_GOTO(sp, bp, blen, nlen); \
+}
+#define ADD_SPACE_RET(sp, bp, blen, nlen) { \
+ GS *L__gp = (sp) == NULL ? NULL : (sp)->gp; \
+ if (L__gp == NULL || bp == L__gp->tmp_bp) { \
+ F_CLR(L__gp, G_TMP_INUSE); \
+ BINC_RET(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen); \
+ bp = L__gp->tmp_bp; \
+ blen = L__gp->tmp_blen; \
+ F_SET(L__gp, G_TMP_INUSE); \
+ } else \
+ BINC_RET(sp, bp, blen, nlen); \
+}
+
+/* Free a GET_SPACE returned buffer. */
+#define FREE_SPACE(sp, bp, blen) { \
+ GS *L__gp = (sp) == NULL ? NULL : (sp)->gp; \
+ if (L__gp != NULL && bp == L__gp->tmp_bp) \
+ F_CLR(L__gp, G_TMP_INUSE); \
+ else \
+ free(bp); \
+}
+
+/*
+ * Malloc a buffer, casting the return pointer. Various versions.
+ *
+ * !!!
+ * The cast should be unnecessary, malloc(3) and friends return void *'s,
+ * which is all we need. However, some systems that nvi needs to run on
+ * don't do it right yet, resulting in the compiler printing out roughly
+ * a million warnings. After awhile, it seemed easier to put the casts
+ * in instead of explaining it all the time.
+ */
+#define CALLOC(sp, p, cast, nmemb, size) { \
+ if ((p = (cast)calloc(nmemb, size)) == NULL) \
+ msgq(sp, M_SYSERR, NULL); \
+}
+#define CALLOC_GOTO(sp, p, cast, nmemb, size) { \
+ if ((p = (cast)calloc(nmemb, size)) == NULL) \
+ goto alloc_err; \
+}
+#define CALLOC_NOMSG(sp, p, cast, nmemb, size) { \
+ p = (cast)calloc(nmemb, size); \
+}
+#define CALLOC_RET(sp, p, cast, nmemb, size) { \
+ if ((p = (cast)calloc(nmemb, size)) == NULL) { \
+ msgq(sp, M_SYSERR, NULL); \
+ return (1); \
+ } \
+}
+
+#define MALLOC(sp, p, cast, size) { \
+ if ((p = (cast)malloc(size)) == NULL) \
+ msgq(sp, M_SYSERR, NULL); \
+}
+#define MALLOC_GOTO(sp, p, cast, size) { \
+ if ((p = (cast)malloc(size)) == NULL) \
+ goto alloc_err; \
+}
+#define MALLOC_NOMSG(sp, p, cast, size) { \
+ p = (cast)malloc(size); \
+}
+#define MALLOC_RET(sp, p, cast, size) { \
+ if ((p = (cast)malloc(size)) == NULL) { \
+ msgq(sp, M_SYSERR, NULL); \
+ return (1); \
+ } \
+}
+/*
+ * XXX
+ * Don't depend on realloc(NULL, size) working.
+ */
+#define REALLOC(sp, p, cast, size) { \
+ if ((p = (cast)(p == NULL ? \
+ malloc(size) : realloc(p, size))) == NULL) \
+ msgq(sp, M_SYSERR, NULL); \
+}
+
+/*
+ * Versions of memmove(3) and memset(3) that use the size of the
+ * initial pointer to figure out how much memory to manipulate.
+ */
+#define MEMMOVE(p, t, len) memmove(p, t, (len) * sizeof(*(p)))
+#define MEMSET(p, value, len) memset(p, value, (len) * sizeof(*(p)))
diff --git a/contrib/nvi/common/msg.c b/contrib/nvi/common/msg.c
new file mode 100644
index 000000000000..2b18082c7ab8
--- /dev/null
+++ b/contrib/nvi/common/msg.c
@@ -0,0 +1,895 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)msg.c 10.48 (Berkeley) 9/15/96";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/types.h> /* XXX: param.h may not have included types.h */
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "common.h"
+#include "../vi/vi.h"
+
+/*
+ * msgq --
+ * Display a message.
+ *
+ * PUBLIC: void msgq __P((SCR *, mtype_t, const char *, ...));
+ */
+void
+#ifdef __STDC__
+msgq(SCR *sp, mtype_t mt, const char *fmt, ...)
+#else
+msgq(sp, mt, fmt, va_alist)
+ SCR *sp;
+ mtype_t mt;
+ const char *fmt;
+ va_dcl
+#endif
+{
+#ifndef NL_ARGMAX
+#define __NL_ARGMAX 20 /* Set to 9 by System V. */
+ struct {
+ const char *str; /* String pointer. */
+ size_t arg; /* Argument number. */
+ size_t prefix; /* Prefix string length. */
+ size_t skip; /* Skipped string length. */
+ size_t suffix; /* Suffix string length. */
+ } str[__NL_ARGMAX];
+#endif
+ static int reenter; /* STATIC: Re-entrancy check. */
+ CHAR_T ch;
+ GS *gp;
+ size_t blen, cnt1, cnt2, len, mlen, nlen, soff;
+ const char *p, *t, *u;
+ char *bp, *mp, *rbp, *s_rbp;
+ va_list ap;
+
+ /*
+ * !!!
+ * It's possible to enter msg when there's no screen to hold the
+ * message. If sp is NULL, ignore the special cases and put the
+ * message out to stderr.
+ */
+ if (sp == NULL) {
+ gp = NULL;
+ if (mt == M_BERR)
+ mt = M_ERR;
+ else if (mt == M_VINFO)
+ mt = M_INFO;
+ } else {
+ gp = sp->gp;
+ switch (mt) {
+ case M_BERR:
+ if (F_ISSET(sp, SC_VI) && !O_ISSET(sp, O_VERBOSE)) {
+ F_SET(gp, G_BELLSCHED);
+ return;
+ }
+ mt = M_ERR;
+ break;
+ case M_VINFO:
+ if (!O_ISSET(sp, O_VERBOSE))
+ return;
+ mt = M_INFO;
+ /* FALLTHROUGH */
+ case M_INFO:
+ if (F_ISSET(sp, SC_EX_SILENT))
+ return;
+ break;
+ case M_ERR:
+ case M_SYSERR:
+ break;
+ default:
+ abort();
+ }
+ }
+
+ /*
+ * It's possible to reenter msg when it allocates space. We're
+ * probably dead anyway, but there's no reason to drop core.
+ *
+ * XXX
+ * Yes, there's a race, but it should only be two instructions.
+ */
+ if (reenter++)
+ return;
+
+ /* Get space for the message. */
+ nlen = 1024;
+ if (0) {
+retry: FREE_SPACE(sp, bp, blen);
+ nlen *= 2;
+ }
+ bp = NULL;
+ blen = 0;
+ GET_SPACE_GOTO(sp, bp, blen, nlen);
+
+ /*
+ * Error prefix.
+ *
+ * mp: pointer to the current next character to be written
+ * mlen: length of the already written characters
+ * blen: total length of the buffer
+ */
+#define REM (blen - mlen)
+ mp = bp;
+ mlen = 0;
+ if (mt == M_SYSERR) {
+ p = msg_cat(sp, "020|Error: ", &len);
+ if (REM < len)
+ goto retry;
+ memcpy(mp, p, len);
+ mp += len;
+ mlen += len;
+ }
+
+ /*
+ * If we're running an ex command that the user didn't enter, display
+ * the file name and line number prefix.
+ */
+ if ((mt == M_ERR || mt == M_SYSERR) &&
+ sp != NULL && gp != NULL && gp->if_name != NULL) {
+ for (p = gp->if_name; *p != '\0'; ++p) {
+ len = snprintf(mp, REM, "%s", KEY_NAME(sp, *p));
+ mp += len;
+ if ((mlen += len) > blen)
+ goto retry;
+ }
+ len = snprintf(mp, REM, ", %d: ", gp->if_lno);
+ mp += len;
+ if ((mlen += len) > blen)
+ goto retry;
+ }
+
+ /* If nothing to format, we're done. */
+ if (fmt == NULL)
+ goto nofmt;
+ fmt = msg_cat(sp, fmt, NULL);
+
+#ifndef NL_ARGMAX
+ /*
+ * Nvi should run on machines that don't support the numbered argument
+ * specifications (%[digit]*$). We do this by reformatting the string
+ * so that we can hand it to vsprintf(3) and it will use the arguments
+ * in the right order. When vsprintf returns, we put the string back
+ * into the right order. It's undefined, according to SVID III, to mix
+ * numbered argument specifications with the standard style arguments,
+ * so this should be safe.
+ *
+ * In addition, we also need a character that is known to not occur in
+ * any vi message, for separating the parts of the string. As callers
+ * of msgq are responsible for making sure that all the non-printable
+ * characters are formatted for printing before calling msgq, we use a
+ * random non-printable character selected at terminal initialization
+ * time. This code isn't fast by any means, but as messages should be
+ * relatively short and normally have only a few arguments, it won't be
+ * too bad. Regardless, nobody has come up with any other solution.
+ *
+ * The result of this loop is an array of pointers into the message
+ * string, with associated lengths and argument numbers. The array
+ * is in the "correct" order, and the arg field contains the argument
+ * order.
+ */
+ for (p = fmt, soff = 0; soff < __NL_ARGMAX;) {
+ for (t = p; *p != '\0' && *p != '%'; ++p);
+ if (*p == '\0')
+ break;
+ ++p;
+ if (!isdigit(*p)) {
+ if (*p == '%')
+ ++p;
+ continue;
+ }
+ for (u = p; *++p != '\0' && isdigit(*p););
+ if (*p != '$')
+ continue;
+
+ /* Up to, and including the % character. */
+ str[soff].str = t;
+ str[soff].prefix = u - t;
+
+ /* Up to, and including the $ character. */
+ str[soff].arg = atoi(u);
+ str[soff].skip = (p - u) + 1;
+ if (str[soff].arg >= __NL_ARGMAX)
+ goto ret;
+
+ /* Up to, and including the conversion character. */
+ for (u = p; (ch = *++p) != '\0';)
+ if (isalpha(ch) &&
+ strchr("diouxXfeEgGcspn", ch) != NULL)
+ break;
+ str[soff].suffix = p - u;
+ if (ch != '\0')
+ ++p;
+ ++soff;
+ }
+
+ /* If no magic strings, we're done. */
+ if (soff == 0)
+ goto format;
+
+ /* Get space for the reordered strings. */
+ if ((rbp = malloc(nlen)) == NULL)
+ goto ret;
+ s_rbp = rbp;
+
+ /*
+ * Reorder the strings into the message string based on argument
+ * order.
+ *
+ * !!!
+ * We ignore arguments that are out of order, i.e. if we don't find
+ * an argument, we continue. Assume (almost certainly incorrectly)
+ * that whoever created the string knew what they were doing.
+ *
+ * !!!
+ * Brute force "sort", but since we don't expect more than one or two
+ * arguments in a string, the setup cost of a fast sort will be more
+ * expensive than the loop.
+ */
+ for (cnt1 = 1; cnt1 <= soff; ++cnt1)
+ for (cnt2 = 0; cnt2 < soff; ++cnt2)
+ if (cnt1 == str[cnt2].arg) {
+ memmove(s_rbp, str[cnt2].str, str[cnt2].prefix);
+ memmove(s_rbp + str[cnt2].prefix,
+ str[cnt2].str + str[cnt2].prefix +
+ str[cnt2].skip, str[cnt2].suffix);
+ s_rbp += str[cnt2].prefix + str[cnt2].suffix;
+ *s_rbp++ =
+ gp == NULL ? DEFAULT_NOPRINT : gp->noprint;
+ break;
+ }
+ *s_rbp = '\0';
+ fmt = rbp;
+#endif
+
+format: /* Format the arguments into the string. */
+#ifdef __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ len = vsnprintf(mp, REM, fmt, ap);
+ va_end(ap);
+ if (len >= nlen)
+ goto retry;
+
+#ifndef NL_ARGMAX
+ if (soff == 0)
+ goto nofmt;
+
+ /*
+ * Go through the resulting string, and, for each separator character
+ * separated string, enter its new starting position and length in the
+ * array.
+ */
+ for (p = t = mp, cnt1 = 1,
+ ch = gp == NULL ? DEFAULT_NOPRINT : gp->noprint; *p != '\0'; ++p)
+ if (*p == ch) {
+ for (cnt2 = 0; cnt2 < soff; ++cnt2)
+ if (str[cnt2].arg == cnt1)
+ break;
+ str[cnt2].str = t;
+ str[cnt2].prefix = p - t;
+ t = p + 1;
+ ++cnt1;
+ }
+
+ /*
+ * Reorder the strings once again, putting them back into the
+ * message buffer.
+ *
+ * !!!
+ * Note, the length of the message gets decremented once for
+ * each substring, when we discard the separator character.
+ */
+ for (s_rbp = rbp, cnt1 = 0; cnt1 < soff; ++cnt1) {
+ memmove(rbp, str[cnt1].str, str[cnt1].prefix);
+ rbp += str[cnt1].prefix;
+ --len;
+ }
+ memmove(mp, s_rbp, rbp - s_rbp);
+
+ /* Free the reordered string memory. */
+ free(s_rbp);
+#endif
+
+nofmt: mp += len;
+ if ((mlen += len) > blen)
+ goto retry;
+ if (mt == M_SYSERR) {
+ len = snprintf(mp, REM, ": %s", strerror(errno));
+ mp += len;
+ if ((mlen += len) > blen)
+ goto retry;
+ mt = M_ERR;
+ }
+
+ /* Add trailing newline. */
+ if ((mlen += 1) > blen)
+ goto retry;
+ *mp = '\n';
+
+ if (sp != NULL)
+ (void)ex_fflush(sp);
+ if (gp != NULL)
+ gp->scr_msg(sp, mt, bp, mlen);
+ else
+ (void)fprintf(stderr, "%.*s", (int)mlen, bp);
+
+ /* Cleanup. */
+ret: FREE_SPACE(sp, bp, blen);
+alloc_err:
+ reenter = 0;
+}
+
+/*
+ * msgq_str --
+ * Display a message with an embedded string.
+ *
+ * PUBLIC: void msgq_str __P((SCR *, mtype_t, char *, char *));
+ */
+void
+msgq_str(sp, mtype, str, fmt)
+ SCR *sp;
+ mtype_t mtype;
+ char *str, *fmt;
+{
+ int nf, sv_errno;
+ char *p;
+
+ if (str == NULL) {
+ msgq(sp, mtype, fmt);
+ return;
+ }
+
+ sv_errno = errno;
+ p = msg_print(sp, str, &nf);
+ errno = sv_errno;
+ msgq(sp, mtype, fmt, p);
+ if (nf)
+ FREE_SPACE(sp, p, 0);
+}
+
+/*
+ * mod_rpt --
+ * Report on the lines that changed.
+ *
+ * !!!
+ * Historic vi documentation (USD:15-8) claimed that "The editor will also
+ * always tell you when a change you make affects text which you cannot see."
+ * This wasn't true -- edit a large file and do "100d|1". We don't implement
+ * this semantic since it requires tracking each line that changes during a
+ * command instead of just keeping count.
+ *
+ * Line counts weren't right in historic vi, either. For example, given the
+ * file:
+ * abc
+ * def
+ * the command 2d}, from the 'b' would report that two lines were deleted,
+ * not one.
+ *
+ * PUBLIC: void mod_rpt __P((SCR *));
+ */
+void
+mod_rpt(sp)
+ SCR *sp;
+{
+ static char * const action[] = {
+ "293|added",
+ "294|changed",
+ "295|deleted",
+ "296|joined",
+ "297|moved",
+ "298|shifted",
+ "299|yanked",
+ };
+ static char * const lines[] = {
+ "300|line",
+ "301|lines",
+ };
+ recno_t total;
+ u_long rptval;
+ int first, cnt;
+ size_t blen, len, tlen;
+ const char *t;
+ char * const *ap;
+ char *bp, *p;
+
+ /* Change reports are turned off in batch mode. */
+ if (F_ISSET(sp, SC_EX_SILENT))
+ return;
+
+ /* Reset changing line number. */
+ sp->rptlchange = OOBLNO;
+
+ /*
+ * Don't build a message if not enough changed.
+ *
+ * !!!
+ * And now, a vi clone test. Historically, vi reported if the number
+ * of changed lines was > than the value, not >=, unless it was a yank
+ * command, which used >=. No lie. Furthermore, an action was never
+ * reported for a single line action. This is consistent for actions
+ * other than yank, but yank didn't report single line actions even if
+ * the report edit option was set to 1. In addition, setting report to
+ * 0 in the 4BSD historic vi was equivalent to setting it to 1, for an
+ * unknown reason (this bug was fixed in System III/V at some point).
+ * I got complaints, so nvi conforms to System III/V historic practice
+ * except that we report a yank of 1 line if report is set to 1.
+ */
+#define ARSIZE(a) sizeof(a) / sizeof (*a)
+#define MAXNUM 25
+ rptval = O_VAL(sp, O_REPORT);
+ for (cnt = 0, total = 0; cnt < ARSIZE(action); ++cnt)
+ total += sp->rptlines[cnt];
+ if (total == 0)
+ return;
+ if (total <= rptval && sp->rptlines[L_YANKED] < rptval) {
+ for (cnt = 0; cnt < ARSIZE(action); ++cnt)
+ sp->rptlines[cnt] = 0;
+ return;
+ }
+
+ /* Build and display the message. */
+ GET_SPACE_GOTO(sp, bp, blen, sizeof(action) * MAXNUM + 1);
+ for (p = bp, first = 1, tlen = 0,
+ ap = action, cnt = 0; cnt < ARSIZE(action); ++ap, ++cnt)
+ if (sp->rptlines[cnt] != 0) {
+ if (first)
+ first = 0;
+ else {
+ *p++ = ';';
+ *p++ = ' ';
+ tlen += 2;
+ }
+ len = snprintf(p, MAXNUM, "%lu ", sp->rptlines[cnt]);
+ p += len;
+ tlen += len;
+ t = msg_cat(sp,
+ lines[sp->rptlines[cnt] == 1 ? 0 : 1], &len);
+ memcpy(p, t, len);
+ p += len;
+ tlen += len;
+ *p++ = ' ';
+ ++tlen;
+ t = msg_cat(sp, *ap, &len);
+ memcpy(p, t, len);
+ p += len;
+ tlen += len;
+ sp->rptlines[cnt] = 0;
+ }
+
+ /* Add trailing newline. */
+ *p = '\n';
+ ++tlen;
+
+ (void)ex_fflush(sp);
+ sp->gp->scr_msg(sp, M_INFO, bp, tlen);
+
+ FREE_SPACE(sp, bp, blen);
+alloc_err:
+ return;
+
+#undef ARSIZE
+#undef MAXNUM
+}
+
+/*
+ * msgq_status --
+ * Report on the file's status.
+ *
+ * PUBLIC: void msgq_status __P((SCR *, recno_t, u_int));
+ */
+void
+msgq_status(sp, lno, flags)
+ SCR *sp;
+ recno_t lno;
+ u_int flags;
+{
+ static int poisoned;
+ recno_t last;
+ size_t blen, len;
+ int cnt, needsep;
+ const char *t;
+ char **ap, *bp, *np, *p, *s;
+
+ /* Get sufficient memory. */
+ len = strlen(sp->frp->name);
+ GET_SPACE_GOTO(sp, bp, blen, len * MAX_CHARACTER_COLUMNS + 128);
+ p = bp;
+
+ /* Copy in the filename. */
+ for (p = bp, t = sp->frp->name; *t != '\0'; ++t) {
+ len = KEY_LEN(sp, *t);
+ memcpy(p, KEY_NAME(sp, *t), len);
+ p += len;
+ }
+ np = p;
+ *p++ = ':';
+ *p++ = ' ';
+
+ /* Copy in the argument count. */
+ if (F_ISSET(sp, SC_STATUS_CNT) && sp->argv != NULL) {
+ for (cnt = 0, ap = sp->argv; *ap != NULL; ++ap, ++cnt);
+ if (cnt > 1) {
+ (void)sprintf(p,
+ msg_cat(sp, "317|%d files to edit", NULL), cnt);
+ p += strlen(p);
+ *p++ = ':';
+ *p++ = ' ';
+ }
+ F_CLR(sp, SC_STATUS_CNT);
+ }
+
+ /*
+ * See nvi/exf.c:file_init() for a description of how and when the
+ * read-only bit is set.
+ *
+ * !!!
+ * The historic display for "name changed" was "[Not edited]".
+ */
+ needsep = 0;
+ if (F_ISSET(sp->frp, FR_NEWFILE)) {
+ F_CLR(sp->frp, FR_NEWFILE);
+ t = msg_cat(sp, "021|new file", &len);
+ memcpy(p, t, len);
+ p += len;
+ needsep = 1;
+ } else {
+ if (F_ISSET(sp->frp, FR_NAMECHANGE)) {
+ t = msg_cat(sp, "022|name changed", &len);
+ memcpy(p, t, len);
+ p += len;
+ needsep = 1;
+ }
+ if (needsep) {
+ *p++ = ',';
+ *p++ = ' ';
+ }
+ if (F_ISSET(sp->ep, F_MODIFIED))
+ t = msg_cat(sp, "023|modified", &len);
+ else
+ t = msg_cat(sp, "024|unmodified", &len);
+ memcpy(p, t, len);
+ p += len;
+ needsep = 1;
+ }
+ if (F_ISSET(sp->frp, FR_UNLOCKED)) {
+ if (needsep) {
+ *p++ = ',';
+ *p++ = ' ';
+ }
+ t = msg_cat(sp, "025|UNLOCKED", &len);
+ memcpy(p, t, len);
+ p += len;
+ needsep = 1;
+ }
+ if (O_ISSET(sp, O_READONLY)) {
+ if (needsep) {
+ *p++ = ',';
+ *p++ = ' ';
+ }
+ t = msg_cat(sp, "026|readonly", &len);
+ memcpy(p, t, len);
+ p += len;
+ needsep = 1;
+ }
+ if (needsep) {
+ *p++ = ':';
+ *p++ = ' ';
+ }
+ if (LF_ISSET(MSTAT_SHOWLAST)) {
+ if (db_last(sp, &last))
+ return;
+ if (last == 0) {
+ t = msg_cat(sp, "028|empty file", &len);
+ memcpy(p, t, len);
+ p += len;
+ } else {
+ t = msg_cat(sp, "027|line %lu of %lu [%ld%%]", &len);
+ (void)sprintf(p, t, lno, last, (lno * 100) / last);
+ p += strlen(p);
+ }
+ } else {
+ t = msg_cat(sp, "029|line %lu", &len);
+ (void)sprintf(p, t, lno);
+ p += strlen(p);
+ }
+#ifdef DEBUG
+ (void)sprintf(p, " (pid %lu)", (u_long)getpid());
+ p += strlen(p);
+#endif
+ *p++ = '\n';
+ len = p - bp;
+
+ /*
+ * There's a nasty problem with long path names. Cscope and tags files
+ * can result in long paths and vi will request a continuation key from
+ * the user as soon as it starts the screen. Unfortunately, the user
+ * has already typed ahead, and chaos results. If we assume that the
+ * characters in the filenames and informational messages only take a
+ * single screen column each, we can trim the filename.
+ *
+ * XXX
+ * Status lines get put up at fairly awkward times. For example, when
+ * you do a filter read (e.g., :read ! echo foo) in the top screen of a
+ * split screen, we have to repaint the status lines for all the screens
+ * below the top screen. We don't want users having to enter continue
+ * characters for those screens. Make it really hard to screw this up.
+ */
+ s = bp;
+ if (LF_ISSET(MSTAT_TRUNCATE) && len > sp->cols) {
+ for (; s < np && (*s != '/' || (p - s) > sp->cols - 3); ++s);
+ if (s == np) {
+ s = p - (sp->cols - 5);
+ *--s = ' ';
+ }
+ *--s = '.';
+ *--s = '.';
+ *--s = '.';
+ len = p - s;
+ }
+
+ /* Flush any waiting ex messages. */
+ (void)ex_fflush(sp);
+
+ sp->gp->scr_msg(sp, M_INFO, s, len);
+
+ FREE_SPACE(sp, bp, blen);
+alloc_err:
+ return;
+}
+
+/*
+ * msg_open --
+ * Open the message catalogs.
+ *
+ * PUBLIC: int msg_open __P((SCR *, char *));
+ */
+int
+msg_open(sp, file)
+ SCR *sp;
+ char *file;
+{
+ /*
+ * !!!
+ * Assume that the first file opened is the system default, and that
+ * all subsequent ones user defined. Only display error messages
+ * if we can't open the user defined ones -- it's useful to know if
+ * the system one wasn't there, but if nvi is being shipped with an
+ * installed system, the file will be there, if it's not, then the
+ * message will be repeated every time nvi is started up.
+ */
+ static int first = 1;
+ DB *db;
+ DBT data, key;
+ recno_t msgno;
+ char *p, *t, buf[MAXPATHLEN];
+
+ if ((p = strrchr(file, '/')) != NULL && p[1] == '\0' &&
+ ((t = getenv("LC_MESSAGES")) != NULL && t[0] != '\0' ||
+ (t = getenv("LANG")) != NULL && t[0] != '\0')) {
+ (void)snprintf(buf, sizeof(buf), "%s%s", file, t);
+ p = buf;
+ } else
+ p = file;
+ if ((db = dbopen(p,
+ O_NONBLOCK | O_RDONLY, 0, DB_RECNO, NULL)) == NULL) {
+ if (first) {
+ first = 0;
+ return (1);
+ }
+ msgq_str(sp, M_SYSERR, p, "%s");
+ return (1);
+ }
+
+ /*
+ * Test record 1 for the magic string. The msgq call is here so
+ * the message catalog build finds it.
+ */
+#define VMC "VI_MESSAGE_CATALOG"
+ key.data = &msgno;
+ key.size = sizeof(recno_t);
+ msgno = 1;
+ if (db->get(db, &key, &data, 0) != 0 ||
+ data.size != sizeof(VMC) - 1 ||
+ memcmp(data.data, VMC, sizeof(VMC) - 1)) {
+ (void)db->close(db);
+ if (first) {
+ first = 0;
+ return (1);
+ }
+ msgq_str(sp, M_ERR, p,
+ "030|The file %s is not a message catalog");
+ return (1);
+ }
+ first = 0;
+
+ if (sp->gp->msg != NULL)
+ (void)sp->gp->msg->close(sp->gp->msg);
+ sp->gp->msg = db;
+ return (0);
+}
+
+/*
+ * msg_close --
+ * Close the message catalogs.
+ *
+ * PUBLIC: void msg_close __P((GS *));
+ */
+void
+msg_close(gp)
+ GS *gp;
+{
+ if (gp->msg != NULL)
+ (void)gp->msg->close(gp->msg);
+}
+
+/*
+ * msg_cont --
+ * Return common continuation messages.
+ *
+ * PUBLIC: const char *msg_cmsg __P((SCR *, cmsg_t, size_t *));
+ */
+const char *
+msg_cmsg(sp, which, lenp)
+ SCR *sp;
+ cmsg_t which;
+ size_t *lenp;
+{
+ switch (which) {
+ case CMSG_CONF:
+ return (msg_cat(sp, "268|confirm? [ynq]", lenp));
+ case CMSG_CONT:
+ return (msg_cat(sp, "269|Press any key to continue: ", lenp));
+ case CMSG_CONT_EX:
+ return (msg_cat(sp,
+ "270|Press any key to continue [: to enter more ex commands]: ",
+ lenp));
+ case CMSG_CONT_R:
+ return (msg_cat(sp, "161|Press Enter to continue: ", lenp));
+ case CMSG_CONT_S:
+ return (msg_cat(sp, "275| cont?", lenp));
+ case CMSG_CONT_Q:
+ return (msg_cat(sp,
+ "271|Press any key to continue [q to quit]: ", lenp));
+ default:
+ abort();
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * msg_cat --
+ * Return a single message from the catalog, plus its length.
+ *
+ * !!!
+ * Only a single catalog message can be accessed at a time, if multiple
+ * ones are needed, they must be copied into local memory.
+ *
+ * PUBLIC: const char *msg_cat __P((SCR *, const char *, size_t *));
+ */
+const char *
+msg_cat(sp, str, lenp)
+ SCR *sp;
+ const char *str;
+ size_t *lenp;
+{
+ GS *gp;
+ DBT data, key;
+ recno_t msgno;
+
+ /*
+ * If it's not a catalog message, i.e. has doesn't have a leading
+ * number and '|' symbol, we're done.
+ */
+ if (isdigit(str[0]) &&
+ isdigit(str[1]) && isdigit(str[2]) && str[3] == '|') {
+ key.data = &msgno;
+ key.size = sizeof(recno_t);
+ msgno = atoi(str);
+
+ /*
+ * XXX
+ * Really sleazy hack -- we put an extra character on the
+ * end of the format string, and then we change it to be
+ * the nul termination of the string. There ought to be
+ * a better way. Once we can allocate multiple temporary
+ * memory buffers, maybe we can use one of them instead.
+ */
+ gp = sp == NULL ? NULL : sp->gp;
+ if (gp != NULL && gp->msg != NULL &&
+ gp->msg->get(gp->msg, &key, &data, 0) == 0 &&
+ data.size != 0) {
+ if (lenp != NULL)
+ *lenp = data.size - 1;
+ ((char *)data.data)[data.size - 1] = '\0';
+ return (data.data);
+ }
+ str = &str[4];
+ }
+ if (lenp != NULL)
+ *lenp = strlen(str);
+ return (str);
+}
+
+/*
+ * msg_print --
+ * Return a printable version of a string, in allocated memory.
+ *
+ * PUBLIC: char *msg_print __P((SCR *, const char *, int *));
+ */
+char *
+msg_print(sp, s, needfree)
+ SCR *sp;
+ const char *s;
+ int *needfree;
+{
+ size_t blen, nlen;
+ const char *cp;
+ char *bp, *ep, *p, *t;
+
+ *needfree = 0;
+
+ for (cp = s; *cp != '\0'; ++cp)
+ if (!isprint(*cp))
+ break;
+ if (*cp == '\0')
+ return ((char *)s); /* SAFE: needfree set to 0. */
+
+ nlen = 0;
+ if (0) {
+retry: if (sp == NULL)
+ free(bp);
+ else
+ FREE_SPACE(sp, bp, blen);
+ needfree = 0;
+ }
+ nlen += 256;
+ if (sp == NULL) {
+ if ((bp = malloc(nlen)) == NULL)
+ goto alloc_err;
+ } else
+ GET_SPACE_GOTO(sp, bp, blen, nlen);
+ if (0) {
+alloc_err: return ("");
+ }
+ *needfree = 1;
+
+ for (p = bp, ep = (bp + blen) - 1, cp = s; *cp != '\0' && p < ep; ++cp)
+ for (t = KEY_NAME(sp, *cp); *t != '\0' && p < ep; *p++ = *t++);
+ if (p == ep)
+ goto retry;
+ *p = '\0';
+ return (bp);
+}
diff --git a/contrib/nvi/common/msg.h b/contrib/nvi/common/msg.h
new file mode 100644
index 000000000000..b10f4ccae5c6
--- /dev/null
+++ b/contrib/nvi/common/msg.h
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)msg.h 10.10 (Berkeley) 5/10/96
+ */
+
+/*
+ * Common messages (continuation or confirmation).
+ */
+typedef enum {
+ CMSG_CONF, CMSG_CONT, CMSG_CONT_EX,
+ CMSG_CONT_R, CMSG_CONT_S, CMSG_CONT_Q } cmsg_t;
+
+/*
+ * Message types.
+ *
+ * !!!
+ * In historical vi, O_VERBOSE didn't exist, and O_TERSE made the error
+ * messages shorter. In this implementation, O_TERSE has no effect and
+ * O_VERBOSE results in informational displays about common errors, for
+ * naive users.
+ *
+ * M_NONE Display to the user, no reformatting, no nothing.
+ *
+ * M_BERR Error: M_ERR if O_VERBOSE, else bell.
+ * M_ERR Error: Display in inverse video.
+ * M_INFO Info: Display in normal video.
+ * M_SYSERR Error: M_ERR, using strerror(3) message.
+ * M_VINFO Info: M_INFO if O_VERBOSE, else ignore.
+ *
+ * The underlying message display routines only need to know about M_NONE,
+ * M_ERR and M_INFO -- all the other message types are converted into one
+ * of them by the message routines.
+ */
+typedef enum {
+ M_NONE = 1, M_BERR, M_ERR, M_INFO, M_SYSERR, M_VINFO } mtype_t;
+
+/*
+ * There are major problems with error messages being generated by routines
+ * preparing the screen to display error messages. It's possible for the
+ * editor to generate messages before we have a screen in which to display
+ * them, or during the transition between ex (and vi startup) and a true vi.
+ * There's a queue in the global area to hold them.
+ *
+ * If SC_EX/SC_VI is set, that's the mode that the editor is in. If the flag
+ * S_SCREEN_READY is set, that means that the screen is prepared to display
+ * messages.
+ */
+typedef struct _msgh MSGH; /* MSGS list head structure. */
+LIST_HEAD(_msgh, _msg);
+struct _msg {
+ LIST_ENTRY(_msg) q; /* Linked list of messages. */
+ mtype_t mtype; /* Message type: M_NONE, M_ERR, M_INFO. */
+ char *buf; /* Message buffer. */
+ size_t len; /* Message length. */
+};
+
+/* Flags to msgq_status(). */
+#define MSTAT_SHOWLAST 0x01 /* Show the line number of the last line. */
+#define MSTAT_TRUNCATE 0x02 /* Truncate the file name if it's too long. */
diff --git a/usr.bin/vi/common/options.awk b/contrib/nvi/common/options.awk
index a6755d9045d2..0c91f0718f07 100644
--- a/usr.bin/vi/common/options.awk
+++ b/contrib/nvi/common/options.awk
@@ -1,4 +1,4 @@
-# @(#)options.awk 8.1 (Berkeley) 4/17/94
+# @(#)options.awk 10.1 (Berkeley) 6/8/95
/^\/\* O_[0-9A-Z_]*/ {
printf("#define %s %d\n", $2, cnt++);
diff --git a/contrib/nvi/common/options.c b/contrib/nvi/common/options.c
new file mode 100644
index 000000000000..973778c78bbd
--- /dev/null
+++ b/contrib/nvi/common/options.c
@@ -0,0 +1,1141 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)options.c 10.51 (Berkeley) 10/14/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "../vi/vi.h"
+#include "pathnames.h"
+
+static int opts_abbcmp __P((const void *, const void *));
+static int opts_cmp __P((const void *, const void *));
+static int opts_print __P((SCR *, OPTLIST const *));
+
+/*
+ * O'Reilly noted options and abbreviations are from "Learning the VI Editor",
+ * Fifth Edition, May 1992. There's no way of knowing what systems they are
+ * actually from.
+ *
+ * HPUX noted options and abbreviations are from "The Ultimate Guide to the
+ * VI and EX Text Editors", 1990.
+ */
+OPTLIST const optlist[] = {
+/* O_ALTWERASE 4.4BSD */
+ {"altwerase", f_altwerase, OPT_0BOOL, 0},
+/* O_AUTOINDENT 4BSD */
+ {"autoindent", NULL, OPT_0BOOL, 0},
+/* O_AUTOPRINT 4BSD */
+ {"autoprint", NULL, OPT_1BOOL, 0},
+/* O_AUTOWRITE 4BSD */
+ {"autowrite", NULL, OPT_0BOOL, 0},
+/* O_BACKUP 4.4BSD */
+ {"backup", NULL, OPT_STR, 0},
+/* O_BEAUTIFY 4BSD */
+ {"beautify", NULL, OPT_0BOOL, 0},
+/* O_CDPATH 4.4BSD */
+ {"cdpath", NULL, OPT_STR, 0},
+/* O_CEDIT 4.4BSD */
+ {"cedit", NULL, OPT_STR, 0},
+/* O_COLUMNS 4.4BSD */
+ {"columns", f_columns, OPT_NUM, OPT_NOSAVE},
+/* O_COMMENT 4.4BSD */
+ {"comment", NULL, OPT_0BOOL, 0},
+/* O_DIRECTORY 4BSD */
+ {"directory", NULL, OPT_STR, 0},
+/* O_EDCOMPATIBLE 4BSD */
+ {"edcompatible",NULL, OPT_0BOOL, 0},
+/* O_ESCAPETIME 4.4BSD */
+ {"escapetime", NULL, OPT_NUM, 0},
+/* O_ERRORBELLS 4BSD */
+ {"errorbells", NULL, OPT_0BOOL, 0},
+/* O_EXRC System V (undocumented) */
+ {"exrc", NULL, OPT_0BOOL, 0},
+/* O_EXTENDED 4.4BSD */
+ {"extended", f_recompile, OPT_0BOOL, 0},
+/* O_FILEC 4.4BSD */
+ {"filec", NULL, OPT_STR, 0},
+/* O_FLASH HPUX */
+ {"flash", NULL, OPT_1BOOL, 0},
+/* O_HARDTABS 4BSD */
+ {"hardtabs", NULL, OPT_NUM, 0},
+/* O_ICLOWER 4.4BSD */
+ {"iclower", f_recompile, OPT_0BOOL, 0},
+/* O_IGNORECASE 4BSD */
+ {"ignorecase", f_recompile, OPT_0BOOL, 0},
+/* O_KEYTIME 4.4BSD */
+ {"keytime", NULL, OPT_NUM, 0},
+/* O_LEFTRIGHT 4.4BSD */
+ {"leftright", f_reformat, OPT_0BOOL, 0},
+/* O_LINES 4.4BSD */
+ {"lines", f_lines, OPT_NUM, OPT_NOSAVE},
+/* O_LISP 4BSD
+ * XXX
+ * When the lisp option is implemented, delete the OPT_NOSAVE flag,
+ * so that :mkexrc dumps it.
+ */
+ {"lisp", f_lisp, OPT_0BOOL, OPT_NOSAVE},
+/* O_LIST 4BSD */
+ {"list", f_reformat, OPT_0BOOL, 0},
+/* O_LOCKFILES 4.4BSD
+ * XXX
+ * Locking isn't reliable enough over NFS to require it, in addition,
+ * it's a serious startup performance problem over some remote links.
+ */
+ {"lock", NULL, OPT_1BOOL, 0},
+/* O_MAGIC 4BSD */
+ {"magic", NULL, OPT_1BOOL, 0},
+/* O_MATCHTIME 4.4BSD */
+ {"matchtime", NULL, OPT_NUM, 0},
+/* O_MESG 4BSD */
+ {"mesg", NULL, OPT_1BOOL, 0},
+/* O_MODELINE 4BSD
+ * !!!
+ * This has been documented in historical systems as both "modeline"
+ * and as "modelines". Regardless of the name, this option represents
+ * a security problem of mammoth proportions, not to mention a stunning
+ * example of what your intro CS professor referred to as the perils of
+ * mixing code and data. Don't add it, or I will kill you.
+ */
+ {"modeline", NULL, OPT_0BOOL, OPT_NOSET},
+/* O_MSGCAT 4.4BSD */
+ {"msgcat", f_msgcat, OPT_STR, 0},
+/* O_NOPRINT 4.4BSD */
+ {"noprint", f_print, OPT_STR, 0},
+/* O_NUMBER 4BSD */
+ {"number", f_reformat, OPT_0BOOL, 0},
+/* O_OCTAL 4.4BSD */
+ {"octal", f_print, OPT_0BOOL, 0},
+/* O_OPEN 4BSD */
+ {"open", NULL, OPT_1BOOL, 0},
+/* O_OPTIMIZE 4BSD */
+ {"optimize", NULL, OPT_1BOOL, 0},
+/* O_PARAGRAPHS 4BSD */
+ {"paragraphs", f_paragraph, OPT_STR, 0},
+/* O_PATH 4.4BSD */
+ {"path", NULL, OPT_STR, 0},
+/* O_PRINT 4.4BSD */
+ {"print", f_print, OPT_STR, 0},
+/* O_PROMPT 4BSD */
+ {"prompt", NULL, OPT_1BOOL, 0},
+/* O_READONLY 4BSD (undocumented) */
+ {"readonly", f_readonly, OPT_0BOOL, OPT_ALWAYS},
+/* O_RECDIR 4.4BSD */
+ {"recdir", NULL, OPT_STR, 0},
+/* O_REDRAW 4BSD */
+ {"redraw", NULL, OPT_0BOOL, 0},
+/* O_REMAP 4BSD */
+ {"remap", NULL, OPT_1BOOL, 0},
+/* O_REPORT 4BSD */
+ {"report", NULL, OPT_NUM, 0},
+/* O_RULER 4.4BSD */
+ {"ruler", NULL, OPT_0BOOL, 0},
+/* O_SCROLL 4BSD */
+ {"scroll", NULL, OPT_NUM, 0},
+/* O_SEARCHINCR 4.4BSD */
+ {"searchincr", NULL, OPT_0BOOL, 0},
+/* O_SECTIONS 4BSD */
+ {"sections", f_section, OPT_STR, 0},
+/* O_SECURE 4.4BSD */
+ {"secure", NULL, OPT_0BOOL, OPT_NOUNSET},
+/* O_SHELL 4BSD */
+ {"shell", NULL, OPT_STR, 0},
+/* O_SHELLMETA 4.4BSD */
+ {"shellmeta", NULL, OPT_STR, 0},
+/* O_SHIFTWIDTH 4BSD */
+ {"shiftwidth", NULL, OPT_NUM, OPT_NOZERO},
+/* O_SHOWMATCH 4BSD */
+ {"showmatch", NULL, OPT_0BOOL, 0},
+/* O_SHOWMODE 4.4BSD */
+ {"showmode", NULL, OPT_0BOOL, 0},
+/* O_SIDESCROLL 4.4BSD */
+ {"sidescroll", NULL, OPT_NUM, OPT_NOZERO},
+/* O_SLOWOPEN 4BSD */
+ {"slowopen", NULL, OPT_0BOOL, 0},
+/* O_SOURCEANY 4BSD (undocumented)
+ * !!!
+ * Historic vi, on startup, source'd $HOME/.exrc and ./.exrc, if they
+ * were owned by the user. The sourceany option was an undocumented
+ * feature of historic vi which permitted the startup source'ing of
+ * .exrc files the user didn't own. This is an obvious security problem,
+ * and we ignore the option.
+ */
+ {"sourceany", NULL, OPT_0BOOL, OPT_NOSET},
+/* O_TABSTOP 4BSD */
+ {"tabstop", f_reformat, OPT_NUM, OPT_NOZERO},
+/* O_TAGLENGTH 4BSD */
+ {"taglength", NULL, OPT_NUM, 0},
+/* O_TAGS 4BSD */
+ {"tags", NULL, OPT_STR, 0},
+/* O_TERM 4BSD
+ * !!!
+ * By default, the historic vi always displayed information about two
+ * options, redraw and term. Term seems sufficient.
+ */
+ {"term", NULL, OPT_STR, OPT_ADISP|OPT_NOSAVE},
+/* O_TERSE 4BSD */
+ {"terse", NULL, OPT_0BOOL, 0},
+/* O_TILDEOP 4.4BSD */
+ {"tildeop", NULL, OPT_0BOOL, 0},
+/* O_TIMEOUT 4BSD (undocumented) */
+ {"timeout", NULL, OPT_1BOOL, 0},
+/* O_TTYWERASE 4.4BSD */
+ {"ttywerase", f_ttywerase, OPT_0BOOL, 0},
+/* O_VERBOSE 4.4BSD */
+ {"verbose", NULL, OPT_0BOOL, 0},
+/* O_W1200 4BSD */
+ {"w1200", f_w1200, OPT_NUM, OPT_NDISP|OPT_NOSAVE},
+/* O_W300 4BSD */
+ {"w300", f_w300, OPT_NUM, OPT_NDISP|OPT_NOSAVE},
+/* O_W9600 4BSD */
+ {"w9600", f_w9600, OPT_NUM, OPT_NDISP|OPT_NOSAVE},
+/* O_WARN 4BSD */
+ {"warn", NULL, OPT_1BOOL, 0},
+/* O_WINDOW 4BSD */
+ {"window", f_window, OPT_NUM, 0},
+/* O_WINDOWNAME 4BSD */
+ {"windowname", NULL, OPT_0BOOL, 0},
+/* O_WRAPLEN 4.4BSD */
+ {"wraplen", NULL, OPT_NUM, 0},
+/* O_WRAPMARGIN 4BSD */
+ {"wrapmargin", NULL, OPT_NUM, 0},
+/* O_WRAPSCAN 4BSD */
+ {"wrapscan", NULL, OPT_1BOOL, 0},
+/* O_WRITEANY 4BSD */
+ {"writeany", NULL, OPT_0BOOL, 0},
+ {NULL},
+};
+
+typedef struct abbrev {
+ char *name;
+ int offset;
+} OABBREV;
+
+static OABBREV const abbrev[] = {
+ {"ai", O_AUTOINDENT}, /* 4BSD */
+ {"ap", O_AUTOPRINT}, /* 4BSD */
+ {"aw", O_AUTOWRITE}, /* 4BSD */
+ {"bf", O_BEAUTIFY}, /* 4BSD */
+ {"co", O_COLUMNS}, /* 4.4BSD */
+ {"dir", O_DIRECTORY}, /* 4BSD */
+ {"eb", O_ERRORBELLS}, /* 4BSD */
+ {"ed", O_EDCOMPATIBLE}, /* 4BSD */
+ {"ex", O_EXRC}, /* System V (undocumented) */
+ {"ht", O_HARDTABS}, /* 4BSD */
+ {"ic", O_IGNORECASE}, /* 4BSD */
+ {"li", O_LINES}, /* 4.4BSD */
+ {"modelines", O_MODELINE}, /* HPUX */
+ {"nu", O_NUMBER}, /* 4BSD */
+ {"opt", O_OPTIMIZE}, /* 4BSD */
+ {"para", O_PARAGRAPHS}, /* 4BSD */
+ {"re", O_REDRAW}, /* O'Reilly */
+ {"ro", O_READONLY}, /* 4BSD (undocumented) */
+ {"scr", O_SCROLL}, /* 4BSD (undocumented) */
+ {"sect", O_SECTIONS}, /* O'Reilly */
+ {"sh", O_SHELL}, /* 4BSD */
+ {"slow", O_SLOWOPEN}, /* 4BSD */
+ {"sm", O_SHOWMATCH}, /* 4BSD */
+ {"smd", O_SHOWMODE}, /* 4BSD */
+ {"sw", O_SHIFTWIDTH}, /* 4BSD */
+ {"tag", O_TAGS}, /* 4BSD (undocumented) */
+ {"tl", O_TAGLENGTH}, /* 4BSD */
+ {"to", O_TIMEOUT}, /* 4BSD (undocumented) */
+ {"ts", O_TABSTOP}, /* 4BSD */
+ {"tty", O_TERM}, /* 4BSD (undocumented) */
+ {"ttytype", O_TERM}, /* 4BSD (undocumented) */
+ {"w", O_WINDOW}, /* O'Reilly */
+ {"wa", O_WRITEANY}, /* 4BSD */
+ {"wi", O_WINDOW}, /* 4BSD (undocumented) */
+ {"wl", O_WRAPLEN}, /* 4.4BSD */
+ {"wm", O_WRAPMARGIN}, /* 4BSD */
+ {"ws", O_WRAPSCAN}, /* 4BSD */
+ {NULL},
+};
+
+/*
+ * opts_init --
+ * Initialize some of the options.
+ *
+ * PUBLIC: int opts_init __P((SCR *, int *));
+ */
+int
+opts_init(sp, oargs)
+ SCR *sp;
+ int *oargs;
+{
+ ARGS *argv[2], a, b;
+ OPTLIST const *op;
+ u_long v;
+ int cnt, optindx;
+ char *s, b1[1024];
+
+ a.bp = b1;
+ b.bp = NULL;
+ a.len = b.len = 0;
+ argv[0] = &a;
+ argv[1] = &b;
+
+ /* Set numeric and string default values. */
+#define OI(indx, str) { \
+ if (str != b1) /* GCC puts strings in text-space. */ \
+ (void)strcpy(b1, str); \
+ a.len = strlen(b1); \
+ if (opts_set(sp, argv, NULL)) { \
+ optindx = indx; \
+ goto err; \
+ } \
+}
+ /*
+ * Indirect global options to global space. Specifically, set up
+ * terminal, lines, columns first, they're used by other options.
+ * Note, don't set the flags until we've set up the indirection.
+ */
+ if (o_set(sp, O_TERM, 0, NULL, GO_TERM))
+ goto err;
+ F_SET(&sp->opts[O_TERM], OPT_GLOBAL);
+ if (o_set(sp, O_LINES, 0, NULL, GO_LINES))
+ goto err;
+ F_SET(&sp->opts[O_LINES], OPT_GLOBAL);
+ if (o_set(sp, O_COLUMNS, 0, NULL, GO_COLUMNS))
+ goto err;
+ F_SET(&sp->opts[O_COLUMNS], OPT_GLOBAL);
+ if (o_set(sp, O_SECURE, 0, NULL, GO_SECURE))
+ goto err;
+ F_SET(&sp->opts[O_SECURE], OPT_GLOBAL);
+
+ /* Initialize string values. */
+ (void)snprintf(b1, sizeof(b1),
+ "cdpath=%s", (s = getenv("CDPATH")) == NULL ? ":" : s);
+ OI(O_CDPATH, b1);
+
+ /*
+ * !!!
+ * Vi historically stored temporary files in /var/tmp. We store them
+ * in /tmp by default, hoping it's a memory based file system. There
+ * are two ways to change this -- the user can set either the directory
+ * option or the TMPDIR environmental variable.
+ */
+ (void)snprintf(b1, sizeof(b1),
+ "directory=%s", (s = getenv("TMPDIR")) == NULL ? _PATH_TMP : s);
+ OI(O_DIRECTORY, b1);
+ OI(O_ESCAPETIME, "escapetime=1");
+ OI(O_KEYTIME, "keytime=6");
+ OI(O_MATCHTIME, "matchtime=7");
+ (void)snprintf(b1, sizeof(b1), "msgcat=%s", _PATH_MSGCAT);
+ OI(O_MSGCAT, b1);
+ OI(O_REPORT, "report=5");
+ OI(O_PARAGRAPHS, "paragraphs=IPLPPPQPP LIpplpipbp");
+ (void)snprintf(b1, sizeof(b1), "path=%s", "");
+ OI(O_PATH, b1);
+ (void)snprintf(b1, sizeof(b1), "recdir=%s", _PATH_PRESERVE);
+ OI(O_RECDIR, b1);
+ OI(O_SECTIONS, "sections=NHSHH HUnhsh");
+ (void)snprintf(b1, sizeof(b1),
+ "shell=%s", (s = getenv("SHELL")) == NULL ? _PATH_BSHELL : s);
+ OI(O_SHELL, b1);
+ OI(O_SHELLMETA, "shellmeta=~{[*?$`'\"\\");
+ OI(O_SHIFTWIDTH, "shiftwidth=8");
+ OI(O_SIDESCROLL, "sidescroll=16");
+ OI(O_TABSTOP, "tabstop=8");
+ (void)snprintf(b1, sizeof(b1), "tags=%s", _PATH_TAGS);
+ OI(O_TAGS, b1);
+
+ /*
+ * XXX
+ * Initialize O_SCROLL here, after term; initializing term should
+ * have created a LINES/COLUMNS value.
+ */
+ if ((v = (O_VAL(sp, O_LINES) - 1) / 2) == 0)
+ v = 1;
+ (void)snprintf(b1, sizeof(b1), "scroll=%ld", v);
+ OI(O_SCROLL, b1);
+
+ /*
+ * The default window option values are:
+ * 8 if baud rate <= 600
+ * 16 if baud rate <= 1200
+ * LINES - 1 if baud rate > 1200
+ *
+ * Note, the windows option code will correct any too-large value
+ * or when the O_LINES value is 1.
+ */
+ if (sp->gp->scr_baud(sp, &v))
+ return (1);
+ if (v <= 600)
+ v = 8;
+ else if (v <= 1200)
+ v = 16;
+ else
+ v = O_VAL(sp, O_LINES) - 1;
+ (void)snprintf(b1, sizeof(b1), "window=%lu", v);
+ OI(O_WINDOW, b1);
+
+ /*
+ * Set boolean default values, and copy all settings into the default
+ * information. OS_NOFREE is set, we're copying, not replacing.
+ */
+ for (op = optlist, cnt = 0; op->name != NULL; ++op, ++cnt)
+ switch (op->type) {
+ case OPT_0BOOL:
+ break;
+ case OPT_1BOOL:
+ O_SET(sp, cnt);
+ O_D_SET(sp, cnt);
+ break;
+ case OPT_NUM:
+ o_set(sp, cnt, OS_DEF, NULL, O_VAL(sp, cnt));
+ break;
+ case OPT_STR:
+ if (O_STR(sp, cnt) != NULL && o_set(sp, cnt,
+ OS_DEF | OS_NOFREE | OS_STRDUP, O_STR(sp, cnt), 0))
+ goto err;
+ break;
+ default:
+ abort();
+ }
+
+ /*
+ * !!!
+ * Some options can be initialized by the command name or the
+ * command-line arguments. They don't set the default values,
+ * it's historic practice.
+ */
+ for (; *oargs != -1; ++oargs)
+ OI(*oargs, optlist[*oargs].name);
+ return (0);
+#undef OI
+
+err: msgq(sp, M_ERR,
+ "031|Unable to set default %s option", optlist[optindx].name);
+ return (1);
+}
+
+/*
+ * opts_set --
+ * Change the values of one or more options.
+ *
+ * PUBLIC: int opts_set __P((SCR *, ARGS *[], char *));
+ */
+int
+opts_set(sp, argv, usage)
+ SCR *sp;
+ ARGS *argv[];
+ char *usage;
+{
+ enum optdisp disp;
+ enum nresult nret;
+ OPTLIST const *op;
+ OPTION *spo;
+ u_long value, turnoff;
+ int ch, equals, nf, nf2, offset, qmark, rval;
+ char *endp, *name, *p, *sep, *t;
+
+ disp = NO_DISPLAY;
+ for (rval = 0; argv[0]->len != 0; ++argv) {
+ /*
+ * The historic vi dumped the options for each occurrence of
+ * "all" in the set list. Puhleeze.
+ */
+ if (!strcmp(argv[0]->bp, "all")) {
+ disp = ALL_DISPLAY;
+ continue;
+ }
+
+ /* Find equals sign or question mark. */
+ for (sep = NULL, equals = qmark = 0,
+ p = name = argv[0]->bp; (ch = *p) != '\0'; ++p)
+ if (ch == '=' || ch == '?') {
+ if (p == name) {
+ if (usage != NULL)
+ msgq(sp, M_ERR,
+ "032|Usage: %s", usage);
+ return (1);
+ }
+ sep = p;
+ if (ch == '=')
+ equals = 1;
+ else
+ qmark = 1;
+ break;
+ }
+
+ turnoff = 0;
+ op = NULL;
+ if (sep != NULL)
+ *sep++ = '\0';
+
+ /* Search for the name, then name without any leading "no". */
+ if ((op = opts_search(name)) == NULL &&
+ name[0] == 'n' && name[1] == 'o') {
+ turnoff = 1;
+ name += 2;
+ op = opts_search(name);
+ }
+ if (op == NULL) {
+ opts_nomatch(sp, name);
+ rval = 1;
+ continue;
+ }
+
+ /* Find current option values. */
+ offset = op - optlist;
+ spo = sp->opts + offset;
+
+ /*
+ * !!!
+ * Historically, the question mark could be a separate
+ * argument.
+ */
+ if (!equals && !qmark &&
+ argv[1]->len == 1 && argv[1]->bp[0] == '?') {
+ ++argv;
+ qmark = 1;
+ }
+
+ /* Set name, value. */
+ switch (op->type) {
+ case OPT_0BOOL:
+ case OPT_1BOOL:
+ /* Some options may not be reset. */
+ if (F_ISSET(op, OPT_NOUNSET) && turnoff) {
+ msgq_str(sp, M_ERR, name,
+ "291|set: the %s option may not be turned off");
+ rval = 1;
+ break;
+ }
+
+ /* Some options may not be set. */
+ if (F_ISSET(op, OPT_NOSET) && !turnoff) {
+ msgq_str(sp, M_ERR, name,
+ "313|set: the %s option may never be turned on");
+ rval = 1;
+ break;
+ }
+
+ if (equals) {
+ msgq_str(sp, M_ERR, name,
+ "034|set: [no]%s option doesn't take a value");
+ rval = 1;
+ break;
+ }
+ if (qmark) {
+ if (!disp)
+ disp = SELECT_DISPLAY;
+ F_SET(spo, OPT_SELECTED);
+ break;
+ }
+
+ /*
+ * Do nothing if the value is unchanged, the underlying
+ * functions can be expensive.
+ */
+ if (!F_ISSET(op, OPT_ALWAYS))
+ if (turnoff) {
+ if (!O_ISSET(sp, offset))
+ break;
+ } else {
+ if (O_ISSET(sp, offset))
+ break;
+ }
+
+ /* Report to subsystems. */
+ if (op->func != NULL &&
+ op->func(sp, spo, NULL, &turnoff) ||
+ ex_optchange(sp, offset, NULL, &turnoff) ||
+ v_optchange(sp, offset, NULL, &turnoff) ||
+ sp->gp->scr_optchange(sp, offset, NULL, &turnoff)) {
+ rval = 1;
+ break;
+ }
+
+ /* Set the value. */
+ if (turnoff)
+ O_CLR(sp, offset);
+ else
+ O_SET(sp, offset);
+ break;
+ case OPT_NUM:
+ if (turnoff) {
+ msgq_str(sp, M_ERR, name,
+ "035|set: %s option isn't a boolean");
+ rval = 1;
+ break;
+ }
+ if (qmark || !equals) {
+ if (!disp)
+ disp = SELECT_DISPLAY;
+ F_SET(spo, OPT_SELECTED);
+ break;
+ }
+
+ if (!isdigit(sep[0]))
+ goto badnum;
+ if ((nret =
+ nget_uslong(&value, sep, &endp, 10)) != NUM_OK) {
+ p = msg_print(sp, name, &nf);
+ t = msg_print(sp, sep, &nf2);
+ switch (nret) {
+ case NUM_ERR:
+ msgq(sp, M_SYSERR,
+ "036|set: %s option: %s", p, t);
+ break;
+ case NUM_OVER:
+ msgq(sp, M_ERR,
+ "037|set: %s option: %s: value overflow", p, t);
+ break;
+ case NUM_OK:
+ case NUM_UNDER:
+ abort();
+ }
+ if (nf)
+ FREE_SPACE(sp, p, 0);
+ if (nf2)
+ FREE_SPACE(sp, t, 0);
+ rval = 1;
+ break;
+ }
+ if (*endp && !isblank(*endp)) {
+badnum: p = msg_print(sp, name, &nf);
+ t = msg_print(sp, sep, &nf2);
+ msgq(sp, M_ERR,
+ "038|set: %s option: %s is an illegal number", p, t);
+ if (nf)
+ FREE_SPACE(sp, p, 0);
+ if (nf2)
+ FREE_SPACE(sp, t, 0);
+ rval = 1;
+ break;
+ }
+
+ /* Some options may never be set to zero. */
+ if (F_ISSET(op, OPT_NOZERO) && value == 0) {
+ msgq_str(sp, M_ERR, name,
+ "314|set: the %s option may never be set to 0");
+ rval = 1;
+ break;
+ }
+
+ /*
+ * Do nothing if the value is unchanged, the underlying
+ * functions can be expensive.
+ */
+ if (!F_ISSET(op, OPT_ALWAYS) &&
+ O_VAL(sp, offset) == value)
+ break;
+
+ /* Report to subsystems. */
+ if (op->func != NULL &&
+ op->func(sp, spo, sep, &value) ||
+ ex_optchange(sp, offset, sep, &value) ||
+ v_optchange(sp, offset, sep, &value) ||
+ sp->gp->scr_optchange(sp, offset, sep, &value)) {
+ rval = 1;
+ break;
+ }
+
+ /* Set the value. */
+ if (o_set(sp, offset, 0, NULL, value))
+ rval = 1;
+ break;
+ case OPT_STR:
+ if (turnoff) {
+ msgq_str(sp, M_ERR, name,
+ "039|set: %s option isn't a boolean");
+ rval = 1;
+ break;
+ }
+ if (qmark || !equals) {
+ if (!disp)
+ disp = SELECT_DISPLAY;
+ F_SET(spo, OPT_SELECTED);
+ break;
+ }
+
+ /*
+ * Do nothing if the value is unchanged, the underlying
+ * functions can be expensive.
+ */
+ if (!F_ISSET(op, OPT_ALWAYS) &&
+ O_STR(sp, offset) != NULL &&
+ !strcmp(O_STR(sp, offset), sep))
+ break;
+
+ /* Report to subsystems. */
+ if (op->func != NULL &&
+ op->func(sp, spo, sep, NULL) ||
+ ex_optchange(sp, offset, sep, NULL) ||
+ v_optchange(sp, offset, sep, NULL) ||
+ sp->gp->scr_optchange(sp, offset, sep, NULL)) {
+ rval = 1;
+ break;
+ }
+
+ /* Set the value. */
+ if (o_set(sp, offset, OS_STRDUP, sep, 0))
+ rval = 1;
+ break;
+ default:
+ abort();
+ }
+ }
+ if (disp != NO_DISPLAY)
+ opts_dump(sp, disp);
+ return (rval);
+}
+
+/*
+ * o_set --
+ * Set an option's value.
+ *
+ * PUBLIC: int o_set __P((SCR *, int, u_int, char *, u_long));
+ */
+int
+o_set(sp, opt, flags, str, val)
+ SCR *sp;
+ int opt;
+ u_int flags;
+ char *str;
+ u_long val;
+{
+ OPTION *op;
+
+ /* Set a pointer to the options area. */
+ op = F_ISSET(&sp->opts[opt], OPT_GLOBAL) ?
+ &sp->gp->opts[sp->opts[opt].o_cur.val] : &sp->opts[opt];
+
+ /* Copy the string, if requested. */
+ if (LF_ISSET(OS_STRDUP) && (str = strdup(str)) == NULL) {
+ msgq(sp, M_SYSERR, NULL);
+ return (1);
+ }
+
+ /* Free the previous string, if requested, and set the value. */
+ if LF_ISSET(OS_DEF)
+ if (LF_ISSET(OS_STR | OS_STRDUP)) {
+ if (!LF_ISSET(OS_NOFREE) && op->o_def.str != NULL)
+ free(op->o_def.str);
+ op->o_def.str = str;
+ } else
+ op->o_def.val = val;
+ else
+ if (LF_ISSET(OS_STR | OS_STRDUP)) {
+ if (!LF_ISSET(OS_NOFREE) && op->o_cur.str != NULL)
+ free(op->o_cur.str);
+ op->o_cur.str = str;
+ } else
+ op->o_cur.val = val;
+ return (0);
+}
+
+/*
+ * opts_empty --
+ * Return 1 if the string option is invalid, 0 if it's OK.
+ *
+ * PUBLIC: int opts_empty __P((SCR *, int, int));
+ */
+int
+opts_empty(sp, off, silent)
+ SCR *sp;
+ int off, silent;
+{
+ char *p;
+
+ if ((p = O_STR(sp, off)) == NULL || p[0] == '\0') {
+ if (!silent)
+ msgq_str(sp, M_ERR, optlist[off].name,
+ "305|No %s edit option specified");
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * opts_dump --
+ * List the current values of selected options.
+ *
+ * PUBLIC: void opts_dump __P((SCR *, enum optdisp));
+ */
+void
+opts_dump(sp, type)
+ SCR *sp;
+ enum optdisp type;
+{
+ OPTLIST const *op;
+ int base, b_num, cnt, col, colwidth, curlen, s_num;
+ int numcols, numrows, row;
+ int b_op[O_OPTIONCOUNT], s_op[O_OPTIONCOUNT];
+ char nbuf[20];
+
+ /*
+ * Options are output in two groups -- those that fit in a column and
+ * those that don't. Output is done on 6 character "tab" boundaries
+ * for no particular reason. (Since we don't output tab characters,
+ * we can ignore the terminal's tab settings.) Ignore the user's tab
+ * setting because we have no idea how reasonable it is.
+ *
+ * Find a column width we can live with, testing from 10 columns to 1.
+ */
+ for (numcols = 10; numcols > 1; --numcols) {
+ colwidth = sp->cols / numcols & ~(STANDARD_TAB - 1);
+ if (colwidth >= 10) {
+ colwidth =
+ (colwidth + STANDARD_TAB) & ~(STANDARD_TAB - 1);
+ numcols = sp->cols / colwidth;
+ break;
+ }
+ colwidth = 0;
+ }
+
+ /*
+ * Get the set of options to list, entering them into
+ * the column list or the overflow list.
+ */
+ for (b_num = s_num = 0, op = optlist; op->name != NULL; ++op) {
+ cnt = op - optlist;
+
+ /* If OPT_NDISP set, it's never displayed. */
+ if (F_ISSET(op, OPT_NDISP))
+ continue;
+
+ switch (type) {
+ case ALL_DISPLAY: /* Display all. */
+ break;
+ case CHANGED_DISPLAY: /* Display changed. */
+ /* If OPT_ADISP set, it's always "changed". */
+ if (F_ISSET(op, OPT_ADISP))
+ break;
+ switch (op->type) {
+ case OPT_0BOOL:
+ case OPT_1BOOL:
+ case OPT_NUM:
+ if (O_VAL(sp, cnt) == O_D_VAL(sp, cnt))
+ continue;
+ break;
+ case OPT_STR:
+ if (O_STR(sp, cnt) == O_D_STR(sp, cnt) ||
+ O_D_STR(sp, cnt) != NULL &&
+ !strcmp(O_STR(sp, cnt), O_D_STR(sp, cnt)))
+ continue;
+ break;
+ }
+ break;
+ case SELECT_DISPLAY: /* Display selected. */
+ if (!F_ISSET(&sp->opts[cnt], OPT_SELECTED))
+ continue;
+ break;
+ default:
+ case NO_DISPLAY:
+ abort();
+ }
+ F_CLR(&sp->opts[cnt], OPT_SELECTED);
+
+ curlen = strlen(op->name);
+ switch (op->type) {
+ case OPT_0BOOL:
+ case OPT_1BOOL:
+ if (!O_ISSET(sp, cnt))
+ curlen += 2;
+ break;
+ case OPT_NUM:
+ (void)snprintf(nbuf,
+ sizeof(nbuf), "%ld", O_VAL(sp, cnt));
+ curlen += strlen(nbuf);
+ break;
+ case OPT_STR:
+ if (O_STR(sp, cnt) != NULL)
+ curlen += strlen(O_STR(sp, cnt));
+ curlen += 3;
+ break;
+ }
+ /* Offset by 2 so there's a gap. */
+ if (curlen <= colwidth - 2)
+ s_op[s_num++] = cnt;
+ else
+ b_op[b_num++] = cnt;
+ }
+
+ if (s_num > 0) {
+ /* Figure out the number of rows. */
+ if (s_num > numcols) {
+ numrows = s_num / numcols;
+ if (s_num % numcols)
+ ++numrows;
+ } else
+ numrows = 1;
+
+ /* Display the options in sorted order. */
+ for (row = 0; row < numrows;) {
+ for (base = row, col = 0; col < numcols; ++col) {
+ cnt = opts_print(sp, &optlist[s_op[base]]);
+ if ((base += numrows) >= s_num)
+ break;
+ (void)ex_printf(sp, "%*s",
+ (int)(colwidth - cnt), "");
+ }
+ if (++row < numrows || b_num)
+ (void)ex_puts(sp, "\n");
+ }
+ }
+
+ for (row = 0; row < b_num;) {
+ (void)opts_print(sp, &optlist[b_op[row]]);
+ if (++row < b_num)
+ (void)ex_puts(sp, "\n");
+ }
+ (void)ex_puts(sp, "\n");
+}
+
+/*
+ * opts_print --
+ * Print out an option.
+ */
+static int
+opts_print(sp, op)
+ SCR *sp;
+ OPTLIST const *op;
+{
+ int curlen, offset;
+
+ curlen = 0;
+ offset = op - optlist;
+ switch (op->type) {
+ case OPT_0BOOL:
+ case OPT_1BOOL:
+ curlen += ex_printf(sp,
+ "%s%s", O_ISSET(sp, offset) ? "" : "no", op->name);
+ break;
+ case OPT_NUM:
+ curlen += ex_printf(sp, "%s=%ld", op->name, O_VAL(sp, offset));
+ break;
+ case OPT_STR:
+ curlen += ex_printf(sp, "%s=\"%s\"", op->name,
+ O_STR(sp, offset) == NULL ? "" : O_STR(sp, offset));
+ break;
+ }
+ return (curlen);
+}
+
+/*
+ * opts_save --
+ * Write the current configuration to a file.
+ *
+ * PUBLIC: int opts_save __P((SCR *, FILE *));
+ */
+int
+opts_save(sp, fp)
+ SCR *sp;
+ FILE *fp;
+{
+ OPTLIST const *op;
+ int ch, cnt;
+ char *p;
+
+ for (op = optlist; op->name != NULL; ++op) {
+ if (F_ISSET(op, OPT_NOSAVE))
+ continue;
+ cnt = op - optlist;
+ switch (op->type) {
+ case OPT_0BOOL:
+ case OPT_1BOOL:
+ if (O_ISSET(sp, cnt))
+ (void)fprintf(fp, "set %s\n", op->name);
+ else
+ (void)fprintf(fp, "set no%s\n", op->name);
+ break;
+ case OPT_NUM:
+ (void)fprintf(fp,
+ "set %s=%-3ld\n", op->name, O_VAL(sp, cnt));
+ break;
+ case OPT_STR:
+ if (O_STR(sp, cnt) == NULL)
+ break;
+ (void)fprintf(fp, "set ");
+ for (p = op->name; (ch = *p) != '\0'; ++p) {
+ if (isblank(ch) || ch == '\\')
+ (void)putc('\\', fp);
+ (void)putc(ch, fp);
+ }
+ (void)putc('=', fp);
+ for (p = O_STR(sp, cnt); (ch = *p) != '\0'; ++p) {
+ if (isblank(ch) || ch == '\\')
+ (void)putc('\\', fp);
+ (void)putc(ch, fp);
+ }
+ (void)putc('\n', fp);
+ break;
+ }
+ if (ferror(fp)) {
+ msgq(sp, M_SYSERR, NULL);
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/*
+ * opts_search --
+ * Search for an option.
+ *
+ * PUBLIC: OPTLIST const *opts_search __P((char *));
+ */
+OPTLIST const *
+opts_search(name)
+ char *name;
+{
+ OPTLIST const *op, *found;
+ OABBREV atmp, *ap;
+ OPTLIST otmp;
+ size_t len;
+
+ /* Check list of abbreviations. */
+ atmp.name = name;
+ if ((ap = bsearch(&atmp, abbrev, sizeof(abbrev) / sizeof(OABBREV) - 1,
+ sizeof(OABBREV), opts_abbcmp)) != NULL)
+ return (optlist + ap->offset);
+
+ /* Check list of options. */
+ otmp.name = name;
+ if ((op = bsearch(&otmp, optlist, sizeof(optlist) / sizeof(OPTLIST) - 1,
+ sizeof(OPTLIST), opts_cmp)) != NULL)
+ return (op);
+
+ /*
+ * Check to see if the name is the prefix of one (and only one)
+ * option. If so, return the option.
+ */
+ len = strlen(name);
+ for (found = NULL, op = optlist; op->name != NULL; ++op) {
+ if (op->name[0] < name[0])
+ continue;
+ if (op->name[0] > name[0])
+ break;
+ if (!memcmp(op->name, name, len)) {
+ if (found != NULL)
+ return (NULL);
+ found = op;
+ }
+ }
+ return (found);
+}
+
+/*
+ * opts_nomatch --
+ * Standard nomatch error message for options.
+ *
+ * PUBLIC: void opts_nomatch __P((SCR *, char *));
+ */
+void
+opts_nomatch(sp, name)
+ SCR *sp;
+ char *name;
+{
+ msgq_str(sp, M_ERR, name,
+ "033|set: no %s option: 'set all' gives all option values");
+}
+
+static int
+opts_abbcmp(a, b)
+ const void *a, *b;
+{
+ return(strcmp(((OABBREV *)a)->name, ((OABBREV *)b)->name));
+}
+
+static int
+opts_cmp(a, b)
+ const void *a, *b;
+{
+ return(strcmp(((OPTLIST *)a)->name, ((OPTLIST *)b)->name));
+}
+
+/*
+ * opts_copy --
+ * Copy a screen's OPTION array.
+ *
+ * PUBLIC: int opts_copy __P((SCR *, SCR *));
+ */
+int
+opts_copy(orig, sp)
+ SCR *orig, *sp;
+{
+ int cnt, rval;
+
+ /* Copy most everything without change. */
+ memcpy(sp->opts, orig->opts, sizeof(orig->opts));
+
+ /* Copy the string edit options. */
+ for (cnt = rval = 0; cnt < O_OPTIONCOUNT; ++cnt) {
+ if (optlist[cnt].type != OPT_STR ||
+ F_ISSET(&optlist[cnt], OPT_GLOBAL))
+ continue;
+ /*
+ * If never set, or already failed, NULL out the entries --
+ * have to continue after failure, otherwise would have two
+ * screens referencing the same memory.
+ */
+ if (rval || O_STR(sp, cnt) == NULL) {
+ o_set(sp, cnt, OS_NOFREE | OS_STR, NULL, 0);
+ o_set(sp, cnt, OS_DEF | OS_NOFREE | OS_STR, NULL, 0);
+ continue;
+ }
+
+ /* Copy the current string. */
+ if (o_set(sp, cnt, OS_NOFREE | OS_STRDUP, O_STR(sp, cnt), 0)) {
+ o_set(sp, cnt, OS_DEF | OS_NOFREE | OS_STR, NULL, 0);
+ goto nomem;
+ }
+
+ /* Copy the default string. */
+ if (O_D_STR(sp, cnt) != NULL && o_set(sp, cnt,
+ OS_DEF | OS_NOFREE | OS_STRDUP, O_D_STR(sp, cnt), 0)) {
+nomem: msgq(orig, M_SYSERR, NULL);
+ rval = 1;
+ }
+ }
+ return (rval);
+}
+
+/*
+ * opts_free --
+ * Free all option strings
+ *
+ * PUBLIC: void opts_free __P((SCR *));
+ */
+void
+opts_free(sp)
+ SCR *sp;
+{
+ int cnt;
+
+ for (cnt = 0; cnt < O_OPTIONCOUNT; ++cnt) {
+ if (optlist[cnt].type != OPT_STR ||
+ F_ISSET(&optlist[cnt], OPT_GLOBAL))
+ continue;
+ if (O_STR(sp, cnt) != NULL)
+ free(O_STR(sp, cnt));
+ if (O_D_STR(sp, cnt) != NULL)
+ free(O_D_STR(sp, cnt));
+ }
+}
diff --git a/contrib/nvi/common/options.h b/contrib/nvi/common/options.h
new file mode 100644
index 000000000000..2646dc301b5a
--- /dev/null
+++ b/contrib/nvi/common/options.h
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)options.h 10.19 (Berkeley) 10/10/96
+ */
+
+/*
+ * Edit option information. Historically, if you set a boolean or numeric
+ * edit option value to its "default" value, it didn't show up in the :set
+ * display, i.e. it wasn't considered "changed". String edit options would
+ * show up as changed, regardless. We maintain a parallel set of values
+ * which are the default values and never consider an edit option changed
+ * if it was reset to the default value.
+ *
+ * Macros to retrieve boolean, integral and string option values, and to
+ * set, clear and test boolean option values. Some options (secure, lines,
+ * columns, terminal type) are global in scope, and are therefore stored
+ * in the global area. The offset in the global options array is stored
+ * in the screen's value field. This is set up when the options are first
+ * initialized.
+ */
+#define O_V(sp, o, fld) \
+ (F_ISSET(&(sp)->opts[(o)], OPT_GLOBAL) ? \
+ (sp)->gp->opts[(sp)->opts[(o)].o_cur.val].fld : \
+ (sp)->opts[(o)].fld)
+
+/* Global option macros. */
+#define OG_CLR(gp, o) ((gp)->opts[(o)].o_cur.val) = 0
+#define OG_SET(gp, o) ((gp)->opts[(o)].o_cur.val) = 1
+#define OG_STR(gp, o) ((gp)->opts[(o)].o_cur.str)
+#define OG_VAL(gp, o) ((gp)->opts[(o)].o_cur.val)
+#define OG_ISSET(gp, o) OG_VAL(gp, o)
+
+#define OG_D_STR(gp, o) ((gp)->opts[(o)].o_def.str)
+#define OG_D_VAL(gp, o) ((gp)->opts[(o)].o_def.val)
+
+/*
+ * Flags to o_set(); need explicit OS_STR as can be setting the value to
+ * NULL.
+ */
+#define OS_DEF 0x01 /* Set the default value. */
+#define OS_NOFREE 0x02 /* Don't free the old string. */
+#define OS_STR 0x04 /* Set to string argument. */
+#define OS_STRDUP 0x08 /* Copy then set to string argument. */
+
+struct _option {
+ union {
+ u_long val; /* Value or boolean. */
+ char *str; /* String. */
+ } o_cur;
+#define O_CLR(sp, o) o_set(sp, o, 0, NULL, 0)
+#define O_SET(sp, o) o_set(sp, o, 0, NULL, 1)
+#define O_STR(sp, o) O_V(sp, o, o_cur.str)
+#define O_VAL(sp, o) O_V(sp, o, o_cur.val)
+#define O_ISSET(sp, o) O_VAL(sp, o)
+
+ union {
+ u_long val; /* Value or boolean. */
+ char *str; /* String. */
+ } o_def;
+#define O_D_CLR(sp, o) o_set(sp, o, OS_DEF, NULL, 0)
+#define O_D_SET(sp, o) o_set(sp, o, OS_DEF, NULL, 1)
+#define O_D_STR(sp, o) O_V(sp, o, o_def.str)
+#define O_D_VAL(sp, o) O_V(sp, o, o_def.val)
+#define O_D_ISSET(sp, o) O_D_VAL(sp, o)
+
+#define OPT_GLOBAL 0x01 /* Option is global. */
+#define OPT_SELECTED 0x02 /* Selected for display. */
+ u_int8_t flags;
+};
+
+/* List of option names, associated update functions and information. */
+struct _optlist {
+ char *name; /* Name. */
+ /* Change function. */
+ int (*func) __P((SCR *, OPTION *, char *, u_long *));
+ /* Type of object. */
+ enum { OPT_0BOOL, OPT_1BOOL, OPT_NUM, OPT_STR } type;
+
+#define OPT_ADISP 0x001 /* Always display the option. */
+#define OPT_ALWAYS 0x002 /* Always call the support function. */
+#define OPT_NDISP 0x004 /* Never display the option. */
+#define OPT_NOSAVE 0x008 /* Mkexrc command doesn't save. */
+#define OPT_NOSET 0x010 /* Option may not be set. */
+#define OPT_NOUNSET 0x020 /* Option may not be unset. */
+#define OPT_NOZERO 0x040 /* Option may not be set to 0. */
+ u_int8_t flags;
+};
+
+/* Option argument to opts_dump(). */
+enum optdisp { NO_DISPLAY, ALL_DISPLAY, CHANGED_DISPLAY, SELECT_DISPLAY };
+
+/* Options array. */
+extern OPTLIST const optlist[];
+
+#include "options_def.h"
diff --git a/contrib/nvi/common/options_f.c b/contrib/nvi/common/options_f.c
new file mode 100644
index 000000000000..ea3c61160cf5
--- /dev/null
+++ b/contrib/nvi/common/options_f.c
@@ -0,0 +1,367 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)options_f.c 10.25 (Berkeley) 7/12/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+
+/*
+ * PUBLIC: int f_altwerase __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_altwerase(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ if (!*valp)
+ O_CLR(sp, O_TTYWERASE);
+ return (0);
+}
+
+/*
+ * PUBLIC: int f_columns __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_columns(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ /* Validate the number. */
+ if (*valp < MINIMUM_SCREEN_COLS) {
+ msgq(sp, M_ERR, "040|Screen columns too small, less than %d",
+ MINIMUM_SCREEN_COLS);
+ return (1);
+ }
+
+ /*
+ * !!!
+ * It's not uncommon for allocation of huge chunks of memory to cause
+ * core dumps on various systems. So, we prune out numbers that are
+ * "obviously" wrong. Vi will not work correctly if it has the wrong
+ * number of lines/columns for the screen, but at least we don't drop
+ * core.
+ */
+#define MAXIMUM_SCREEN_COLS 500
+ if (*valp > MAXIMUM_SCREEN_COLS) {
+ msgq(sp, M_ERR, "041|Screen columns too large, greater than %d",
+ MAXIMUM_SCREEN_COLS);
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * PUBLIC: int f_lines __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_lines(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ /* Validate the number. */
+ if (*valp < MINIMUM_SCREEN_ROWS) {
+ msgq(sp, M_ERR, "042|Screen lines too small, less than %d",
+ MINIMUM_SCREEN_ROWS);
+ return (1);
+ }
+
+ /*
+ * !!!
+ * It's not uncommon for allocation of huge chunks of memory to cause
+ * core dumps on various systems. So, we prune out numbers that are
+ * "obviously" wrong. Vi will not work correctly if it has the wrong
+ * number of lines/columns for the screen, but at least we don't drop
+ * core.
+ */
+#define MAXIMUM_SCREEN_ROWS 500
+ if (*valp > MAXIMUM_SCREEN_ROWS) {
+ msgq(sp, M_ERR, "043|Screen lines too large, greater than %d",
+ MAXIMUM_SCREEN_ROWS);
+ return (1);
+ }
+
+ /*
+ * Set the value, and the related scroll value. If no window
+ * value set, set a new default window.
+ */
+ o_set(sp, O_LINES, 0, NULL, *valp);
+ if (*valp == 1) {
+ sp->defscroll = 1;
+
+ if (O_VAL(sp, O_WINDOW) == O_D_VAL(sp, O_WINDOW) ||
+ O_VAL(sp, O_WINDOW) > *valp) {
+ o_set(sp, O_WINDOW, 0, NULL, 1);
+ o_set(sp, O_WINDOW, OS_DEF, NULL, 1);
+ }
+ } else {
+ sp->defscroll = (*valp - 1) / 2;
+
+ if (O_VAL(sp, O_WINDOW) == O_D_VAL(sp, O_WINDOW) ||
+ O_VAL(sp, O_WINDOW) > *valp) {
+ o_set(sp, O_WINDOW, 0, NULL, *valp - 1);
+ o_set(sp, O_WINDOW, OS_DEF, NULL, *valp - 1);
+ }
+ }
+ return (0);
+}
+
+/*
+ * PUBLIC: int f_lisp __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_lisp(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ msgq(sp, M_ERR, "044|The lisp option is not implemented");
+ return (0);
+}
+
+/*
+ * PUBLIC: int f_msgcat __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_msgcat(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ (void)msg_open(sp, str);
+ return (0);
+}
+
+/*
+ * PUBLIC: int f_paragraph __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_paragraph(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ if (strlen(str) & 1) {
+ msgq(sp, M_ERR,
+ "048|The paragraph option must be in two character groups");
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * PUBLIC: int f_print __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_print(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ /* Reinitialize the key fast lookup table. */
+ v_key_ilookup(sp);
+
+ /* Reformat the screen. */
+ F_SET(sp, SC_SCR_REFORMAT);
+ return (0);
+}
+
+/*
+ * PUBLIC: int f_readonly __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_readonly(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ /*
+ * !!!
+ * See the comment in exf.c.
+ */
+ if (*valp)
+ F_CLR(sp, SC_READONLY);
+ else
+ F_SET(sp, SC_READONLY);
+ return (0);
+}
+
+/*
+ * PUBLIC: int f_recompile __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_recompile(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ if (F_ISSET(sp, SC_RE_SEARCH)) {
+ regfree(&sp->re_c);
+ F_CLR(sp, SC_RE_SEARCH);
+ }
+ if (F_ISSET(sp, SC_RE_SUBST)) {
+ regfree(&sp->subre_c);
+ F_CLR(sp, SC_RE_SUBST);
+ }
+ return (0);
+}
+
+/*
+ * PUBLIC: int f_reformat __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_reformat(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ F_SET(sp, SC_SCR_REFORMAT);
+ return (0);
+}
+
+/*
+ * PUBLIC: int f_section __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_section(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ if (strlen(str) & 1) {
+ msgq(sp, M_ERR,
+ "049|The section option must be in two character groups");
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * PUBLIC: int f_ttywerase __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_ttywerase(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ if (!*valp)
+ O_CLR(sp, O_ALTWERASE);
+ return (0);
+}
+
+/*
+ * PUBLIC: int f_w300 __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_w300(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ u_long v;
+
+ /* Historical behavior for w300 was < 1200. */
+ if (sp->gp->scr_baud(sp, &v))
+ return (1);
+ if (v >= 1200)
+ return (0);
+
+ return (f_window(sp, op, str, valp));
+}
+
+/*
+ * PUBLIC: int f_w1200 __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_w1200(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ u_long v;
+
+ /* Historical behavior for w1200 was == 1200. */
+ if (sp->gp->scr_baud(sp, &v))
+ return (1);
+ if (v < 1200 || v > 4800)
+ return (0);
+
+ return (f_window(sp, op, str, valp));
+}
+
+/*
+ * PUBLIC: int f_w9600 __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_w9600(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ u_long v;
+
+ /* Historical behavior for w9600 was > 1200. */
+ if (sp->gp->scr_baud(sp, &v))
+ return (1);
+ if (v <= 4800)
+ return (0);
+
+ return (f_window(sp, op, str, valp));
+}
+
+/*
+ * PUBLIC: int f_window __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_window(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ if (*valp >= O_VAL(sp, O_LINES) - 1 &&
+ (*valp = O_VAL(sp, O_LINES) - 1) == 0)
+ *valp = 1;
+ return (0);
+}
diff --git a/usr.bin/vi/common/put.c b/contrib/nvi/common/put.c
index e6dbf3ae4963..8c0ca4b7c14f 100644
--- a/usr.bin/vi/common/put.c
+++ b/contrib/nvi/common/put.c
@@ -1,67 +1,39 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)put.c 8.9 (Berkeley) 5/21/94";
+static const char sccsid[] = "@(#)put.c 10.11 (Berkeley) 9/23/96";
#endif /* not lint */
#include <sys/types.h>
#include <sys/queue.h>
-#include <sys/time.h>
#include <bitstring.h>
#include <ctype.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-#include "vi.h"
+#include "common.h"
/*
* put --
* Put text buffer contents into the file.
+ *
+ * PUBLIC: int put __P((SCR *, CB *, CHAR_T *, MARK *, MARK *, int));
*/
int
-put(sp, ep, cbp, namep, cp, rp, append)
+put(sp, cbp, namep, cp, rp, append)
SCR *sp;
- EXF *ep;
CB *cbp;
CHAR_T *namep;
MARK *cp, *rp;
@@ -78,15 +50,16 @@ put(sp, ep, cbp, namep, cp, rp, append)
if (namep == NULL) {
cbp = sp->gp->dcbp;
if (cbp == NULL) {
- msgq(sp, M_ERR, "The default buffer is empty");
+ msgq(sp, M_ERR,
+ "053|The default buffer is empty");
return (1);
}
} else {
name = *namep;
CBNAME(sp, cbp, name);
if (cbp == NULL) {
- msgq(sp, M_ERR,
- "Buffer %s is empty", KEY_NAME(sp, name));
+ msgq(sp, M_ERR, "054|Buffer %s is empty",
+ KEY_NAME(sp, name));
return (1);
}
}
@@ -108,12 +81,12 @@ put(sp, ep, cbp, namep, cp, rp, append)
* in the file.
*/
if (cp->lno == 1) {
- if (file_lline(sp, ep, &lno))
+ if (db_last(sp, &lno))
return (1);
if (lno == 0) {
for (; tp != (void *)&cbp->textq;
++lno, ++sp->rptlines[L_ADDED], tp = tp->q.cqe_next)
- if (file_aline(sp, ep, 1, lno, tp->lb, tp->len))
+ if (db_append(sp, 1, lno, tp->lb, tp->len))
return (1);
rp->lno = 1;
rp->cno = 0;
@@ -127,10 +100,10 @@ put(sp, ep, cbp, namep, cp, rp, append)
rp->lno = lno + 1;
for (; tp != (void *)&cbp->textq;
++lno, ++sp->rptlines[L_ADDED], tp = tp->q.cqe_next)
- if (file_aline(sp, ep, 1, lno, tp->lb, tp->len))
+ if (db_append(sp, 1, lno, tp->lb, tp->len))
return (1);
rp->cno = 0;
- (void)nonblank(sp, ep, rp->lno, &rp->cno);
+ (void)nonblank(sp, rp->lno, &rp->cno);
return (0);
}
@@ -144,27 +117,43 @@ put(sp, ep, cbp, namep, cp, rp, append)
* Get the first line.
*/
lno = cp->lno;
- if ((p = file_gline(sp, ep, lno, &len)) == NULL) {
- GETLINE_ERR(sp, lno);
+ if (db_get(sp, lno, DBG_FATAL, &p, &len))
return (1);
- }
GET_SPACE_RET(sp, bp, blen, tp->len + len + 1);
t = bp;
/* Original line, left of the split. */
if (len > 0 && (clen = cp->cno + (append ? 1 : 0)) > 0) {
- memmove(bp, p, clen);
+ memcpy(bp, p, clen);
p += clen;
t += clen;
}
/* First line from the CB. */
- memmove(t, tp->lb, tp->len);
- t += tp->len;
+ if (tp->len != 0) {
+ memcpy(t, tp->lb, tp->len);
+ t += tp->len;
+ }
+
+ /* Calculate length left in the original line. */
+ clen = len == 0 ? 0 : len - (cp->cno + (append ? 1 : 0));
- /* Calculate length left in original line. */
- clen = len ? len - cp->cno - (append ? 1 : 0) : 0;
+ /*
+ * !!!
+ * In the historical 4BSD version of vi, character mode puts within
+ * a single line have two cursor behaviors: if the put is from the
+ * unnamed buffer, the cursor moves to the character inserted which
+ * appears last in the file. If the put is from a named buffer,
+ * the cursor moves to the character inserted which appears first
+ * in the file. In System III/V, it was changed at some point and
+ * the cursor always moves to the first character. In both versions
+ * of vi, character mode puts that cross line boundaries leave the
+ * cursor on the first character. Nvi implements the System III/V
+ * behavior, and expect POSIX.2 to do so as well.
+ */
+ rp->lno = lno;
+ rp->cno = len == 0 ? 0 : sp->cno + (append && tp->len ? 1 : 0);
/*
* If no more lines in the CB, append the rest of the original
@@ -172,22 +161,13 @@ put(sp, ep, cbp, namep, cp, rp, append)
* the intermediate lines, because the line changes will lose
* the cached line.
*/
- rval = 0;
if (tp->q.cqe_next == (void *)&cbp->textq) {
- /*
- * Historical practice is that if a non-line mode put
- * is inside a single line, the cursor ends up on the
- * last character inserted.
- */
- rp->lno = lno;
- rp->cno = (t - bp) - 1;
-
if (clen > 0) {
- memmove(t, p, clen);
+ memcpy(t, p, clen);
t += clen;
}
- if (file_sline(sp, ep, lno, bp, t - bp))
- goto mem;
+ if (db_set(sp, lno, bp, t - bp))
+ goto err;
if (sp->rptlchange != lno) {
sp->rptlchange = lno;
++sp->rptlines[L_CHANGED];
@@ -209,9 +189,9 @@ put(sp, ep, cbp, namep, cp, rp, append)
t = bp + len;
/* Add in last part of the CB. */
- memmove(t, ltp->lb, ltp->len);
+ memcpy(t, ltp->lb, ltp->len);
if (clen)
- memmove(t + ltp->len, p, clen);
+ memcpy(t + ltp->len, p, clen);
clen += ltp->len;
/*
@@ -223,32 +203,29 @@ put(sp, ep, cbp, namep, cp, rp, append)
*
* Output the line replacing the original line.
*/
- if (file_sline(sp, ep, lno, bp, t - bp))
- goto mem;
+ if (db_set(sp, lno, bp, t - bp))
+ goto err;
if (sp->rptlchange != lno) {
sp->rptlchange = lno;
++sp->rptlines[L_CHANGED];
}
- /*
- * Historical practice is that if a non-line mode put
- * covers multiple lines, the cursor ends up on the
- * first character inserted. (Of course.)
- */
- rp->lno = lno;
- rp->cno = (t - bp) - 1;
-
/* Output any intermediate lines in the CB. */
for (tp = tp->q.cqe_next;
tp->q.cqe_next != (void *)&cbp->textq;
++lno, ++sp->rptlines[L_ADDED], tp = tp->q.cqe_next)
- if (file_aline(sp, ep, 1, lno, tp->lb, tp->len))
- goto mem;
+ if (db_append(sp, 1, lno, tp->lb, tp->len))
+ goto err;
- if (file_aline(sp, ep, 1, lno, t, clen))
-mem: rval = 1;
+ if (db_append(sp, 1, lno, t, clen))
+ goto err;
++sp->rptlines[L_ADDED];
}
+ rval = 0;
+
+ if (0)
+err: rval = 1;
+
FREE_SPACE(sp, bp, blen);
return (rval);
}
diff --git a/usr.bin/vi/common/recover.c b/contrib/nvi/common/recover.c
index f218c0645d3e..f3abaab5a536 100644
--- a/usr.bin/vi/common/recover.c
+++ b/contrib/nvi/common/recover.c
@@ -1,44 +1,22 @@
/*-
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)recover.c 8.72 (Berkeley) 7/21/94";
+static const char sccsid[] = "@(#)recover.c 10.21 (Berkeley) 9/15/96";
#endif /* not lint */
#include <sys/param.h>
+#include <sys/types.h> /* XXX: param.h may not have included types.h */
#include <sys/queue.h>
#include <sys/stat.h>
-#include <sys/time.h>
/*
* We include <sys/file.h>, because the open #defines were found there
@@ -47,27 +25,20 @@ static char sccsid[] = "@(#)recover.c 8.72 (Berkeley) 7/21/94";
*/
#include <sys/file.h>
-#include <netdb.h> /* MAXHOSTNAMELEN on some systems. */
-
#include <bitstring.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <pwd.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
+#include <time.h>
#include <unistd.h>
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-#include <pathnames.h>
-
-#include "vi.h"
+#include "common.h"
+#include "pathnames.h"
/*
* Recovery code.
@@ -99,7 +70,7 @@ static char sccsid[] = "@(#)recover.c 8.72 (Berkeley) 7/21/94";
* To find out if a backing file can be deleted at boot time, check for an
* owner execute bit. (Yes, I know it's ugly, but it's either that or put
* special stuff into the backing file itself, or correlate the files at
- * boot time, neither or which looks like fun.) Note also that there's a
+ * boot time, neither of which looks like fun.) Note also that there's a
* window between when the file is created and the X bit is set. It's small,
* but it's there. To fix the window, check for 0 length files as well.
*
@@ -141,12 +112,14 @@ static char sccsid[] = "@(#)recover.c 8.72 (Berkeley) 7/21/94";
static int rcv_copy __P((SCR *, int, char *));
static void rcv_email __P((SCR *, char *));
static char *rcv_gets __P((char *, size_t, int));
-static int rcv_mailfile __P((SCR *, EXF *, int, char *));
+static int rcv_mailfile __P((SCR *, int, char *));
static int rcv_mktemp __P((SCR *, char *, char *, int));
/*
* rcv_tmp --
* Build a file name that will be used as the recovery file.
+ *
+ * PUBLIC: int rcv_tmp __P((SCR *, EXF *, char *));
*/
int
rcv_tmp(sp, ep, name)
@@ -159,12 +132,18 @@ rcv_tmp(sp, ep, name)
char *dp, *p, path[MAXPATHLEN];
/*
+ * !!!
+ * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+ *
+ *
* If the recovery directory doesn't exist, try and create it. As
* the recovery files are themselves protected from reading/writing
* by other than the owner, the worst that can happen is that a user
* would have permission to remove other user's recovery files. If
* the sticky bit has the BSD semantics, that too will be impossible.
*/
+ if (opts_empty(sp, O_RECDIR, 0))
+ goto err;
dp = O_STR(sp, O_RECDIR);
if (stat(dp, &sb)) {
if (errno != ENOENT || mkdir(dp, 0)) {
@@ -178,7 +157,7 @@ rcv_tmp(sp, ep, name)
for (p = name; *p; ++p)
if (*p == '\n') {
msgq(sp, M_ERR,
- "Files with newlines in the name are unrecoverable");
+ "055|Files with newlines in the name are unrecoverable");
goto err;
}
@@ -191,7 +170,7 @@ rcv_tmp(sp, ep, name)
msgq(sp, M_SYSERR, NULL);
(void)unlink(path);
err: msgq(sp, M_ERR,
- "Modifications not recoverable if the session fails");
+ "056|Modifications not recoverable if the session fails");
return (1);
}
@@ -203,14 +182,17 @@ err: msgq(sp, M_ERR,
/*
* rcv_init --
* Force the file to be snapshotted for recovery.
+ *
+ * PUBLIC: int rcv_init __P((SCR *));
*/
int
-rcv_init(sp, ep)
+rcv_init(sp)
SCR *sp;
- EXF *ep;
{
+ EXF *ep;
recno_t lno;
- int btear;
+
+ ep = sp->ep;
/* Only do this once. */
F_CLR(ep, F_FIRSTMODIFY);
@@ -225,32 +207,23 @@ rcv_init(sp, ep)
/* Test if we're recovering a file, not editing one. */
if (ep->rcv_mpath == NULL) {
/* Build a file to mail to the user. */
- if (rcv_mailfile(sp, ep, 0, NULL))
+ if (rcv_mailfile(sp, 0, NULL))
goto err;
/* Force a read of the entire file. */
- if (file_lline(sp, ep, &lno))
+ if (db_last(sp, &lno))
goto err;
/* Turn on a busy message, and sync it to backing store. */
- btear = F_ISSET(sp, S_EXSILENT) ? 0 :
- !busy_on(sp, "Copying file for recovery...");
+ sp->gp->scr_busy(sp,
+ "057|Copying file for recovery...", BUSY_ON);
if (ep->db->sync(ep->db, R_RECNOSYNC)) {
- msgq(sp, M_ERR, "Preservation failed: %s: %s",
- ep->rcv_path, strerror(errno));
- if (btear)
- busy_off(sp);
+ msgq_str(sp, M_SYSERR, ep->rcv_path,
+ "058|Preservation failed: %s");
+ sp->gp->scr_busy(sp, NULL, BUSY_OFF);
goto err;
}
- if (btear)
- busy_off(sp);
- }
-
- /* Turn on the recovery timer, if it's not yet running. */
- if (!F_ISSET(sp->gp, G_RECOVER_SET) && rcv_on(sp, ep)) {
-err: msgq(sp, M_ERR,
- "Modifications not recoverable if the session fails");
- return (1);
+ sp->gp->scr_busy(sp, NULL, BUSY_OFF);
}
/* Turn off the owner execute bit. */
@@ -259,6 +232,10 @@ err: msgq(sp, M_ERR,
/* We believe the file is recoverable. */
F_SET(ep, F_RCV_ON);
return (0);
+
+err: msgq(sp, M_ERR,
+ "059|Modifications not recoverable if the session fails");
+ return (1);
}
/*
@@ -268,28 +245,34 @@ err: msgq(sp, M_ERR,
* snapshotting the backup file and send email to the user
* sending email to the user if the file was modified
* ending the file session
+ *
+ * PUBLIC: int rcv_sync __P((SCR *, u_int));
*/
int
-rcv_sync(sp, ep, flags)
+rcv_sync(sp, flags)
SCR *sp;
- EXF *ep;
u_int flags;
{
- int btear, fd, rval;
+ EXF *ep;
+ int fd, rval;
char *dp, buf[1024];
/* Make sure that there's something to recover/sync. */
+ ep = sp->ep;
if (ep == NULL || !F_ISSET(ep, F_RCV_ON))
return (0);
/* Sync the file if it's been modified. */
if (F_ISSET(ep, F_MODIFIED)) {
+ SIGBLOCK;
if (ep->db->sync(ep->db, R_RECNOSYNC)) {
F_CLR(ep, F_RCV_ON | F_RCV_NORM);
- msgq(sp, M_SYSERR,
- "File backup failed: %s", ep->rcv_path);
+ msgq_str(sp, M_SYSERR,
+ ep->rcv_path, "060|File backup failed: %s");
+ SIGUNBLOCK;
return (1);
}
+ SIGUNBLOCK;
/* REQUEST: don't remove backing file on exit. */
if (LF_ISSET(RCV_PRESERVE))
@@ -312,26 +295,28 @@ rcv_sync(sp, ep, flags)
*/
rval = 0;
if (LF_ISSET(RCV_SNAPSHOT)) {
- btear = F_ISSET(sp, S_EXSILENT) ? 0 :
- !busy_on(sp, "Copying file for recovery...");
+ if (opts_empty(sp, O_RECDIR, 0))
+ goto err;
dp = O_STR(sp, O_RECDIR);
(void)snprintf(buf, sizeof(buf), "%s/vi.XXXXXX", dp);
if ((fd = rcv_mktemp(sp, buf, dp, S_IRUSR | S_IWUSR)) == -1)
- goto e1;
- if (rcv_copy(sp, fd, ep->rcv_path) || close(fd))
- goto e2;
- if (rcv_mailfile(sp, ep, 1, buf)) {
-e2: (void)unlink(buf);
-e1: if (fd != -1)
- (void)close(fd);
+ goto err;
+ sp->gp->scr_busy(sp,
+ "061|Copying file for recovery...", BUSY_ON);
+ if (rcv_copy(sp, fd, ep->rcv_path) ||
+ close(fd) || rcv_mailfile(sp, 1, buf)) {
+ (void)unlink(buf);
+ (void)close(fd);
rval = 1;
}
- if (btear)
- busy_off(sp);
+ sp->gp->scr_busy(sp, NULL, BUSY_OFF);
+ }
+ if (0) {
+err: rval = 1;
}
/* REQUEST: end the file session. */
- if (LF_ISSET(RCV_ENDSESSION) && file_end(sp, ep, 1))
+ if (LF_ISSET(RCV_ENDSESSION) && file_end(sp, NULL, 1))
rval = 1;
return (rval);
@@ -342,25 +327,40 @@ e1: if (fd != -1)
* Build the file to mail to the user.
*/
static int
-rcv_mailfile(sp, ep, issync, cp_path)
+rcv_mailfile(sp, issync, cp_path)
SCR *sp;
- EXF *ep;
int issync;
char *cp_path;
{
+ EXF *ep;
+ GS *gp;
struct passwd *pw;
size_t len;
time_t now;
uid_t uid;
int fd;
- char *dp, *p, *t, buf[4096], host[MAXHOSTNAMELEN], mpath[MAXPATHLEN];
+ char *dp, *p, *t, buf[4096], mpath[MAXPATHLEN];
char *t1, *t2, *t3;
+ /*
+ * XXX
+ * MAXHOSTNAMELEN is in various places on various systems, including
+ * <netdb.h> and <sys/socket.h>. If not found, use a large default.
+ */
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 1024
+#endif
+ char host[MAXHOSTNAMELEN];
+
+ gp = sp->gp;
if ((pw = getpwuid(uid = getuid())) == NULL) {
- msgq(sp, M_ERR, "Information on user id %u not found", uid);
+ msgq(sp, M_ERR,
+ "062|Information on user id %u not found", uid);
return (1);
}
+ if (opts_empty(sp, O_RECDIR, 0))
+ return (1);
dp = O_STR(sp, O_RECDIR);
(void)snprintf(mpath, sizeof(mpath), "%s/recover.XXXXXX", dp);
if ((fd = rcv_mktemp(sp, mpath, dp, S_IRUSR | S_IWUSR)) == -1)
@@ -373,8 +373,9 @@ rcv_mailfile(sp, ep, issync, cp_path)
* be recovered. There's an obvious window between the mkstemp call
* and the lock, but it's pretty small.
*/
- if (file_lock(NULL, NULL, fd, 1) != LOCK_SUCCESS)
- msgq(sp, M_SYSERR, "Unable to lock recovery file");
+ ep = sp->ep;
+ if (file_lock(sp, NULL, NULL, fd, 1) != LOCK_SUCCESS)
+ msgq(sp, M_SYSERR, "063|Unable to lock recovery file");
if (!issync) {
/* Save the recover file descriptor, and mail path. */
ep->rcv_fd = fd;
@@ -413,15 +414,16 @@ rcv_mailfile(sp, ep, issync, cp_path)
if (write(fd, buf, len) != len)
goto werr;
- len = snprintf(buf, sizeof(buf), "%s%.24s%s%s%s%s%s%s%s%s%s%s%s\n\n",
+ len = snprintf(buf, sizeof(buf),
+ "%s%.24s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n\n",
"On ", ctime(&now), ", the user ", pw->pw_name,
" was editing a file named ", t, " on the machine ",
host, ", when it was saved for recovery. ",
"You can recover most, if not all, of the changes ",
- "to this file using the -r option to nex or nvi:\n\n",
- "\tnvi -r ", t);
+ "to this file using the -r option to ", gp->progname, ":\n\n\t",
+ gp->progname, " -r ", t);
if (len > sizeof(buf) - 1) {
-lerr: msgq(sp, M_ERR, "recovery file buffer overrun");
+lerr: msgq(sp, M_ERR, "064|Recovery file buffer overrun");
goto err;
}
@@ -455,15 +457,17 @@ lerr: msgq(sp, M_ERR, "recovery file buffer overrun");
wout: *t2++ = '\n';
/* t2 points one after the last character to display. */
- if (write(fd, t1, t2 - t1) != t2 - t1) {
-werr: msgq(sp, M_SYSERR, "recovery file");
- goto err;
- }
+ if (write(fd, t1, t2 - t1) != t2 - t1)
+ goto werr;
}
- if (issync)
+ if (issync) {
rcv_email(sp, mpath);
-
+ if (close(fd)) {
+werr: msgq(sp, M_SYSERR, "065|Recovery file");
+ goto err;
+ }
+ }
return (0);
err: if (!issync)
@@ -480,6 +484,8 @@ err: if (!issync)
*
* rcv_list --
* List the files that can be recovered by this user.
+ *
+ * PUBLIC: int rcv_list __P((SCR *));
*/
int
rcv_list(sp)
@@ -492,16 +498,16 @@ rcv_list(sp)
int found;
char *p, *t, file[MAXPATHLEN], path[MAXPATHLEN];
- /*
- * XXX
- * Messages aren't yet set up.
- */
- if (chdir(O_STR(sp, O_RECDIR)) || (dirp = opendir(".")) == NULL) {
- (void)fprintf(stderr,
- "vi: %s: %s\n", O_STR(sp, O_RECDIR), strerror(errno));
+ /* Open the recovery directory for reading. */
+ if (opts_empty(sp, O_RECDIR, 0))
+ return (1);
+ p = O_STR(sp, O_RECDIR);
+ if (chdir(p) || (dirp = opendir(".")) == NULL) {
+ msgq_str(sp, M_SYSERR, p, "recdir: %s");
return (1);
}
+ /* Read the directory. */
for (found = 0; (dp = readdir(dirp)) != NULL;) {
if (strncmp(dp->d_name, "recover.", 8))
continue;
@@ -517,7 +523,7 @@ rcv_list(sp)
if ((fp = fopen(dp->d_name, "r+")) == NULL)
continue;
- switch (file_lock(NULL, NULL, fileno(fp), 1)) {
+ switch (file_lock(sp, NULL, NULL, fileno(fp), 1)) {
case LOCK_FAILED:
/*
* XXX
@@ -542,8 +548,8 @@ rcv_list(sp)
fgets(path, sizeof(path), fp) == NULL ||
strncmp(path, VI_PHEADER, sizeof(VI_PHEADER) - 1) ||
(t = strchr(path, '\n')) == NULL) {
- msgq(sp, M_ERR,
- "%s: malformed recovery file", dp->d_name);
+ msgq_str(sp, M_ERR, dp->d_name,
+ "066|%s: malformed recovery file");
goto next;
}
*p = *t = '\0';
@@ -565,8 +571,8 @@ rcv_list(sp)
/* Get the last modification time and display. */
(void)fstat(fileno(fp), &sb);
- (void)printf("%s: %s",
- file + sizeof(VI_FHEADER) - 1, ctime(&sb.st_mtime));
+ (void)printf("%.24s: %s\n",
+ ctime(&sb.st_mtime), file + sizeof(VI_FHEADER) - 1);
found = 1;
/* Close, discarding lock. */
@@ -581,6 +587,8 @@ next: (void)fclose(fp);
/*
* rcv_read --
* Start a recovered file as the file to edit.
+ *
+ * PUBLIC: int rcv_read __P((SCR *, FREF *));
*/
int
rcv_read(sp, frp)
@@ -593,12 +601,14 @@ rcv_read(sp, frp)
EXF *ep;
time_t rec_mtime;
int fd, found, locked, requested, sv_fd;
- char *name, *p, *t, *recp, *pathp;
+ char *name, *p, *t, *rp, *recp, *pathp;
char file[MAXPATHLEN], path[MAXPATHLEN], recpath[MAXPATHLEN];
- if ((dirp = opendir(O_STR(sp, O_RECDIR))) == NULL) {
- msgq(sp, M_ERR,
- "%s: %s", O_STR(sp, O_RECDIR), strerror(errno));
+ if (opts_empty(sp, O_RECDIR, 0))
+ return (1);
+ rp = O_STR(sp, O_RECDIR);
+ if ((dirp = opendir(rp)) == NULL) {
+ msgq_str(sp, M_ERR, rp, "%s");
return (1);
}
@@ -609,8 +619,8 @@ rcv_read(sp, frp)
for (found = requested = 0; (dp = readdir(dirp)) != NULL;) {
if (strncmp(dp->d_name, "recover.", 8))
continue;
- (void)snprintf(recpath, sizeof(recpath),
- "%s/%s", O_STR(sp, O_RECDIR), dp->d_name);
+ (void)snprintf(recpath,
+ sizeof(recpath), "%s/%s", rp, dp->d_name);
/*
* If it's readable, it's recoverable. It would be very
@@ -627,7 +637,7 @@ rcv_read(sp, frp)
if ((fd = open(recpath, O_RDWR, 0)) == -1)
continue;
- switch (file_lock(NULL, NULL, fd, 1)) {
+ switch (file_lock(sp, NULL, NULL, fd, 1)) {
case LOCK_FAILED:
/*
* XXX
@@ -654,8 +664,8 @@ rcv_read(sp, frp)
rcv_gets(path, sizeof(path), fd) == NULL ||
strncmp(path, VI_PHEADER, sizeof(VI_PHEADER) - 1) ||
(t = strchr(path, '\n')) == NULL) {
- msgq(sp, M_ERR,
- "%s: malformed recovery file", recpath);
+ msgq_str(sp, M_ERR, recpath,
+ "067|%s: malformed recovery file");
goto next;
}
*p = *t = '\0';
@@ -695,22 +705,20 @@ rcv_read(sp, frp)
p = recp;
t = pathp;
if ((recp = strdup(recpath)) == NULL) {
- msgq(sp, M_ERR,
- "vi: Error: %s.\n", strerror(errno));
+ msgq(sp, M_SYSERR, NULL);
recp = p;
goto next;
}
if ((pathp = strdup(path)) == NULL) {
- msgq(sp, M_ERR,
- "vi: Error: %s.\n", strerror(errno));
- FREE(recp, strlen(recp) + 1);
+ msgq(sp, M_SYSERR, NULL);
+ free(recp);
recp = p;
pathp = t;
goto next;
}
if (p != NULL) {
- FREE(p, strlen(p) + 1);
- FREE(t, strlen(t) + 1);
+ free(p);
+ free(t);
}
rec_mtime = sb.st_mtime;
if (sv_fd != -1)
@@ -722,17 +730,17 @@ next: (void)close(fd);
(void)closedir(dirp);
if (recp == NULL) {
- msgq(sp, M_INFO,
- "No files named %s, readable by you, to recover", name);
+ msgq_str(sp, M_INFO, name,
+ "068|No files named %s, readable by you, to recover");
return (1);
}
if (found) {
if (requested > 1)
msgq(sp, M_INFO,
- "There are older versions of this file for you to recover");
+ "069|There are older versions of this file for you to recover");
if (found > requested)
msgq(sp, M_INFO,
- "There are other files for you to recover");
+ "070|There are other files for you to recover");
}
/*
@@ -786,7 +794,7 @@ rcv_copy(sp, wfd, fname)
if (nr == 0)
return (0);
-err: msgq(sp, M_SYSERR, "%s", fname);
+err: msgq_str(sp, M_SYSERR, fname, "%s");
return (1);
}
@@ -800,7 +808,7 @@ rcv_gets(buf, len, fd)
size_t len;
int fd;
{
- ssize_t nr;
+ int nr;
char *p;
if ((nr = read(fd, buf, len - 1)) == -1)
@@ -834,7 +842,7 @@ rcv_mktemp(sp, path, dname, perms)
* be nice to use fchmod(2) instead of chmod(2), here.
*/
if ((fd = mkstemp(path)) == -1)
- msgq(sp, M_SYSERR, "%s", dname);
+ msgq_str(sp, M_SYSERR, dname, "%s");
else
(void)chmod(path, perms);
return (fd);
@@ -852,8 +860,9 @@ rcv_email(sp, fname)
struct stat sb;
char buf[MAXPATHLEN * 2 + 20];
- if (stat(_PATH_SENDMAIL, &sb))
- msgq(sp, M_SYSERR, "not sending email: %s", _PATH_SENDMAIL);
+ if (_PATH_SENDMAIL[0] != '/' || stat(_PATH_SENDMAIL, &sb))
+ msgq_str(sp, M_SYSERR,
+ _PATH_SENDMAIL, "071|not sending email: %s");
else {
/*
* !!!
diff --git a/contrib/nvi/common/screen.c b/contrib/nvi/common/screen.c
new file mode 100644
index 000000000000..ba9e287b648b
--- /dev/null
+++ b/contrib/nvi/common/screen.c
@@ -0,0 +1,233 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)screen.c 10.15 (Berkeley) 9/15/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "../vi/vi.h"
+
+/*
+ * screen_init --
+ * Do the default initialization of an SCR structure.
+ *
+ * PUBLIC: int screen_init __P((GS *, SCR *, SCR **));
+ */
+int
+screen_init(gp, orig, spp)
+ GS *gp;
+ SCR *orig, **spp;
+{
+ SCR *sp;
+ size_t len;
+
+ *spp = NULL;
+ CALLOC_RET(orig, sp, SCR *, 1, sizeof(SCR));
+ *spp = sp;
+
+/* INITIALIZED AT SCREEN CREATE. */
+ sp->id = ++gp->id;
+ sp->refcnt = 1;
+
+ sp->gp = gp; /* All ref the GS structure. */
+
+ sp->ccnt = 2; /* Anything > 1 */
+
+ /*
+ * XXX
+ * sp->defscroll is initialized by the opts_init() code because
+ * we don't have the option information yet.
+ */
+
+ CIRCLEQ_INIT(&sp->tiq);
+
+/* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */
+ if (orig == NULL) {
+ sp->searchdir = NOTSET;
+ } else {
+ /* Alternate file name. */
+ if (orig->alt_name != NULL &&
+ (sp->alt_name = strdup(orig->alt_name)) == NULL)
+ goto mem;
+
+ /* Last executed at buffer. */
+ if (F_ISSET(orig, SC_AT_SET)) {
+ F_SET(sp, SC_AT_SET);
+ sp->at_lbuf = orig->at_lbuf;
+ }
+
+ /* Retain searching/substitution information. */
+ sp->searchdir = orig->searchdir == NOTSET ? NOTSET : FORWARD;
+ if (orig->re != NULL && (sp->re =
+ v_strdup(sp, orig->re, orig->re_len)) == NULL)
+ goto mem;
+ sp->re_len = orig->re_len;
+ if (orig->subre != NULL && (sp->subre =
+ v_strdup(sp, orig->subre, orig->subre_len)) == NULL)
+ goto mem;
+ sp->subre_len = orig->subre_len;
+ if (orig->repl != NULL && (sp->repl =
+ v_strdup(sp, orig->repl, orig->repl_len)) == NULL)
+ goto mem;
+ sp->repl_len = orig->repl_len;
+ if (orig->newl_len) {
+ len = orig->newl_len * sizeof(size_t);
+ MALLOC(sp, sp->newl, size_t *, len);
+ if (sp->newl == NULL) {
+mem: msgq(orig, M_SYSERR, NULL);
+ goto err;
+ }
+ sp->newl_len = orig->newl_len;
+ sp->newl_cnt = orig->newl_cnt;
+ memcpy(sp->newl, orig->newl, len);
+ }
+
+ if (opts_copy(orig, sp))
+ goto err;
+
+ F_SET(sp, F_ISSET(orig, SC_EX | SC_VI));
+ }
+
+ if (ex_screen_copy(orig, sp)) /* Ex. */
+ goto err;
+ if (v_screen_copy(orig, sp)) /* Vi. */
+ goto err;
+
+ *spp = sp;
+ return (0);
+
+err: screen_end(sp);
+ return (1);
+}
+
+/*
+ * screen_end --
+ * Release a screen, no matter what had (and had not) been
+ * initialized.
+ *
+ * PUBLIC: int screen_end __P((SCR *));
+ */
+int
+screen_end(sp)
+ SCR *sp;
+{
+ int rval;
+
+ /* If multiply referenced, just decrement the count and return. */
+ if (--sp->refcnt != 0)
+ return (0);
+
+ /*
+ * Remove the screen from the displayed queue.
+ *
+ * If a created screen failed during initialization, it may not
+ * be linked into the chain.
+ */
+ if (sp->q.cqe_next != NULL)
+ CIRCLEQ_REMOVE(&sp->gp->dq, sp, q);
+
+ /* The screen is no longer real. */
+ F_CLR(sp, SC_SCR_EX | SC_SCR_VI);
+
+ rval = 0;
+#ifdef HAVE_PERL_INTERP
+ if (perl_screen_end(sp)) /* End perl. */
+ rval = 1;
+#endif
+ if (v_screen_end(sp)) /* End vi. */
+ rval = 1;
+ if (ex_screen_end(sp)) /* End ex. */
+ rval = 1;
+
+ /* Free file names. */
+ { char **ap;
+ if (!F_ISSET(sp, SC_ARGNOFREE) && sp->argv != NULL) {
+ for (ap = sp->argv; *ap != NULL; ++ap)
+ free(*ap);
+ free(sp->argv);
+ }
+ }
+
+ /* Free any text input. */
+ if (sp->tiq.cqh_first != NULL)
+ text_lfree(&sp->tiq);
+
+ /* Free alternate file name. */
+ if (sp->alt_name != NULL)
+ free(sp->alt_name);
+
+ /* Free up search information. */
+ if (sp->re != NULL)
+ free(sp->re);
+ if (F_ISSET(sp, SC_RE_SEARCH))
+ regfree(&sp->re_c);
+ if (sp->subre != NULL)
+ free(sp->subre);
+ if (F_ISSET(sp, SC_RE_SUBST))
+ regfree(&sp->subre_c);
+ if (sp->repl != NULL)
+ free(sp->repl);
+ if (sp->newl != NULL)
+ free(sp->newl);
+
+ /* Free all the options */
+ opts_free(sp);
+
+ /* Free the screen itself. */
+ free(sp);
+
+ return (rval);
+}
+
+/*
+ * screen_next --
+ * Return the next screen in the queue.
+ *
+ * PUBLIC: SCR *screen_next __P((SCR *));
+ */
+SCR *
+screen_next(sp)
+ SCR *sp;
+{
+ GS *gp;
+ SCR *next;
+
+ /* Try the display queue, without returning the current screen. */
+ gp = sp->gp;
+ for (next = gp->dq.cqh_first;
+ next != (void *)&gp->dq; next = next->q.cqe_next)
+ if (next != sp)
+ break;
+ if (next != (void *)&gp->dq)
+ return (next);
+
+ /* Try the hidden queue; if found, move screen to the display queue. */
+ if (gp->hq.cqh_first != (void *)&gp->hq) {
+ next = gp->hq.cqh_first;
+ CIRCLEQ_REMOVE(&gp->hq, next, q);
+ CIRCLEQ_INSERT_HEAD(&gp->dq, next, q);
+ return (next);
+ }
+ return (NULL);
+}
diff --git a/contrib/nvi/common/screen.h b/contrib/nvi/common/screen.h
new file mode 100644
index 000000000000..bb7254f62a21
--- /dev/null
+++ b/contrib/nvi/common/screen.h
@@ -0,0 +1,203 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)screen.h 10.24 (Berkeley) 7/19/96
+ */
+
+/*
+ * There are minimum values that vi has to have to display a screen. The row
+ * minimum is fixed at 1 (the svi code can share a line between the text line
+ * and the colon command/message line). Column calculation is a lot trickier.
+ * For example, you have to have enough columns to display the line number,
+ * not to mention guaranteeing that tabstop and shiftwidth values are smaller
+ * than the current column value. It's simpler to have a fixed value and not
+ * worry about it.
+ *
+ * XXX
+ * MINIMUM_SCREEN_COLS is almost certainly wrong.
+ */
+#define MINIMUM_SCREEN_ROWS 1
+#define MINIMUM_SCREEN_COLS 20
+
+/*
+ * SCR --
+ * The screen structure. To the extent possible, all screen information
+ * is stored in the various private areas. The only information here
+ * is used by global routines or is shared by too many screens.
+ */
+struct _scr {
+/* INITIALIZED AT SCREEN CREATE. */
+ CIRCLEQ_ENTRY(_scr) q; /* Screens. */
+
+ int id; /* Screen id #. */
+ int refcnt; /* Reference count. */
+
+ GS *gp; /* Pointer to global area. */
+ SCR *nextdisp; /* Next display screen. */
+ SCR *ccl_parent; /* Colon command-line parent screen. */
+ EXF *ep; /* Screen's current EXF structure. */
+
+ FREF *frp; /* FREF being edited. */
+ char **argv; /* NULL terminated file name array. */
+ char **cargv; /* Current file name. */
+
+ u_long ccnt; /* Command count. */
+ u_long q_ccnt; /* Quit or ZZ command count. */
+
+ /* Screen's: */
+ size_t rows; /* 1-N: number of rows. */
+ size_t cols; /* 1-N: number of columns. */
+ size_t t_rows; /* 1-N: cur number of text rows. */
+ size_t t_maxrows; /* 1-N: max number of text rows. */
+ size_t t_minrows; /* 1-N: min number of text rows. */
+ size_t woff; /* 0-N: screen offset in frame. */
+
+ /* Cursor's: */
+ recno_t lno; /* 1-N: file line. */
+ size_t cno; /* 0-N: file character in line. */
+
+ size_t rcm; /* Vi: 0-N: Most attractive column. */
+
+#define L_ADDED 0 /* Added lines. */
+#define L_CHANGED 1 /* Changed lines. */
+#define L_DELETED 2 /* Deleted lines. */
+#define L_JOINED 3 /* Joined lines. */
+#define L_MOVED 4 /* Moved lines. */
+#define L_SHIFT 5 /* Shift lines. */
+#define L_YANKED 6 /* Yanked lines. */
+ recno_t rptlchange; /* Ex/vi: last L_CHANGED lno. */
+ recno_t rptlines[L_YANKED + 1];/* Ex/vi: lines changed by last op. */
+
+ TEXTH tiq; /* Ex/vi: text input queue. */
+
+ SCRIPT *script; /* Vi: script mode information .*/
+
+ recno_t defscroll; /* Vi: ^D, ^U scroll information. */
+
+ /* Display character. */
+ CHAR_T cname[MAX_CHARACTER_COLUMNS + 1];
+ size_t clen; /* Length of display character. */
+
+ enum { /* Vi editor mode. */
+ SM_APPEND = 0, SM_CHANGE, SM_COMMAND, SM_INSERT,
+ SM_REPLACE } showmode;
+
+ void *ex_private; /* Ex private area. */
+ void *vi_private; /* Vi private area. */
+ void *perl_private; /* Perl private area. */
+
+/* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */
+ char *alt_name; /* Ex/vi: alternate file name. */
+
+ CHAR_T at_lbuf; /* Ex/vi: Last executed at buffer. */
+
+ /* Ex/vi: re_compile flags. */
+#define RE_C_CSCOPE 0x0001 /* Compile cscope pattern. */
+#define RE_C_SEARCH 0x0002 /* Compile search replacement. */
+#define RE_C_SILENT 0x0004 /* No error messages. */
+#define RE_C_SUBST 0x0008 /* Compile substitute replacement. */
+#define RE_C_TAG 0x0010 /* Compile ctag pattern. */
+
+#define RE_WSTART "[[:<:]]" /* Ex/vi: not-in-word search pattern. */
+#define RE_WSTOP "[[:>:]]"
+ /* Ex/vi: flags to search routines. */
+#define SEARCH_CSCOPE 0x0001 /* Search for a cscope pattern. */
+#define SEARCH_EOL 0x0002 /* Offset past EOL is okay. */
+#define SEARCH_FILE 0x0004 /* Search the entire file. */
+#define SEARCH_INCR 0x0008 /* Search incrementally. */
+#define SEARCH_MSG 0x0010 /* Display search messages. */
+#define SEARCH_PARSE 0x0020 /* Parse the search pattern. */
+#define SEARCH_SET 0x0040 /* Set search direction. */
+#define SEARCH_TAG 0x0080 /* Search for a tag pattern. */
+#define SEARCH_WMSG 0x0100 /* Display search-wrapped messages. */
+
+ /* Ex/vi: RE information. */
+ dir_t searchdir; /* Last file search direction. */
+ regex_t re_c; /* Search RE: compiled form. */
+ char *re; /* Search RE: uncompiled form. */
+ size_t re_len; /* Search RE: uncompiled length. */
+ regex_t subre_c; /* Substitute RE: compiled form. */
+ char *subre; /* Substitute RE: uncompiled form. */
+ size_t subre_len; /* Substitute RE: uncompiled length). */
+ char *repl; /* Substitute replacement. */
+ size_t repl_len; /* Substitute replacement length.*/
+ size_t *newl; /* Newline offset array. */
+ size_t newl_len; /* Newline array size. */
+ size_t newl_cnt; /* Newlines in replacement. */
+ u_int8_t c_suffix; /* Edcompatible 'c' suffix value. */
+ u_int8_t g_suffix; /* Edcompatible 'g' suffix value. */
+
+ OPTION opts[O_OPTIONCOUNT]; /* Ex/vi: Options. */
+
+/*
+ * Screen flags.
+ *
+ * Editor screens.
+ */
+#define SC_EX 0x00000001 /* Ex editor. */
+#define SC_VI 0x00000002 /* Vi editor. */
+
+/*
+ * Screen formatting flags, first major, then minor.
+ *
+ * SC_SCR_EX
+ * Ex screen, i.e. cooked mode.
+ * SC_SCR_VI
+ * Vi screen, i.e. raw mode.
+ * SC_SCR_EXWROTE
+ * The editor had to write on the screen behind curses' back, and we can't
+ * let curses change anything until the user agrees, e.g. entering the
+ * commands :!utility followed by :set. We have to switch back into the
+ * vi "editor" to read the user's command input, but we can't touch the
+ * rest of the screen because it's known to be wrong.
+ * SC_SCR_REFORMAT
+ * The expected presentation of the lines on the screen have changed,
+ * requiring that the intended screen lines be recalculated. Implies
+ * SC_SCR_REDRAW.
+ * SC_SCR_REDRAW
+ * The screen doesn't correctly represent the file; repaint it. Note,
+ * setting SC_SCR_REDRAW in the current window causes *all* windows to
+ * be repainted.
+ * SC_SCR_CENTER
+ * If the current line isn't already on the screen, center it.
+ * SC_SCR_TOP
+ * If the current line isn't already on the screen, put it at the to@.
+ */
+#define SC_SCR_EX 0x00000004 /* Screen is in ex mode. */
+#define SC_SCR_VI 0x00000008 /* Screen is in vi mode. */
+#define SC_SCR_EXWROTE 0x00000010 /* Ex overwrite: see comment above. */
+#define SC_SCR_REFORMAT 0x00000020 /* Reformat (refresh). */
+#define SC_SCR_REDRAW 0x00000040 /* Refresh. */
+
+#define SC_SCR_CENTER 0x00000080 /* Center the line if not visible. */
+#define SC_SCR_TOP 0x00000100 /* Top the line if not visible. */
+
+/* Screen/file changes. */
+#define SC_EXIT 0x00000200 /* Exiting (not forced). */
+#define SC_EXIT_FORCE 0x00000400 /* Exiting (forced). */
+#define SC_FSWITCH 0x00000800 /* Switch underlying files. */
+#define SC_SSWITCH 0x00001000 /* Switch screens. */
+
+#define SC_ARGNOFREE 0x00002000 /* Argument list wasn't allocated. */
+#define SC_ARGRECOVER 0x00004000 /* Argument list is recovery files. */
+#define SC_AT_SET 0x00008000 /* Last at buffer set. */
+#define SC_COMEDIT 0x00010000 /* Colon command-line edit window. */
+#define SC_EX_GLOBAL 0x00020000 /* Ex: executing a global command. */
+#define SC_EX_SILENT 0x00040000 /* Ex: batch script. */
+#define SC_EX_WAIT_NO 0x00080000 /* Ex: don't wait for the user. */
+#define SC_EX_WAIT_YES 0x00100000 /* Ex: do wait for the user. */
+#define SC_READONLY 0x00200000 /* Persistent readonly state. */
+#define SC_RE_SEARCH 0x00400000 /* Search RE has been compiled. */
+#define SC_RE_SUBST 0x00800000 /* Substitute RE has been compiled. */
+#define SC_SCRIPT 0x01000000 /* Shell script window. */
+#define SC_STATUS 0x02000000 /* Welcome message. */
+#define SC_STATUS_CNT 0x04000000 /* Welcome message plus file count. */
+#define SC_TINPUT 0x08000000 /* Doing text input. */
+#define SC_TINPUT_INFO 0x10000000 /* Doing text input on info line. */
+ u_int32_t flags;
+};
diff --git a/contrib/nvi/common/search.c b/contrib/nvi/common/search.c
new file mode 100644
index 000000000000..3fd2719778fa
--- /dev/null
+++ b/contrib/nvi/common/search.c
@@ -0,0 +1,492 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)search.c 10.25 (Berkeley) 6/30/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+
+typedef enum { S_EMPTY, S_EOF, S_NOPREV, S_NOTFOUND, S_SOF, S_WRAP } smsg_t;
+
+static void search_msg __P((SCR *, smsg_t));
+static int search_init __P((SCR *, dir_t, char *, size_t, char **, u_int));
+
+/*
+ * search_init --
+ * Set up a search.
+ */
+static int
+search_init(sp, dir, ptrn, plen, epp, flags)
+ SCR *sp;
+ dir_t dir;
+ char *ptrn, **epp;
+ size_t plen;
+ u_int flags;
+{
+ recno_t lno;
+ int delim;
+ char *p, *t;
+
+ /* If the file is empty, it's a fast search. */
+ if (sp->lno <= 1) {
+ if (db_last(sp, &lno))
+ return (1);
+ if (lno == 0) {
+ if (LF_ISSET(SEARCH_MSG))
+ search_msg(sp, S_EMPTY);
+ return (1);
+ }
+ }
+
+ if (LF_ISSET(SEARCH_PARSE)) { /* Parse the string. */
+ /*
+ * Use the saved pattern if no pattern specified, or if only
+ * one or two delimiter characters specified.
+ *
+ * !!!
+ * Historically, only the pattern itself was saved, vi didn't
+ * preserve addressing or delta information.
+ */
+ if (ptrn == NULL)
+ goto prev;
+ if (plen == 1) {
+ if (epp != NULL)
+ *epp = ptrn + 1;
+ goto prev;
+ }
+ if (ptrn[0] == ptrn[1]) {
+ if (epp != NULL)
+ *epp = ptrn + 2;
+
+ /* Complain if we don't have a previous pattern. */
+prev: if (sp->re == NULL) {
+ search_msg(sp, S_NOPREV);
+ return (1);
+ }
+ /* Re-compile the search pattern if necessary. */
+ if (!F_ISSET(sp, SC_RE_SEARCH) && re_compile(sp,
+ sp->re, sp->re_len, NULL, NULL, &sp->re_c,
+ RE_C_SEARCH |
+ (LF_ISSET(SEARCH_MSG) ? 0 : RE_C_SILENT)))
+ return (1);
+
+ /* Set the search direction. */
+ if (LF_ISSET(SEARCH_SET))
+ sp->searchdir = dir;
+ return (0);
+ }
+
+ /*
+ * Set the delimiter, and move forward to the terminating
+ * delimiter, handling escaped delimiters.
+ *
+ * QUOTING NOTE:
+ * Only discard an escape character if it escapes a delimiter.
+ */
+ for (delim = *ptrn, p = t = ++ptrn;; *t++ = *p++) {
+ if (--plen == 0 || p[0] == delim) {
+ if (plen != 0)
+ ++p;
+ break;
+ }
+ if (plen > 1 && p[0] == '\\' && p[1] == delim) {
+ ++p;
+ --plen;
+ }
+ }
+ if (epp != NULL)
+ *epp = p;
+
+ plen = t - ptrn;
+ }
+
+ /* Compile the RE. */
+ if (re_compile(sp, ptrn, plen, &sp->re, &sp->re_len, &sp->re_c,
+ RE_C_SEARCH |
+ (LF_ISSET(SEARCH_MSG) ? 0 : RE_C_SILENT) |
+ (LF_ISSET(SEARCH_TAG) ? RE_C_TAG : 0) |
+ (LF_ISSET(SEARCH_CSCOPE) ? RE_C_CSCOPE : 0)))
+ return (1);
+
+ /* Set the search direction. */
+ if (LF_ISSET(SEARCH_SET))
+ sp->searchdir = dir;
+
+ return (0);
+}
+
+/*
+ * f_search --
+ * Do a forward search.
+ *
+ * PUBLIC: int f_search __P((SCR *,
+ * PUBLIC: MARK *, MARK *, char *, size_t, char **, u_int));
+ */
+int
+f_search(sp, fm, rm, ptrn, plen, eptrn, flags)
+ SCR *sp;
+ MARK *fm, *rm;
+ char *ptrn, **eptrn;
+ size_t plen;
+ u_int flags;
+{
+ busy_t btype;
+ recno_t lno;
+ regmatch_t match[1];
+ size_t coff, len;
+ int cnt, eval, rval, wrapped;
+ char *l;
+
+ if (search_init(sp, FORWARD, ptrn, plen, eptrn, flags))
+ return (1);
+
+ if (LF_ISSET(SEARCH_FILE)) {
+ lno = 1;
+ coff = 0;
+ } else {
+ if (db_get(sp, fm->lno, DBG_FATAL, &l, &len))
+ return (1);
+ lno = fm->lno;
+
+ /*
+ * If doing incremental search, start searching at the previous
+ * column, so that we search a minimal distance and still match
+ * special patterns, e.g., \< for beginning of a word.
+ *
+ * Otherwise, start searching immediately after the cursor. If
+ * at the end of the line, start searching on the next line.
+ * This is incompatible (read bug fix) with the historic vi --
+ * searches for the '$' pattern never moved forward, and the
+ * "-t foo" didn't work if the 'f' was the first character in
+ * the file.
+ */
+ if (LF_ISSET(SEARCH_INCR)) {
+ if ((coff = fm->cno) != 0)
+ --coff;
+ } else if (fm->cno + 1 >= len) {
+ coff = 0;
+ lno = fm->lno + 1;
+ if (db_get(sp, lno, 0, &l, &len)) {
+ if (!O_ISSET(sp, O_WRAPSCAN)) {
+ if (LF_ISSET(SEARCH_MSG))
+ search_msg(sp, S_EOF);
+ return (1);
+ }
+ lno = 1;
+ }
+ } else
+ coff = fm->cno + 1;
+ }
+
+ btype = BUSY_ON;
+ for (cnt = INTERRUPT_CHECK, rval = 1, wrapped = 0;; ++lno, coff = 0) {
+ if (cnt-- == 0) {
+ if (INTERRUPTED(sp))
+ break;
+ if (LF_ISSET(SEARCH_MSG)) {
+ search_busy(sp, btype);
+ btype = BUSY_UPDATE;
+ }
+ cnt = INTERRUPT_CHECK;
+ }
+ if (wrapped && lno > fm->lno || db_get(sp, lno, 0, &l, &len)) {
+ if (wrapped) {
+ if (LF_ISSET(SEARCH_MSG))
+ search_msg(sp, S_NOTFOUND);
+ break;
+ }
+ if (!O_ISSET(sp, O_WRAPSCAN)) {
+ if (LF_ISSET(SEARCH_MSG))
+ search_msg(sp, S_EOF);
+ break;
+ }
+ lno = 0;
+ wrapped = 1;
+ continue;
+ }
+
+ /* If already at EOL, just keep going. */
+ if (len != 0 && coff == len)
+ continue;
+
+ /* Set the termination. */
+ match[0].rm_so = coff;
+ match[0].rm_eo = len;
+
+#if defined(DEBUG) && 0
+ TRACE(sp, "F search: %lu from %u to %u\n",
+ lno, coff, len != 0 ? len - 1 : len);
+#endif
+ /* Search the line. */
+ eval = regexec(&sp->re_c, l, 1, match,
+ (match[0].rm_so == 0 ? 0 : REG_NOTBOL) | REG_STARTEND);
+ if (eval == REG_NOMATCH)
+ continue;
+ if (eval != 0) {
+ if (LF_ISSET(SEARCH_MSG))
+ re_error(sp, eval, &sp->re_c);
+ else
+ (void)sp->gp->scr_bell(sp);
+ break;
+ }
+
+ /* Warn if the search wrapped. */
+ if (wrapped && LF_ISSET(SEARCH_WMSG))
+ search_msg(sp, S_WRAP);
+
+#if defined(DEBUG) && 0
+ TRACE(sp, "F search: %qu to %qu\n",
+ match[0].rm_so, match[0].rm_eo);
+#endif
+ rm->lno = lno;
+ rm->cno = match[0].rm_so;
+
+ /*
+ * If a change command, it's possible to move beyond the end
+ * of a line. Historic vi generally got this wrong (e.g. try
+ * "c?$<cr>"). Not all that sure this gets it right, there
+ * are lots of strange cases.
+ */
+ if (!LF_ISSET(SEARCH_EOL) && rm->cno >= len)
+ rm->cno = len != 0 ? len - 1 : 0;
+
+ rval = 0;
+ break;
+ }
+
+ if (LF_ISSET(SEARCH_MSG))
+ search_busy(sp, BUSY_OFF);
+ return (rval);
+}
+
+/*
+ * b_search --
+ * Do a backward search.
+ *
+ * PUBLIC: int b_search __P((SCR *,
+ * PUBLIC: MARK *, MARK *, char *, size_t, char **, u_int));
+ */
+int
+b_search(sp, fm, rm, ptrn, plen, eptrn, flags)
+ SCR *sp;
+ MARK *fm, *rm;
+ char *ptrn, **eptrn;
+ size_t plen;
+ u_int flags;
+{
+ busy_t btype;
+ recno_t lno;
+ regmatch_t match[1];
+ size_t coff, last, len;
+ int cnt, eval, rval, wrapped;
+ char *l;
+
+ if (search_init(sp, BACKWARD, ptrn, plen, eptrn, flags))
+ return (1);
+
+ /*
+ * If doing incremental search, set the "starting" position past the
+ * current column, so that we search a minimal distance and still
+ * match special patterns, e.g., \> for the end of a word. This is
+ * safe when the cursor is at the end of a line because we only use
+ * it for comparison with the location of the match.
+ *
+ * Otherwise, start searching immediately before the cursor. If in
+ * the first column, start search on the previous line.
+ */
+ if (LF_ISSET(SEARCH_INCR)) {
+ lno = fm->lno;
+ coff = fm->cno + 1;
+ } else {
+ if (fm->cno == 0) {
+ if (fm->lno == 1 && !O_ISSET(sp, O_WRAPSCAN)) {
+ if (LF_ISSET(SEARCH_MSG))
+ search_msg(sp, S_SOF);
+ return (1);
+ }
+ lno = fm->lno - 1;
+ } else
+ lno = fm->lno;
+ coff = fm->cno;
+ }
+
+ btype = BUSY_ON;
+ for (cnt = INTERRUPT_CHECK, rval = 1, wrapped = 0;; --lno, coff = 0) {
+ if (cnt-- == 0) {
+ if (INTERRUPTED(sp))
+ break;
+ if (LF_ISSET(SEARCH_MSG)) {
+ search_busy(sp, btype);
+ btype = BUSY_UPDATE;
+ }
+ cnt = INTERRUPT_CHECK;
+ }
+ if (wrapped && lno < fm->lno || lno == 0) {
+ if (wrapped) {
+ if (LF_ISSET(SEARCH_MSG))
+ search_msg(sp, S_NOTFOUND);
+ break;
+ }
+ if (!O_ISSET(sp, O_WRAPSCAN)) {
+ if (LF_ISSET(SEARCH_MSG))
+ search_msg(sp, S_SOF);
+ break;
+ }
+ if (db_last(sp, &lno))
+ break;
+ if (lno == 0) {
+ if (LF_ISSET(SEARCH_MSG))
+ search_msg(sp, S_EMPTY);
+ break;
+ }
+ ++lno;
+ wrapped = 1;
+ continue;
+ }
+
+ if (db_get(sp, lno, 0, &l, &len))
+ break;
+
+ /* Set the termination. */
+ match[0].rm_so = 0;
+ match[0].rm_eo = len;
+
+#if defined(DEBUG) && 0
+ TRACE(sp, "B search: %lu from 0 to %qu\n", lno, match[0].rm_eo);
+#endif
+ /* Search the line. */
+ eval = regexec(&sp->re_c, l, 1, match,
+ (match[0].rm_eo == len ? 0 : REG_NOTEOL) | REG_STARTEND);
+ if (eval == REG_NOMATCH)
+ continue;
+ if (eval != 0) {
+ if (LF_ISSET(SEARCH_MSG))
+ re_error(sp, eval, &sp->re_c);
+ else
+ (void)sp->gp->scr_bell(sp);
+ break;
+ }
+
+ /* Check for a match starting past the cursor. */
+ if (coff != 0 && match[0].rm_so >= coff)
+ continue;
+
+ /* Warn if the search wrapped. */
+ if (wrapped && LF_ISSET(SEARCH_WMSG))
+ search_msg(sp, S_WRAP);
+
+#if defined(DEBUG) && 0
+ TRACE(sp, "B found: %qu to %qu\n",
+ match[0].rm_so, match[0].rm_eo);
+#endif
+ /*
+ * We now have the first match on the line. Step through the
+ * line character by character until find the last acceptable
+ * match. This is painful, we need a better interface to regex
+ * to make this work.
+ */
+ for (;;) {
+ last = match[0].rm_so++;
+ if (match[0].rm_so >= len)
+ break;
+ match[0].rm_eo = len;
+ eval = regexec(&sp->re_c, l, 1, match,
+ (match[0].rm_so == 0 ? 0 : REG_NOTBOL) |
+ REG_STARTEND);
+ if (eval == REG_NOMATCH)
+ break;
+ if (eval != 0) {
+ if (LF_ISSET(SEARCH_MSG))
+ re_error(sp, eval, &sp->re_c);
+ else
+ (void)sp->gp->scr_bell(sp);
+ goto err;
+ }
+ if (coff && match[0].rm_so >= coff)
+ break;
+ }
+ rm->lno = lno;
+
+ /* See comment in f_search(). */
+ if (!LF_ISSET(SEARCH_EOL) && last >= len)
+ rm->cno = len != 0 ? len - 1 : 0;
+ else
+ rm->cno = last;
+ rval = 0;
+ break;
+ }
+
+err: if (LF_ISSET(SEARCH_MSG))
+ search_busy(sp, BUSY_OFF);
+ return (rval);
+}
+
+/*
+ * search_msg --
+ * Display one of the search messages.
+ */
+static void
+search_msg(sp, msg)
+ SCR *sp;
+ smsg_t msg;
+{
+ switch (msg) {
+ case S_EMPTY:
+ msgq(sp, M_ERR, "072|File empty; nothing to search");
+ break;
+ case S_EOF:
+ msgq(sp, M_ERR,
+ "073|Reached end-of-file without finding the pattern");
+ break;
+ case S_NOPREV:
+ msgq(sp, M_ERR, "074|No previous search pattern");
+ break;
+ case S_NOTFOUND:
+ msgq(sp, M_ERR, "075|Pattern not found");
+ break;
+ case S_SOF:
+ msgq(sp, M_ERR,
+ "076|Reached top-of-file without finding the pattern");
+ break;
+ case S_WRAP:
+ msgq(sp, M_ERR, "077|Search wrapped");
+ break;
+ default:
+ abort();
+ }
+}
+
+/*
+ * search_busy --
+ * Put up the busy searching message.
+ *
+ * PUBLIC: void search_busy __P((SCR *, busy_t));
+ */
+void
+search_busy(sp, btype)
+ SCR *sp;
+ busy_t btype;
+{
+ sp->gp->scr_busy(sp, "078|Searching...", btype);
+}
diff --git a/usr.bin/vi/common/seq.c b/contrib/nvi/common/seq.c
index 7b217084aaa0..e2be879ab686 100644
--- a/usr.bin/vi/common/seq.c
+++ b/contrib/nvi/common/seq.c
@@ -1,75 +1,48 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)seq.c 8.30 (Berkeley) 7/15/94";
+static const char sccsid[] = "@(#)seq.c 10.10 (Berkeley) 3/30/96";
#endif /* not lint */
#include <sys/types.h>
#include <sys/queue.h>
-#include <sys/time.h>
#include <bitstring.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-#include "vi.h"
-#include "excmd.h"
+#include "common.h"
/*
* seq_set --
* Internal version to enter a sequence.
+ *
+ * PUBLIC: int seq_set __P((SCR *, CHAR_T *,
+ * PUBLIC: size_t, CHAR_T *, size_t, CHAR_T *, size_t, seq_t, int));
*/
int
seq_set(sp, name, nlen, input, ilen, output, olen, stype, flags)
SCR *sp;
- char *name, *input, *output;
+ CHAR_T *name, *input, *output;
size_t nlen, ilen, olen;
- enum seqtype stype;
+ seq_t stype;
int flags;
{
- SEQ *lastqp, *qp;
CHAR_T *p;
+ SEQ *lastqp, *qp;
int sv_errno;
/*
@@ -79,7 +52,10 @@ seq_set(sp, name, nlen, input, ilen, output, olen, stype, flags)
*
* Just replace the output field if the string already set.
*/
- if ((qp = seq_find(sp, &lastqp, input, ilen, stype, NULL)) != NULL) {
+ if ((qp =
+ seq_find(sp, &lastqp, NULL, input, ilen, stype, NULL)) != NULL) {
+ if (LF_ISSET(SEQ_NOOVERWRITE))
+ return (0);
if (output == NULL || olen == 0) {
p = NULL;
olen = 0;
@@ -126,7 +102,7 @@ seq_set(sp, name, nlen, input, ilen, output, olen, stype, flags)
free(qp->input);
mem3: if (qp->name != NULL)
free(qp->name);
-mem2: FREE(qp, sizeof(SEQ));
+mem2: free(qp);
mem1: errno = sv_errno;
msgq(sp, M_SYSERR, NULL);
return (1);
@@ -145,7 +121,8 @@ mem1: errno = sv_errno;
}
/* Set the fast lookup bit. */
- bit_set(sp->gp->seqb, qp->input[0]);
+ if (qp->input[0] < MAX_BIT_SEQ)
+ bit_set(sp->gp->seqb, qp->input[0]);
return (0);
}
@@ -153,17 +130,19 @@ mem1: errno = sv_errno;
/*
* seq_delete --
* Delete a sequence.
+ *
+ * PUBLIC: int seq_delete __P((SCR *, CHAR_T *, size_t, seq_t));
*/
int
seq_delete(sp, input, ilen, stype)
SCR *sp;
- char *input;
+ CHAR_T *input;
size_t ilen;
- enum seqtype stype;
+ seq_t stype;
{
SEQ *qp;
- if ((qp = seq_find(sp, NULL, input, ilen, stype, NULL)) == NULL)
+ if ((qp = seq_find(sp, NULL, NULL, input, ilen, stype, NULL)) == NULL)
return (1);
return (seq_mdel(qp));
}
@@ -171,6 +150,8 @@ seq_delete(sp, input, ilen, stype)
/*
* seq_mdel --
* Delete a map entry, without lookup.
+ *
+ * PUBLIC: int seq_mdel __P((SEQ *));
*/
int
seq_mdel(qp)
@@ -182,7 +163,7 @@ seq_mdel(qp)
free(qp->input);
if (qp->output != NULL)
free(qp->output);
- FREE(qp, sizeof(SEQ));
+ free(qp);
return (0);
}
@@ -190,14 +171,18 @@ seq_mdel(qp)
* seq_find --
* Search the sequence list for a match to a buffer, if ispartial
* isn't NULL, partial matches count.
+ *
+ * PUBLIC: SEQ *seq_find
+ * PUBLIC: __P((SCR *, SEQ **, EVENT *, CHAR_T *, size_t, seq_t, int *));
*/
SEQ *
-seq_find(sp, lastqp, input, ilen, stype, ispartialp)
+seq_find(sp, lastqp, e_input, c_input, ilen, stype, ispartialp)
SCR *sp;
SEQ **lastqp;
- char *input;
+ EVENT *e_input;
+ CHAR_T *c_input;
size_t ilen;
- enum seqtype stype;
+ seq_t stype;
int *ispartialp;
{
SEQ *lqp, *qp;
@@ -217,15 +202,26 @@ seq_find(sp, lastqp, input, ilen, stype, ispartialp)
*ispartialp = 0;
for (lqp = NULL, qp = sp->gp->seqq.lh_first;
qp != NULL; lqp = qp, qp = qp->q.le_next) {
- /* Fast checks on the first character and type. */
- if (qp->input[0] > input[0])
- break;
- if (qp->input[0] < input[0] ||
- qp->stype != stype || F_ISSET(qp, SEQ_FUNCMAP))
- continue;
-
- /* Check on the real comparison. */
- diff = memcmp(qp->input, input, MIN(qp->ilen, ilen));
+ /*
+ * Fast checks on the first character and type, and then
+ * a real comparison.
+ */
+ if (e_input == NULL) {
+ if (qp->input[0] > c_input[0])
+ break;
+ if (qp->input[0] < c_input[0] ||
+ qp->stype != stype || F_ISSET(qp, SEQ_FUNCMAP))
+ continue;
+ diff = memcmp(qp->input, c_input, MIN(qp->ilen, ilen));
+ } else {
+ if (qp->input[0] > e_input->e_c)
+ break;
+ if (qp->input[0] < e_input->e_c ||
+ qp->stype != stype || F_ISSET(qp, SEQ_FUNCMAP))
+ continue;
+ diff =
+ e_memcmp(qp->input, e_input, MIN(qp->ilen, ilen));
+ }
if (diff > 0)
break;
if (diff < 0)
@@ -259,47 +255,73 @@ seq_find(sp, lastqp, input, ilen, stype, ispartialp)
}
/*
+ * seq_close --
+ * Discard all sequences.
+ *
+ * PUBLIC: void seq_close __P((GS *));
+ */
+void
+seq_close(gp)
+ GS *gp;
+{
+ SEQ *qp;
+
+ while ((qp = gp->seqq.lh_first) != NULL) {
+ if (qp->name != NULL)
+ free(qp->name);
+ if (qp->input != NULL)
+ free(qp->input);
+ if (qp->output != NULL)
+ free(qp->output);
+ LIST_REMOVE(qp, q);
+ free(qp);
+ }
+}
+
+/*
* seq_dump --
* Display the sequence entries of a specified type.
+ *
+ * PUBLIC: int seq_dump __P((SCR *, seq_t, int));
*/
int
seq_dump(sp, stype, isname)
SCR *sp;
- enum seqtype stype;
+ seq_t stype;
int isname;
{
+ CHAR_T *p;
+ GS *gp;
SEQ *qp;
int cnt, len, olen;
- CHAR_T *p;
cnt = 0;
- for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) {
+ gp = sp->gp;
+ for (qp = gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) {
if (stype != qp->stype || F_ISSET(qp, SEQ_FUNCMAP))
continue;
++cnt;
for (p = qp->input,
olen = qp->ilen, len = 0; olen > 0; --olen, ++p)
- len += ex_printf(EXCOOKIE, "%s", KEY_NAME(sp, *p));
+ len += ex_puts(sp, KEY_NAME(sp, *p));
for (len = STANDARD_TAB - len % STANDARD_TAB; len > 0;)
- len -= ex_printf(EXCOOKIE, " ");
+ len -= ex_puts(sp, " ");
if (qp->output != NULL)
for (p = qp->output,
olen = qp->olen, len = 0; olen > 0; --olen, ++p)
- len +=
- ex_printf(EXCOOKIE, "%s", KEY_NAME(sp, *p));
+ len += ex_puts(sp, KEY_NAME(sp, *p));
else
len = 0;
if (isname && qp->name != NULL) {
for (len = STANDARD_TAB - len % STANDARD_TAB; len > 0;)
- len -= ex_printf(EXCOOKIE, " ");
+ len -= ex_puts(sp, " ");
for (p = qp->name,
olen = qp->nlen; olen > 0; --olen, ++p)
- (void)ex_printf(EXCOOKIE,
- "%s", KEY_NAME(sp, *p));
+ (void)ex_puts(sp, KEY_NAME(sp, *p));
}
- (void)ex_printf(EXCOOKIE, "\n");
+ (void)ex_puts(sp, "\n");
}
return (cnt);
}
@@ -307,23 +329,24 @@ seq_dump(sp, stype, isname)
/*
* seq_save --
* Save the sequence entries to a file.
+ *
+ * PUBLIC: int seq_save __P((SCR *, FILE *, char *, seq_t));
*/
int
seq_save(sp, fp, prefix, stype)
SCR *sp;
FILE *fp;
char *prefix;
- enum seqtype stype;
+ seq_t stype;
{
+ CHAR_T *p;
SEQ *qp;
size_t olen;
int ch;
- char *p;
/* Write a sequence command for all keys the user defined. */
for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) {
- if (stype != qp->stype ||
- F_ISSET(qp, SEQ_FUNCMAP) || !F_ISSET(qp, SEQ_USERDEF))
+ if (stype != qp->stype || !F_ISSET(qp, SEQ_USERDEF))
continue;
if (prefix)
(void)fprintf(fp, "%s", prefix);
@@ -348,3 +371,25 @@ seq_save(sp, fp, prefix, stype)
}
return (0);
}
+
+/*
+ * e_memcmp --
+ * Compare a string of EVENT's to a string of CHAR_T's.
+ *
+ * PUBLIC: int e_memcmp __P((CHAR_T *, EVENT *, size_t));
+ */
+int
+e_memcmp(p1, ep, n)
+ CHAR_T *p1;
+ EVENT *ep;
+ size_t n;
+{
+ if (n != 0) {
+ do {
+ if (*p1++ != ep->e_c)
+ return (*--p1 - ep->e_c);
+ ++ep;
+ } while (--n != 0);
+ }
+ return (0);
+}
diff --git a/contrib/nvi/common/seq.h b/contrib/nvi/common/seq.h
new file mode 100644
index 000000000000..984bb6c0bd18
--- /dev/null
+++ b/contrib/nvi/common/seq.h
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)seq.h 10.3 (Berkeley) 3/6/96
+ */
+
+/*
+ * Map and abbreviation structures.
+ *
+ * The map structure is doubly linked list, sorted by input string and by
+ * input length within the string. (The latter is necessary so that short
+ * matches will happen before long matches when the list is searched.)
+ * Additionally, there is a bitmap which has bits set if there are entries
+ * starting with the corresponding character. This keeps us from walking
+ * the list unless it's necessary.
+ *
+ * The name and the output fields of a SEQ can be empty, i.e. NULL.
+ * Only the input field is required.
+ *
+ * XXX
+ * The fast-lookup bits are never turned off -- users don't usually unmap
+ * things, though, so it's probably not a big deal.
+ */
+struct _seq {
+ LIST_ENTRY(_seq) q; /* Linked list of all sequences. */
+ seq_t stype; /* Sequence type. */
+ CHAR_T *name; /* Sequence name (if any). */
+ size_t nlen; /* Name length. */
+ CHAR_T *input; /* Sequence input keys. */
+ size_t ilen; /* Input keys length. */
+ CHAR_T *output; /* Sequence output keys. */
+ size_t olen; /* Output keys length. */
+
+#define SEQ_FUNCMAP 0x01 /* If unresolved function key.*/
+#define SEQ_NOOVERWRITE 0x02 /* Don't replace existing entry. */
+#define SEQ_SCREEN 0x04 /* If screen specific. */
+#define SEQ_USERDEF 0x08 /* If user defined. */
+ u_int8_t flags;
+};
diff --git a/contrib/nvi/common/util.c b/contrib/nvi/common/util.c
new file mode 100644
index 000000000000..5a4422a2c422
--- /dev/null
+++ b/contrib/nvi/common/util.c
@@ -0,0 +1,230 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)util.c 10.11 (Berkeley) 9/15/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+
+/*
+ * binc --
+ * Increase the size of a buffer.
+ *
+ * PUBLIC: void *binc __P((SCR *, void *, size_t *, size_t));
+ */
+void *
+binc(sp, bp, bsizep, min)
+ SCR *sp; /* sp MAY BE NULL!!! */
+ void *bp;
+ size_t *bsizep, min;
+{
+ size_t csize;
+
+ /* If already larger than the minimum, just return. */
+ if (min && *bsizep >= min)
+ return (bp);
+
+ csize = *bsizep + MAX(min, 256);
+ REALLOC(sp, bp, void *, csize);
+
+ if (bp == NULL) {
+ /*
+ * Theoretically, realloc is supposed to leave any already
+ * held memory alone if it can't get more. Don't trust it.
+ */
+ *bsizep = 0;
+ return (NULL);
+ }
+ /*
+ * Memory is guaranteed to be zero-filled, various parts of
+ * nvi depend on this.
+ */
+ memset((char *)bp + *bsizep, 0, csize - *bsizep);
+ *bsizep = csize;
+ return (bp);
+}
+
+/*
+ * nonblank --
+ * Set the column number of the first non-blank character
+ * including or after the starting column. On error, set
+ * the column to 0, it's safest.
+ *
+ * PUBLIC: int nonblank __P((SCR *, recno_t, size_t *));
+ */
+int
+nonblank(sp, lno, cnop)
+ SCR *sp;
+ recno_t lno;
+ size_t *cnop;
+{
+ char *p;
+ size_t cnt, len, off;
+ int isempty;
+
+ /* Default. */
+ off = *cnop;
+ *cnop = 0;
+
+ /* Get the line, succeeding in an empty file. */
+ if (db_eget(sp, lno, &p, &len, &isempty))
+ return (!isempty);
+
+ /* Set the offset. */
+ if (len == 0 || off >= len)
+ return (0);
+
+ for (cnt = off, p = &p[off],
+ len -= off; len && isblank(*p); ++cnt, ++p, --len);
+
+ /* Set the return. */
+ *cnop = len ? cnt : cnt - 1;
+ return (0);
+}
+
+/*
+ * tail --
+ * Return tail of a path.
+ *
+ * PUBLIC: char *tail __P((char *));
+ */
+char *
+tail(path)
+ char *path;
+{
+ char *p;
+
+ if ((p = strrchr(path, '/')) == NULL)
+ return (path);
+ return (p + 1);
+}
+
+/*
+ * v_strdup --
+ * Strdup for wide character strings with an associated length.
+ *
+ * PUBLIC: CHAR_T *v_strdup __P((SCR *, const CHAR_T *, size_t));
+ */
+CHAR_T *
+v_strdup(sp, str, len)
+ SCR *sp;
+ const CHAR_T *str;
+ size_t len;
+{
+ CHAR_T *copy;
+
+ MALLOC(sp, copy, CHAR_T *, len + 1);
+ if (copy == NULL)
+ return (NULL);
+ memcpy(copy, str, len * sizeof(CHAR_T));
+ copy[len] = '\0';
+ return (copy);
+}
+
+/*
+ * nget_uslong --
+ * Get an unsigned long, checking for overflow.
+ *
+ * PUBLIC: enum nresult nget_uslong __P((u_long *, const char *, char **, int));
+ */
+enum nresult
+nget_uslong(valp, p, endp, base)
+ u_long *valp;
+ const char *p;
+ char **endp;
+ int base;
+{
+ errno = 0;
+ *valp = strtoul(p, endp, base);
+ if (errno == 0)
+ return (NUM_OK);
+ if (errno == ERANGE && *valp == ULONG_MAX)
+ return (NUM_OVER);
+ return (NUM_ERR);
+}
+
+/*
+ * nget_slong --
+ * Convert a signed long, checking for overflow and underflow.
+ *
+ * PUBLIC: enum nresult nget_slong __P((long *, const char *, char **, int));
+ */
+enum nresult
+nget_slong(valp, p, endp, base)
+ long *valp;
+ const char *p;
+ char **endp;
+ int base;
+{
+ errno = 0;
+ *valp = strtol(p, endp, base);
+ if (errno == 0)
+ return (NUM_OK);
+ if (errno == ERANGE) {
+ if (*valp == LONG_MAX)
+ return (NUM_OVER);
+ if (*valp == LONG_MIN)
+ return (NUM_UNDER);
+ }
+ return (NUM_ERR);
+}
+
+#ifdef DEBUG
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+/*
+ * TRACE --
+ * debugging trace routine.
+ *
+ * PUBLIC: void TRACE __P((SCR *, const char *, ...));
+ */
+void
+#ifdef __STDC__
+TRACE(SCR *sp, const char *fmt, ...)
+#else
+TRACE(sp, fmt, va_alist)
+ SCR *sp;
+ char *fmt;
+ va_dcl
+#endif
+{
+ FILE *tfp;
+ va_list ap;
+
+ if ((tfp = sp->gp->tracefp) == NULL)
+ return;
+#ifdef __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ (void)vfprintf(tfp, fmt, ap);
+ va_end(ap);
+
+ (void)fflush(tfp);
+}
+#endif
diff --git a/contrib/nvi/common/util.h b/contrib/nvi/common/util.h
new file mode 100644
index 000000000000..46edb4aae5a8
--- /dev/null
+++ b/contrib/nvi/common/util.h
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)util.h 10.5 (Berkeley) 3/16/96
+ */
+
+/* Macros to init/set/clear/test flags. */
+#define FL_INIT(l, f) (l) = (f) /* Specific flags location. */
+#define FL_SET(l, f) ((l) |= (f))
+#define FL_CLR(l, f) ((l) &= ~(f))
+#define FL_ISSET(l, f) ((l) & (f))
+
+#define LF_INIT(f) FL_INIT(flags, f) /* Local variable flags. */
+#define LF_SET(f) FL_SET(flags, f)
+#define LF_CLR(f) FL_CLR(flags, f)
+#define LF_ISSET(f) FL_ISSET(flags, f)
+
+#define F_INIT(p, f) FL_INIT((p)->flags, f) /* Structure element flags. */
+#define F_SET(p, f) FL_SET((p)->flags, f)
+#define F_CLR(p, f) FL_CLR((p)->flags, f)
+#define F_ISSET(p, f) FL_ISSET((p)->flags, f)
+
+/* Offset to next column of stop size, e.g. tab offsets. */
+#define COL_OFF(c, stop) ((stop) - ((c) % (stop)))
+
+/* Busy message types. */
+typedef enum { B_NONE, B_OFF, B_READ, B_RECOVER, B_SEARCH, B_WRITE } bmsg_t;
+
+/*
+ * Number handling defines and protoypes.
+ *
+ * NNFITS: test for addition of two negative numbers under a limit
+ * NPFITS: test for addition of two positive numbers under a limit
+ * NADD_SLONG: test for addition of two signed longs
+ * NADD_USLONG: test for addition of two unsigned longs
+ */
+enum nresult { NUM_ERR, NUM_OK, NUM_OVER, NUM_UNDER };
+#define NNFITS(min, cur, add) \
+ (((long)(min)) - (cur) <= (add))
+#define NPFITS(max, cur, add) \
+ (((unsigned long)(max)) - (cur) >= (add))
+#define NADD_SLONG(sp, v1, v2) \
+ ((v1) < 0 ? \
+ ((v2) < 0 && \
+ NNFITS(LONG_MIN, (v1), (v2))) ? NUM_UNDER : NUM_OK : \
+ (v1) > 0 ? \
+ (v2) > 0 && \
+ NPFITS(LONG_MAX, (v1), (v2)) ? NUM_OK : NUM_OVER : \
+ NUM_OK)
+#define NADD_USLONG(sp, v1, v2) \
+ (NPFITS(ULONG_MAX, (v1), (v2)) ? NUM_OK : NUM_OVER)
diff --git a/contrib/nvi/docs/TODO b/contrib/nvi/docs/TODO
new file mode 100644
index 000000000000..6fe88295d5ff
--- /dev/null
+++ b/contrib/nvi/docs/TODO
@@ -0,0 +1,147 @@
+CL: In single-line screens, have to press 'q' twice when quitting out
+ of a ":set all" display.
+
+COMMON: There's a serious problem with error returns -- we need to separate
+ command failure from fatal error, consistently, over the entire source
+ tree.
+
+ We need to rework all of vi to have three return values:
+
+ 0: success
+ 1: vi error, continue
+ 2: fatal error, die
+
+ Right now we don't recognize fatal errors for what they are.
+
+VI: Change the screen scrolling to not eat user characters... i.e.
+ g/pattern/foo should not eat already entered chars.
+
+COMMON: It's known that it's possible to sync the backing files in the
+ wrong manner, leaving backup files that aren't recoverable. This
+ is going to be left alone until we have a logging version of DB,
+ which will hopefully fix this (or at least make it possible to
+ easily do so).
+
+COMMON: The complete list of POSIX.1 calls that can return EINTR are:
+
+ wait, waitpid, sleep, dup2, close, read, write,
+ fcntl(SETLCKW) tcsetattr, tcdrain
+
+ The problem is that technically, any system/library call can
+ return EINTR, so, while nvi blocks (most of?) the obvious ones,
+ someone may have to do a complete pass and block signals
+ everywhere.
+
+COMMON: The vi main command loop should use the general-purpose overflow
+ and underflow routines. In addition, the vi command loop uses
+ unsigned longs -- should probably be fixed as a 32-bit unsigned
+ type, and then check to make sure it's never used as as variable
+ type again.
+
+DB: When nvi edits files that don't have trailing newlines, it appends
+ one, regardless. This is required, by default, from POSIX.2.
+
+COMMON: Open mode is not yet implemented.
+
+COMMON: ^C isn't passed to the shell in the script windows as an interrupt
+ character.
+
+COMMON: The options:
+
+ hardtabs, lisp, optimize, redraw, slowopen
+
+ are recognized, but not implemented. These options are unlikely
+ to be implemented, so if you want them you might want to say
+ something! I will implement lisp if anyone ever documents how it
+ worked.
+
+COMMON: If you run out of space in the recovery directory, the recovery
+ file is left in place.
+
+COMMON: Should "view" set a lock on the file?
+
+COMMON: Field editing shouldn't be hard to add to nvi:
+
+ Field editing file template:
+
+ version #
+ field # row/column start row/column stop
+ label field # Label string
+ re field # Matching re string.
+ field # row/column start row/column stop
+ label field # Label string
+ re field # Matching re string.
+
+ <tab> moves to the next field
+ <bs> in column 0 moves to the previous field
+
+COMMON: Let's rethink using an IPC mechanism:
+
+ Two way channel, with events passing in both directions.
+
+ Load into the same address space (else, how do file permissions) forks
+ in v_init -- screens get events from vi, vi gets events queued up from
+ screens.
+
+ Vi:
+ E_CHARACTER, /* Input character: e_c set. */
+ E_EOF, /* End of input (NOT ^D). */
+ E_ERR, /* Input error. */
+ E_INTERRUPT, /* Interrupt. */
+ E_REPAINT, /* Repaint: e_flno, e_tlno set. */
+ E_RESIZE, /* SIGWINCH: e_lno, e_cno set. */
+ E_SIGCONT, /* SIGCONT arrived. */
+ E_SIGFATAL, /* fatal signal arrived.
+ E_START, /* Start ex/vi. */
+ E_STOP, /* Stop ex/vi. */
+ E_STRING, /* Input string: e_csp, e_len set. */
+
+ Screen:
+ E_ADDSTR /* Add a string to the screen. */
+ E_ATTRIBUTE /* Screen attribute. */
+ E_BELL /* Beep/bell/flash the terminal. */
+ E_BUSY /* Display a busy message. */
+ E_CANONICAL /* Enter tty canonical mode. */
+ E_CLRTOEOL /* Clear to the end of the line. */
+ E_CURSOR /* Return the cursor location. */
+ E_DELETELN /* Delete a line. */
+ E_DISCARD /* Discard a screen. */
+ E_EXADJUST /* Ex: screen adjustment routine. */
+ E_FMAP /* Set a function key. */
+ E_GETKEY /* Get a key event. */
+ E_INSERTLN /* Insert a line. */
+ E_MOVE /* Move the cursor. */
+ E_MESSAGE /* Message or ex output. */
+ E_REFRESH /* Refresh the screen. */
+ E_RESIZE /* Resize two screens. */
+ E_SPLIT /* Split the screen. */
+ E_SUSPEND /* Suspend the editor. */
+
+EX: It would be nice to inverse video the replaced text during
+ interactive substitute.
+
+EX: The :args command should put the current file name out in reverse
+ video. This isn't going to be easy, currently only full lines can
+ be in reverse video, not just parts.
+
+TK: We currently permit the user to change the lines, columns and term
+ edit options. Shouldn't that be illegal in tknvi?
+
+VI: The strings found by searches should be highlighted until the next
+ character is entered.
+
+VI: Display a split vi screen for the :help command.
+
+VI: When getting a key for a continue screen, we should always read from
+ the terminal, not from a mapped key.
+
+VI: The sentence, paragraph and section movement commands don't match
+ historic practice in some boundary cases. This should be left
+ alone until POSIX 1003.2 makes up its mind.
+
+VI: The vs_sm_fill routine should scroll if possible, not always redraw.
+
+VI: Think about setting a dirty/inuse bits on the lines of the SMAP
+ structure. That way the message routines could steal lines and
+ refresh would continue to work, because it would know not to touch
+ the lines that were in use.
diff --git a/contrib/nvi/docs/USD.doc/edit/Makefile b/contrib/nvi/docs/USD.doc/edit/Makefile
new file mode 100644
index 000000000000..0c59f6d0816e
--- /dev/null
+++ b/contrib/nvi/docs/USD.doc/edit/Makefile
@@ -0,0 +1,11 @@
+# @(#)Makefile 8.4 (Berkeley) 8/18/96
+
+ROFF= groff
+TBL= tbl
+
+edittut.ps: edittut.ms
+ ${TBL} edittut.ms | ${ROFF} -ms > $@
+ chmod 444 $@
+
+clean:
+ rm -f edittut.ps
diff --git a/usr.bin/vi/USD.doc/edit/edit.vindex b/contrib/nvi/docs/USD.doc/edit/edit.vindex
index 2098f14ea190..2098f14ea190 100644
--- a/usr.bin/vi/USD.doc/edit/edit.vindex
+++ b/contrib/nvi/docs/USD.doc/edit/edit.vindex
diff --git a/usr.bin/vi/USD.doc/edit/edittut.ms b/contrib/nvi/docs/USD.doc/edit/edittut.ms
index 5f4c28cb6d2a..8a9d66ede2e6 100644
--- a/usr.bin/vi/USD.doc/edit/edittut.ms
+++ b/contrib/nvi/docs/USD.doc/edit/edittut.ms
@@ -29,14 +29,14 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)edittut.ms 8.1 (Berkeley) 6/8/93
+.\" @(#)edittut.ms 8.3 (Berkeley) 8/18/96
.\"
+.ll 6.5i
+.nr LL 6.5i
.EH 'USD:11-%''Edit: A Tutorial'
.OH 'Edit: A Tutorial''USD:11-%'
.LP
.ds u \s-2UNIX\s0
-.ll 5i
-.nr LL 5i
.ND
.sp 4
.ce
@@ -89,19 +89,19 @@ September 1981
.nf
Introduction\ \ \ 3
.sp
-Session 1\ \ \4
+Session 1\ \ 4
.in +.5i
Making contact with \s-2UNIX\s+2\ \ \ 4
-Logging in\ \ \4
+Logging in\ \ 4
Asking for \fIedit\fR\ \ \ 4
The ``Command not found'' message\ \ \ 5
-A summary\ \ \5
+A summary\ \ 5
Entering text\ \ \ 5
Messages from \fIedit\fR\ \ \ 5
Text input mode\ \ \ 6
Making corrections\ \ \ 6
Writing text to disk\ \ \ 7
-Signing off\ \ \7
+Signing off\ \ 7
.in -.5i
.sp
Session 2\ \ \ 8
@@ -1034,56 +1034,14 @@ Instead, you may identify the line you want to change
by asking edit to search for a specified pattern of letters
that occurs in that line.
The parts of the above command are:
-.TS
.in +1i
-.nr 35 \n(.u
-.nf
-.ds #d .d
-.if \(ts\n(.z\(ts\(ts .ds #d nl
-.nr 80 0
-.nr 38 \w\f3/strange/\fP
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \w\f3s\fP
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 38 \w\f3/strange, but //\fP
-.if \n(80<\n(38 .nr 80 \n(38
-.nr 81 0
-.nr 38 \wtells edit to find the characters ``strange'' in the text
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wtells edit to make a substitution
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 \wsubstitutes nothing at all for the characters ``strange, but ''
-.if \n(81<\n(38 .nr 81 \n(38
-.nr 38 1n
-.nr 79 0
-.nr 40 \n(79+(0*\n(38)
-.nr 80 +\n(40
-.nr 41 \n(80+(3*\n(38)
-.nr 81 +\n(41
-.nr TW \n(81
-.if t .if (\n(TW+\n(.o)>7.75i .tm Table at line 307 file ed2.tbl is too wide - \n(TW units
-.fc  
-.nr #T 0
-.eo
-.de T#
-.ds #d .d
-.if \(ts\n(.z\(ts\(ts .ds #d nl
-.mk ##
-.nr ## -1v
-..
-.ec
-.ta \n(80u \n(81u
-\&\h'|\n(40u'\f3/strange/\fP\h'|\n(41u'tells edit to find the characters ``strange'' in the text
-.ta \n(80u \n(81u
-\&\h'|\n(40u'\f3s\fP\h'|\n(41u'tells edit to make a substitution
-.ta \n(80u \n(81u
-\&\h'|\n(40u'\f3/strange, but //\fP\h'|\n(41u'substitutes nothing at all for the characters ``strange, but ''
-.fc
-.nr T. 1
-.T# 1
-.if \n(35>0 .fi
-.in -1i
+.TS
+l l.
+\fB/strange/\fP tells edit to find the characters ``strange'' in the text
+\fBs\fP tells edit to make a substitution
+\fB/strange, but //\fP substitutes nothing at all for the characters ``strange, but ''
.TE
+.in -1i
.PP
You should note the space after ``but'' in ``/strange, but /''.
If you do not indicate that the space is to be taken out,
diff --git a/contrib/nvi/docs/USD.doc/exref/Makefile b/contrib/nvi/docs/USD.doc/exref/Makefile
new file mode 100644
index 000000000000..11b5423607e7
--- /dev/null
+++ b/contrib/nvi/docs/USD.doc/exref/Makefile
@@ -0,0 +1,17 @@
+# @(#)Makefile 8.8 (Berkeley) 10/10/96
+
+ROFF= groff
+TBL= tbl
+
+all: exref.ps summary.ps
+
+exref.ps: ex.rm
+ ${TBL} ex.rm | ${ROFF} -ms > $@
+ chmod 444 $@
+
+summary.ps: ex.summary
+ ${TBL} ex.summary | ${ROFF} -ms > $@
+ chmod 444 $@
+
+clean:
+ rm -f exref.ps summary.ps
diff --git a/usr.bin/vi/USD.doc/exref/ex.rm b/contrib/nvi/docs/USD.doc/exref/ex.rm
index 79670c2cf66b..217bad46d277 100644
--- a/usr.bin/vi/USD.doc/exref/ex.rm
+++ b/contrib/nvi/docs/USD.doc/exref/ex.rm
@@ -29,10 +29,13 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)ex.rm 8.1 (Berkeley) 6/8/93
+.\" @(#)ex.rm 8.5 (Berkeley) 8/18/96
.\"
-.EH 'USD:13-%''Ex Reference Manual'
-.OH 'Ex Reference Manual''USD:13-%'
+.nr LL 6.5i
+.nr FL 6.5i
+.EH 'USD:12-%''Ex Reference Manual'
+.OH 'Ex Reference Manual''USD:12-%'
+.nr )P 0
.de ZP
.nr pd \\n()P
.nr )P 0
@@ -2197,28 +2200,8 @@ Inhibit the checks normally made before
commands, allowing a write to any file which the system protection
mechanism will allow.
.NH 1
-Limitations
-.PP
-Editor limits that the user is likely to encounter are as follows:
-1024 characters per line,
-256 characters per global command list,
-128 characters per file name,
-128 characters in the previous inserted and deleted text in
-.I open
-or
-.I visual,
-100 characters in a shell escape command,
-63 characters in a string valued option,
-and 30 characters in a tag name, and
-a limit of 250000 lines in the file is silently enforced.
+Acknowledgements
.PP
-The
-.I visual
-implementation limits the number of macros defined with map to
-32, and the total number of characters in macros to be less than 512.
-.LP
-.LP
-.I Acknowledgments.
Chuck Haley contributed greatly to the early development of
.I ex.
Bruce Englar encouraged the redesign which led to
diff --git a/usr.bin/vi/USD.doc/exref/ex.summary b/contrib/nvi/docs/USD.doc/exref/ex.summary
index 618da07c7420..83084a368ed8 100644
--- a/usr.bin/vi/USD.doc/exref/ex.summary
+++ b/contrib/nvi/docs/USD.doc/exref/ex.summary
@@ -29,15 +29,14 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)ex.summary 8.1 (Berkeley) 6/8/93
+.\" @(#)ex.summary 8.3 (Berkeley) 8/18/96
.\"
.ds p \v'-0.2'.\v'+0.2'
.ds U \s-2UNIX\s+2
.ds c \v'-0.2':\v'+0.2'
-.nr PO .25i
-.nr LL 6.75i
-.lt 6.75i
-.ll 6.75i
+.nr LL 6.5i
+.lt 6.5i
+.ll 6.5i
.ds CH
.ds LF Computing Services, U.C. Berkeley
.ds RF April 3, 1979
@@ -51,11 +50,10 @@
.ft B
.ce 1
Ex/Edit Command Summary (Version 2.0)
+.sp 1
.ft R
.nr VS 11
.nr PS 9
-.nr HM 0.5i
-.nr CW
.2C
.PP
.I Ex
@@ -251,10 +249,6 @@ rather than with its special meaning,
precede it by a backslash (\\).
The backslash always has a special meaning.
.1C
-.rm LF
-.rm RF
-.rm CF
-.nr FM 0.4
.TS
cp10 cp10 cp10 cp10
ltw(1.0i) lt2w(0.40i)fB ltw(3.0i) ltw(1.8i).
@@ -402,7 +396,7 @@ be added prior to line 1.
\&.
\fR:
.fi
-T} \^
+T}
.SP
\fR(.,.+1)\fBjoin j T{
Join lines together, adjusting white space (spaces
@@ -413,7 +407,7 @@ T} T{
Resulting line is printed
:
.fi
-T} \^
+T}
.TE
.bp
.TS
@@ -497,10 +491,13 @@ after the current line
T}
.TE
.FS
-\(dg Seek assistance from a consultant as soon as possible
-after saving a file with the
+.ll 6.5i
+\(dg You should seek assistance from a system administrator as soon as
+possible after saving a file with the
.I preserve
-command, because the file is saved on system storage space for only one week.
+command, because the preserved copy of the file is saved in a
+directory used to store temporary files, and thus, the preserved
+copy may only be available for a short period of time.
.FE
.SP
.nf
@@ -731,4 +728,3 @@ moving in the reverse direction
through the buffer.
T}
.TE
-
diff --git a/contrib/nvi/docs/USD.doc/vi.man/Makefile b/contrib/nvi/docs/USD.doc/vi.man/Makefile
new file mode 100644
index 000000000000..54338646791f
--- /dev/null
+++ b/contrib/nvi/docs/USD.doc/vi.man/Makefile
@@ -0,0 +1,16 @@
+# @(#)Makefile 8.7 (Berkeley) 8/18/96
+
+ROFF= groff
+
+all: vi.0 vi.0.ps
+
+vi.0: vi.1
+ ${ROFF} -man -Tascii < vi.1 > $@
+ chmod 444 $@
+
+vi.0.ps: vi.1
+ ${ROFF} -man < vi.1 > $@
+ chmod 444 $@
+
+clean:
+ rm -f vi.0 vi.0.ps
diff --git a/contrib/nvi/docs/USD.doc/vi.man/spell.ok b/contrib/nvi/docs/USD.doc/vi.man/spell.ok
new file mode 100644
index 000000000000..80ebcaba829d
--- /dev/null
+++ b/contrib/nvi/docs/USD.doc/vi.man/spell.ok
@@ -0,0 +1,179 @@
+Ar
+Bostic
+CDPATH
+COLUMNSXX
+Cscope
+Ds
+EXINIT
+Ee
+Ev
+Fa
+Ff
+Fl
+HUnhsh
+IPLPPPQPP
+LIpplpipbp
+Li
+Lite
+NEXINIT
+NHSHH
+Nex
+Nn
+POSIX
+Pp
+QQ
+SIGWINCHXX
+Std
+Sy
+TMPDIR
+Tt
+USD
+Unmap
+VI
+Vi
+XXXX
+ZZ
+ags
+ai
+altwerase
+ap
+autoindent
+autoprint
+autowrite
+aw
+bf
+bigwords
+cd
+cdpath
+cedit
+cmd
+co
+creens
+cs
+ctags
+db
+dbopen
+dd
+di
+dir
+dit
+doc
+docs
+eFRrsv
+eFRrv
+eFlRrv
+ead
+eb
+edcompatible
+egrep
+elete
+errorbells
+esc
+exrc
+exu
+fg
+filec
+hange
+hardtabs
+ht
+ic
+iclower
+ignorecase
+ile
+ind
+ious
+ist
+ize
+keytime
+leftright
+lhs
+li
+libc
+lobal
+lp
+matchtime
+mber
+mesg
+mk
+modeful
+modeline
+modelines
+nex
+nexrc
+nk
+nonblank
+nooption
+noprint
+nsert
+nul
+nvi
+oin
+onnections
+ove
+ppend
+prev
+pu
+readonly
+rec
+recdir
+redist
+rhs
+rint
+rk
+ro
+rsion
+sccs
+scr
+se
+searchincr
+sh
+shareware
+shellmeta
+shiftwidth
+showmatch
+showmode
+sidescroll
+slowopen
+sm
+smd
+sourceany
+su
+sual
+sw
+ta
+tabstop
+taglength
+tagn
+tagp
+tagstring
+th's
+tildeop
+tl
+tmp
+tr
+ts
+ttytype
+ttywerase
+ubstitute
+uffers
+uit
+unm
+urce
+var
+ve
+vi
+viu
+wa
+wi
+windowname
+wl
+wm
+wn
+wq
+wraplen
+wrapmargin
+wrapscan
+writeany
+ws
+ya
+yy
diff --git a/usr.bin/vi/USD.doc/vi.man/vi.1 b/contrib/nvi/docs/USD.doc/vi.man/vi.1
index 25f2a2ce0f3b..22aee3e7e952 100644
--- a/usr.bin/vi/USD.doc/vi.man/vi.1
+++ b/contrib/nvi/docs/USD.doc/vi.man/vi.1
@@ -1,210 +1,213 @@
.\" Copyright (c) 1994
.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 1994, 1995, 1996
+.\" Keith Bostic. All rights reserved.
.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
+.\" This document may not be republished without written permission from
+.\" Keith Bostic.
.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
+.\" See the LICENSE file for redistribution information.
.\"
-.\" @(#)vi.1 8.12 (Berkeley) 7/15/94
+.\" @(#)vi.1 8.51 (Berkeley) 10/10/96
.\"
-.Dd "July 15, 1994"
-.Dt EX/VI 1
-.Os
-.Sh NAME
-.Nm ex, vi, view
-.Nd text editors
-.Sh SYNOPSIS
-.Nm \&ex
-.Op Fl eFRrsv
-.Op Fl c Ar cmd
-.Op Fl t Ar tag
-.Op Fl w Ar size
-.\".Op Fl X Ar \&aw
-.Op Ar "file ..."
-.Nm \&vi
-.Op Fl eFRrv
-.Op Fl c Ar cmd
-.Op Fl t Ar tag
-.Op Fl w Ar size
-.\".Op Fl X Ar \&aw
-.Op Ar "file ..."
-.Nm view
-.Op Fl eFRrv
-.Op Fl c Ar cmd
-.Op Fl t Ar tag
-.Op Fl w Ar size
-.\".Op Fl X Ar \&aw
-.Op Ar "file ..."
-.Sh DESCRIPTION
-.Nm \&Vi
+.TH VI 1 "October 10, 1996"
+.UC
+.SH NAME
+ex, vi, view \- text editors
+.SH SYNOPSIS
+.B ex
+[\c
+.B -eFRrSsv\c
+] [\c
+.BI -c " cmd"\c
+] [\c
+.BI -t " tag"\c
+] [\c
+.BI -w " size"\c
+] [file ...]
+.br
+.B vi
+[\c
+.B -eFlRrSv\c
+] [\c
+.BI -c " cmd"\c
+] [\c
+.BI -t " tag"\c
+] [\c
+.BI -w " size"\c
+] [file ...]
+.br
+.B view
+[\c
+.B -eFRrSv\c
+] [\c
+.BI -c " cmd"\c
+] [\c
+.BI -t " tag"\c
+] [\c
+.BI -w " size"\c
+] [file ...]
+.SH LICENSE
+The vi program is freely redistributable. You are welcome to copy,
+modify and share it with others under the conditions listed in the
+LICENSE file. If any company (not individual!) finds vi sufficiently
+useful that you would have purchased it, or if any company wishes to
+redistribute it, contributions to the authors would be appreciated.
+.SH DESCRIPTION
+.I \&Vi
is a screen oriented text editor.
-.Nm \&Ex
+.I \&Ex
is a line-oriented text editor.
-.Nm \&Ex
+.I \&Ex
and
-.Nm \&vi
+.I \&vi
are different interfaces to the same program,
and it is possible to switch back and forth during an edit session.
-.Nm View
+.I View
is the equivalent of using the
-.Fl R
+.B \-R
(read-only) option of
-.Nm \&vi .
-.Pp
+.IR \&vi .
+.PP
This manual page is the one provided with the
-.Nm nex/nvi
+.I nex/nvi
versions of the
-.Nm ex/vi
+.I ex/vi
text editors.
-.Nm Nex/nvi
+.I Nex/nvi
are intended as bug-for-bug compatible replacements for the original
Fourth Berkeley Software Distribution (4BSD)
-.Nm \&ex
+.I \&ex
and
-.Nm \&vi
+.I \&vi
programs.
For the rest of this manual page,
-.Nm nex/nvi
+.I nex/nvi
is used only when it's necessary to distinguish it from the historic
implementations of
-.Nm ex/vi .
-.Pp
+.IR ex/vi .
+.PP
This manual page is intended for users already familiar with
-.Nm ex/vi .
+.IR ex/vi .
Anyone else should almost certainly read a good tutorial on the
editor before this manual page.
If you're in an unfamiliar environment, and you absolutely have to
get work done immediately, read the section after the options
-description, entitled
-.Dq "Fast Startup" .
+description, entitled ``Fast Startup''.
It's probably enough to get you going.
-.Pp
+.PP
The following options are available:
-.Bl -tag -width Ds
-.It Fl c
+.TP
+.B \-c
Execute
-.Ar cmd
+.B cmd
immediately after starting the edit session.
Particularly useful for initial positioning in the file, however
-.Ar cmd
+.B cmd
is not limited to positioning commands.
-This is the POSIX 1003.2 interface for the historic
-.Dq "+cmd"
-syntax.
-.Nm Nex/nvi
+This is the POSIX 1003.2 interface for the historic ``+cmd'' syntax.
+.I Nex/nvi
supports both the old and new syntax.
-.It Fl e
+.TP
+.B \-e
Start editing in ex mode, as if the command name were
-.Nm \&ex .
-.It Fl F
+.IR \&ex .
+.TP
+.B \-F
Don't copy the entire file when first starting to edit.
(The default is to make a copy in case someone else modifies
the file during your edit session.)
-.It Fl R
+.TP
+.B \-l
+Start editing with the lisp and showmatch options set.
+.TP
+.B \-R
Start editing in read-only mode, as if the command name was
-.Nm view ,
-or the readonly option was set.
-.It Fl r
+.IR view ,
+or the
+.B readonly
+option was set.
+.TP
+.B \-r
Recover the specified files, or, if no files are specified,
list the files that could be recovered.
If no recoverable files by the specified name exist,
the file is edited as if the
-.Fl r
+.B \-r
option had not been specified.
-.It Fl s
+.TP
+.B \-S
+Run with the
+.B secure
+edit option set, disallowing all access to external programs.
+.TP
+.B \-s
Enter batch mode; applicable only to
-.Nm \&ex
+.I \&ex
edit sessions.
Batch mode is useful when running
-.Nm \&ex
+.I \&ex
scripts.
Prompts, informative messages and other user oriented message
are turned off,
and no startup files or environmental variables are read.
-This is the POSIX 1003.2 interface for the historic
-.Dq \&\-
-argument.
-.Nm \&Nex/nvi
+This is the POSIX 1003.2 interface for the historic ``\-'' argument.
+.I \&Nex/nvi
supports both the old and new syntax.
-.It Fl t
+.TP
+.B \-t
Start editing at the specified tag.
(See
-.Xr ctags 1 ).
-.It Fl w
+.IR ctags (1)).
+.TP
+.B \-w
Set the initial window size to the specified number of lines.
-.It Fl v
+.TP
+.B \-v
Start editing in vi mode, as if the command name was
-.Nm \&vi
+.I \&vi
or
-.Nm view .
-.It Fl X
-Reserved for X11 interfaces.
-.Em "No X11 support is currently implemented."
-.El
-.Pp
+.IR view .
+.PP
Command input for
-.Nm ex/vi
+.I ex/vi
is read from the standard input.
In the
-.Nm \&vi
+.I \&vi
interface, it is an error if standard input is not a terminal.
In the
-.Nm \&ex
+.I \&ex
interface, if standard input is not a terminal,
-.Nm \&ex
+.I \&ex
will read commands from it regardless, however, the session will be a
batch mode session, exactly as if the
-.Fl s
+.B \-s
option had been specified.
-.Pp
-.Nm Ex/vi
+.PP
+.I Ex/vi
exits 0 on success, and greater than 0 if an error occurs.
-.Sh FAST STARTUP
+.SH FAST STARTUP
This section will tell you the minimum amount that you need to
do simple editing tasks using
-.Nm \&vi .
+.IR \&vi .
If you've never used any screen editor before, you're likely to have
problems even with this simple introduction.
In that case you should find someone that already knows
-.Nm \&vi
+.I \&vi
and have them walk you through this section.
-.Pp
-.Nm \&Vi
+.PP
+.I \&Vi
is a screen editor.
This means that it takes up almost the entire screen, displaying part
of the file on each screen line, except for the last line of the screen.
The last line of the screen is used for you to give commands to
-.Nm \&vi ,
+.IR \&vi ,
and for
-.Nm \&vi
+.I \&vi
to give information to you.
-.Pp
+.PP
The other fact that you need to understand is that
-.Nm \&vi
+.I \&vi
is a modeful editor, i.e. you are either entering text or you
are executing commands, and you have to be in the right mode
to do one or the other.
@@ -213,1082 +216,1393 @@ There are commands that switch you into input mode.
There is only one key that takes you out of input mode,
and that is the <escape> key.
(Key names are written using less-than and greater-than signs, e.g.
-<escape> means the
-.Dq escape
-key, usually labeled
-.Dq esc
-on your terminal's keyboard.)
+<escape> means the ``escape'' key, usually labeled ``esc'' on your
+terminal's keyboard.)
If you're ever confused as to which mode you're in,
keep entering the <escape> key until
-.Nm \&vi
+.I \&vi
beeps at you.
(Generally,
-.Nm \&vi
+.I \&vi
will beep at you if you try and do something that's not allowed.
It will also display error messages.)
-.Pp
-To start editing a file, enter the command
-.Dq Li "vi file_name<carriage-return>" .
+.PP
+To start editing a file, enter the command ``vi file_name<carriage-return>''.
The command you should enter as soon as you start editing is
-.Dq Li ":set verbose showmode<carriage-return>" .
+``:set verbose showmode<carriage-return>''.
This will make the editor give you verbose error messages and display
the current mode at the bottom of the screen.
-.Pp
+.PP
The commands to move around the file are:
-.Bl -tag -width XXXX -compact
-.It Sy h
+.TP
+.B h
Move the cursor left one character.
-.It Sy j
+.TP
+.B j
Move the cursor down one line.
-.It Sy k
+.TP
+.B k
Move the cursor up one line.
-.It Sy l
+.TP
+.B l
Move the cursor right one character.
-.It Sy <cursor-arrows>
+.TP
+.B <cursor-arrows>
The cursor arrow keys should work, too.
-.It Sy /text<carriage-return>
-Search for the string
-.Dq text
-in the file, and move the cursor to its first character.
-.El
-.Pp
+.TP
+.B /text<carriage-return>
+Search for the string ``text'' in the file,
+and move the cursor to its first character.
+.PP
The commands to enter new text are:
-.Bl -tag -width XXXX -compact
-.It Sy a
+.TP
+.B a
Append new text,
-.Em after
+.I after
the cursor.
-.It Sy i
+.TP
+.B i
Insert new text,
-.Em before
+.I before
the cursor.
-.It Sy o
+.TP
+.B o
Open a new line below the line the cursor is on, and start
entering text.
-.It Sy O
+.TP
+.B O
Open a new line above the line the cursor is on, and start
entering text.
-.It Sy <escape>
+.TP
+.B <escape>
Once you've entered input mode using the one of the
-.Sy \&a ,
-.Sy \&i ,
-.Sy \&O ,
+.BR \&a ,
+.BR \&i ,
+.BR \&O
or
-.Sy \&o
+.B \&o
commands, use
-.Sy <escape>
+.B <escape>
to quit entering text and return to command mode.
-.El
-.Pp
+.PP
The commands to copy text are:
-.Bl -tag -width XXXX -compact
-.It Sy yy
+.TP
+.B yy
Copy the line the cursor is on.
-.It Sy p
+.TP
+.B p
Append the copied line after the line the cursor is on.
-.El
-.Pp
+.PP
The commands to delete text are:
-.Bl -tag -width XXXX -compact
-.It Sy dd
+.TP
+.B dd
Delete the line the cursor is on.
-.It Sy x
+.TP
+.B x
Delete the character the cursor is on.
-.El
-.Pp
+.PP
The commands to write the file are:
-.Bl -tag -width XXXX -compact
-.It Sy :w<carriage-return>
+.TP
+.B :w<carriage-return>
Write the file back to the file with the name that you originally used
as an argument on the
-.Nm \&vi
+.I \&vi
command line.
-.It Sy :w file_name<carriage-return>
-Write the file back to the file with the name
-.Dq file_name .
-.El
-.Pp
+.TP
+.B ":w file_name<carriage-return>"
+Write the file back to the file with the name ``file_name''.
+.PP
The commands to quit editing and exit the editor are:
-.Bl -tag -width XXXX -compact
-.It Sy :q<carriage-return>
+.TP
+.B :q<carriage-return>
Quit editing and leave vi (if you've modified the file, but not
saved your changes,
-.Nm \&vi
+.I \&vi
will refuse to quit).
-.It Sy :q!<carriage-return>
+.TP
+.B :q!<carriage-return>
Quit, discarding any modifications that you may have made.
-.El
-.Pp
+.PP
One final caution.
Unusual characters can take up more than one column on the screen,
and long lines can take up more than a single screen line.
-The above commands work on
-.Dq physical
-characters and lines, i.e. they affect the entire line no matter
-how many screen lines it takes up and the entire character no matter
-how many screen columns it takes up.
-.Sh VI COMMANDS
+The above commands work on ``physical'' characters and lines,
+i.e. they affect the entire line no matter how many screen lines it
+takes up and the entire character no matter how many screen columns
+it takes up.
+.SH VI COMMANDS
The following section describes the commands available in the command
mode of the
-.Nm \&vi
+.I \&vi
editor.
In each entry below, the tag line is a usage synopsis for the command
character.
-.sp
-.Bl -tag -width "XXXX" -compact
-.It Sy "[count] <control-A>"
+.PP
+.TP
+.B "[count] <control-A>"
Search forward
-.Li count
+.I count
times for the current word.
-.It Sy "[count] <control-B>"
+.TP
+.B "[count] <control-B>"
Page backwards
-.Li count
+.I count
screens.
-.It Sy "[count] <control-D>"
+.TP
+.B "[count] <control-D>"
Scroll forward
-.Li count
+.I count
lines.
-.It Sy "[count] <control-E>"
+.TP
+.B "[count] <control-E>"
Scroll forward
-.Li count
+.I count
lines, leaving the current line and column as is, if possible.
-.It Sy "[count] <control-F>"
+.TP
+.B "[count] <control-F>"
Page forward
-.Li count
+.I count
screens.
-.It Sy "<control-G>"
+.TP
+.B "<control-G>"
Display the file information.
-.It Sy "<control-H>"
-.It Sy "[count] h"
+.TP
+.B "<control-H>"
+.TP
+.B "[count] h"
Move the cursor back
-.Li count
+.I count
characters in the current line.
-.It Sy "[count] <control-J>"
-.It Sy "[count] <control-N>"
-.It Sy "[count] j"
+.TP
+.B "[count] <control-J>"
+.TP
+.B "[count] <control-N>"
+.TP
+.B "[count] j"
Move the cursor down
-.Li count
+.I count
lines without changing the current column.
-.It Sy "<control-L>"
-.It Sy "<control-R>"
+.TP
+.B "<control-L>"
+.TP
+.B "<control-R>"
Repaint the screen.
-.It Sy "[count] <control-M>"
-.It Sy "[count] +"
+.TP
+.B "[count] <control-M>"
+.TP
+.B "[count] +"
Move the cursor down
-.Li count
+.I count
lines to the first nonblank character of that line.
-.It Sy "[count] <control-P>"
-.It Sy "[count] k"
+.TP
+.B "[count] <control-P>"
+.TP
+.B "[count] k"
Move the cursor up
-.Li count
+.I count
lines, without changing the current column.
-.It Sy "<control-T>"
+.TP
+.B "<control-T>"
Return to the most recent tag context.
-.It Sy "<control-U>"
+.TP
+.B "<control-U>"
Scroll backwards
-.Li count
+.I count
lines.
-.It Sy "<control-W>"
+.TP
+.B "<control-W>"
Switch to the next lower screen in the window, or, to the first
screen if there are no lower screens in the window.
-.It Sy "<control-Y>"
+.TP
+.B "<control-Y>"
Scroll backwards
-.Li count
+.I count
lines, leaving the current line and column as is, if possible.
-.It Sy "<control-Z>"
+.TP
+.B "<control-Z>"
Suspend the current editor session.
-.It Sy "<escape>"
+.TP
+.B "<escape>"
Execute
-.Nm \&ex
+.I \&ex
commands or cancel partial commands.
-.It Sy "<control-]>"
+.TP
+.B "<control-]>"
Push a tag reference onto the tag stack.
-.It Sy "<control-^>"
+.TP
+.B "<control-^>"
Switch to the most recently edited file.
-.It Sy "[count] <space>"
-.It Sy "[count] l"
+.TP
+.B "[count] <space>"
+.TP
+.B "[count] l"
Move the cursor forward
-.Li count
+.I count
characters without changing the current line.
-.It Sy "[count] ! motion shell-argument(s)"
+.TP
+.B "[count] ! motion shell-argument(s)"
Replace text with results from a shell command.
-.It Sy "[count] # +|-|#"
+.TP
+.B "[count] # #|+|-"
Increment or decrement the cursor number.
-.It Sy "[count] $"
+.TP
+.B "[count] $"
Move the cursor to the end of a line.
-.It Sy "%"
+.TP
+.B "%"
Move to the matching character.
-.It Sy "&"
+.TP
+.B "&"
Repeat the previous substitution command on the current line.
-.It Sy "'<character>"
-.It Sy "`<character>"
+.TP
+.B "'<character>"
+.TP
+.B "`<character>"
Return to a context marked by the character
-.Li <character> .
-.It Sy "[count] ("
+.IR <character> .
+.TP
+.B "[count] ("
Back up
-.Li count
+.I count
sentences.
-.It Sy "[count] )"
+.TP
+.B "[count] )"
Move forward
-.Li count
+.I count
sentences.
-.It Sy "[count] ,"
+.TP
+.B "[count] ,"
Reverse find character
-.Li count
+.I count
times.
-.It Sy "[count] -"
+.TP
+.B "[count] -"
Move to first nonblank of the previous line,
-.Li count
+.I count
times.
-.It Sy "[count] ."
+.TP
+.B "[count] ."
Repeat the last
-.Nm \&vi
+.I \&vi
command that modified text.
-.It Sy "/RE<carriage-return>"
-.It Sy "/RE/ [offset]<carriage-return>"
-.It Sy "?RE<carriage-return>"
-.It Sy "?RE? [offset]<carriage-return>"
-.It Sy "N"
-.It Sy "n"
+.TP
+.B "/RE<carriage-return>"
+.TP
+.B "/RE/ [offset]<carriage-return>"
+.TP
+.B "?RE<carriage-return>"
+.TP
+.B "?RE? [offset]<carriage-return>"
+.TP
+.B "N"
+.TP
+.B "n"
Search forward or backward for a regular expression.
-.It Sy "0"
+.TP
+.B "0"
Move to the first character in the current line.
-.It Sy ":"
+.TP
+.B ":"
Execute an ex command.
-.It Sy "[count] ;"
+.TP
+.B "[count] ;"
Repeat the last character find
-.Li count
+.I count
times.
-.It Sy "[count] < motion"
-.It Sy "[count] > motion"
+.TP
+.B "[count] < motion"
+.TP
+.B "[count] > motion"
Shift lines left or right.
-.It Sy "@ buffer"
+.TP
+.B "@ buffer"
Execute a named buffer.
-.It Sy "[count] A"
+.TP
+.B "[count] A"
Enter input mode, appending the text after the end of the line.
-.It Sy "[count] B"
+.TP
+.B "[count] B"
Move backwards
-.Li count
+.I count
bigwords.
-.It Sy "[buffer] [count] C"
+.TP
+.B "[buffer] [count] C"
Change text from the current position to the end-of-line.
-.It Sy "[buffer] D"
+.TP
+.B "[buffer] D"
Delete text from the current position to the end-of-line.
-.It Sy "[count] E"
+.TP
+.B "[count] E"
Move forward
-.Li count
+.I count
end-of-bigwords.
-.It Sy "[count] F <character>"
+.TP
+.B "[count] F <character>"
Search
-.Li count
+.I count
times backward through the current line for
-.Li <character> .
-.It Sy "[count] G"
+.IR <character> .
+.TP
+.B "[count] G"
Move to line
-.Li count ,
+.IR count ,
or the last line of the file if
-.Li count
+.I count
not specified.
-.It Sy "[count] H"
+.TP
+.B "[count] H"
Move to the screen line
-.Li "count - 1"
+.I "count - 1"
lines below the top of the screen.
-.It Sy "[count] I"
+.TP
+.B "[count] I"
Enter input mode, inserting the text at the beginning of the line.
-.It Sy "[count] J"
+.TP
+.B "[count] J"
Join lines.
-.It Sy "[count] L"
+.TP
+.B "[count] L"
Move to the screen line
-.Li "count - 1"
+.I "count - 1"
lines above the bottom of the screen.
-.It Sy " M"
+.TP
+.B " M"
Move to the screen line in the middle of the screen.
-.It Sy "[count] O"
+.TP
+.B "[count] O"
Enter input mode, appending text in a new line above the current line.
-.It Sy "[buffer] P"
+.TP
+.B "[buffer] P"
Insert text from a buffer.
-.It Sy "Q"
+.TP
+.B "Q"
Exit
-.Nm \&vi
+.I \&vi
(or visual) mode and switch to
-.Nm \&ex
+.I \&ex
mode.
-.It Sy "[count] R"
+.TP
+.B "[count] R"
Enter input mode, replacing the characters in the current line.
-.It Sy "[buffer] [count] S"
+.TP
+.B "[buffer] [count] S"
Substitute
-.Li count
+.I count
lines.
-.It Sy "[count] T <character>"
+.TP
+.B "[count] T <character>"
Search backwards,
-.Li count
+.I count
times,
through the current line for the character
-.Em after
+.I after
the specified
-.Li <character> .
-.It Sy "U"
+.IR <character> .
+.TP
+.B "U"
Restore the current line to its state before the cursor last
moved to it.
-.It Sy "[count] W"
+.TP
+.B "[count] W"
Move forward
-.Li count
+.I count
bigwords.
-.It Sy "[buffer] [count] X"
+.TP
+.B "[buffer] [count] X"
Delete
-.Li count
+.I count
characters before the cursor.
-.It Sy "[buffer] [count] Y"
-Copy (or
-.Dq yank )
-.Li count
+.TP
+.B "[buffer] [count] Y"
+Copy (or ``yank'')
+.I count
lines into the specified buffer.
-.It Sy "ZZ"
+.TP
+.B "ZZ"
Write the file and exit
-.Nm \&vi .
-.It Sy "[count] [["
+.IR \&vi .
+.TP
+.B "[count] [["
Back up
-.Li count
+.I count
section boundaries.
-.It Sy "[count] ]]"
+.TP
+.B "[count] ]]"
Move forward
-.Li count
+.I count
section boundaries.
-.It Sy "\&^"
+.TP
+.B "\&^"
Move to first nonblank character on the current line.
-.It Sy "[count] _"
+.TP
+.B "[count] _"
Move down
-.Li "count - 1"
+.I "count - 1"
lines, to the first nonblank character.
-.It Sy "[count] a"
+.TP
+.B "[count] a"
Enter input mode, appending the text after the cursor.
-.It Sy "[count] b"
+.TP
+.B "[count] b"
Move backwards
-.Li count
+.I count
words.
-.It Sy "[buffer] [count] c motion"
+.TP
+.B "[buffer] [count] c motion"
Change a region of text.
-.It Sy "[buffer] [count] d motion"
+.TP
+.B "[buffer] [count] d motion"
Delete a region of text.
-.It Sy "[count] e"
+.TP
+.B "[count] e"
Move forward
-.Li count
+.I count
end-of-words.
-.It Sy "[count] f<character>"
+.TP
+.B "[count] f<character>"
Search forward,
-.Li count
+.I count
times, through the rest of the current line for
-.Li <character> .
-.It Sy "[count] i"
+.IR <character> .
+.TP
+.B "[count] i"
Enter input mode, inserting the text before the cursor.
-.It Sy "m <character>"
+.TP
+.B "m <character>"
Save the current context (line and column) as
-.Li <character> .
-.It Sy "[count] o"
+.IR <character> .
+.TP
+.B "[count] o"
Enter input mode, appending text in a new line under the current line.
-.It Sy "[buffer] p"
+.TP
+.B "[buffer] p"
Append text from a buffer.
-.It Sy "[count] r <character>
+.TP
+.B "[count] r <character>"
Replace
-.Li count
+.I count
characters.
-.It Sy "[buffer] [count] s"
+.TP
+.B "[buffer] [count] s"
Substitute
-.Li count
+.I count
characters in the current line starting with the current character.
-.It Sy "[count] t <character>"
+.TP
+.B "[count] t <character>"
Search forward,
-.Li count
+.I count
times, through the current line for the character immediately
-.Em before
-.Li <character> .
-.It Sy "u"
+.I before
+.IR <character> .
+.TP
+.B "u"
Undo the last change made to the file.
-.It Sy "[count] w"
+.TP
+.B "[count] w"
Move forward
-.Li count
+.I count
words.
-.It Sy "[buffer] [count] x"
+.TP
+.B "[buffer] [count] x"
Delete
-.Li count
+.I count
characters.
-.It Sy "[buffer] [count] y motion"
-Copy (or
-.Dq yank )
+.TP
+.B "[buffer] [count] y motion"
+Copy (or ``yank'')
a text region specified by the
-.Li count
+.I count
and motion into a buffer.
-.It Sy "[count1] z [count2] -|.|+|^|<carriage-return>"
+.TP
+.B "[count1] z [count2] -|.|+|^|<carriage-return>"
Redraw, optionally repositioning and resizing the screen.
-.It Sy "[count] {"
+.TP
+.B "[count] {"
Move backward
-.Li count
+.I count
paragraphs.
-.It Sy "[count] |"
+.TP
+.B "[count] |"
Move to a specific
-.Em column
+.I column
position on the current line.
-.It Sy "[count] }"
+.TP
+.B "[count] }"
Move forward
-.Li count
+.I count
paragraphs.
-.It Sy "[count] ~"
+.TP
+.B "[count] ~"
Reverse the case of the next
-.Li count
+.I count
character(s).
-.It Sy "[count] ~ motion"
+.TP
+.B "[count] ~ motion"
Reverse the case of the characters in a text region specified by the
-.Li count
+.I count
and
-.Li motion .
-.It Sy "<interrupt>"
+.IR motion .
+.TP
+.B "<interrupt>"
Interrupt the current operation.
-.El
-.Sh VI TEXT INPUT COMMANDS
+.SH VI TEXT INPUT COMMANDS
The following section describes the commands available in the text
input mode of the
-.Nm \&vi
+.I \&vi
editor.
-.Pp
-.Bl -tag -width "XXXX" -compact
-.It Sy "<nul>"
+.PP
+.TP
+.B "<nul>"
Replay the previous input.
-.It Sy "<control-D>"
-Erase the previous autoindent character.
-.It Sy "^<control-D>"
+.TP
+.B "<control-D>"
+Erase to the previous
+.B shiftwidth
+column boundary.
+.TP
+.B "^<control-D>"
Erase all of the autoindent characters, and reset the autoindent level.
-.It Sy "0<control-D>"
+.TP
+.B "0<control-D>"
Erase all of the autoindent characters.
-.It Sy "<control-T>"
+.TP
+.B "<control-T>"
Insert sufficient
-.Li <tab>
+.I <tab>
and
-.Li <space>
-characters to move the cursor forward to a column immediately
-after the next column which is an even multiple of the
-.Sy shiftwidth
-option.
-.It Sy "<erase>
-.It Sy "<control-H>"
+.I <space>
+characters to move forward to the next
+.B shiftwidth
+column boundary.
+.TP
+.B "<erase>
+.TP
+.B "<control-H>"
Erase the last character.
-.It Sy "<literal next>"
+.TP
+.B "<literal next>"
Quote the next character.
-.It Sy "<escape>
+.TP
+.B "<escape>
Resolve all text input into the file, and return to command mode.
-.It Sy "<line erase>
+.TP
+.B "<line erase>"
Erase the current line.
-.It Sy "<control-W>"
-.It Sy "<word erase>
+.TP
+.B "<control-W>"
+.TP
+.B "<word erase>"
Erase the last word.
The definition of word is dependent on the
-.Sy altwerase
+.B altwerase
and
-.Sy ttywerase
+.B ttywerase
options.
-.It Sy "<control-X>[0-9A-Fa-f]*"
+.TP
+.B "<control-X>[0-9A-Fa-f]+"
Insert a character with the specified hexadecimal value into the text.
-.It Sy "<interrupt>"
+.TP
+.B "<interrupt>"
Interrupt text input mode, returning to command mode.
-.El
-.Sh EX COMMANDS
+.SH EX COMMANDS
The following section describes the commands available in the
-.Nm \&ex
+.I \&ex
editor.
In each entry below, the tag line is a usage synopsis for the command.
-.sp
-.Bl -tag -width "XXXX" -compact
-.It Sy "<end-of-file>"
+.PP
+.TP
+.B "<end-of-file>"
Scroll the screen.
-.It Sy "! argument(s)"
-.It Sy "[range]! argument(s)"
+.TP
+.B "! argument(s)"
+.TP
+.B "[range]! argument(s)"
Execute a shell command, or filter lines through a shell command.
-.It Sy \&"
+.TP
+.B \&"
A comment.
-.It Sy "[range] nu[mber] [count] [flags]"
-.It Sy "[range] # [count] [flags]"
+.TP
+.B "[range] nu[mber] [count] [flags]"
+.TP
+.B "[range] # [count] [flags]"
Display the selected lines, each preceded with its line number.
-.It Sy "@ buffer"
-.It Sy "* buffer"
+.TP
+.B "@ buffer"
+.TP
+.B "* buffer"
Execute a buffer.
-.It Sy "[range] d[elete] [buffer] [count] [flags]"
+.TP
+.B "[line] a[ppend][!]"
+The input text is appended after the specified line.
+.TP
+.B "[range] c[hange][!] [count]"
+The input text replaces the specified range.
+.TP
+.B "cs[cope] add | find | help | kill | reset"
+Execute a Cscope command.
+.TP
+.B "[range] d[elete] [buffer] [count] [flags]"
Delete the lines from the file.
-.It Sy "di[splay] b[uffers] | s[creens] | t[ags]"
-Display buffers, screens or tags.
-.It Sy "e[dit][!] [+cmd] [file]"
-.It Sy "ex[!] [+cmd] [file]"
+.TP
+.B "di[splay] b[uffers] | c[onnections] | s[creens] | t[ags]"
+Display buffers, Cscope connections, screens or tags.
+.TP
+.B "[Ee][dit][!] [+cmd] [file]"
+.TP
+.B "[Ee]x[!] [+cmd] [file]"
Edit a different file.
-.It Sy "exu[sage] [command]"
+.TP
+.B "exu[sage] [command]"
Display usage for an
-.Nm \&ex
+.I \&ex
command.
-.It Sy "f[ile] [file]"
+.TP
+.B "f[ile] [file]"
Display and optionally change the file name.
-.It Sy "fg [name]"
-.Nm \&Vi
+.TP
+.B "[Ff]g [name]"
+.I \&Vi
mode only.
Foreground the specified screen.
-.It Sy "[range] g[lobal] /pattern/ [commands]"
-.It Sy "[range] v /pattern/ [commands]
+.TP
+.B "[range] g[lobal] /pattern/ [commands]"
+.TP
+.B "[range] v /pattern/ [commands]"
Apply commands to lines matching (or not matching) a pattern.
-.It Sy "he[lp]"
+.TP
+.B "he[lp]"
Display a help message.
-.It Sy "[line] i[nsert][!]"
+.TP
+.B "[line] i[nsert][!]"
The input text is inserted before the specified line.
-.It Sy "[range] j[oin][!] [count] [flags]"
+.TP
+.B "[range] j[oin][!] [count] [flags]"
Join lines of text together.
-.It Sy "[range] l[ist] [count] [flags]"
+.TP
+.B "[range] l[ist] [count] [flags]"
Display the lines unambiguously.
-.It Sy "map[!] [lhs rhs]"
+.TP
+.B "map[!] [lhs rhs]"
Define or display maps (for
-.Nm \&vi
+.I \&vi
only).
-.It Sy "[line] ma[rk] <character>"
-.It Sy "[line] k <character>"
+.TP
+.B "[line] ma[rk] <character>"
+.TP
+.B "[line] k <character>"
Mark the line with the mark
-.Li <character> .
-.It Sy "[range] m[ove] line"
+.IR <character> .
+.TP
+.B "[range] m[ove] line"
Move the specified lines after the target line.
-.It Sy "mk[exrc][!] file"
+.TP
+.B "mk[exrc][!] file"
Write the abbreviations, editor options and maps to the specified
file.
-.It Sy "n[ext][!] [file ...]"
+.TP
+.B "[Nn][ext][!] [file ...]"
Edit the next file from the argument list.
-.It Sy "[line] o[pen] /pattern/ [flags]"
+.TP
+.B "[line] o[pen] /pattern/ [flags]"
Enter open mode.
-.It Sy "pre[serve]"
+.TP
+.B "pre[serve]"
Save the file in a form that can later be recovered using the
-.Nm \&ex
-.Fl r
+.I \&ex
+.B \-r
option.
-.It Sy "prev[ious][!]"
+.TP
+.B "[Pp]rev[ious][!]"
Edit the previous file from the argument list.
-.It Sy "[range] p[rint] [count] [flags]"
+.TP
+.B "[range] p[rint] [count] [flags]"
Display the specified lines.
-.It Sy "[line] pu[t] [buffer]"
+.TP
+.B "[line] pu[t] [buffer]"
Append buffer contents to the current line.
-.It Sy "q[uit][!]"
+.TP
+.B "q[uit][!]"
End the editing session.
-.It Sy "[line] r[ead][!] [file]"
+.TP
+.B "[line] r[ead][!] [file]"
Read a file.
-.It Sy "rec[over] file"
+.TP
+.B "rec[over] file"
Recover
-.Li file
+.I file
if it was previously saved.
-.It Sy "res[ize] [+|-]size"
-.Nm \&Vi
+.TP
+.B "res[ize] [+|-]size"
+.I \&Vi
mode only.
Grow or shrink the current screen.
-.It Sy "rew[ind][!]"
+.TP
+.B "rew[ind][!]"
Rewind the argument list.
-.It Sy "se[t] [option[=[value]] ...] [nooption ...] [option? ...] [all]"
+.TP
+.B "se[t] [option[=[value]] ...] [nooption ...] [option? ...] [all]"
Display or set editor options.
-.It Sy "sh[ell]"
+.TP
+.B "sh[ell]"
Run a shell program.
-.It Sy "so[urce] file"
+.TP
+.B "so[urce] file"
Read and execute
-.Nm \&ex
+.I \&ex
commands from a file.
-.It Sy "sp[lit] [file ...]"
-.Nm \&Vi
-mode only.
-Split the screen.
-.It Sy "[range] s[ubstitute] [/pattern/replace/] [options] [count] [flags]"
-.It Sy "[range] & [options] [count] [flags]"
-.It Sy "[range] ~ [options] [count] [flags]"
+.TP
+.B "[range] s[ubstitute] [/pattern/replace/] [options] [count] [flags]"
+.TP
+.B "[range] & [options] [count] [flags]"
+.TP
+.B "[range] ~ [options] [count] [flags]"
Make substitutions.
-.It Sy "su[spend][!]"
-.It Sy "st[op][!]"
-.It Sy <suspend>
+.TP
+.B "su[spend][!]"
+.TP
+.B "st[op][!]"
+.TP
+.B <suspend>
Suspend the edit session.
-.It Sy "ta[g][!] tagstring"
+.TP
+.B "[Tt]a[g][!] tagstring"
Edit the file containing the specified tag.
-.It Sy "tagp[op][!] [file | number]"
+.TP
+.B "tagn[ext][!]"
+Edit the file containing the next context for the current tag.
+.TP
+.B "tagp[op][!] [file | number]"
Pop to the specified tag in the tags stack.
-.It Sy "unm[ap][!] lhs"
+.TP
+.B "tagp[rev][!]"
+Edit the file containing the previous context for the current tag.
+.TP
+.B "unm[ap][!] lhs"
Unmap a mapped string.
-.It Sy "ve[rsion]"
+.TP
+.B "ve[rsion]"
Display the version of the
-.Nm \&ex/vi
+.I \&ex/vi
editor.
-.It Sy "[line] vi[sual] [type] [count] [flags]"
-.Nm \&Ex
+.TP
+.B "[line] vi[sual] [type] [count] [flags]"
+.I \&Ex
mode only.
Enter
-.Nm \&vi .
-.It Sy "vi[sual][!] [+cmd] [file]"
-.Nm \&Vi
+.IR \&vi .
+.TP
+.B "[Vi]i[sual][!] [+cmd] [file]"
+.I \&Vi
mode only.
Edit a new file.
-.It Sy "viu[sage] [command]"
+.TP
+.B "viu[sage] [command]"
Display usage for a
-.Nm \&vi
+.I \&vi
command.
-.It Sy "[range] w[rite][!] [>>] [file]"
-.It Sy "[range] w[rite] [!] [file]"
-.It Sy "[range] wn[!] [>>] [file]"
-.It Sy "[range] wq[!] [>>] [file]"
+.TP
+.B "[range] w[rite][!] [>>] [file]"
+.TP
+.B "[range] w[rite] [!] [file]"
+.TP
+.B "[range] wn[!] [>>] [file]"
+.TP
+.B "[range] wq[!] [>>] [file]"
Write the file.
-.It Sy "[range] x[it][!] [file]"
+.TP
+.B "[range] x[it][!] [file]"
Write the file if it has been modified.
-.It Sy "[range] ya[nk] [buffer] [count]"
+.TP
+.B "[range] ya[nk] [buffer] [count]"
Copy the specified lines to a buffer.
-.It Sy "[line] z [type] [count] [flags]"
+.TP
+.B "[line] z [type] [count] [flags]"
Adjust the window.
-.El
-.Sh SET OPTIONS
+.SH SET OPTIONS
There are a large number of options that may be set (or unset) to
change the editor's behavior.
This section describes the options, their abbreviations and their
default values.
-.Pp
+.PP
In each entry below, the first part of the tag line is the full name
of the option, followed by any equivalent abbreviations.
The part in square brackets is the default value of the option.
Most of the options are boolean, i.e. they are either on or off,
and do not have an associated value.
-.Pp
+.PP
Options apply to both
-.Nm \&ex
+.I \&ex
and
-.Nm \&vi
+.I \&vi
modes, unless otherwise specified.
-.sp
-.Bl -tag -width "XXXX" -compact
-.It Sy "altwerase [off]"
-.Nm \&Vi
+.PP
+.TP
+.B "altwerase [off]"
+.I \&Vi
only.
Select an alternate word erase algorithm.
-.It Sy "autoindent, ai [off]"
+.TP
+.B "autoindent, ai [off]"
Automatically indent new lines.
-.It Sy "autoprint, ap [off]"
-.Nm \&Ex
+.TP
+.B "autoprint, ap [off]"
+.I \&Ex
only.
Display the current line automatically.
-.It Sy "autowrite, aw [off]"
+.TP
+.B "autowrite, aw [off]"
Write modified files automatically when changing files.
-.It Sy "beautify, bf [off]"
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life. The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms backup [QQ]
+.TP
+.B "\*(ms"
+.tr QQ
+Backup files before they are overwritten.
+.TP
+.B "beautify, bf [off]"
Discard control characters.
-.It Sy "cdpath [environment variable CDPATH, or current directory]"
+.TP
+.B "cdpath [environment variable CDPATH, or current directory]"
The directory paths used as path prefixes for the
-.Sy cd
+.B cd
command.
-.It Sy "columns, co [80]"
+.TP
+.B "cedit [no default]"
+Set the character to edit the colon command-line history.
+.TP
+.B "columns, co [80]"
Set the number of columns in the screen.
-.It Sy "comment [off]"
-.Nm \&Vi
+.TP
+.B "comment [off]"
+.I \&Vi
only.
-Skip leading comments in files.
-.It Sy "directory, dir [environment variable TMPDIR, or /tmp]"
+Skip leading comments in shell, C and C++ language files.
+.TP
+.B "directory, dir [environment variable TMPDIR, or /tmp]"
The directory where temporary files are created.
-.It Sy "edcompatible, ed [off]"
-Remember the values of the
-.Dq \&c
-and
-.Dq \&g
-suffices to the
-.Sy substitute
+.TP
+.B "edcompatible, ed [off]"
+Remember the values of the ``c'' and ``g'' suffices to the
+.B substitute
commands, instead of initializing them as unset for each new
command.
-.It Sy "errorbells, eb [off]"
-.Nm \&Ex
+.TP
+.B "errorbells, eb [off]"
+.I \&Ex
only.
Announce error messages with a bell.
-.It Sy "exrc, ex [off]"
-Never read startup files in the local directory.
-.It Sy "extended [off]"
+.TP
+.B "exrc, ex [off]"
+Read the startup files in the local directory.
+.TP
+.B "extended [off]"
Regular expressions are extended (i.e.
-.Xr egrep 1
+.IR egrep (1)\-\c
style) expressions.
-.It Sy "flash [on]"
+.TP
+.B "filec [no default]"
+Set the character to perform file path completion on the colon
+command line.
+.TP
+.B "flash [on]"
Flash the screen instead of beeping the keyboard on error.
-.It Sy "hardtabs, ht [8]"
+.TP
+.B "hardtabs, ht [8]"
Set the spacing between hardware tab settings.
-.It Sy "ignorecase, ic [off]"
+.TP
+.B "iclower [off]"
+Makes all Regular Expressions case-insensitive,
+as long as an upper-case letter does not appear in the search string.
+.TP
+.B "ignorecase, ic [off]"
Ignore case differences in regular expressions.
-.It Sy "keytime [6]"
+.TP
+.B "keytime [6]"
The 10th's of a second
-.Nm ex/vi
+.I ex/vi
waits for a subsequent key to complete a key mapping.
-.It Sy "leftright [off]"
-.Nm \&Vi
+.TP
+.B "leftright [off]"
+.I \&Vi
only.
Do left-right scrolling.
-.It Sy "lines, li [24]"
-.Nm \&Vi
+.TP
+.B "lines, li [24]"
+.I \&Vi
only.
Set the number of lines in the screen.
-.It Sy "lisp [off]"
-.Nm \&Vi
+.TP
+.B "lisp [off]"
+.I \&Vi
only.
Modify various search commands and options to work with Lisp.
-.Pp
-.Em "This option is not yet implemented."
-.It Sy "list [off]"
+.I "This option is not yet implemented."
+.TP
+.B "list [off]"
Display lines in an unambiguous fashion.
-.It Sy "magic [on]"
+.TP
+.B "lock [on]"
+Attempt to get an exclusive lock on any file being edited,
+read or written.
+.TP
+.B "magic [on]"
Treat certain characters specially in regular expressions.
-.It Sy "matchtime [7]"
-.Nm \&Vi
+.TP
+.B "matchtime [7]"
+.I \&Vi
only.
The 10th's of a second
-.Nm ex/vi
+.I ex/vi
pauses on the matching character when the
-.Sy showmatch
+.B showmatch
option is set.
-.It Sy "mesg [on]"
+.TP
+.B "mesg [on]"
Permit messages from other users.
-.It Sy "modelines, modeline [off]"
+.TP
+.B "modelines, modeline [off]"
Read the first and last few lines of each file for
-.Nm ex
+.I ex
commands.
-.Pp
-.Em "This option will never be implemented."
-.It Sy "number, nu [off]"
+.I "This option will never be implemented."
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life. The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms noprint [QQ]
+.TP
+.B "\*(ms"
+.tr QQ
+Characters that are never handled as printable characters.
+.TP
+.B "number, nu [off]"
Precede each line displayed with its current line number.
-.It Sy "octal [off]"
+.TP
+.B "octal [off]"
Display unknown characters as octal numbers, instead of the default
hexadecimal.
-.It Sy "open [on]"
-.Nm \&Ex
+.TP
+.B "open [on]"
+.I \&Ex
only.
If this option is not set, the
-.Sy open
+.B open
and
-.Sy visual
+.B visual
commands are disallowed.
-.It Sy "optimize, opt [on]"
-.Nm \&Vi
+.TP
+.B "optimize, opt [on]"
+.I \&Vi
only.
Optimize text throughput to dumb terminals.
-.Pp
-.Em "This option is not yet implemented."
-.It Sy "paragraphs, para [IPLPPPQPP LIpplpipbp]"
-.Nm \&Vi
+.I "This option is not yet implemented."
+.TP
+.B "paragraphs, para [IPLPPPQPP LIpplpipbp]"
+.I \&Vi
only.
Define additional paragraph boundaries for the
-.Sy \&{
+.B \&{
and
-.Sy \&}
+.B \&}
commands.
-.It Sy "prompt [on]"
-.Nm \&Ex
+.TP
+.B "path []"
+Define additional directories to search for files being edited.
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life. The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms print [QQ]
+.TP
+.B "\*(ms"
+.tr QQ
+Characters that are always handled as printable characters.
+.TP
+.B "prompt [on]"
+.I \&Ex
only.
Display a command prompt.
-.It Sy "readonly, ro [off]"
-Mark the file as read-only.
-.It Sy "recdir [/var/tmp/vi.recover]"
+.TP
+.B "readonly, ro [off]"
+Mark the file and session as read-only.
+.TP
+.B "recdir [/var/tmp/vi.recover]"
The directory where recovery files are stored.
-.It Sy "redraw, re [off]"
-.Nm \&Vi
+.TP
+.B "redraw, re [off]"
+.I \&Vi
only.
Simulate an intelligent terminal on a dumb one.
-.Pp
-.Em "This option is not yet implemented."
-.It Sy "remap [on]"
+.I "This option is not yet implemented."
+.TP
+.B "remap [on]"
Remap keys until resolved.
-.It Sy "report [5]"
+.TP
+.B "report [5]"
Set the number of lines about which the editor reports changes
or yanks.
-.It Sy "ruler [off]"
-.Nm \&Vi
+.TP
+.B "ruler [off]"
+.I \&Vi
only.
Display a row/column ruler on the colon command line.
-.It Sy "scroll, scr [window / 2]"
+.TP
+.B "scroll, scr [window / 2]"
Set the number of lines scrolled.
-.It Sy "sections, sect [NHSHH HUnhsh]"
-.Nm \&Vi
+.TP
+.B "searchincr [off]"
+Makes the
+.B \&/
+and
+.B \&?
+commands incremental.
+.TP
+.B "sections, sect [NHSHH HUnhsh]"
+.I \&Vi
only.
Define additional section boundaries for the
-.Sy \&[[
+.B \&[[
and
-.Sy \&]]
+.B \&]]
commands.
-.It Sy "shell, sh [environment variable SHELL, or /bin/sh]"
+.TP
+.B "secure [off]"
+Turns off all access to external programs.
+.TP
+.B "shell, sh [environment variable SHELL, or /bin/sh]"
Select the shell used by the editor.
-.It Sy "shiftwidth, sw [8]"
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life. The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms shellmeta [~{[*?$`'Q\e]
+.TP
+.B "\*(ms"
+.tr QQ
+Set the meta characters checked to determine if file name expansion
+is necessary.
+.TP
+.B "shiftwidth, sw [8]"
Set the autoindent and shift command indentation width.
-.It Sy "showdirty [off]"
-.Nm \&Vi
+.TP
+.B "showmatch, sm [off]"
+.I \&Vi
only.
-Display an asterisk on the colon command line if the file has been modified.
-.It Sy "showmatch, sm [off]"
-.Nm \&Vi
-only.
-Note matching
-.Dq \&{
-and
-.Dq \&(
-for
-.Dq \&}
-and
-.Dq \&)
-characters.
-.It Sy "showmode [off]"
-.Nm \&Vi
+Note matching ``{'' and ``('' for ``}'' and ``)'' characters.
+.TP
+.B "showmode, smd [off]"
+.I \&Vi
only.
-Display the current editor mode (command or input).
-.It Sy "sidescroll [16]"
-.Nm \&Vi
+Display the current editor mode and a ``modified'' flag.
+.TP
+.B "sidescroll [16]"
+.I \&Vi
only.
Set the amount a left-right scroll will shift.
-.It Sy "slowopen, slow [off]"
+.TP
+.B "slowopen, slow [off]"
Delay display updating during text input.
-.Pp
-.Em "This option is not yet implemented."
-.It Sy "sourceany [off]"
+.I "This option is not yet implemented."
+.TP
+.B "sourceany [off]"
Read startup files not owned by the current user.
-.Pp
-.Em "This option will never be implemented."
-.It Sy "tabstop, ts [8]"
+.I "This option will never be implemented."
+.TP
+.B "tabstop, ts [8]"
This option sets tab widths for the editor display.
-.It Sy "taglength, tl [0]"
+.TP
+.B "taglength, tl [0]"
Set the number of significant characters in tag names.
-.It Sy "tags, tag [tags /var/db/libc.tags /sys/kern/tags]"
+.TP
+.B "tags, tag [tags /var/db/libc.tags /sys/kern/tags]"
Set the list of tags files.
-.It Sy "term, ttytype, tty [environment variable TERM]"
+.TP
+.B "term, ttytype, tty [environment variable TERM]"
Set the terminal type.
-.It Sy "terse [off]"
+.TP
+.B "terse [off]"
This option has historically made editor messages less verbose.
It has no effect in this implementation.
-.It Sy "tildeop"
+.TP
+.B "tildeop [off]"
Modify the
-.Sy \&~
+.B \&~
command to take an associated motion.
-.It Sy "timeout, to [on]"
+.TP
+.B "timeout, to [on]"
Time out on keys which may be mapped.
-.It Sy "ttywerase [off]"
-.Nm \&Vi
+.TP
+.B "ttywerase [off]"
+.I \&Vi
only.
Select an alternate erase algorithm.
-.It Sy "verbose [off]"
-.NM \&Vi
+.TP
+.B "verbose [off]"
+.I \&Vi
only.
Display an error message for every error.
-.It Sy "w300 [no default]"
-.Nm \&Vi
+.TP
+.B "w300 [no default]"
+.I \&Vi
only.
Set the window size if the baud rate is less than 1200 baud.
-.It Sy "w1200 [no default]"
-.Nm \&Vi
+.TP
+.B "w1200 [no default]"
+.I \&Vi
only.
Set the window size if the baud rate is equal to 1200 baud.
-.It Sy "w9600 [no default]"
-.Nm \&Vi
+.TP
+.B "w9600 [no default]"
+.I \&Vi
only.
Set the window size if the baud rate is greater than 1200 baud.
-.It Sy "warn [on]"
-.Nm \&Ex
+.TP
+.B "warn [on]"
+.I \&Ex
only.
This option causes a warning message to the terminal if the file has
been modified, since it was last written, before a
-.Sy \&!
+.B \&!
command.
-.It Sy "window, w, wi [environment variable LINES]"
+.TP
+.B "window, w, wi [environment variable LINES]"
Set the window size for the screen.
-.It Sy "wrapmargin, wm [0]"
-.Nm \&Vi
+.TP
+.B "windowname [off]"
+Change the icon/window name to the current file name even if it can't
+be restored on editor exit.
+.TP
+.B "wraplen, wl [0]"
+.I \&Vi
only.
-Break lines automatically when they reach the right-hand margin.
-.It Sy "wrapscan, ws [on]"
+Break lines automatically, the specified number of columns from the
+left-hand margin.
+If both the
+.B wraplen
+and
+.B wrapmargin
+edit options are set, the
+.B wrapmargin
+value is used.
+.TP
+.B "wrapmargin, wm [0]"
+.I \&Vi
+only.
+Break lines automatically, the specified number of columns from the
+right-hand margin.
+If both the
+.B wraplen
+and
+.B wrapmargin
+edit options are set, the
+.B wrapmargin
+value is used.
+.TP
+.B "wrapscan, ws [on]"
Set searches to wrap around the end or beginning of the file.
-.It Sy "writeany, wa [off]"
+.TP
+.B "writeany, wa [off]"
Turn off file-overwriting checks.
-.El
-.Sh ENVIRONMENTAL VARIABLES
-.Bl -tag -width "COLUMNSXX" -compact
-.It Ev COLUMNS
+.SH ENVIRONMENTAL VARIABLES
+.TP
+.I COLUMNS
The number of columns on the screen.
This value overrides any system or terminal specific values.
-If the COLUMNS environmental variable is not set when
-.Nm ex/vi
+If the
+.I COLUMNS
+environmental variable is not set when
+.I ex/vi
runs, or the
-.Sy columns
+.B columns
option is explicitly reset by the user,
-.Nm ex/vi
+.I ex/vi
enters the value into the environment.
-.It Ev EXINIT
+.TP
+.I EXINIT
A list of
-.Nm \&ex
+.I \&ex
startup commands, read if the variable
-.Ev NEXINIT
+.I NEXINIT
is not set.
-.It Ev HOME
+.TP
+.I HOME
The user's home directory, used as the initial directory path
-for the startup
-.Pa $HOME/.nexrc
-and
-.Pa $HOME/.exrc
+for the startup ``$\fIHOME\fP/.nexrc'' and ``$\fIHOME\fP/.exrc''
files.
This value is also used as the default directory for the
-.Nm \&vi
-.Sy \&cd
+.I \&vi
+.B \&cd
command.
-.It Ev LINES
+.TP
+.I LINES
The number of rows on the screen.
This value overrides any system or terminal specific values.
-If the LINES environmental variable is not set when
-.Nm ex/vi
+If the
+.I LINES
+environmental variable is not set when
+.I ex/vi
runs, or the
-.Sy lines
+.B lines
option is explicitly reset by the user,
-.Nm ex/vi
+.I ex/vi
enters the value into the environment.
-.It Ev NEXINIT
+.TP
+.I NEXINIT
A list of
-.Nm \&ex
+.I \&ex
startup commands.
-.It Ev SHELL
+.TP
+.I SHELL
The user's shell of choice (see also the
-.Sy shell
+.B shell
option).
-.It Ev TERM
+.TP
+.I TERM
The user's terminal type.
-The default is the type
-.Dq unknown .
-If the TERM environmental variable is not set when
-.Nm ex/vi
+The default is the type ``unknown''.
+If the
+.I TERM
+environmental variable is not set when
+.I ex/vi
runs, or the
-.Sy term
+.B term
option is explicitly reset by the user,
-.Nm ex/vi
+.I ex/vi
enters the value into the environment.
-.It Ev TMPDIR
+.TP
+.I TMPDIR
The location used to stored temporary files (see also the
-.Sy directory
-option).
-.El
-.Sh ASYNCHRONOUS EVENTS
-.Bl -tag -width "SIGWINCHXX" -compact
-.It SIGALRM
-.Nm \&Vi/ex
-uses this signal for periodic backups of file modifications
-and to display
-.Dq busy
-messages when operations are likely to take a long time.
-.It SIGHUP
-.It SIGTERM
+.B directory
+edit option).
+.SH ASYNCHRONOUS EVENTS
+.TP
+SIGALRM
+.I \&Vi/ex
+uses this signal for periodic backups of file modifications and to
+display ``busy'' messages when operations are likely to take a long time.
+.TP
+SIGHUP
+.TP
+SIGTERM
If the current buffer has changed since it was last written in its
entirety, the editor attempts to save the modified file so it can
be later recovered.
See the
-.Nm \&vi/ex
-Reference manual section entitled
-.Dq Recovery
-for more information.
-.It SIGINT
+.I \&vi/ex
+Reference manual section entitled ``Recovery'' for more information.
+.TP
+SIGINT
When an interrupt occurs,
the current operation is halted,
and the editor returns to the command level.
If interrupted during text input,
the text already input is resolved into the file as if the text
input had been normally terminated.
-.It SIGWINCH
+.TP
+SIGWINCH
The screen is resized.
See the
-.Nm \&vi/ex
-Reference manual section entitled
-.Dq "Sizing the Screen"
-for more information.
-.It SIGCONT
-.It SIGQUIT
-.It SIGTSTP
-.Nm \&Vi/ex
+.I \&vi/ex
+Reference manual section entitled ``Sizing the Screen'' for more information.
+.TP
+SIGCONT
+.TP
+SIGQUIT
+.TP
+SIGTSTP
+.I \&Vi/ex
ignores these signals.
-.El
-.Sh BUGS
-See the file
-.Pa nvi/docs/bugs.current
-for a list of the known bugs in this version.
-.Sh FILES
-.Bl -tag -width /var/tmp/vi.recover -compact
-.It Pa /bin/sh
+.SH FILES
+.TP
+/bin/sh
The default user shell.
-.It Pa /etc/vi.exrc
+.TP
+/etc/vi.exrc
System-wide vi startup file.
-.It Pa /tmp
+.TP
+/tmp
Temporary file directory.
-.It Pa /var/tmp/vi.recover
+.TP
+/var/tmp/vi.recover
The default recovery file directory.
-.It Pa $HOME/.nexrc
+.TP
+$HOME/.nexrc
1st choice for user's home directory startup file.
-.It Pa $HOME/.exrc
+.TP
+$HOME/.exrc
2nd choice for user's home directory startup file.
-.It Pa .nexrc
+.TP
+\&.nexrc
1st choice for local directory startup file.
-.It Pa .exrc
+.TP
+\&.exrc
2nd choice for local directory startup file.
-.El
-.Sh SEE ALSO
-.Xr ctags 1 ,
-.Xr more 1 ,
-.Xr curses 3 ,
-.Xr dbopen 3
+.SH SEE ALSO
+.IR ctags (1),
+.IR more (3),
+.IR curses (3),
+.IR dbopen (3)
.sp
-The
-.Dq "Vi Quick Reference"
-card.
+The ``Vi Quick Reference'' card.
.sp
-.Dq "\&An Introduction to Display Editing with Vi" ,
-found in the
-.Dq "UNIX User's Manual Supplementary Documents"
+``An Introduction to Display Editing with Vi'', found in the
+``UNIX User's Manual Supplementary Documents''
section of both the 4.3BSD and 4.4BSD manual sets.
This document is the closest thing available to an introduction to the
-.Nm \&vi
+.I \&vi
screen editor.
.sp
-.Dq "\&Ex Reference Manual (Version 3.7)" ,
+``Ex Reference Manual (Version 3.7)'',
found in the
-.Dq "UNIX User's Manual Supplementary Documents"
+``UNIX User's Manual Supplementary Documents''
section of both the 4.3BSD and 4.4BSD manual sets.
This document is the final reference for the
-.Nm \&ex
+.I \&ex
editor, as distributed in most historic 4BSD and System V systems.
.sp
-.Dq "Edit: A tutorial" ,
+``Edit: A tutorial'',
found in the
-.Dq "UNIX User's Manual Supplementary Documents"
+``UNIX User's Manual Supplementary Documents''
section of the 4.3BSD manual set.
This document is an introduction to a simple version of the
-.Nm \&ex
+.I \&ex
screen editor.
.sp
-.Dq "\&Ex/Vi Reference Manual" ,
+``Ex/Vi Reference Manual'',
found in the
-.Dq "UNIX User's Manual Supplementary Documents"
+``UNIX User's Manual Supplementary Documents''
section of the 4.4BSD manual set.
This document is the final reference for the
-.Nm \&nex/nvi
+.I \&nex/nvi
text editors, as distributed in 4.4BSD and 4.4BSD-Lite.
-.Pp
-.Nm Roff
+.PP
+.I Roff
source for all of these documents is distributed with
-.Nm nex/nvi
+.I nex/nvi
in the
-.Pa nvi/USD.doc
+.I nvi/USD.doc
directory of the
-.Nm nex/nvi
+.I nex/nvi
source code.
.sp
-The files
-.Dq autowrite ,
-.Dq input ,
-.Dq quoting ,
-and
-.Dq structures ,
+The files ``autowrite'', ``input'', ``quoting'' and ``structures''
found in the
-.Pa nvi/docs/internals
+.I nvi/docs/internals
directory of the
-.Nm nex/nvi
+.I nex/nvi
source code.
-.Sh HISTORY
+.SH HISTORY
The
-.Nm nex/nvi
+.I nex/nvi
replacements for the
-.Nm ex/vi
+.I ex/vi
editor first appeared in 4.4BSD.
-.Sh STANDARDS
-.Nm \&Nex/nvi
+.SH STANDARDS
+.I \&Nex/nvi
is close to IEEE Std1003.2 (``POSIX'').
That document differs from historical
-.Nm ex/vi
+.I ex/vi
practice in several places; there are changes to be made on both sides.
diff --git a/contrib/nvi/docs/USD.doc/vi.ref/Makefile b/contrib/nvi/docs/USD.doc/vi.ref/Makefile
new file mode 100644
index 000000000000..0e1b6343350d
--- /dev/null
+++ b/contrib/nvi/docs/USD.doc/vi.ref/Makefile
@@ -0,0 +1,32 @@
+# @(#)Makefile 8.20 (Berkeley) 8/18/96
+
+MACROS= -me
+ROFF= groff
+TBL= tbl
+
+all: vi.ref.txt vi.ref.ps
+
+vi.ref.txt: vi.ref index.so
+ soelim vi.ref | ${TBL} | groff ${MACROS} -Tascii > $@
+ rm -f index
+ chmod 444 $@
+
+vi.ref.ps: vi.ref index.so
+ soelim vi.ref | ${TBL} | ${ROFF} ${MACROS} > $@
+ rm -f index
+ chmod 444 $@
+
+index.so: vi.ref
+ # Build index.so, side-effect of building the paper.
+ soelim vi.ref | ${TBL} | ${ROFF} ${MACROS} > /dev/null
+ sed -e 's/MINUSSIGN/\\-/' \
+ -e 's/DOUBLEQUOTE/""/' \
+ -e "s/SQUOTE/'/" \
+ -e 's/ /__SPACE/g' < index | \
+ sort -u '-t ' +0 -1 +1n | awk -f merge.awk | \
+ sed -e 's/__SPACE/ /g' > $@
+ rm -f index
+ chmod 444 $@
+
+clean:
+ rm -f vi.ref.ps vi.ref.txt index index.so
diff --git a/usr.bin/vi/USD.doc/vi.ref/ex.cmd.roff b/contrib/nvi/docs/USD.doc/vi.ref/ex.cmd.roff
index a9cba6ae336d..382e635a6fdd 100644
--- a/usr.bin/vi/USD.doc/vi.ref/ex.cmd.roff
+++ b/contrib/nvi/docs/USD.doc/vi.ref/ex.cmd.roff
@@ -1,49 +1,27 @@
.\" Copyright (c) 1994
.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 1994, 1995, 1996
+.\" Keith Bostic. All rights reserved.
.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
+.\" See the LICENSE file for redistribution information.
.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" @(#)ex.cmd.roff 8.24 (Berkeley) 7/17/94
+.\" @(#)ex.cmd.roff 8.41 (Berkeley) 8/17/96
.\"
.SH 1 "Ex Description"
.pp
The following words have special meanings for
.CO ex
commands.
-.KY "<eof>"
-.IP "<eof>"
+.KY "<end-of-file>"
+.IP "<end-of-file>"
The end-of-file character is used to scroll the screen in the
.CO ex
editor.
This character is normally
-.LI <control-D> ,
-however, whatever character is set for the current terminal is used.
+.LI <control-D> .
+However, whatever character is set for the current terminal is supported
+as well as
+.LI <control-D> .
.KY "line"
.IP "line"
A single-line address, given in any of the forms described in the
@@ -183,14 +161,21 @@ Each
.CO ex
command described below notes the new current line after it
is executed, as well as any options that affect the command.
+.\" I cannot get a double quote to print to save my life. The ONLY way
+.\" I've been able to get this to work is with the .tr command.
+.tr Q"
+.ds ms Q
.KY DOUBLEQUOTE
-.IP """"
+.IP "\*(ms"
+.tr QQ
A comment.
Command lines beginning with the double-quote character
.PQ """"
are ignored.
This permits comments in editor scripts and startup files.
+.KY "<control-D>"
.KY "<end-of-file>"
+.IP "<control-D>"
.IP "<end-of-file>"
Scroll the screen.
Write the next N lines, where N is the value of the
@@ -216,7 +201,9 @@ treats it as any other character.
.SP Line:
Set to the last line written.
.SP Options:
-None.
+Affected by the
+.OP scroll
+option.
.SE
.KY "!"
.IP "! argument(s)"
@@ -300,15 +287,15 @@ Unchanged if no range was specified, otherwise set to the first
line of the range.
.SP Options:
Affected by the
-.OP autowrite
+.OP shell
and
-.OP writeany
+.OP warn
options.
.SE
-.KY "number"
-.IP "[range] nu[mber] [count] [flags]"
.KY "#"
-.Ip "[range] # [count] [flags]"
+.IP "[range] # [count] [flags]"
+.KY "number"
+.Ip "[range] nu[mber] [count] [flags]"
Display the selected lines, each preceded with its line number.
.sp
The line number format is
@@ -318,7 +305,9 @@ followed by two spaces.
.SP Line:
Set to the last line displayed.
.SP Options:
-None.
+Affected by the
+.OP list
+option.
.SE
.KY "@"
.IP "@ buffer"
@@ -368,7 +357,6 @@ option.
.SE
.KY =
.IP "[line] = [flags]"
-Display the line number.
Display the line number of
.LI line
(which defaults to the last line in the file).
@@ -395,18 +383,77 @@ additional command character.
.SP Line:
Set to the last line modified by the command.
.SP Options:
-None.
+Affected by the
+.OP shiftwidth
+option.
.SE
.KY abbrev
.IP "ab[brev] lhs rhs"
Add an abbreviation to the current abbreviation list.
-In
+When inserting text in
.CO vi ,
-if
-.LI lhs
-is entered such that it is preceded and followed by characters
-that cannot be part of a word, it is replaced by the string
+each time a non-word character is entered after a word character,
+a set of characters ending at the word character are checked for
+a match with
+.LI lhs .
+If a match is found, they are replaced with
.LI rhs .
+The set of characters that are checked for a match are defined as follows,
+for inexplicable historical reasons.
+If only one or two characters were entered before the non-word character
+that triggered the check,
+and after the beginning of the insertion,
+or the beginning of the line or the file,
+or the last
+.LI <blank>
+character that was entered,
+then the one or the both characters are checked for a match.
+Otherwise, the set includes both characters,
+as well as the characters that precede them that are the same word
+class (i.e. word or non-word) as the
+.b second
+to last character entered before the non-word character that triggered
+the check,
+back to the first
+.LI <blank> character,
+the beginning of the insertion,
+or the beginning of the line or the file.
+.sp
+For example, the abbreviations:
+.sp
+.ne 3v
+.ft C
+.TS
+r l l.
+:abbreviate abc ABC
+:abbreviate #i #include
+:abbreviate /*#i /*#include
+.TE
+.ft R
+will all work, while the abbreviations:
+.sp
+.ne 2v
+.ft C
+.TS
+r l l.
+:abbreviate a#i A#include
+:abbreviate /* /********************
+.TE
+.ft R
+will not work, and are not permitted by
+.CO nvi .
+.sp
+To keep the abbreviation expansion from happening,
+the character immediately following the
+.LI lhs
+characters should be quoted with a
+.LI <literal-next>
+character.
+.sp
+The replacement
+.LI rhs
+is itself subject to both further abbreviation expansion and further
+map expansion.
.SS
.SP Line:
Unchanged.
@@ -433,13 +480,9 @@ option to be toggled for the duration of the command.
Unchanged.
.SP Options:
Affected by the
-.OP altwerase ,
-.OP autoindent ,
-.OP beautify ,
-.OP showmatch ,
-.OP ttywerase
+.OP autoindent
and
-.OP wrapmargin
+.OP number
options.
.SE
.KY args
@@ -465,6 +508,11 @@ None.
.CO Vi
mode only.
Background the current screen.
+The screen is unchanged,
+but is no longer accessible and disappears from the display.
+Use the
+.CO fg
+command to bring the screen back to the display foreground.
.SS
.SP Line:
Set to the current line when the screen was last edited.
@@ -486,13 +534,9 @@ set to the line before the target line, or to the first
line of the file if there are no lines preceding the target line.
.SP Options:
Affected by the
-.OP altwerase ,
-.OP autoindent ,
-.OP beautify ,
-.OP showmatch ,
-.OP ttywerase
+.OP autoindent
and
-.OP wrapmargin
+.OP number
options.
.SE
.KY cd
@@ -543,6 +587,13 @@ Unchanged.
.SP Options:
None.
.SE
+.KY cscope
+.IP "cs[cope] command [args]"
+Execute a
+.CO cscope
+command.
+For more information, see the section of the reference manual entitled
+.QB "Tags, Tag Stacks, and Cscope" .
.KY delete
.IP "[range] d[elete] [buffer] [count] [flags]"
Delete the lines from the file.
@@ -569,8 +620,10 @@ or to the last line if the deleted lines were at the end.
None.
.SE
.KY display
-.IP "di[splay] b[uffers] | s[creens] | t[ags]"
-Display buffers, screens or tags.
+.IP "di[splay] b[uffers] | c[onnections] | s[creens] | t[ags]"
+Display buffers,
+.CO cscope
+connections, screens or tags.
The
.CO display
command takes one of three additional arguments, which are as follows:
@@ -578,6 +631,10 @@ command takes one of three additional arguments, which are as follows:
.SP b[uffers]
Display all buffers (including named, unnamed, and numeric)
that contain text.
+.SP c[onnections]
+Display the source directories for all attached
+.CO cscope
+databases.
.SP s[creens]
Display the file names of all background screens.
.SP t[ags]
@@ -609,6 +666,15 @@ Any
command may be used, although the most common use of this feature is
to specify a line number or search pattern to set the initial location
in the new file.
+.sp
+Capitalizing the first letter of the command, i.e.
+.CO Edit
+or
+.CO Ex ,
+while in
+.CO vi
+mode, will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
.SS
.SP Line:
If you have previously edited the file, the current line will be set
@@ -620,11 +686,7 @@ you are in
mode, and the last line of the file if you are in
.CO ex .
.SP Options:
-Affected by the
-.OP autowrite
-and
-.OP writeany
-options.
+None.
.SE
.KY exusage
.IP "exu[sage] [command]"
@@ -661,8 +723,19 @@ None.
.CO Vi
mode only.
Foreground the specified screen.
-Swap the current screen with the specified backgrounded screen.
-If no screen is specified, the first background screen is foregrounded.
+If the argument name doesn't exactly match the name of a file displayed
+by a background screen,
+it is compared against the last component of each of the file names.
+If no background screen is specified,
+the first background screen is foregrounded.
+.sp
+By default,
+foregrounding causes the current screen to be swapped with the backgrounded
+screen.
+Capitalizing the first letter of the command, i.e.
+.CO Fg ,
+will foreground the backgrounded screen in a new screen instead of
+swapping it with the current screen.
.SS
.SP Line:
Set to the current line when the screen was last edited.
@@ -726,8 +799,8 @@ and
commands cannot be used as part of these commands.
.sp
The editor options
-.OP autoprint ,
.OP autoindent ,
+.OP autoprint
and
.OP report
are turned off for the duration of the
@@ -739,7 +812,17 @@ commands.
.SP Line:
The last line modified.
.SP Options:
-None.
+Affected by the
+.OP ignorecase
+and
+.OP magic
+options.
+Turns off the
+.OP autoindent ,
+.OP autoprint
+and
+.OP report
+options.
.SE
.KY help
.IP "he[lp]"
@@ -763,15 +846,10 @@ option setting to be toggled for the duration of this command.
Set to the last line input; if no lines were input,
set to the line before the target line, or to the first line
of the file if there are no lines preceding the target line.
-.SP Options:
Affected by the
-.OP altwerase ,
-.OP autoindent ,
-.OP beautify ,
-.OP showmatch ,
-.OP ttywerase
+.OP autoindent
and
-.OP wrapmargin
+.OP number
options.
.SE
.KY join
@@ -827,7 +905,9 @@ character.
.SP Line:
Set to the last line displayed.
.SP Options:
-None.
+Affected by the
+.OP number
+option.
.SE
.KY map
.IP "map[!] [lhs rhs]"
@@ -863,7 +943,7 @@ to have two different macro definitions at the same time: one for command
mode and one for input mode.
.sp
Whitespace characters require escaping with a
-.LI <literal next>
+.LI <literal-next>
character to be entered in the
.LI lhs
string in visual mode.
@@ -895,7 +975,9 @@ character.
.SP Line:
Unchanged.
.SP Options:
-None.
+Affected by the
+.OP remap
+option.
.SE
.KY mark
.KY k
@@ -960,6 +1042,13 @@ character to the command name.
The argument list can optionally be replaced by specifying a new one
as arguments to this command.
In this case, editing starts with the first file on the new list.
+.sp
+Capitalizing the first letter of the command, i.e.
+.CO Next ,
+while in
+.CO vi
+mode, will set the argument list and edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
.SS
.SP Line:
Set as described for the
@@ -1016,6 +1105,13 @@ write.
This check can be overridden by appending the
.QT !
character to the command name.
+.sp
+Capitalizing the first letter of the command, i.e.
+.CO Previous ,
+while in
+.CO vi
+mode, will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
.SS
.SP Line:
Set as described for the
@@ -1035,7 +1131,11 @@ Display the specified lines.
.SP Line:
Set to the last line displayed.
.SP Options:
-None.
+Affected by the
+.OP list
+and
+.OP number
+option.
.SE
.KY put
.IP "[line] pu[t] [buffer]"
@@ -1103,8 +1203,8 @@ character,
.LI file
is treated as if it were a shell command, and passed to the program
named by the
-.LI SHELL
-environment variable.
+.OP shell
+edit option.
The standard and standard error outputs of that command are read into
the file after the specified line.
The special meaning of the
@@ -1130,7 +1230,7 @@ Recover
if it was previously saved.
If no saved file by that name exists, the
.CO recover
-command behaves similarly to the
+command behaves equivalently to the
.CO edit
command.
.SS
@@ -1228,7 +1328,7 @@ None.
.SE
.KY shell
.IP "sh[ell]"
-Run a shell program.
+Run the shell program.
The program named by the
.OP shell
option is run with a
@@ -1239,7 +1339,9 @@ Editing is resumed when that program exits.
.SP Line:
Unchanged.
.SP Options:
-None.
+Affected by the
+.OP shell
+option.
.SE
.KY source
.IP "so[urce] file"
@@ -1254,35 +1356,6 @@ Unchanged.
.SP Options:
None.
.SE
-.KY split
-.IP "sp[lit] [file ...]"
-.CO Vi
-mode only.
-Split the screen.
-The current screen is split into two screens, of approximately equal size.
-If the cursor is in the lower half of the screen, the screen will split
-up, i.e. the new screen will be above the old one.
-If the cursor is in the upper half of the screen, the new screen will be
-below the old one.
-.sp
-If
-.LI file
-is specified, the new screen is editing that file, otherwise, both
-screens are editing the same file, and changes in each will be
-be reflected in the other.
-The argument list for the new screen consists of the list of files
-specified as arguments to this command, or, the current pathname if
-no files are specified.
-.SS
-.SP Line:
-If
-.LI file
-is specified, set as for the
-.CO edit
-command, otherwise unchanged.
-.SP Options:
-None.
-.SE
.KY substitute
.IP "[range] s[ubstitute] [/pattern/replace/] [options] [count] [flags]"
.KY &
@@ -1302,6 +1375,8 @@ argument is not specified, the
from the previous
.CO substitute
command is used.
+Any character other than an alphabetic, numeric, <blank> or backslash
+character may be used as the delimiter.
.sp
If
.LI options
@@ -1371,7 +1446,11 @@ All substitutions completed before the interrupt are retained.
.SP Line:
Set to the last line upon which a substitution was made.
.SP Options:
-None.
+Affected by the
+.OP ignorecase
+and
+.OP magic
+option.
.SE
.KY suspend
.IP "su[spend][!]"
@@ -1391,12 +1470,13 @@ Unchanged.
.SP Options:
Affected by the
.OP autowrite
-option.
+and
+.OP writeany
+options.
.SE
.KY tag
.IP "ta[g][!] tagstring"
Edit the file containing the specified tag.
-Search for the tagstring, which can be in a different file.
If the tag is in a different file, then the new file is edited.
If the current file has been modified since the last complete write,
the
@@ -1416,6 +1496,13 @@ option.
(See
.XR ctags 1
for more information on tags files.)
+.sp
+Capitalizing the first letter of the command, i.e.
+.CO Tag ,
+while in
+.CO vi
+mode, will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
.SS
.SP Line:
Set to the line indicated by the tag.
@@ -1428,6 +1515,34 @@ and
.OP writeany
options.
.SE
+.KY tagnext
+.IP "tagn[ext][!]"
+Edit the file containing the next context for the current tag.
+If the context is in a different file, then the new file is edited.
+If the current file has been modified since the last complete write,
+the
+.CO tagnext
+command will fail.
+This check can be overridden by appending the
+.QT !
+character to the command name.
+.sp
+Capitalizing the first letter of the command, i.e.
+.CO Tagnext ,
+while in
+.CO vi
+mode, will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+.SS
+.SP Line:
+Set to the line indicated by the tag.
+.SP Options:
+Affected by the
+.OP autowrite
+and
+.OP writeany
+options.
+.SE
.KY tagpop
.IP "tagp[op][!] [file | number]"
Pop to the specified tag in the tags stack.
@@ -1461,7 +1576,35 @@ character to the command name.
Set to the line indicated by the tag.
.SP Options:
Affected by the
-.OP autowrite ,
+.OP autowrite
+and
+.OP writeany
+options.
+.SE
+.KY tagprev
+.IP "tagp[rev][!]"
+Edit the file containing the previous context for the current tag.
+If the context is in a different file, then the new file is edited.
+If the current file has been modified since the last complete write,
+the
+.CO tagprev
+command will fail.
+This check can be overridden by appending the
+.QT !
+character to the command name.
+.sp
+Capitalizing the first letter of the command, i.e.
+.CO Tagprev ,
+while in
+.CO vi
+mode, will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
+.SS
+.SP Line:
+Set to the line indicated by the tag.
+.SP Options:
+Affected by the
+.OP autowrite
and
.OP writeany
options.
@@ -1471,7 +1614,7 @@ options.
Pop to the least recent tag on the tags stack, clearing the tags stack.
.sp
If the file has been modified since the last complete write, the
-.CO tagpop
+.CO tagtop
command will fail.
This check may be overridden by appending a
.QT !
@@ -1481,7 +1624,7 @@ character to the command name.
Set to the line indicated by the tag.
.SP Options:
Affected by the
-.OP autowrite ,
+.OP autowrite
and
.OP writeany
options.
@@ -1551,7 +1694,7 @@ or
as in the
.CO ex
.CO z
-command, to specify the the position of the specified line in the screen
+command, to specify the position of the specified line in the screen
window.
(The default is to place the line at the top of the screen window.)
A
@@ -1576,6 +1719,11 @@ Edit a new file.
Identical to the
.QT "edit[!] [+cmd] [file]"
command.
+.sp
+Capitalizing the first letter of the command, i.e.
+.CO Visual ,
+will edit the file in a new screen.
+In this case, any modifications to the current file are ignored.
.KY viusage
.IP "viu[sage] [command]"
Display usage for a
@@ -1624,9 +1772,9 @@ no tests are made for the file already existing.
.sp
If the file is preceded by a
.QT !
-character, the program named in the SHELL environment variable is
-invoked with file as its second argument, and the specified lines
-are passed as standard input to that command.
+character, the program named by the shell edit option is
+invoked with file as its second argument, and the specified
+lines are passed as standard input to that command.
The
.QT !
in this usage must be separated from command name by at least one
@@ -1771,6 +1919,6 @@ Set to the last line displayed, with the exception of the
where the current line is set to the line specified by the command.
.SP Options:
Affected by the
-.Sy window
+.OP scroll
option.
.SE
diff --git a/contrib/nvi/docs/USD.doc/vi.ref/index.so b/contrib/nvi/docs/USD.doc/vi.ref/index.so
new file mode 100644
index 000000000000..4c3acb6e4f04
--- /dev/null
+++ b/contrib/nvi/docs/USD.doc/vi.ref/index.so
@@ -0,0 +1,260 @@
+! 21, 42
+"" 42
+# 22, 43
+$ 22
+% 22
+& 23, 51
+'<character> 23
+( 23
+) 24
+* 43
++ 19
+, 24
+. 24
+/RE/ 25
+0 25
+0<control-D> 38
+: 26
+; 26
+< 26, 43
+<carriage-return> 14
+<control-A> 17
+<control-B> 17
+<control-D> 17, 38, 42
+<control-E> 18
+<control-F> 18
+<control-G> 18
+<control-H> 18, 39
+<control-J> 19
+<control-L> 19
+<control-M> 19
+<control-N> 19
+<control-P> 19
+<control-R> 19
+<control-T> 19, 38
+<control-U> 20
+<control-W> 20, 39
+<control-X> 39
+<control-Y> 20
+<control-Z> 20, 52
+<control-]> 20
+<control-^> 21
+<end-of-file> 40, 42
+<erase> 39
+<escape> 20, 39
+<interrupt> 12, 37, 39
+<line erase> 39
+<literal-next> 12, 39
+<newline> 14
+<nul> 38
+<space> 21
+<word erase> 39
+= 43
+> 26, 43
+?RE? 25
+@ 26, 43
+A 27
+B 27
+C 27
+D 27
+E 28
+F 28
+G 28
+H 28
+I 28
+J 29
+L 29
+M 29
+N 25
+O 29
+P 29
+Q 30
+R 30
+S 30
+T 30
+U 30
+W 31
+X 31
+Y 31
+ZZ 31
+[[ 31
+\- 24
+]] 32
+^ 32
+^<control-D> 38
+_ 32
+`<character> 23
+a 32
+abbrev 43
+alternate pathname 13
+altwerase 56
+append 44
+args 44
+autoindent 56
+autoprint 56
+autowrite 57
+b 32
+backup 57
+beautify 57
+bg 44
+bigword 16
+buffer 13
+c 33
+cd 45
+cdpath 57
+cedit 57
+change 45
+chdir 45
+columns 58
+comment 58
+copy 45
+count 16, 41
+cscope 45
+current pathname 12
+d 33
+delete 45
+directory 58
+display 45
+e 33
+edcompatible 58
+edit 46
+errorbells 58
+escapetime 58
+exrc 58
+extended 58
+exusage 46
+f 33
+fg 46
+file 41, 46
+filec 58
+flags 41
+flash 59
+global 47
+hardtabs 59
+help 47
+i 33
+iclower 59
+ignorecase 59
+insert 47
+j 19
+join 47
+k 19, 48
+keytime 59
+l 21
+leftright 59
+line 41
+lines 59
+lisp 59
+list 48, 59
+lock 59
+m 34
+magic 60
+map 48
+mark 48
+matchtime 60
+mesg 60
+mkexrc 49
+modelines 60
+motion 15
+move 48
+msgcat 60
+n 25
+next 49
+noprint 60
+number 43, 61
+o 34
+octal 61
+open 49, 61
+optimize 61
+p 34
+paragraph 16
+paragraphs 61
+path 61
+preserve 49
+previous 49
+previous context 15
+print 50, 61
+prompt 61
+put 50
+quit 50
+r 34
+range 41
+read 50
+readonly 61
+recdir 62
+recover 50
+redraw 62
+remap 62
+report 62
+resize 50
+rewind 51
+ruler 62
+s 34
+scroll 62
+searchincr 62
+section 17
+sections 63
+secure 63
+sentence 17
+set 51
+shell 51, 63
+shellmeta 63
+shiftwidth 63
+showmatch 63
+showmode 63
+sidescroll 63
+slowopen 63
+source 51
+sourceany 64
+stop 52
+substitute 51
+suspend 52
+t 35, 45
+tabstop 64
+tag 52
+taglength 64
+tagnext 52
+tagpop 53
+tagprev 53
+tags 64
+tagtop 53
+term 64
+terse 64
+tildeop 64
+timeout 64
+ttywerase 64
+u 35
+unabbrev 53
+undo 53
+unmap 54
+unnamed buffer 14
+v 47
+verbose 64
+version 54
+visual 54
+viusage 54
+w 35
+w1200 64
+w300 64
+w9600 64
+warn 65
+whitespace 14
+window 65
+windowname 65
+wn 54
+word 16
+wq 54
+wraplen 65
+wrapmargin 65
+wrapscan 65
+write 54
+writeany 66
+x 35
+xit 55
+y 35
+yank 55
+z 36, 55
+{ 36
+| 36
+} 37
+~ 37, 51
diff --git a/usr.bin/vi/USD.doc/vi.ref/merge.awk b/contrib/nvi/docs/USD.doc/vi.ref/merge.awk
index 16b51520a778..c65207c106a7 100644
--- a/usr.bin/vi/USD.doc/vi.ref/merge.awk
+++ b/contrib/nvi/docs/USD.doc/vi.ref/merge.awk
@@ -1,4 +1,4 @@
-# @(#)merge.awk 8.3 (Berkeley) 5/26/94
+# @(#)merge.awk 8.3 (Berkeley) 5/25/94
#
# merge index entries into one line per label
$1 == prev {
diff --git a/contrib/nvi/docs/USD.doc/vi.ref/ref.so b/contrib/nvi/docs/USD.doc/vi.ref/ref.so
new file mode 100644
index 000000000000..a82c79258bb1
--- /dev/null
+++ b/contrib/nvi/docs/USD.doc/vi.ref/ref.so
@@ -0,0 +1,103 @@
+.\" Copyright (c) 1994
+.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 1994, 1995, 1996
+.\" Keith Bostic. All rights reserved.
+.\"
+.\" See the LICENSE file for redistribution information.
+.\"
+.\" @(#)ref.so 8.9 (Berkeley) 8/17/96
+.\"
+.\"
+.\" indented paragraph, with spaces between the items, bold font
+.de IP
+.\".tm arg 1 \\$1 arg 2 \\$2 arg 3 \\$3
+.sp 1
+.nr PS \\n(ps
+.nr ps 0
+.ip "\fB\\$1\fP" \\$2
+.nr ps \\n(PS
+.br
+..
+.\" indented paragraph, no spaces between the items, bold font
+.de Ip
+.\".tm arg 1 \\$1 arg 2 \\$2 arg 3 \\$3
+.nr PS \\n(ps
+.nr ps 0
+.ns
+.ip "\fB\\$1\fP" \\$2
+.nr ps \\n(PS
+.br
+..
+.\" start nested .IP
+.de SS
+.sp
+.ba +5n
+..
+.\" end nested .IP
+.de SE
+.ba -5n
+..
+.\" nested .IP, no spaces, normal font
+.de SP
+.\".tm arg 1 \\$1 arg 2 \\$2 arg 3 \\$3
+.nr PS \\n(ps
+.nr ps 0
+.ns
+.ip "\\$1" 9n
+.nr ps \\n(PS
+..
+.\" typewriter font
+.de LI
+\&\fC\\$1\fP\\$2
+..
+.\" ex/vi names in command font
+.de EV
+\&\fB\\$1\fP/\fB\\$2\fP\\$3
+..
+.\" command names
+.de CO
+\&\fB\\$1\fP\\$2
+..
+.\" key words for index
+.de KY
+.sy echo >>index '\\$1 \\n%'
+..
+.\" option names
+.de OP
+\&\fB\\$1\fP\\$2
+..
+.\" paren quoted (typewriter font)
+.de PQ
+(\*(lq\fC\\$1\fP\*(rq)\\$2
+..
+.\" quoted bold
+.de QB
+\*(lq\fB\\$1\fP\*(rq\\$2
+..
+.\" quoted command
+.de QC
+\*(lq\fB\\$1\fP\*(rq\\$2
+..
+.\" quoted option
+.de QO
+\*(lq\fB\\$1\fP\*(rq\\$2
+..
+.\" quoted (no font change)
+.de QQ
+\*(lq\\$1\*(rq\\$2
+..
+.\" quoted (typewriter font)
+.de QT
+\*(lq\fC\\$1\fP\*(rq\\$2
+..
+.\" section macro to build TOC
+.de SH
+.(x
+\\$2
+.)x
+.sh \\$1 "\\$2"
+..
+.\" manual section
+.de XR
+\&\fI\\$1\fP(\\$2)\\$3
+..
diff --git a/usr.bin/vi/USD.doc/vi.ref/set.opt.roff b/contrib/nvi/docs/USD.doc/vi.ref/set.opt.roff
index d59599d14268..838412897ab0 100644
--- a/usr.bin/vi/USD.doc/vi.ref/set.opt.roff
+++ b/contrib/nvi/docs/USD.doc/vi.ref/set.opt.roff
@@ -1,35 +1,11 @@
.\" Copyright (c) 1994
.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 1994, 1995, 1996
+.\" Keith Bostic. All rights reserved.
.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
+.\" See the LICENSE file for redistribution information.
.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" @(#)set.opt.roff 8.26 (Berkeley) 8/11/94
+.\" @(#)set.opt.roff 8.66 (Berkeley) 10/10/96
.\"
.SH 1 "Set Options"
.pp
@@ -59,6 +35,19 @@ and
.CO vi
modes, unless otherwise specified.
.pp
+With a few exceptions,
+all options are settable per screen, i.e. the
+.OP tags
+option can be set differently in each screen.
+The exceptions are the
+.OP columns ,
+.OP lines ,
+.OP secure
+and
+.OP term
+options.
+Changing these options modifies the respective information for all screens.
+.pp
For information on modifying the options or to display the options and
their current values, see the
.QQ set
@@ -131,10 +120,10 @@ if you have an indented line, containing only blanks, the first
character you enter will erase up to end of the indent characters,
and the second will erase back to the beginning of the line.
(Historically, only the
-.CO <control-D>
+.LI <control-D>
key would erase the indent characters.
Both the
-.CO <control-D>
+.LI <control-D>
key and the usual erase keys work in
.CO nvi .)
In addition, if the cursor is positioned at the end of the indent
@@ -176,7 +165,7 @@ and
This automatic display is suppressed during
.CO global
and
-.CO vglobal
+.CO v
commands, and for any command where optional flags are used to explicitly
display the line.
.KY autowrite
@@ -234,6 +223,39 @@ are
affected by the
.OP autowrite
option.
+.sp
+The
+.OP autowrite
+option is ignored if the file is considered read-only for any reason.
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life. The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms backup [QQ]
+.KY backup
+.IP "\*(ms"
+.tr QQ
+If this option is set, it specifies a pathname used as a backup file,
+and, whenever a file is written, the file's current contents are copied
+to it.
+The pathname is
+.QT \&# ,
+.QT \&%
+and
+.QT \&!
+expanded.
+.sp
+If the first character of the pathname is
+.QT \&N ,
+a version number is appended to the pathname (and the
+.QT \&N
+character is then discarded).
+Version numbers are always incremented, and each backup file will have
+a version number one greater than the highest version number currently
+found in the directory.
+.sp
+Backup files must be regular files, owned by the real user ID of the
+user running the editor, and not accessible by any other user.
.KY beautify
.IP "beautify, bf [off]"
If this option is set, all control characters that are not currently being
@@ -277,6 +299,50 @@ It may be so specified by entering an empty string or a
character into the
.LI CDPATH
variable or the option value.
+.KY cedit
+.IP "cedit [no default]"
+This option adds the ability to edit the colon command-line history.
+This option is set to a string.
+Whenever the first character of that string is entered on the colon
+command line,
+you will enter a normal editing window on the collected commands that
+you've entered on the
+.CO vi
+colon command-line.
+You may then modify and/or execute the commands.
+All normal text editing is available,
+except that you cannot use
+.CO <control-W>
+to switch to an alternate screen.
+Entering a
+.CO <carriage-return>
+will execute the current line of the screen window as an ex command in
+the context of the screen from which you created the colon command-line
+screen,
+and you will then return to that screen.
+.sp
+Because of
+.CO vi \&'s
+parsing rules, it can be difficult to set the colon command-line edit
+character to the
+.LI <escape>
+character.
+To set it to
+.LI <escape> ,
+use
+.QT "set cedit=<literal-next><escape>" .
+.sp
+If the
+.OP cedit
+edit option is set to the same character as the
+.OP filec
+edit option,
+.CO vi
+will perform colon command-line editing if the character is entered as
+the first character of the line,
+otherwise,
+.CO vi
+will perform file name expansion.
.KY columns
.IP "columns, co [80]"
The number of columns in the screen.
@@ -292,11 +358,14 @@ more information.
.CO Vi
only.
If the first non-empty line of the file begins with the string
-.QT /\&* ,
+.QT # ,
+.QT /\&*
+or
+.QT // ,
this option causes
.CO vi
-to skip to the end of that C-language comment (probably a terribly boring
-legal notice) before displaying the file.
+to skip to the end of that shell, C or C++ comment (probably a
+terribly boring legal notice) before displaying the file.
.KY directory
.IP "directory, dir [environment variable TMPDIR, or /tmp]"
The directory where temporary files are created.
@@ -311,7 +380,7 @@ Remember the values of the
.QQ c
and
.QQ g
-suffices to the
+suffixes to the
.CO substitute
commands, instead of initializing them as unset for each new
command.
@@ -321,7 +390,14 @@ command unsets the
.QQ c
and
.QQ g
-suffices as well.
+suffixes as well.
+.KY escapetime
+.IP "escapetime [1]"
+The 10th's of a second
+.EV ex vi
+waits for a subsequent key to complete an
+.LI <escape>
+key mapping.
.KY errorbells
.IP "errorbells, eb [off]"
.CO Ex
@@ -332,11 +408,11 @@ If that is not possible for the terminal, setting this option causes
error messages to be announced by ringing the terminal bell.
.KY exrc
.IP "exrc, ex [off]"
-If this option is turned off in the system or $HOME startup files,
-the local startup files are never read (unless they are the same
-as the system or $HOME startup files).
-Turning it on has no effect, i.e. the normal checks for local startup
-files are performed, regardless.
+If this option is turned on in the EXINIT environment variables,
+or the system or $HOME startup files,
+the local startup files are read,
+unless they are the same as the system or $HOME startup files or
+fail to pass the standard permission checks.
See the section entitled
.QB "Startup Information"
for more information.
@@ -346,6 +422,56 @@ This option causes all regular expressions to be treated as POSIX
1003.2 Extended Regular Expressions (which are similar to historic
.XR egrep 1
style expressions).
+.KY filec
+.IP "filec [no default]"
+This option adds the ability to do shell expansion when entering input
+on the colon command line.
+This option is set to a string.
+Whenever the first character of that string is entered on the colon
+command line,
+the <blank> delimited string immediately before the cursor is expanded
+as if it were followed by a
+.LI \&*
+character, and file name expansion for the
+.CO ex
+edit command was done.
+If no match is found, the screen is flashed and text input resumed.
+If a single match results, that match replaces the expanded text.
+In addition, if the single match is for a directory, a
+.LI \&/
+character is appended and file completion is repeated.
+If more than a single match results,
+any unique prefix shared by the matches replaces the expanded text,
+the matches are displayed,
+and text input resumed.
+.sp
+Because of
+.CO vi \&'s
+parsing rules, it can be difficult to set the path completion character
+to two command values,
+.LI <escape>
+and
+.LI <tab> .
+To set it to
+.LI <escape> ,
+use
+.QT "set filec=<literal-next><escape>" .
+To set it to
+.LI <tab> ,
+use
+.QT "set filec=\e<tab>" .
+.sp
+If the
+.OP cedit
+edit option is set to the same character as the
+.OP filec
+edit option,
+.CO vi
+will perform colon command-line editing if the character is entered as
+the first character of the line,
+otherwise,
+.CO vi
+will perform file name expansion.
.KY flash
.IP "flash [on]"
This option causes the screen to flash instead of beeping the keyboard,
@@ -362,6 +488,12 @@ never writes
characters to the terminal, unlike historic versions of
.EV ex vi ,
this option does not currently have any affect.
+.KY iclower
+.IP "iclower [off]"
+The
+.OP iclower
+edit option makes all Regular Expressions case-insensitive,
+as long as an upper-case letter does not appear in the search string.
.KY ignorecase
.IP "ignorecase, ic [off]"
This option causes regular expressions, both in
@@ -421,6 +553,16 @@ Specifically, tabs are displayed as control characters, i.e.
and the ends of lines are marked with a
.QT $
character.
+.KY lock
+.IP "lock [on]"
+This option causes the editor to attempt to get an exclusive lock on
+any file being edited, read or written.
+Reading or writing a file that cannot be locked produces a warning
+message, but no other effect.
+Editing a file that cannot be locked results in a read only edit session,
+as if the
+.OP readonly
+edit option were set.
.KY magic
.IP "magic [on]"
This option is on by default.
@@ -445,7 +587,7 @@ for more information.
.CO Vi
only.
The 10th's of a second
-.EV ex vi
+.CO vi
pauses on the matching character when the
.OP showmatch
option is set.
@@ -463,6 +605,30 @@ This option only permits you to disallow messages for the edit session.
See the
.XR mesg 1
utility for more information.
+.KY msgcat
+.IP "msgcat [./]"
+This option selects a message catalog to be used to display error and
+informational messages in a specified language.
+If the value of this option ends with a '/', it is treated as the name
+of a directory that contains a message catalog
+.QT "vi_XXXX" ,
+where
+.QT XXXX
+is the value of the
+.LI LANG
+environmental variable, if it's set, or the value of the
+.LI LC_MESSAGES
+environmental variable if it's not.
+If neither of those environmental variables are set,
+or if the option doesn't end in a '/',
+the option is treated as the full path name of the message catalog to use.
+.sp
+If any messages are missing from the catalog,
+the backup text (English) is used instead.
+.sp
+See the distribution file
+.LI catalog/README
+for additional information on building and installing message catalogs.
.KY modelines
.IP "modelines, modeline [off]"
If the
@@ -496,13 +662,29 @@ This option is a security problem of immense proportions,
and should not be used under any circumstances.
.sp
.i "This option will never be implemented."
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life. The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms noprint [QQ]
+.KY noprint
+.IP "\*(ms"
+.tr QQ
+Characters that are never handled as printable characters.
+By default, the C library function
+.XR isprint 3
+is used to determine if a character is printable or not.
+This edit option overrides that decision.
.KY number
.IP "number, nu [off]"
Precede each line displayed with its current line number.
.KY octal
.IP "octal [off]"
-Display unknown characters as octal numbers, instead of the default
-hexadecimal.
+Display unknown characters as octal numbers
+.PQ "\e###" ,
+instead of the default
+hexadecimal
+.PQ "\ex##" .
.KY open
.IP "open [on]"
.CO Ex
@@ -550,6 +732,36 @@ recognized:
<newline>.A<space>
<newline>.##
.)l
+.KY path
+.IP "path []"
+The path option can be used to specify a <colon>-separated list of
+paths, similar to the
+.LI PATH
+environment variable in the shells.
+If this option is set,
+the name of the file to be edited is not an absolute pathname,
+the first component of the filename is not
+.QT \&.
+or
+.QT \&.. ,
+and the file to be edited doesn't exist in the current directory,
+the elements of the
+.OP path
+option are sequentially searched for a file of the specified name.
+If such a file is found, it is edited.
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life. The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms print [QQ]
+.KY print
+.IP "\*(ms"
+.tr QQ
+Characters that are always handled as printable characters.
+By default, the C library function
+.XR isprint 3
+is used to determine if a character is printable or not.
+This edit option overrides that decision.
.KY prompt
.IP "prompt [on]"
.CO Ex
@@ -561,17 +773,47 @@ to prompt for command input with a
character; when it is not set, no prompt is displayed.
.KY readonly
.IP "readonly, ro [off]"
-This option causes a force flag to be required to attempt to write
-the file back to the original file name.
+This option causes a force flag to be required to attempt to write the file.
Setting this option is equivalent to using the
.b \-R
-command line option, or editing a file which lacks write permission.
+command line option,
+or executing the
+.CO vi
+program using the name
+.CO view .
+.sp
+The
+.OP readonly
+edit option is not usually persistent, like other edit options.
+If the
+.b \-R
+command line option is set,
+.CO vi
+is executed as
+.CO view ,
+or the
+.OP readonly
+edit option is explicitly set,
+all files edited in the screen will be marked readonly,
+and the force flag will be required to write them.
+However, if none of these conditions are true,
+or the
+.OP readonly
+edit option is explicitly unset,
+then the
+.OP readonly
+edit option will toggle based on the write permissions of the file currently
+being edited as of when it is loaded into the edit buffer.
+In other words, the
+.OP readonly
+edit option will be set if the current file lacks write permissions,
+and will not be set if the user has write permissions for the file.
.KY recdir
.IP "recdir [/var/tmp/vi.recover]"
The directory where recovery files are stored.
.sp
If you change the value of
-.CO recdir ,
+.OP recdir ,
be careful to choose a directory whose contents are not regularly
deleted.
Bad choices include directories in memory based filesystems,
@@ -590,7 +832,7 @@ There is no requirement that you use a public directory,
e.g. a sub-directory of your home directory will work fine.
.sp
Finally, if you change the value of
-.CO recdir ,
+.OP recdir ,
you must modify the recovery script to operate in your chosen recovery
area.
.sp
@@ -646,12 +888,12 @@ the set value, it is reported to the user.
only.
Display a row/column ruler on the colon command line.
.KY scroll
-.IP "scroll, scr [window / 2]"
+.IP "scroll, scr [(environment variable LINES - 1) / 2]"
Set the number of lines scrolled by the
-.CO vi
+.CO ex
.CO <control-D>
and
-.CO <control-U>
+.CO <end-of-file>
commands.
.sp
Historically, the
@@ -660,6 +902,20 @@ Historically, the
command, when specified without a count, used two times the size of the
scroll value; the POSIX 1003.2 standard specified the window size, which
is a better choice.
+.KY searchincr
+.IP "searchincr [off]"
+The
+.OP searchincr
+edit option makes the search commands
+.CO \&/
+and
+.CO \&?
+incremental, i.e. the screen is updated and the cursor moves to the matching
+text as the search pattern is entered.
+If the search pattern is not found,
+the screen is beeped and the cursor remains on the colon-command line.
+Erasing characters from the search pattern backs the cursor up to the
+previous matching text.
.KY sections
.IP "sections, sect [NHSHH HUnhsh]"
.CO Vi
@@ -679,8 +935,37 @@ In the text to be edited, the character string
.LI <char-pair>
is one of the character pairs in the option's value),
defines a section boundary in the same manner that
-.OP paragraph
+.OP paragraphs
option boundaries are defined.
+.KY secure
+.IP "secure [off]"
+The
+.OP secure
+edit option turns off all access to external programs.
+This means that the versions of the
+.CO read
+and
+.CO write
+commands that filter text through other programs,
+the
+.CO vi
+.CO \&!
+and
+.CO <control-Z>
+commands,
+the
+.CO ex
+.CO \&! ,
+.CO script ,
+.CO shell ,
+.CO stop
+and
+.CO suspend
+commands and file name expansion will not be permitted.
+Once set,
+the
+.OP secure
+edit option may not be unset.
.KY shell
.IP "shell, sh [environment variable SHELL, or /bin/sh]"
Select the shell used by the editor.
@@ -694,6 +979,26 @@ command.
This program is also used to resolve any shell meta-characters in
.CO ex
commands.
+.\" I cannot get a double quote to print between the square brackets
+.\" to save my life. The ONLY way I've been able to get this to work
+.\" is with the .tr command.
+.tr Q"
+.ds ms shellmeta [~{[*?$`'Q\e]
+.KY shellmeta
+.IP "\*(ms"
+.tr QQ
+The set of characters that
+.CO ex
+checks for when doing file name expansion.
+If any of the specified characters are found in the file name arguments
+to the
+.CO ex
+commands,
+the arguments are expanded using the program defined by the
+.OP shell
+option.
+The default set of characters is a union of meta characters
+from the Version 7 and the Berkeley C shell.
.KY shiftwidth
.IP "shiftwidth, sw [8]"
Set the autoindent and shift command indentation width.
@@ -705,11 +1010,6 @@ option and by the
and
.CO shift
commands.
-.KY showdirty
-.IP "showdirty [off]"
-.CO Vi
-only.
-Display an asterisk on the colon command line if the file has been modified.
.KY showmatch
.IP "showmatch, sm [off]"
.CO Vi
@@ -728,13 +1028,15 @@ See the
.OP matchtime
option for more information.
.KY showmode
-.IP "showmode [off]"
+.IP "showmode, smd [off]"
.CO Vi
only.
This option causes
.CO vi
-to display a string identifying the current editor mode on the
-colon command line.
+to display a string identifying the current editor mode on the colon
+command line.
+The string is preceded by an asterisk (``*'') if the file has been
+modified since it was last completely written,
.KY sidescroll
.IP "sidescroll [16]"
.CO Vi
@@ -796,7 +1098,7 @@ See the
.OP verbose
option for more information.
.KY tildeop
-.IP "tildeop"
+.IP "tildeop [off]"
Modify the
.CO ~
command to take an associated motion.
@@ -861,22 +1163,28 @@ been modified, since it was last written, before a
.CO !
command.
.KY window
-.IP "window, w, wi [environment variable LINES]"
+.IP "window, w, wi [environment variable LINES - 1]"
This option determines the default number of lines in a screenful,
-as written by the
+as displayed by the
.CO z
command.
It also determines the number of lines scrolled by the
.CO vi
commands
-.CO <control-F>
+.CO <control-B>
+and
+.CO <control-F> ,
+and the default number of lines scrolled by the
+.CO vi
+commands
+.CO <control-D>
and
-.CO <control-B> .
+.CO <control-U> .
The value of window can be unrelated to the real screen size,
-although it starts out as the number of lines on the screen (see
-the section entitled
+although it starts out as the number of lines on the screen.
+See the section entitled
.QB "Sizing the Screen"
-for more information).
+for more information.
Setting the value of the
.OP window
option is the same as using the
@@ -891,13 +1199,51 @@ option (as set by the
.OP w1200
or
.OP w9600
-options) is smaller than the actual size of the screen, large screen
-movements will result in displaying only that smaller number of lines
-on the screen.
+options) is smaller than the actual size of the screen,
+large screen movements will result in displaying only that smaller
+number of lines on the screen.
(Further movements in that same area will result in the screen being
filled.)
This can provide a performance improvement when viewing different
places in one or more files over a slow link.
+.sp
+Resetting the window size does not reset the default number of lines
+scrolled by the
+.CO <control-D>
+and
+.CO <control-U>
+commands.
+.KY windowname
+.IP "windowname [off]"
+.CO Vi
+changes the name of the editor's icon/window to the current file name
+when it's possible and not destructive, i.e.,
+when the editor can restore it to its original value on exit or when
+the icon/window will be discarded as the editor exits.
+If the
+.OP windowname
+edit option is set,
+.CO vi
+will change the icon/window name even when it's destructive and the
+icon/window name will remain after the editor exits.
+(This is the case for
+.XR xterm 1 ).
+.KY wraplen
+.IP "wraplen, wl [0]"
+This option is identical to the
+.OP wrapmargin
+option, with the exception that it specifies the number of columns
+from the
+.i left
+margin before the line splits, not the right margin.
+.sp
+If both
+.OP wraplen
+and
+.OP wrapmargin
+are set, the
+.OP wrapmargin
+value is used.
.KY wrapmargin
.IP "wrapmargin, wm [0]"
.CO Vi
@@ -906,7 +1252,7 @@ If the value of the
.OP wrapmargin
option is non-zero,
.CO vi
-will split lines so that they end at least that number of characters
+will split lines so that they end at least that number of columns
before the right-hand margin of the screen.
(Note, the value of
.OP wrapmargin
@@ -931,6 +1277,14 @@ character, it is discarded.
If wrapmargin is set to 0,
or if there is no blank character upon which to split the line,
the line is not broken.
+.sp
+If both
+.OP wraplen
+and
+.OP wrapmargin
+are set, the
+.OP wrapmargin
+value is used.
.KY wrapscan
.IP "wrapscan, ws [on]"
This option causes searches to wrap around the end or the beginning
diff --git a/usr.bin/vi/USD.doc/vi.ref/spell.ok b/contrib/nvi/docs/USD.doc/vi.ref/spell.ok
index 60084e31bcf4..a7d95e35d03a 100644
--- a/usr.bin/vi/USD.doc/vi.ref/spell.ok
+++ b/contrib/nvi/docs/USD.doc/vi.ref/spell.ok
@@ -1,8 +1,14 @@
+ABC
Amir
+Autoindent
Autoprint
BRE's
Bostic
Bourne
+CDPATH
+CSCOPE
+Cscope
+DIRS
DOUBLEQUOTE
Dq
Ds
@@ -12,44 +18,64 @@ Englar
Ev
FF
Fa
+Fg
+FindScreen
Fl
+Foregrounding
HUnhsh
IPLPPPQPP
Kirkendall
Korn
+LC
LIpplpipbp
LaA
Li
Lowercase
MINUSSIGN
Makefiles
+Mayoff
NEX
NEXINIT
NHSHH
NVI
+Neville
Nex
Nvi
OS
POSIX
+Perl
PostScript
+QQ
RE's
README
RECDIR
Reference''USD:13
+SENDMAIL
SIGHUP
SIGWINCH
SQUOTE
Se
Std
Std1003.2
+Sven
Sy
TANDARDS
TIOCGWINSZ
TMPDIR
+TOC
+Tagnext
+Tagprev
+Tcl
+Tk
Todo
+USD
USD.doc
USD:13
UUNET
+Unmap
+VI
+Verdoolaege
+Vi
Vx
Whitespace
XOFF
@@ -62,64 +88,102 @@ XXb
ZZ
ab
abbrev
+abc
ags
ai
al
altwerase
+ap
+api
+ar
arg
args
+att
autoindent
autoprint
autowrite
aw
+backgrounded
+backgrounding
bbrev
+berkeley
bf
+bg
bigword
bigwords
bostic
+bp
brev
+bsd
bugs.current
c2w
carat
+cd
+cdpath
cdy
+cedit
changelog
chd
+chdir
cmd
+co
count1
count2
creens
+cs
cs.berkeley.edu
+cscope
+ctags
+cw
db
dbopen
+dd
def
di
dir
dit
docs
+eE
eFlRsv
eFlRv
+eL
+eU
ead
eb
edcompatible
+edu
+ee
+egrep
elete
+elp
elvis
email
enum
eof
errorbells
esc
+escapetime
+eset
+eu
ex.cmd.roff
exrc
ext
exu
exusage
+fcntl
+fg
fi
+filec
filesystem
filesystems
+foo
+foregrounded
+foregrounding
ftp.cs.berkeley.edu
ftp.uu.net
gdb
gdb.script
+getpwent
gs
gzip'd
halfbyte
@@ -127,13 +191,19 @@ hange
hangup
hardtabs
ht
+html
+http
ic
+iclower
ifdef
ignorecase
ile
ind
+initially
ious
ir
+iscntrl
+isprint
ist
ize
keystroke
@@ -143,24 +213,34 @@ leftright
lhs
li
lib
+libc
libc.tags
+lineNum
+lineNumber
lobal
lowercase
lp
+luR
matchtime
mber
+mesg
meta
mk
mkexrc
modeful
modeline
modelines
+ms
+msgcat
ndo
nex
nexrc
nk
nomagic
+nonblank
+nonoverlapping
nooption
+noprint
nsert
nul
nvi
@@ -168,14 +248,20 @@ nvi.tar.Z
nvi.tar.z
nz
oin
+onnections
op
ove
para
pathname
pathnames
+pe
+perl
+perld
ppend
+prev
pu
py
+rc
rc.local
readonly
rec
@@ -185,46 +271,75 @@ recover.XXXX
recover.XXXXXX
recover.c
recover.script
+redist
+redistributable
+reimplementations
remapmax
+remapped
+repl
res
rew
rhs
+rint
ript
rk
+rl
ro
roff
rsion
sc
+sccs
scr
screeen
+screenId
se
+searchincr
+sendmail
set.opt.roff
+settable
+setuid
+sh
+shareware
+shellmeta
shiftwidth
showmatch
showmode
sidescroll
slowopen
sm
+smd
sourceany
sp
spell.ok
+ssg
st
+su
sual
svi
sw
ta
tabstop
taglength
+tagn
+tagnext
tagp
tagpop
+tagprev
tagstring
tagt
tagtop
+tc
+tcl
+tclproc
terminfo
th
+th's
tildeop
tl
tmp
+toolchest
+tpath
+tr
ts
ttytype
ttywerase
@@ -235,13 +350,18 @@ uffers
uit
una
unabbrev
+unescaped
unm
+unmap
+unsets
uppercase
urce
+usr
uunet
+v
var
ve
-vglobal
+vi
vi.0.ps
vi.0.txt
vi.1
@@ -250,6 +370,25 @@ vi.XXXXXX
vi.cmd.roff
vi.exrc
vi.recover
+viAppendLine
+viDelLine
+viEndScreen
+viFindScreen
+viGetCursor
+viGetLine
+viGetMark
+viGetOpt
+viInsertLine
+viLastLine
+viMapKey
+viMsg
+viNewScreen
+viSetCursor
+viSetLine
+viSetMark
+viSetOpt
+viSwitchScreen
+viUnmMapKey
vibackup
virecovery
viu
@@ -257,14 +396,19 @@ viusage
wa
whitespace
wi
+windowname
+wl
wm
wn
wq
+wraplen
wrapmargin
wrapscan
writeany
ws
+www
xaw
xit
+xterm
ya
yy
diff --git a/usr.bin/vi/USD.doc/vi.ref/vi.cmd.roff b/contrib/nvi/docs/USD.doc/vi.ref/vi.cmd.roff
index 57c0d372af69..12030cd52b08 100644
--- a/usr.bin/vi/USD.doc/vi.ref/vi.cmd.roff
+++ b/contrib/nvi/docs/USD.doc/vi.ref/vi.cmd.roff
@@ -1,35 +1,11 @@
.\" Copyright (c) 1994
.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 1994, 1995, 1996
+.\" Keith Bostic. All rights reserved.
.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
+.\" See the LICENSE file for redistribution information.
.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" @(#)vi.cmd.roff 8.28 (Berkeley) 7/17/94
+.\" @(#)vi.cmd.roff 8.49 (Berkeley) 8/17/96
.\"
.SH 1 "Vi Description"
.pp
@@ -46,8 +22,7 @@ the default display can show the current cursor row and cursor column,
an indication of whether the file has been modified,
and the current mode of the editor.
See the
-.OP ruler ,
-.OP showdirty
+.OP ruler
and
.OP showmode
options for more information.
@@ -97,14 +72,19 @@ In
text insert mode, the cursor is positioned on the first column of
characters which take up more than one column on the screen.
.pp
-Generally, if the cursor line and cursor column are not on the screen,
-then the screen is scrolled (if the target cursor is close) or repainted
-(if the target cursor is far away) so that the cursor is on the screen.
-If the screen is scrolled, it is moved a minimal amount, and the cursor
-line will usually appear at the top or bottom of the screen.
-In the screen is repainted, the cursor line will appear in the center of
-the screen, unless the cursor is sufficiently close to the beginning or
-end of the file that this is not possible.
+When positioning the cursor to a new line and column,
+the type of movement is defined by the distance to the new cursor position.
+If the new position is close,
+the screen is scrolled to the new location.
+If the new position is far away,
+the screen is repainted so that the new position is on the screen.
+If the screen is scrolled,
+it is moved a minimal amount,
+and the cursor line will usually appear at the top or bottom of the screen.
+If the screen is repainted,
+the cursor line will appear in the center of the screen,
+unless the cursor is sufficiently close to the beginning or end of the file
+that this isn't possible.
If the
.OP leftright
option is set, the screen may be scrolled or repainted in a horizontal
@@ -131,7 +111,7 @@ these commands acted on physical (as opposed to logical, or screen)
lines.
For lines that were sufficiently long in relation to the size of the
screen, this meant that single line scroll commands might repaint the
-entire screen, scrolling or screen positioning command might not change
+entire screen, scrolling or screen positioning commands might not change
the screen or move the cursor at all, and some lines simply could not
be displayed, even though
.CO vi
@@ -146,14 +126,13 @@ with lines significantly longer than a screen width.
keeps track of the currently
.QQ "most attractive"
cursor position.
-Each command description (for commands that can change the current
-cursor position),
+Each command description (for commands that alter the current cursor
+position),
specifies if the cursor is set to a specific location in the line,
or if it is moved to the
.QQ "most attractive cursor position" .
-The latter means that the cursor is moved to the cursor position
-that is vertically as close as possible to the current cursor
-position.
+The latter means that the cursor is moved to the cursor position that
+is horizontally as close as possible to the current cursor position.
If the current line is shorter than the cursor position
.CO vi
would select, the cursor is positioned on the last character in the line.
@@ -205,9 +184,9 @@ A second
.CO vi
command can be used as an optional trailing argument to the
.CO vi
-.CO \&! ,
.CO \&< ,
.CO \&> ,
+.CO \&! ,
.CO \&c ,
.CO \&d ,
.CO \&y ,
@@ -256,8 +235,8 @@ l n t w
.sp
The optional count prefix available for some of the
.CO vi
-commands that take motion commands, or the count prefix available
-for the
+commands that take motion commands,
+or the count prefix available for the
.CO vi
commands that are used as motion components,
may be included and is
@@ -270,10 +249,11 @@ and
are equivalent, and the region affected by the
.CO c
command is two words of text.
-In addition, if the optional count prefix is specified for both the
+In addition,
+if the optional count prefix is specified for both the
.CO vi
-command and its motion component, the effect is multiplicative and
-is considered part of the motion argument.
+command and its motion component,
+the effect is multiplicative and is considered part of the motion argument.
For example, the commands
.QT 4cw
and
@@ -296,28 +276,40 @@ command synopsis shows both a
and
.LI [count] ,
they may be presented in any order.
-.KY "bigword"
-.IP "bigword"
-A set of non-whitespace characters preceded and followed by whitespace
-characters or the beginning or end of the file or line.
-.sp
-Groups of empty lines (or lines containing only whitespace characters)
-are treated as a single bigword.
.KY word
.IP word
Generally, in languages where it is applicable,
.CO vi
recognizes two kinds of words.
-First, a sequence of letters, digits and underscores, delimited at both
-ends by: characters other than letters, digits, or underscores; the
-beginning or end of a line; the beginning or end of the file.
+First, a sequence of letters, digits and underscores,
+delimited at both ends by:
+characters other than letters, digits, or underscores,
+the beginning or end of a line, and the beginning or end of the file.
Second, a sequence of characters other than letters, digits, underscores,
or whitespace characters, delimited at both ends by: a letter, digit,
-underscore, or whitespace character;
-the beginning or end of a line; the beginning or end of the file.
+underscore, or whitespace character,
+the beginning or end of a line, and the beginning or end of the file.
+For example, the characters
+.QT " !@#abc$%^ "
+contain three words:
+.QT "!@#" ,
+.QT "abc"
+and
+.QT "$%^" .
.sp
Groups of empty lines (or lines containing only whitespace characters)
are treated as a single word.
+.KY "bigword"
+.IP "bigword"
+A set of non-whitespace characters preceded and followed by whitespace
+characters or the beginning or end of the file or line.
+For example, the characters
+.QT " !@#abc$%^ "
+contain one bigword:
+.QT "!@#abc$%^" .
+.sp
+Groups of empty lines (or lines containing only whitespace characters)
+are treated as a single bigword.
.KY "paragraph"
.IP "paragraph"
An area of text that begins with either the beginning of a file,
@@ -328,7 +320,7 @@ Groups of empty lines (or lines containing only whitespace characters)
are treated as a single paragraph.
.sp
Additional paragraph boundaries can be defined using the
-.OP paragraph
+.OP paragraphs
option.
.KY "section"
.IP "section"
@@ -344,7 +336,7 @@ option.
.IP "sentence"
An area of text that begins with either the beginning of the file or the
first nonblank character following the previous sentence, paragraph, or
-section boundary and continues until the end of the file or a or a period
+section boundary and continues until the end of the file or a period
.PQ \&.
exclamation point
.PQ !
@@ -355,9 +347,11 @@ followed by either an end-of-line or two whitespace characters.
Any number of closing parentheses
.PQ ) ,
brackets
-.PQ ]
-or double-quote
+.PQ ] ,
+double-quote
.PQ """"
+or single quote
+.PQ '
characters can appear between the period, exclamation point,
or question mark and the whitespace characters or end-of-line.
.sp
@@ -402,7 +396,6 @@ Set to the line where the word is found.
Set to the first character of the word.
.SP Options:
Affected by the
-.OP extended ,
.OP ignorecase
and
.OP wrapscan
@@ -413,8 +406,8 @@ options.
Page backward
.LI count
screens.
-Two lines of overlap are maintained by displaying the window
-starting at line
+Two lines of overlap are maintained, if possible,
+by displaying the window starting at line
.LI "(top_line - count * window_size) + 2" ,
where
.LI window_size
@@ -423,18 +416,16 @@ is the value of the
option.
(In the case of split screens, this size is corrected to the
current screen size.)
-This is an error if the movement is past the beginning of the file.
-.sp
-The
-.CO <control-B>
-command is an absolute movement.
+It is an error if the movement is past the beginning of the file.
.SS
.SP Line:
Set to the last line of text displayed on the screen.
.SP Column:
Set to the first nonblank character of the line.
.SP Options:
-None.
+Affected by the
+.OP window
+option.
.SE
.KY <control-D>
.IP "[count] <control-D>"
@@ -456,11 +447,7 @@ command,
scroll forward half the number of lines in the screen.
(In the case of split screens, the default scrolling distance is
corrected to half the current screen size.)
-This is an error if the movement is past the end of the file.
-.sp
-The
-.CO <control-D>
-command is an absolute movement.
+It is an error if the movement is past the end of the file.
.SS
.SP Line:
Set to the current line plus the number of lines scrolled.
@@ -474,7 +461,7 @@ None.
Scroll forward
.LI count
lines, leaving the cursor on the current line and column, if possible.
-This is an error if the movement is past the end of the file.
+It is an error if the movement is past the end of the file.
.SS
.SP Line:
Unchanged unless the current line scrolls off the screen,
@@ -490,8 +477,8 @@ None.
Page forward
.LI count
screens.
-Two lines of overlap are maintained by displaying the window
-starting at line
+Two lines of overlap are maintained, if possible,
+by displaying the window starting at line
.LI "top_line + count * window_size - 2" ,
where
.LI window_size
@@ -500,18 +487,16 @@ is the value of the
option.
(In the case of split screens, this size is corrected to the
current screen size.)
-This is an error if the movement is past the end of the file.
-.sp
-The
-.CO <control-F>
-command is an absolute movement.
+It is an error if the movement is past the end of the file.
.SS
.SP Line:
Set to the first line on the screen.
.SP Column:
Set to the first nonblank character of the current line.
.SP Options:
-None.
+Affected by the
+.OP window
+option.
.SE
.KY <control-G>
.IP "<control-G>"
@@ -530,12 +515,12 @@ Unchanged.
None.
.SE
.KY <control-H>
-.IP "<control-H>"
+.IP "[count] <control-H>"
.Ip "[count] h"
Move the cursor back
.LI count
characters in the current line.
-This is an error if the cursor is on the first character in the line.
+It is an error if the cursor is on the first character in the line.
.sp
The
.CO <control-H>
@@ -567,7 +552,7 @@ None.
Move the cursor down
.LI count
lines without changing the current column.
-This is an error if the movement is past the end of the file.
+It is an error if the movement is past the end of the file.
.sp
The
.CO <control-J> ,
@@ -607,7 +592,7 @@ None.
Move the cursor down
.LI count
lines to the first nonblank character of that line.
-This is an error if the movement is past the end of the file.
+It is an error if the movement is past the end of the file.
.sp
The
.CO <control-M>
@@ -633,7 +618,7 @@ None.
Move the cursor up
.LI count
lines, without changing the current column.
-This is an error if the movement is past the beginning of the file.
+It is an error if the movement is past the beginning of the file.
.sp
The
.CO <control-P>
@@ -645,7 +630,8 @@ commands, in which case any text copied into a buffer is
line oriented.
.SS
.SP Line:
-Set to the current line minus count.
+Set to the current line minus
+.LI count .
.SP Column:
The most attractive cursor position.
.SP Options:
@@ -666,7 +652,7 @@ Set to the context of the previous tag command.
None.
.SE
.KY <control-U>
-.IP "<control-U>"
+.IP "[count] <control-U>"
Scroll backward
.LI count
lines.
@@ -686,11 +672,7 @@ command,
scroll backward half the number of lines in the screen.
(In the case of split screens, the default scrolling distance is
corrected to half the current screen size.)
-This is an error if the movement is past the beginning of the file.
-.sp
-The
-.CO <control-U>
-command is an absolute movement.
+It is an error if the movement is past the beginning of the file.
.SS
.SP Line:
Set to the current line minus the amount scrolled.
@@ -712,11 +694,11 @@ Set to the previous cursor position in the window.
None.
.SE
.KY <control-Y>
-.IP "<control-Y>"
+.IP "[count] <control-Y>"
Scroll backward
.LI count
lines, leaving the current line and column as is, if possible.
-This is an error if the movement is past the beginning of the file.
+It is an error if the movement is past the beginning of the file.
.SS
.SP Line:
Unchanged unless the current line scrolls off the screen,
@@ -762,9 +744,9 @@ or
.CO ! ),
the command is executed.
If a partial command has been entered, e.g.
-.QL "[0-9]*" ,
+.QT "[0-9]*" ,
or
-.QL "[0-9]*[!<>cdy]" ,
+.QT "[0-9]*[!<>cdy]" ,
the command is cancelled.
Otherwise, it is an error.
.SS
@@ -841,7 +823,7 @@ option.
Move the cursor forward
.LI count
characters without changing the current line.
-This is an error if the cursor is on the last character in the line.
+It is an error if the cursor is on the last character in the line.
.sp
The
.CO <space>
@@ -868,7 +850,7 @@ current character.
None.
.SE
.KY !
-.IP "[count] ! motion shell-argument(s)"
+.IP "[count] ! motion shell-argument(s)<carriage-return>"
Replace text with results from a shell command.
Pass the lines specified by the
.LI count
@@ -897,7 +879,7 @@ or
.CO :!
commands.
(Therefore, the command
-.CO !!
+.CO !<motion>!
repeats the previous
.CO !
command.)
@@ -911,9 +893,10 @@ If no
.CO !
or
.CO :!
-command has yet been executed, it is an error to use an unescaped
+command has yet been executed,
+it is an error to use an unescaped
.QT !
-character.
+character as a shell argument.
The
.CO !
command does
@@ -948,32 +931,53 @@ Affected by the
option.
.SE
.KY #
-.IP "[count] # +|-|#"
-Increment or decrement the current number.
-The current number begins at the first non-number character on or
-before the current cursor position, or the beginning of the line,
-and extends up to the first non-number character on or after the
-current cursor position or the end of the line.
+.IP "[count] # #|+|-"
+Increment or decrement the number referenced by the cursor.
If the trailing character is a
-.LI \&+ ,
+.LI \&+
+or
+.LI \&# ,
the number is incremented by
.LI count .
If the trailing character is a
.LI \&- ,
the number is decremented by
.LI count .
-If the trailing character is a
-.LI \&# ,
-the previous increment or decrement is repeated.
.sp
-The format of the number (decimal, hexadecimal, and octal,
-and leading 0's) is retained unless the new value cannot be
-represented in the previous format.
+A leading
+.QT \&0X
+or
+.QT \&0x
+causes the number to be interpreted as a hexadecimal number.
+Otherwise, a leading
+.QT \&0
+causes the number to be interpreted as an octal number, unless a non-octal
+digit is found as part of the number.
+Otherwise, the number is interpreted as a decimal number, and may
+have a leading
+.LI \&+
+or
+.LI \&-
+sign.
+The current number begins at the first non-blank character at or after
+the current cursor position, and extends up to the end of the line or
+the first character that isn't a possible character for the numeric type.
+The format of the number (e.g. leading 0's, signs) is retained unless
+the new value cannot be represented in the previous format.
+.sp
+Octal and hexadecimal numbers, and the result of the operation, must fit
+into an
+.QT "unsigned long" .
+Similarly, decimal numbers and their result must fit into a
+.QT "signed long" .
+It is an error to use this command when the cursor is not positioned at
+a number.
+.sp
.SS
.SP Line:
Unchanged.
.SP Column:
-Set to the first character in the cursor word.
+Set to the first character in the cursor number.
.SP Options:
None.
.SE
@@ -1117,16 +1121,17 @@ For the
command, any text copied into a buffer is line oriented.
For the
.CO `
-command, any text copied into a buffer is character oriented, unless
-it both starts and stops at the first character in the line, in which
-case it is line oriented.
+command,
+any text copied into a buffer is character oriented,
+unless it both starts and stops at the first character in the line,
+in which case it is line oriented.
In addition, when using the
.CO `
command as a motion component,
-commands which move backward and started at the first character in the
-line, or move forward and ended at the first character in the line,
-are corrected to the last character of the starting and ending lines,
-respectively.
+commands which move backward and started at the first character in the line,
+or move forward and ended at the first character in the line,
+are corrected to the last character of the line preceding the starting and
+ending lines, respectively.
.SS
.SP Line:
Set to the line from the context.
@@ -1152,20 +1157,23 @@ The
.CO (
command may be used as the motion component of other
.CO vi
-commands, in which case any text copied into a buffer is
-character oriented, unless the starting and stopping points of the
-region are the first character in the line, in which case it is
-line oriented.
-In the latter case, the stopping point of the region is adjusted
-to be the end of the line immediately before it, and not the original
-cursor position.
+commands,
+in which case any text copied into a buffer is character oriented,
+unless the starting and stopping points of the region are the first
+character in the line,
+in which case it is line oriented.
+If it is line oriented,
+the starting point of the region is adjusted to be the end of the line
+immediately before the starting cursor position.
.SS
.SP Line:
Set to the line containing the beginning of the sentence.
.SP Column:
Set to the first nonblank character of the sentence.
.SP Options:
-None.
+Affected by the
+.OP lisp
+option.
.SE
.KY )
.IP "[count] )"
@@ -1192,7 +1200,9 @@ Set to the line containing the beginning of the sentence.
.SP Column:
Set to the first nonblank character of the sentence.
.SP Options:
-None.
+Affected by the
+.OP lisp
+option.
.SE
.KY ,
.IP "[count] ,"
@@ -1208,6 +1218,13 @@ or
command, searching the other way in the line,
.LI count
times.
+It is an error if a
+.CO F ,
+.CO f ,
+.CO T
+or
+.CO t
+command has not been performed yet.
.sp
The
.CO ,
@@ -1219,17 +1236,27 @@ character oriented.
.SP Line:
Unchanged.
.SP Column:
-Set to the searched-for character.
+Set to the searched-for character for the
+.CO F
+and
+.CO f
+commands,
+before the character for the
+.CO t
+command
+and after the character for the
+.CO T
+command.
.SP Options:
None.
.SE
.KY MINUSSIGN
.IP "[count] \-"
-Move to first nonblank of the previous line,
+Move to the first nonblank of the previous line,
.LI count
times.
.sp
-This is an error if the movement is past the beginning of the file.
+It is an error if the movement is past the beginning of the file.
.sp
The
.CO -
@@ -1334,12 +1361,19 @@ be line oriented (e.g.
will always guarantee a line orientation).
.sp
The
+.CO N
+command repeats the previous search, but in the reverse direction.
+The
.CO n
command repeats the previous search.
-.sp
-The
+If either the
.CO N
-command repeats the previous search, but in the reverse direction.
+or
+.CO n
+commands are used as motion components for the
+.CO !
+command, you will not be prompted for the text of the bang command,
+instead the previous bang command will be executed.
.sp
Missing RE's (e.g.
.QT //<carriage-return> ,
@@ -1352,6 +1386,25 @@ search for the last search RE, in the indicated direction.
Searches may be interrupted using the
.LI <interrupt>
character.
+.sp
+Multiple search patterns may be grouped together by delimiting
+them with semicolons and zero or more whitespace characters, e.g.
+.LI "/foo/ ; ?bar?"
+searches forward for
+.LI foo
+and then, from that location, backwards for
+.LI bar .
+When search patterns are grouped together in this manner,
+the search patterns are evaluated left to right with the
+final cursor position determined by the last search pattern.
+.sp
+It is also permissible to append a
+.CO z
+command to the search strings, e.g.
+.LI "/foo/ z."
+searches forward for the next occurrence of
+.LI foo ,
+and then positions that line in the middle of screen.
.SS
.SP Line:
Set to the line in which the match occurred.
@@ -1378,8 +1431,10 @@ The
.CO 0
command may be used as the motion component of other
.CO vi
-commands, in which case it is an error if the cursor is on the
-first character in the line.
+commands,
+in which case it is an error if the cursor is on the first character
+in the line,
+and any text copied into a buffer is character oriented.
.SS
.SP Line:
Unchanged.
@@ -1390,7 +1445,9 @@ None.
.SE
.KY :
.IP ":"
-Execute an ex command.
+Execute an
+.CO ex
+command.
.CO Vi
prompts for an
.CO ex
@@ -1403,7 +1460,7 @@ The command is terminated by a
or
.LI <escape>
character; all of these characters may be escaped by using a
-.LI "<literal next>"
+.LI "<literal-next>"
character.
The command is then executed.
.sp
@@ -1450,7 +1507,9 @@ The current column is set as described for the
.CO ex
command.
.SP Options:
-None.
+Affected as described for the
+.CO ex
+command.
.SE
.KY ;
.IP "[count] ;"
@@ -1464,6 +1523,13 @@ The last character find is one of the
or
.CO t
commands.
+It is an error if a
+.CO F ,
+.CO f ,
+.CO T
+or
+.CO t
+command has not been performed yet.
.sp
The
.CO ;
@@ -1475,7 +1541,17 @@ character oriented.
.SP Line:
Unchanged.
.SP Column:
-Set to the searched-for character.
+Set to the searched-for character for the
+.CO F
+and
+.CO f
+commands,
+before the character for the
+.CO t
+command
+and after the character for the
+.CO T
+command.
.SP Options:
None.
.SE
@@ -1484,9 +1560,10 @@ None.
.KY >
.Ip "[count] > motion"
Shift lines left or right.
-Shift the number of lines in the region specified by the motion component,
-times
-.LI count ,
+Shift the number of lines in the region specified by the
+.LI count
+and
+.LI motion
left (for the
.CO <
command) or right (for the
@@ -1494,11 +1571,10 @@ command) or right (for the
command) by the number of columns specified by the
.OP shiftwidth
option.
-Only whitespace characters are deleted when shifting left;
-once the first character in the line contains a nonblank character,
-the
-.CO shift
-will succeed, but the line will not be modified.
+Only whitespace characters are deleted when shifting left.
+Once the first character in the line no longer contains a whitespace
+character, the command will succeed,
+but the line will not be modified.
.SS
.SP Line:
Unchanged.
@@ -1535,9 +1611,9 @@ then the last buffer executed shall be used.
It is an error to specify
.QT @@
or
-.QT **
-if there were no buffer previous executions.
-The text of a macro may contain an
+.QT @*
+if there were no previous buffer executions.
+The text of a buffer may contain a
.CO @
command,
and it is possible to create infinite loops in this manner.
@@ -2112,7 +2188,7 @@ commands, in which case any text copied into a buffer is
character oriented, unless the starting position is column 0,
in which case it is line oriented.
.sp
-This is an error if the movement is past the beginning of the file.
+It is an error if the movement is past the beginning of the file.
.SS
.SP Line:
Set to the previous line that is
@@ -2144,7 +2220,7 @@ commands, in which case any text copied into a buffer is
character oriented, unless the starting position is column 0,
in which case it is line oriented.
.sp
-This is an error if the movement is past the end of the file.
+It is an error if the movement is past the end of the file.
.SS
.SP Line:
Set to the line that is
@@ -2255,16 +2331,14 @@ None.
.SE
.KY c
.IP "[buffer] [count] c motion"
-Change a region of text.
+Change the region of text specified by the
+.LI count
+and
+.LI motion .
If only part of a single line is affected, then the last character
being changed is marked with a
.QT $ .
Otherwise, the region of text is deleted, and input mode is entered.
-.sp
-If
-.LI count
-is specified, it is applied to the
-.LI motion .
.SS
.SP Line:
Set to the last line upon which characters were entered.
@@ -2283,10 +2357,9 @@ options.
.SE
.KY d
.IP "[buffer] [count] d motion"
-Delete a region of text.
-If
+Delete the region of text specified by the
.LI count
-is specified, it is applied to the
+and
.LI motion .
.SS
.SP Line:
@@ -2380,8 +2453,8 @@ The line is referred to by
.sp
Historically,
.LI <character>
-was restricted to lower-case letters only,
-.CO nvi
+was restricted to lower-case letters.
+.CO Nvi
permits the use of any character.
.SS
.SP Line:
@@ -2588,13 +2661,11 @@ None.
.IP "[buffer] [count] y motion"
Copy (or
.QQ yank )
-a text region specified by the
+the text region specified by the
.LI count
-and motion into a buffer.
-If
-.LI count
-is specified, it is applied to the
-.LI motion .
+and
+.LI motion ,
+into a buffer.
.SS
.SP Line:
Unchanged, unless the region covers more than a single line,
@@ -2874,6 +2945,10 @@ erase character and the
and
.QT ^<control-D>
erase strings could erase autoindent characters.
+(Autoindent characters include both the characters inserted automatically
+at the beginning of an input line as well as characters inserted using the
+.LI <control-T>
+command.)
This implementation permits erasure to continue past the beginning
of the current line, and back to where text input mode was entered.
In addition, autoindent characters may be erased using the standard
@@ -2902,8 +2977,19 @@ the previous input is replayed, as if just entered.
.KY <control-D>
.IP "<control-D>"
If the previous character on the line was an autoindent character,
-erase it.
-Otherwise, if the user is entering the first character in the line,
+erase characters to move the cursor back to the column immediately
+after the previous (1-based) column which is a multiple of the
+.OP shiftwidth
+edit option.
+This may result in any number of
+.LI <tab>
+and
+.LI <space>
+characters preceding the cursor being changed.
+.sp
+Otherwise, if the
+.OP autoindent
+option is set and the user is entering the first character in the line,
.LI <control-D>
is ignored.
Otherwise, a literal
@@ -2918,16 +3004,22 @@ In addition, the autoindent level is reset to 0.
.IP "0<control-D>"
If the previous character on the line was an autoindent character,
erase all of the autoindent characters on the line.
+The autoindent level is not altered.
.KY <control-T>
.IP "<control-T>"
Insert sufficient
.LI <tab>
and
.LI <space>
-characters to move the cursor forward to a column immediately
-after the next column which is an even multiple of the
+characters to move the cursor forward to the column immediately
+after the next (1-based) column which is a multiple of the
.OP shiftwidth
-option.
+edit option.
+This may result in any number of
+.LI <tab>
+and
+.LI <space>
+characters preceding the cursor being changed.
.sp
Historically,
.CO vi
@@ -2942,8 +3034,8 @@ permits it to be used at any time during insert mode.
.KY <control-H>
.Ip <control-H>
Erase the last character.
-.KY "<literal next>"
-.IP "<literal next>"
+.KY "<literal-next>"
+.IP "<literal-next>"
Quote the next character.
The next character will not be mapped (see the
.CO map
@@ -2955,7 +3047,13 @@ character will be displayed immediately as a placeholder,
but will be replaced by the next character.
.KY <escape>
.IP <escape>
-Resolve all text input into the file, and return to command mode.
+If on the colon command line, and the
+.OP filec
+edit option is set, behave as described for that option.
+Otherwise, if on the colon command line,
+execute the command.
+Otherwise, if not on the colon command line,
+resolve all text input into the file, and return to command mode.
.KY "<line erase>"
.IP "<line erase>"
Erase the current line.
@@ -2970,8 +3068,11 @@ and
.OP ttywerase
options.
.KY "<control-X>"
-.IP "<control-X>[0-9A-Fa-f]*"
+.IP "<control-X>[0-9A-Fa-f]+"
Insert a character with the specified hexadecimal value into the text.
+The value is delimited by any non-hexadecimal character or the input
+of the maximum number of characters that can be translated into a single
+character value.
.KY <interrupt>
.IP "<interrupt>"
Interrupt text input mode, returning to command mode.
diff --git a/usr.bin/vi/USD.doc/vi.ref/vi.ref b/contrib/nvi/docs/USD.doc/vi.ref/vi.ref
index 5058cc780dd5..a880c1659e11 100644
--- a/usr.bin/vi/USD.doc/vi.ref/vi.ref
+++ b/contrib/nvi/docs/USD.doc/vi.ref/vi.ref
@@ -1,35 +1,14 @@
.\" Copyright (c) 1994
.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 1994, 1995, 1996
+.\" Keith Bostic. All rights reserved.
.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
+.\" This document may not be republished without written permission from
+.\" Keith Bostic.
.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
+.\" See the LICENSE file for redistribution information.
.\"
-.\" @(#)vi.ref 8.52 (Berkeley) 8/13/94
+.\" @(#)vi.ref 8.88 (Berkeley) 10/19/96
.\"
.\"
.so ref.so
@@ -37,7 +16,7 @@
.(l C
.ps 12
.ft B
-Ex/Vi Reference Manual
+Vi/Ex Reference Manual
.ft
.ps
.sp
@@ -49,21 +28,42 @@ University of California, Berkeley
Berkeley, California 94720
.sp 1
\*(td
+.)l
.sp 3
+.(l C
.i Abstract
-.sp
.)l
.(q
.pp
This document is the reference guide for the 4.4BSD
implementations of
.EV nex nvi ,
-which are reimplementations of the historic Berkeley
+which are implementations of the historic Berkeley
.EV ex vi
editors.
.)q
.sp 3
.(l C
+.i Licensing
+.)l
+.sp
+.lp
+Copyright (c) 1991, 1992, 1993, 1994
+.ti +5
+The Regents of the University of California. All Rights Reserved.
+.lp
+Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996
+.ti +5
+Keith Bostic. All Rights Reserved.
+.sp
+.pp
+The vi program is freely redistributable. You are welcome to copy,
+modify and share it with others under the conditions listed in the
+LICENSE file. If any company (not individual!) finds vi sufficiently
+useful that you would have purchased it, or if any company wishes to
+redistribute it, contributions to the authors would be appreciated.
+.bp 2
+.(l C
.i Acknowledgements
.)l
.sp
@@ -95,6 +95,11 @@ Scrolling and reworking for
.CO nvi
was done by Elan Amir.
.pp
+George Neville-Neil added the Tcl interpreter,
+and Sven Verdoolaege added the Perl interpreter.
+.pp
+Rob Mayoff added Cscope support.
+.pp
The Institute of Electrical and Electronics Engineers has
given us permission to reprint portions of their documentation.
Portions of this document are reprinted and reproduced from
@@ -107,9 +112,9 @@ The financial support of UUNET Communications Services is gratefully
acknowledged.
.)q
.sy echo -n >index
-.oh 'Nvi/Nex Reference''USD:13-%'
-.eh 'USD:13-%''Nvi/Nex Reference'
-.bp 3
+.oh 'Vi/Ex Reference''USD:13-%'
+.eh 'USD:13-%''Vi/Ex Reference'
+.bp 4
.SH 1 Description
.pp
.CO Vi
@@ -162,9 +167,8 @@ There are a few features in
that are not found in historic versions of
.EV ex vi .
Some of the more interesting of those features are briefly described
-in the section entitled
-.QB "Additional Features"
-near the end of this document.
+in the next section, entitled
+.QB "Additional Features" .
For the rest of this document,
.EV nex nvi
is used only when it is necessary to distinguish it from the historic
@@ -176,6 +180,159 @@ by anonymous ftp, and can be retrieved from
.LI ftp.cs.berkeley.edu ,
in the directory
.LI ucb/4bsd .
+.SH 1 "Additional Features in Nex/Nvi"
+.pp
+There are a few features in
+.EV nex nvi
+that are not found in historic versions of
+.EV ex vi .
+Some of the more interesting of these are as follows:
+.IP "8-bit clean data, large lines, files"
+.EV Nex nvi
+will edit any format file.
+Line lengths are limited by available memory,
+and file sizes are limited by available disk space.
+The
+.CO vi
+text input mode command
+.CO <control-X>
+can insert any possible character value into the text.
+.IP "Background and foreground screens"
+The
+.CO bg
+command backgrounds the current screen, and the
+.CO fg
+command foregrounds backgrounded screens.
+The
+.CO display
+command can be used to list the background screens.
+.IP "Command Editing"
+You can enter a normal editing window on the collected commands that
+you've entered on the
+.CO vi
+colon command-line,
+and then modify and/or execute the commands.
+See the
+.OP cedit
+edit option for more information.
+.IP "Displays"
+The
+.CO display
+command can be used to display the current buffers, the backgrounded
+screens, and the tags stack.
+.IP "Extended Regular Expressions"
+The
+.CO extended
+option causes Regular Expressions to be interpreted as as Extended
+Regular Expressions, (i.e. \fIegrep\fP(1) style Regular Expressions).
+.IP "File Name Completion"
+It is possible to do file name completion and file name displays when
+entering commands on the
+.CO vi
+colon command-line.
+See the
+.OP filec
+option for more information.
+.IP "Infinite undo"
+Changes made during an edit session may be rolled backward and forward.
+A
+.CO \&.
+command immediately after a
+.CO u
+command continues either forward or backward depending on whether the
+.CO u
+command was an undo or a redo.
+.IP "Left-right scrolling"
+The
+.CO leftright
+option causes
+.CO nvi
+to do left-right screen scrolling, instead of the traditional
+.CO vi
+line wrapping.
+.IP "Message Catalogs"
+It is possible to display informational and error messages in different
+languages by providing a catalog of messages.
+See the
+.OP msgcat
+option and the file
+.LI "catalog/README"
+for more information.
+.IP "Incrementing numbers"
+The
+.CO \&#
+command increments or decrements the number referenced by the cursor.
+.IP "Previous file"
+The
+.CO previous
+command edits the previous file from the argument list.
+.IP "Scripting languages"
+The
+.CO ":pe[rl] cmd" ,
+.CO ":perld[o] cmd"
+and
+.CO ":tc[l] cmd"
+commands execute Perl and Tcl/Tk commands, respectively,
+on lines from the edit buffer.
+See the
+.QB "Scripting Languages"
+section and the specific commands for more information.
+.\".IP "Shell screens"
+.\"The
+.\".CO ":sc[ript] [file ...]"
+.\"command runs a shell in the screen.
+.\"Editing is unchanged, with the exception that a \fC<carriage-return>\fP
+.\"enters the current line (stripped of any prompt) as input to the
+.\"shell.
+.IP "Split screens"
+The
+.CO Edit ,
+.CO Ex ,
+.CO Next ,
+.CO Previous ,
+.CO Tag
+and
+.CO Visual
+(in
+.CO vi
+mode) commands divide the screen into multiple editing regions and
+then perform their normal function in a new screen area.
+The
+.CO <control-W>
+command rotates between the foreground screens.
+The
+.CO resize
+command can be used to grow or shrink a particular screen.
+.IP "Tag stacks"
+Tags are now maintained in a stack.
+The
+.CO <control-T>
+command returns to the previous tag location.
+The
+.CO tagpop
+command returns to the most recent tag location by default, or,
+optionally to a specific tag number in the tag stack,
+or the most recent tag from a specified file.
+The
+.CO display
+command can be used to list the tags stack.
+The
+.CO tagtop
+command returns to the top of the tag stack.
+.IP "Usage information"
+The
+.CO exusage
+and
+.CO viusage
+commands provide usage information for all of the
+.CO ex
+and
+.CO vi
+commands by default, or, optionally, for a specific command or key.
+.IP "Word search"
+The
+.CO <control-A>
+command searches for the word referenced by the cursor.
.SH 1 "Startup Information"
.pp
.EV Ex vi
@@ -199,8 +356,7 @@ Because the
.CO ex
command set supported by
.EV nex nvi
-is a superset of the command set supported by most historical
-implementations of
+is a superset of the command set supported by historical implementations of
.CO ex ,
.EV nex nvi
can use the startup files created for the historical implementations,
@@ -243,6 +399,18 @@ if
does not exist) is read,
as long as the effective user ID of the user is root or is the same as
the owner of the file.
+.sp
+When the $HOME directory is being used for both
+.EV nex nvi
+and an historic implementation of
+.EV ex vi ,
+a possible solution is to put
+.EV nex nvi
+specific commands in the
+.LI \&.nexrc
+file, along with a
+.CO ":source $HOME/.exrc"
+command to read in the commands common to both implementations.
.np
If the
.OP exrc
@@ -267,7 +435,7 @@ the first file to be edited is read in (or a temporary file is created).
Then, any commands specified using the
.b \-c
option are executed, in the context of that file.
-.SH 1 Recovery
+.SH 1 "Recovery"
.pp
There is no recovery program for
.EV nex nvi ,
@@ -375,38 +543,19 @@ not yet have this bit set.
This is due to the method in which the files are created.)
Such files should be deleted when the system reboots.
.pp
-A simple way to do this cleanup is to insert the following Bourne
-shell script into your
+A simple way to do this cleanup is to run the Bourne shell script
+.CO recover ,
+from your
.LI /etc/rc.local
-(or other startup) file.
+(or other system startup) file.
The script should work with the historic Bourne shell,
a POSIX 1003.2 shell or the Korn shell.
-(A copy of this script is included as
-.LI nvi/install/recover.script
-in the
+The
+.CO recover
+script is installed as part of the
.EV nex nvi
-distribution.)
-.sp
-.(b
-.ft C
-.so ../../install/recover.script
-.ft R
-.)b
-.sp
-.pp
-If you are not using the default value for the
-.OP recdir
-option, be sure to substitute the value you're using for the
-.LI RECDIR
-value in the recovery script.
+installation process.
.pp
-If the path of your system's
-.CO sendmail
-program (or whatever mailer you're using) is not
-.LI /usr/lib/sendmail ,
-be sure to substitute the correct pathname for the
-.LI SENDMAIL
-value in the recovery script.
Consult the manual page for details on recovering preserved or
aborted editing sessions.
.SH 1 "Sizing the Screen"
@@ -455,7 +604,7 @@ are displayed using the local character set.
.pp
Non-printable characters, for which
.XR iscntrl 3
-returns true, and which are less than octal \e076,
+returns true, and which are less than octal \e040,
are displayed as the string
.QT ^<character> ,
where
@@ -494,22 +643,30 @@ supports multiple screens by dividing the window into regions.
It also supports stacks of screens by permitting the user to change
the set of screens that are currently displayed.
.pp
-The command
-.CO split
-divides the current screen into two regions of approximately equal
-size.
-If a list of files are specified as arguments to the
-.CO split
-command, the list of files to be edited is initialized as if the
-.CO next
-command had been used.
-If no files are specified, the new screen will begin by editing the same
-file as the previous screen.
+The
+.CO Edit ,
+.CO Ex ,
+.CO Fg ,
+.CO Next ,
+.CO Previous ,
+.CO Tag
+and
+.CO Visual
+(in
+.CO vi
+mode)
+commands divide the current screen into two regions of approximately
+equal size and then perform their usual action in a new screen area.
+If the cursor is in the lower half of the screen, the screen will split
+up, i.e. the new screen will be above the old one.
+If the cursor is in the upper half of the screen, the new screen will be
+below the old one.
.pp
When more than one screen is editing a file, changes in any screen are
reflected in all other screens editing the same file.
-Exiting any screen without saving any changes (or explicitly discarding
-them) is permitted until the last screen editing the file is exited.
+Exiting a screen without saving any changes (or explicitly discarding
+them) is permitted until the last screen editing the file is exited,
+at which time the changes must be saved or discarded.
.pp
The
.CO resize
@@ -540,18 +697,323 @@ backgrounded screens in the window.
.pp
The
.CO "fg [file]"
-command
-.QQ foregrounds
-the first screen in the list of backgrounded screens that is
-associated with its argument.
+command moves the specified screen from the list of backgrounded screens
+to the foreground.
If no file argument is specified, the first screen on the list is
foregrounded.
-Foregrounding consists of backgrounding the current screen,
+By default,
+foregrounding consists of backgrounding the current screen,
and replacing its space in the window with the foregrounded screen.
.pp
-If the last screen in the window is exited, and there are backgrounded
-screens, the first screen on the list of backgrounded screens takes over
-the window.
+Capitalizing the first letter of the command, i.e.
+.CO Fg ,
+will foreground the backgrounded screen in a new screen instead of
+swapping it with the current screen.
+.pp
+If the last foregrounded screen in the window is exited,
+and there are backgrounded screens,
+the first screen on the list of backgrounded screens takes over the window.
+.SH 1 "Tags, Tag Stacks, and Cscope"
+.pp
+.CO Nvi
+supports the historic
+.CO vi
+tag command
+.CO <control-]> ,
+and the historic
+.CO ex
+tag command
+.CO tag .
+These commands change the current file context to a new location,
+based on information found in the
+.LI tags
+files.
+If you are unfamiliar with these commands,
+you should review their description in the
+.CO ex
+and
+.CO vi
+commands section of this manual.
+For additional information on tags files,
+see the discussion of the
+.OP tags
+edit option and the system
+.XR ctags 1
+manual page.
+.pp
+In addition,
+.CO nvi
+supports the notion of
+.QQ "tags stacks" ,
+using the
+.CO <control-T>
+command.
+The
+.CO <control-T>
+command returns the user to the previous context, i.e.,
+the last place from which a
+.CO <control-]>
+or
+.CO "tag"
+command was entered.
+These three commands provide the basic functionality which allows you
+to use
+.CO vi
+to review source code in a structured manner.
+.pp
+.CO Nvi
+also provides two other basic
+.CO ex
+commands for tag support:
+.CO tagpop
+and
+.CO tagtop .
+The
+.CO tagpop
+command is identical to the
+.CO <control-T>
+command,
+with the additional functionality that you may specify that modifications
+to the current file are to be discarded.
+This cannot be done using the
+.CO <control-T>
+command.
+The
+.CO tagtop
+command discards all of the contexts that have been pushed onto the tag
+stack, returning to the context from which the first
+.CO <control-]>
+or
+.CO tag
+command was entered.
+.pp
+The historic
+.XR ctags 1
+tags file format supports only a single location per tag,
+normally the function declaration or structure or string definition.
+More sophisticated source code tools often provide multiple locations
+per tag, e.g.,
+a list of the places from which a function is called or a string
+definition is used.
+An example of this functionality is the System V source code tool,
+.CO cscope .
+.sp
+.CO Cscope
+creates a database of information on source code files,
+and supports a query language for that information as described in the
+.XR cscope 1
+manual page.
+.CO Nvi
+contains an interface to the
+.CO cscope
+query language which permits you to query
+.CO cscope
+and then sequentially step through the locations in the sources files which
+.CO cscope
+returns.
+There are two
+.CO nvi
+commands which support this ability to step through multiple locations.
+They are the
+.CO ex
+commands
+.CO tagnext
+and
+.CO tagprev .
+The
+.CO tagnext
+command moves to the next location for the current tag.
+The
+.CO tagprev
+command moves to the previous location for the current tag.
+(See the
+.CO tagnext
+and
+.CO tagprev
+command discussion in the
+.CO ex
+commands section of this manual for more information.)
+At any time during this sequential walk,
+you may use the
+.CO <control-]> ,
+.CO tag
+or
+.CO cscope
+commands to move to a new tag context, and then use the
+.CO <control-T>
+or
+.CO tagpop
+commands to return and continue stepping through the locations for this
+tag.
+This is similar to the previous model of a simple tag stack,
+except that each entry in the tag stack may have more than one file context
+that is of interest.
+.pp
+Although there is no widely distributed version of
+.XR ctags 1
+that creates tags files with multiple locations per tag,
+.CO nvi
+has been written to understand the obvious extension to the historic
+tags file format, i.e., more than a single line in the tags file with
+the same initial tag name.
+If you wish to extend your
+.CO ctags
+implementation or other tool with which you build tags files,
+this extension should be simple and will require no changes to
+.CO nvi .
+.pp
+The
+.CO nvi
+and
+.CO cscope
+interface is based on the new
+.CO ex
+command
+.CO cscope ,
+which has five subcommands:
+.CO add ,
+.CO find ,
+.CO help ,
+.CO kill
+and
+.CO reset .
+The subcommand
+.CO find
+itself has eight subcommands:
+.CO \&c ,
+.CO \&d ,
+.CO \&e ,
+.CO \&f ,
+.CO \&g ,
+.CO \&i ,
+.CO \&s
+and
+.CO \&t .
+.pp
+.IP "cs[cope] a[dd] file"
+The
+.CO add
+command attaches to the specified
+.CO cscope
+database.
+The file name is expanded using the standard filename expansions.
+If
+.CO file
+is a directory, the file
+.QQ cscope.out
+in that directory is used as the database.
+.pp
+After
+.CO nvi
+attaches to a new database,
+all subsequent
+.CO cscope
+queries will be asked of that database.
+The result of any single query is the collection of response to the query
+from all of the attached databases.
+.sp
+If the
+.QQ CSCOPE_DIRS
+environmental variable is set when
+.CO nvi
+is run,
+it is expected to be a <colon> or <blank>-separated list of
+.CO cscope
+databases or directories containing
+.CO cscope
+databases, to which the user wishes to attach.
+.IP ":cs[cope] f[ind] c|d|e|f|g|i|s|t buffer|pattern"
+The
+.CO find
+command is the
+.CO cscope
+query command for
+.CO nvi .
+For this command,
+.CO nvi
+queries all attached
+.CO cscope
+databases for the pattern.
+If the pattern is a double-quote character followed by a valid buffer
+name (e.g.,
+.LI """<character>" ),
+then the contents of the named buffer are used as the pattern.
+Otherwise, the pattern is a Regular Expression.
+.sp
+The
+.CO find
+command pushes the current location onto the tags stack,
+and switches to the first location resulting from the query,
+if the query returned at least one result.
+.sp
+File names returned by the
+.CO cscope
+query, if not absolute paths, are searched for relative to the directory
+where the
+.CO cscope
+database is located.
+In addition, if the file
+.QQ cscope.tpath
+appears in the same directory as the
+.CO cscope
+database,
+it is expected to contain a colon-separated list of directory names
+where files referenced by its associated
+.CO cscope
+database may be found.
+.sp
+The
+.CO find
+subcommand is one of the following:
+.SS
+.SP \&c
+Find callers of the name.
+.SP \&d
+Find all function calls made from name.
+.SP \&e
+Find pattern.
+.SP \&f
+Find files with name as substring.
+.SP \&g
+Find definition of name.
+.SP \&i
+Find files #including name.
+.SP \&s
+Find all uses of name.
+.SP \&t
+Find assignments to name.
+.SE
+.IP ":cs[cope] h[elp] [command]"
+List the
+.CO cscope
+commands,
+or optionally list usage help for any single
+.CO cscope
+command.
+.IP ":display c[onnections]"
+Display the list of
+.CO cscope
+databases to which
+.CO nvi
+is currently connected.
+.IP ":cs[cope] k[ill] #"
+Disconnect from a specific
+.CO cscope
+database.
+The connection number is the one displayed by the
+.CO ex
+.CO "display connections"
+command.
+.IP ":cs[cope] r[eset]"
+Disconnect from all attached
+.CO cscope
+databases.
+.pp
+Cscope is not freely redistributable software,
+but is fairly inexpensive and easily available.
+To purchase a copy of
+.CO cscope ,
+see http://www.att.com/ssg/products/toolchest.html.
.SH 1 "Regular Expressions and Replacement Strings"
.pp
Regular expressions are used in line addresses,
@@ -560,7 +1022,7 @@ as the first part of the
.CO substitute ,
.CO global ,
and
-.CO vglobal
+.CO v
commands, and in search patterns.
.pp
The regular expressions supported by
@@ -699,7 +1161,7 @@ replaces the string
.LI abc
with
.LI ABC ).
-The strings
+The string
.QT \eL
causes characters up to the end of the string or the next occurrence
of the strings
@@ -724,6 +1186,126 @@ the matched line to be split into two lines at that point.
(The
.LI <control-M>
will be discarded.)
+.SH 1 "Scripting Languages"
+.pp
+The
+.CO nvi
+editor currently supports two scripting languages, Tcl/Tk and Perl.
+(Note that Perl4 isn't sufficient, and that the Perl5 used must be
+version 5.002 or later.
+See the
+.QB "Building Nvi"
+section for more information.
+.pp
+The scripting language interface is still being worked on,
+therefore the following information is probably incomplete,
+probably wrong in cases, and likely to change.
+See the
+.LI perl_api
+and
+.LI tcl_api
+source directories for more information.
+As a quick reference, the following function calls are provided for
+both the Perl and Tcl interfaces.
+The Perl interface uses a slightly different naming convention,
+e.g. ``viFindScreen'' is named ``VI::FindScreen''.
+.IP "viFindScreen file"
+Return the
+.LI "screenId" associated with
+.LI file .
+.IP "viAppendLine screenId lineNumber text"
+Append
+.LI text
+as a new line after line number
+.LI lineNumber ,
+in the screen
+.LI screenId .
+.IP "viDelLine screenId lineNum"
+Delete the line
+.LI lineNumber
+from the screen
+.LI screenId .
+.IP "viGetLine screenId lineNumber"
+Return the line
+.LI lineNumber
+from the screen
+.LI screenId .
+.IP "viInsertLine screenId lineNumber text"
+Insert
+.LI text
+as a new line before line number
+.LI lineNumber
+in the screen
+.LI screenId .
+.IP "viLastLine screenId"
+Return the line number of the last line in the screen
+.LI screenId .
+.IP "viSetLine screenId lineNumber text"
+Change the line
+.LI lineNumber
+in the screen
+.LI screenId
+to match the specified
+.LI text .
+.IP "viGetMark screenId mark"
+Return the current line and column for the specified
+.LI mark
+from the screen
+.LI screenId .
+.IP "viSetMark screenId mark line column"
+Set the specified
+.LI mark
+to be at line
+.LI line ,
+column
+.LI column ,
+in the screen
+.LI screenId .
+.IP "viGetCursor screenId"
+Return the current line and column for the cursor in the screen
+.LI screenId .
+.IP "viSetCursor screenId line column"
+Set the cursor in the screen
+.LI screenId
+to the specified
+.LI line
+and
+.LI column .
+.IP "viMsg screenId text"
+Display the specified
+.LI text
+as a vi message in the screen
+.LI screenId .
+.IP "viNewScreen screenId [file]"
+Create a new screen.
+.IP "viEndScreen screenId"
+Exit the screen
+.LI screenId .
+.IP "viSwitchScreen screenId screenId"
+Switch from the screen
+.LI screenId
+to the screen
+.LI screenId .
+.IP "viMapKey screenId key tclproc"
+Map the specified
+.LI key
+in the screen
+.LI screenId
+to the Tcl procedure
+.LI tclproc .
+.IP "viUnmMapKey screenId key"
+Unmap the specified
+.LI key
+in the screen
+.LI screenId
+.IP "viGetOpt screenId option"
+Return the value of the specified
+.LI option
+from the screen
+.LI screenId .
+.IP "viSetOpt screenId command"
+Set one or more options in the screen
+.LI screenId .
.SH 1 "General Editor Description"
.pp
When
@@ -787,7 +1369,7 @@ and
.CO insert .
Once in input mode, entering a line containing only a single period
.PQ \&.
-terminates text input mode and returns to command mode,
+ends text input mode and returns to command mode,
where the prompt is redisplayed.
.pp
When
@@ -810,7 +1392,23 @@ and
.CO s .
Once in input mode, entering an
.LI <escape>
-character terminates text input mode and returns to command mode.
+character ends text input mode and returns to command mode.
+.pp
+.EV Ex vi
+present three different interfaces to editing a file.
+.CO Ex
+presents a line oriented interface.
+.CO Vi
+presents a full screen display oriented interface,
+also known as
+.QQ "visual mode" .
+In addition, there is a third mode,
+.QQ "open mode" ,
+which is line oriented,
+but supports cursor movement and editing within the displayed line,
+similarly to visual mode.
+Open mode is not yet implemented in
+.CO nvi .
.pp
The following words have special meanings in both the
.CO ex
@@ -823,8 +1421,8 @@ The interrupt character is used to interrupt the current operation.
Normally
.LI <control-C> ,
whatever character is set for the current terminal is used.
-.KY "<literal next>"
-.IP "<literal next>"
+.KY "<literal-next>"
+.IP "<literal-next>"
The literal next character is used to escape the subsequent character
from any special meaning.
This character is always
@@ -870,14 +1468,25 @@ it (i.e. the
command cannot save the changed text in a named buffer).
Buffers are named with a single character, preceded by a double quote,
e.g.
-.LI """<character>" .
+.LI """<character>"
+in
+.CO vi
+and
+without the double quote, e.g.
+.LI <character> ,
+in
+.CO ex .
+(The double quote isn't necessary for
+.CO ex
+because buffers names are denoted by their position in the command line.)
Historic implementations of
.EV ex vi
limited
.LI <character>
to the alphanumeric characters;
.EV nex nvi
-permits the use of any character.
+permits the use of any character without another meaning in the position
+where a buffer name is expected.
.sp
Buffers named by uppercase characters are the same as buffers
named by lowercase characters, e.g. the buffer named by the
@@ -897,12 +1506,40 @@ The buffers named by the numeric characters (in English,
.QT 1
through
.QT 9 ),
-are special, in that if at least one line is changed or deleted in
-the file,
-(or a command changes or deletes a region that crosses a line boundary)
-a copy of the text is placed into the numeric buffer
+are special.
+If a region of text including characters from more than one line,
+or a single line of text specified by using a line-oriented motion,
+is changed or deleted in the file using the
+.CO vi
+.CO change
+or
+.CO delete
+commands, a copy of the text is placed into the numeric buffer
.QT 1 ,
regardless of the user specifying another buffer in which to save it.
+In addition, there are a few commands which, when used as a
+.LI motion
+with the
+.CO vi
+.CO change
+and
+.CO delete
+commands,
+.i always
+copy the specified region of text into the numeric buffers regardless
+of the region including characters from more than one line.
+These commands are:
+.sp
+.ne 3v
+.ft C
+.TS
+r r r r.
+<control-A> % ( )
+`<character> / ? N
+n { }
+.TE
+.ft R
+.sp
Before this copy is done, the previous contents of buffer
.QT 1
are moved into buffer
@@ -919,11 +1556,17 @@ In
text may be explicitly stored into the numeric buffers.
In this case, the buffer rotation described above occurs before the
replacement of the buffer's contents.
-(Text cannot be explicitly stored into the numeric buffers in
+The numeric buffers are only available in
+.LI visual
+and
+.LI open
+modes,
+and are not accessible by
.CO ex
-because of ambiguities that this would cause in the
+in any way, although changed and deleted text is still stored there
+while in
.CO ex
-command syntax.)
+mode.
.sp
When a
.CO vi
@@ -966,14 +1609,45 @@ line itself will be split.
.KY "unnamed buffer"
.IP "unnamed buffer"
The unnamed buffer is a text storage area which is used by commands
-that take a buffer as an argument, when no buffer is specified by
-the user.
-There is no way to explicitly reference this buffer.
-.oh 'Nvi/Nex Reference (Vi Commands)''USD:13-%'
-.eh 'USD:13-%''Nvi/Nex Reference (Vi Commands)'
+that use or operate on a buffer when no buffer is specified by the user.
+If the command stores text into a buffer,
+the text is stored into the unnamed buffer even if a buffer is also
+specified by the user.
+It is not possible to append text to the unnamed buffer.
+If text is appended to a named buffer,
+the named buffer contains both the old and new text,
+while the unnamed buffer contains only the new text.
+There is no way to explicitly reference the unnamed buffer.
+.sp
+Historically, the contents of the unnamed buffer were discarded by many
+different commands, even ones that didn't store text into it.
+.EV Nex nvi
+never discards the contents of the unnamed buffer until new text
+replaces them.
+.KY whitespace
+.IP whitespace
+The characters <tab> and <space>.
+.KY "<carriage-return>"
+.IP "<carriage-return>"
+The character represented by an ASCII
+.LI <control-M> .
+This character is almost always treated identically to a
+.LI <newline>
+character, but differs in that it can be escaped into the file text or
+into a command.
+.KY <newline>
+.IP <newline>
+The character represented by an ASCII
+.LI <control-J> .
+This character is almost always treated identically to a
+.LI <control-M>
+character, but differs in that it cannot be escaped into the file text or
+into a command.
+.oh 'Vi/Ex Reference (Vi Commands)''USD:13-%'
+.eh 'USD:13-%''Vi/Ex Reference (Vi Commands)'
.so vi.cmd.roff
-.oh 'Nvi/Nex Reference''USD:13-%'
-.eh 'USD:13-%''Nvi/Nex Reference'
+.oh 'Vi/Ex Reference''USD:13-%'
+.eh 'USD:13-%''Vi/Ex Reference'
.SH 1 "Ex Addressing"
.pp
Addressing in
@@ -1140,120 +1814,14 @@ The first address must be less than or equal to the second address.
The first address must be greater than or equal to the first line of the
file, and the last address must be less than or equal to the last line
of the file.
-.oh 'Nvi/Nex Reference (Ex Commands)''USD:13-%'
-.eh 'USD:13-%''Nvi/Nex Reference (Ex Commands)'
+.oh 'Vi/Ex Reference (Ex Commands)''USD:13-%'
+.eh 'USD:13-%''Vi/Ex Reference (Ex Commands)'
.so ex.cmd.roff
-.oh 'Nvi/Nex Reference''USD:13-%'
-.eh 'USD:13-%''Nvi/Nex Reference'
+.oh 'Vi/Ex Reference (Options)''USD:13-%'
+.eh 'USD:13-%''Vi/Ex Reference (Options)'
.so set.opt.roff
-.SH 1 "Additional Features in Nex/Nvi"
-.pp
-There are a few features in
-.EV nex nvi
-that are not found in historic versions of
-.EV ex vi .
-Some of the more interesting of those features are as follows:
-.IP "8-bit clean data, large lines, files"
-.EV Nex nvi
-will edit any format file.
-Line lengths are limited by available memory,
-and file sizes are limited by available disk space.
-The
-.CO vi
-text input mode command
-.CO <control-X>
-can insert any possible character value into the text.
-.IP "Split screens"
-The
-.CO split
-command divides the screen into multiple editing regions.
-The
-.CO <control-W>
-command rotates between the foreground screens.
-The
-.CO resize
-command can be used to grow or shrink a particular screen.
-.IP "Background and foreground screens"
-The
-.CO bg
-command backgrounds the current screen, and the
-.CO fg
-command foregrounds backgrounded screens.
-The
-.CO display
-command can be used to list the background screens.
-.\".IP "Shell screens"
-.\"The
-.\".CO ":sc[ript] [file ...]"
-.\"command runs a shell in the screen.
-.\"Editing is unchanged, with the exception that a \fC<carriage-return>\fP
-.\"enters the current line (stripped of any prompt) as input to the
-.\"shell.
-.IP "Tag stacks"
-Tags are now maintained in a stack.
-The
-.CO <control-T>
-command returns to the previous tag location.
-The
-.CO tagpop
-command returns to the most recent tag location by default, or,
-optionally to a specific tag number in the tag stack,
-or the most recent tag from a specified file.
-The
-.CO display
-command can be used to list the tags stack.
-The
-.CO tagtop
-command returns to the top of the tag stack.
-.IP "New displays"
-The
-.CO display
-command can be used to display the current buffers, the backgrounded
-screens, and the tags stack.
-.IP "Infinite undo"
-Changes made during an edit session may be rolled backward and forward.
-A
-.CO \&.
-command immediately after a
-.CO u
-command continues either forward or backward depending on whether the
-.CO u
-command was an undo or a redo.
-.IP "Usage information"
-The
-.CO exusage
-and
-.CO viusage
-commands provide usage information for all of the
-.CO ex
-and
-.CO vi
-commands by default, or, optionally, for a specific command or key.
-.IP "Extended Regular Expressions"
-The
-.CO extended
-option causes Regular Expressions to be interpreted as as Extended
-Regular Expressions, (i.e. \fIegrep\fP(1) style Regular Expressions).
-.IP "Word search"
-The
-.CO <control-A>
-command searches for the word referenced by the cursor.
-.IP "Number increment"
-The
-.CO \&#
-command increments or decrements the number referenced by the cursor.
-.IP "Previous file"
-The
-.CO previous
-command edits the previous file from the argument list.
-.IP "Left-right scrolling"
-The
-.CO leftright
-option causes
-.CO nvi
-to do left-right screen scrolling, instead of the traditional
-.CO vi
-line wrapping.
+.oh 'Vi/Ex Reference''USD:13-%'
+.eh 'USD:13-%''Vi/Ex Reference'
.bp
.SH 1 Index
.lp
@@ -1262,7 +1830,9 @@ line wrapping.
.nf
.so index.so
.fi
-.bp 2
+.\" Force the TOC to an odd page, in case it's a duplex printer.
+.if o .bp
+.bp 3
.1c
.ce 1
\fB\s+2Table of Contents\s0\fP
diff --git a/contrib/nvi/docs/USD.doc/vitut/Makefile b/contrib/nvi/docs/USD.doc/vitut/Makefile
new file mode 100644
index 000000000000..3d4aca0a64e6
--- /dev/null
+++ b/contrib/nvi/docs/USD.doc/vitut/Makefile
@@ -0,0 +1,22 @@
+# @(#)Makefile 8.7 (Berkeley) 8/18/96
+
+MACROS= -ms
+ROFF= groff
+TBL= tbl
+
+all: vitut.ps summary.ps viapwh.ps
+
+vitut.ps: vi.in vi.chars
+ ${TBL} vi.in vi.chars | ${ROFF} ${MACROS} > $@
+ chmod 444 $@
+
+summary.ps: vi.summary
+ ${TBL} vi.summary | ${ROFF} ${MACROS} > $@
+ chmod 444 $@
+
+viapwh.ps: vi.apwh.ms
+ ${TBL} vi.apwh.ms | ${ROFF} ${MACROS} > $@
+ chmod 444 $@
+
+clean:
+ rm -f vitut.ps summary.ps viapwh.ps
diff --git a/usr.bin/vi/USD.doc/vitut/vi.apwh.ms b/contrib/nvi/docs/USD.doc/vitut/vi.apwh.ms
index d0b62611c701..6b0763055ca9 100644
--- a/usr.bin/vi/USD.doc/vitut/vi.apwh.ms
+++ b/contrib/nvi/docs/USD.doc/vitut/vi.apwh.ms
@@ -29,8 +29,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)vi.apwh.ms 8.1 (Berkeley) 6/8/93
+.\" @(#)vi.apwh.ms 8.2 (Berkeley) 8/18/96
.\"
+.nr LL 6.5i
+.nr FL 6.5i
.TL
Vi Command & Function Reference
.AU CB 2675
diff --git a/usr.bin/vi/USD.doc/vitut/vi.chars b/contrib/nvi/docs/USD.doc/vitut/vi.chars
index 147c4ff7f2d8..7941065d1d0f 100644
--- a/usr.bin/vi/USD.doc/vitut/vi.chars
+++ b/contrib/nvi/docs/USD.doc/vitut/vi.chars
@@ -29,10 +29,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)vi.chars 8.1 (Berkeley) 6/8/93
+.\" @(#)vi.chars 8.3 (Berkeley) 6/27/96
.\"
.bd S 3
-..pn 21
+.pn 21
.de iP
.IP "\fB\\$1\fR" \\$2
..
@@ -111,6 +111,7 @@ The \s-2ASCII\s0 formfeed character, this causes the screen to be cleared
and redrawn. This is useful after a transmission error, if characters
typed by a program other than the editor scramble the screen,
or after output is stopped by an interrupt (5.4, 7.2f).
+.ne 1i
.iP "^M\ (\fR\s-2CR\s0\fP)" 15
A carriage return advances to the next line, at the first non-white position
in the line. Given a count, it advances that many lines (2.3).
diff --git a/usr.bin/vi/USD.doc/vitut/vi.in b/contrib/nvi/docs/USD.doc/vitut/vi.in
index 3bdfeb95b65e..c36ebe41743e 100644
--- a/usr.bin/vi/USD.doc/vitut/vi.in
+++ b/contrib/nvi/docs/USD.doc/vitut/vi.in
@@ -29,10 +29,12 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)vi.in 8.1 (Berkeley) 6/8/93
+.\" @(#)vi.in 8.5 (Berkeley) 8/18/96
.\"
-.EH 'USD:12-%''An Introduction to Display Editing with Vi'
-.OH 'An Introduction to Display Editing with Vi''USD:12-%'
+.nr LL 6.5i
+.nr FL 6.5i
+.EH 'USD:11-%''An Introduction to Display Editing with Vi'
+.OH 'An Introduction to Display Editing with Vi''USD:11-%'
.bd S 3
.if t .ds dg \(dg
.if n .ds dg +
@@ -586,6 +588,7 @@ This will set the
.I readonly
option which will prevent you from
accidently overwriting the file.
+.sp
.NH 1
Making simple changes
.NH 2
@@ -664,6 +667,7 @@ you can't backspace around the end of a line. If you need to back up
to the previous line to make a correction, just hit \s-2ESC\s0 and move
the cursor back to the previous line. After making the correction you
can return to where you were and use the insert or append command again.
+.sp .5
.NH 2
Making small corrections
.PP
@@ -720,6 +724,7 @@ Find a word which you can change to another, and try this
now.
Notice that the end of the text to be changed was marked with the character
`$' so that you can see this as you are typing in the new material.
+.sp .5
.NH 2
Operating on lines
.PP
@@ -1000,6 +1005,7 @@ F\fIx\fR f backward in line
P put text back, before cursor or above current line
T\fIx\fR t backward in line
.TE
+.ne 1i
.NH 1
High level commands
.NH 2
@@ -1167,6 +1173,18 @@ Options, set, and editor startup files
.PP
The editor has a set of options, some of which have been mentioned above.
The most useful options are given in the following table.
+.PP
+The options are of three kinds: numeric options, string options, and
+toggle options. You can set numeric and string options by a statement
+of the form
+.DS
+\fBset\fR \fIopt\fR\fB=\fR\fIval\fR
+.DE
+and toggle options can be set or unset by statements of one of the forms
+.DS
+\fBset\fR \fIopt\fR
+\fBset\fR \fBno\fR\fIopt\fR
+.DE
.KF
.TS
lb lb lb lb
@@ -1189,18 +1207,6 @@ slowopen slow Postpone display updates during inserts
term dumb The kind of terminal you are using.
.TE
.KE
-.PP
-The options are of three kinds: numeric options, string options, and
-toggle options. You can set numeric and string options by a statement
-of the form
-.DS
-\fBset\fR \fIopt\fR\fB=\fR\fIval\fR
-.DE
-and toggle options can be set or unset by statements of one of the forms
-.DS
-\fBset\fR \fIopt\fR
-\fBset\fR \fBno\fR\fIopt\fR
-.DE
These statements can be placed in your EXINIT in your environment,
or given while you are running
.I vi
@@ -1487,7 +1493,7 @@ command from
.I EXINIT )
with a command of the form:
.DS
-:map \fIlhs\fR \fIrhs\fR\s-2CR\f0
+:map \fIlhs\fR \fIrhs\fR\s-2CR
.DE
mapping
.I lhs
@@ -1758,6 +1764,7 @@ If you make changes to the editor's copy of a file, but do not wish to
write them back, then you must give an \fB!\fR after the command you
would otherwise use; this forces the editor to discard any changes
you have made. Use this carefully.
+.ne 1i
.PP
The \fB:e\fR command can be given a \fB+\fR argument to start at the
end of the file, or a \fB+\fR\fIn\fR argument to start at line \fIn\fR\^.
@@ -1810,7 +1817,7 @@ of the string. If you are using an operator such as \fBd\fR,
\fBc\fR or \fBy\fR, then you may well wish to affect lines up to the
line before the line containing the pattern. You can give a search of
the form \fB/\fR\fIpat\fR\fB/\-\fR\fIn\fR to refer to the \fIn\fR'th line
-before the next line containing \fIpat\fR, or you can use \fB\+\fR instead
+before the next line containing \fIpat\fR, or you can use \fB+\fR instead
of \fB\-\fR to refer to the lines after the one containing \fIpat\fR.
If you don't give a line offset, then the editor will affect characters
up to the match place, rather than whole lines; thus use ``+0'' to affect
@@ -1819,6 +1826,7 @@ to the line which matches.
You can have the editor ignore the case of words in the searches it does
by giving the command \fB:se ic\fR\s-2CR\s0.
The command \fB:se noic\fR\s-2CR\s0 turns this off.
+.ne 1i
.PP
Strings given to searches may actually be regular expressions.
If you do not want or need this facility, you should
@@ -1836,7 +1844,7 @@ It is also necessary to use a \e before a
The following table gives the extended forms when \fBmagic\fR is set.
.DS
.TS
-bl l.
+lb l.
\(ua at beginning of pattern, matches beginning of line
$ at end of pattern, matches end of line
\fB\&.\fR matches any character
@@ -1856,6 +1864,7 @@ More about input mode
.PP
There are a number of characters which you can use to make corrections
during input mode. These are summarized in the following table.
+.sp .5
.DS
.TS
lb l.
@@ -1873,6 +1882,7 @@ kill your kill character, deletes the input on this line
^V quotes the next non-printing character into the file
.TE
.DE
+.sp .5
.PP
The most usual way of making corrections to input is by typing \fB^H\fR
to correct a single character, or by typing one or more \fB^W\fR's to
diff --git a/usr.bin/vi/USD.doc/vitut/vi.summary b/contrib/nvi/docs/USD.doc/vitut/vi.summary
index a7d99384dc86..8a09ce944407 100644
--- a/usr.bin/vi/USD.doc/vitut/vi.summary
+++ b/contrib/nvi/docs/USD.doc/vitut/vi.summary
@@ -29,7 +29,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)vi.summary 8.1 (Berkeley) 6/8/93
+.\" @(#)vi.summary 8.3 (Berkeley) 8/18/96
.\"
.ds CH
.ds CF
@@ -49,10 +49,10 @@
.vs 11
.nr HM .50i
.nr FM .25i
-.nr PO 0
-.po 0
-.nr LL 3.5i
-.ll 3.5i
+.nr PO 1.0i
+.po 1.0i
+.nr LL 4.5i
+.ll 4.5i
.de nc
.bp
..
@@ -434,7 +434,7 @@ c change
< left shift
> right shift
! filter through command
-\&\= indent for \s-2LISP\s0
+\&= indent for \s-2LISP\s0
y yank lines to buffer
.TE
.h "Miscellaneous operations"
diff --git a/contrib/nvi/docs/changelog b/contrib/nvi/docs/changelog
new file mode 100644
index 000000000000..1f2a8c67b478
--- /dev/null
+++ b/contrib/nvi/docs/changelog
@@ -0,0 +1,1102 @@
+1.78 -> 1.79 (10/23/96)
+ + Rename delete() to del(), for C++.
+ + Add Spanish to the list of translations.
+ + Update to Perl 5.003_06, and other Perl interpreter updates.
+ + Update the set-edit-option interface for the scripting languages.
+ + Rework ex command parsing to match historic practice for backslash
+ escaped <newline> characters inside of global commands.
+ + Enhance the comment edit option to skip C++ comments.
+ + Change installation to configure the recovery shell script to match
+ the system pathnames and to install it into the vi data directory.
+ Move the recover script into the build directory, and delete the
+ recover directory.
+ + Enhance LynxOS support.
+1.76 -> 1.78 (10/01/96)
+ + Fix bugs when both the leftright scrolling and number edit options
+ were on.
+ + Fix bug where splitting in the middle of the screen could repaint
+ incorrectly.
+ + Fix first-nul in input bug, where random garbage was inserted.
+ + Correct search and mark-as-motion-command bug, it's a line mode
+ action if the search starts at or before the first non<blank>.
+ + Fix bug autoindent bug, where ^D could shift too far in the line.
+ + Fix core dump where ! command called from the .exrc file.
+ + Add the -S command-line option, which initializes vi to have the
+ secure edit option preset.
+1.75 -> 1.76 (09/15/96)
+ + Fix bug where ^V didn't keep input mapping from happening.
+ + Fix a core dump bug in the R command.
+ + Give up on licensing: no more shareware, adware, whatever.
+ + Fix cursor positioning bug for C, S and c$ in an empty file.
+1.74 -> 1.75 (08/22/96)
+ + Add French to the error message translations.
+ + Move the UNLICENSED message to the end of the message line.
+ + Fix bug where wide characters in a file name weren't calculated
+ correctly in the status message.
+ + Fix bug where cl_rename was called directly, by the ex shell code.
+ + Fix bug where splitting a screen resulting in a new screen at the
+ top of the display resulted in badly displayed status messages.
+1.73 -> 1.74 (08/18/96)
+ + Fix bug where the status line wasn't redisplayed if the user ran
+ an ex command that trashed the screen.
+ + Fix bug where the long version of the status line wasn't displayed
+ when switching screens.
+ + Rework fast-path filename completion code to sort the entries, and
+ strip out . and .. by default.
+ + Fix bug where ex went to the first line instead of the last one when
+ reading in a file.
+1.72 -> 1.73 (08/12/96)
+ + Do filename completion and some file expansion internally for speed.
+ + Fix CSCOPE_DIRS environmental variable support.
+ + Ex parser fix for global commands in script files.
+ + Add the O_PATH option, so you can specify a directory search path
+ for files.
+ + Make it possible to specify the database file to cscope, allowing
+ multiple databases in a single directory.
+ + Fix incremental search to overwrite erased characters so the user
+ can tell where they are on the colon-command line.
+ + Fix incremental search to restart the search if the user enters an
+ unescaped shell meta character.
+1.71 -> 1.72 (07/12/96)
+ + Cscope fix: test for files newer than the database was reversed.
+ + Display "files to edit" message for rewind, next and initial screen.
+ + Fix a bug in the R command where it could fail if the user extended
+ the file.
+ + Fix a bug where text abbreviations could corrupt the line.
+ + Fix a bug where the windowname edit option couldn't be set before a
+ file was loaded into the edit buffer.
+ + Fix a bug where the system .exrc values weren't being overridden by
+ the user's $HOME .exrc values.
+ + Fix a bug in the filename completion code, where garbage characters
+ could be added to the colon command line.
+ + Fix bug where multiple edit sessions on a non-existent file could
+ all write the file without warning.
+ + Fix bug where screen update was incorrect if a character triggered
+ both a wrapmargin and showmatch condition.
+ + Fix bug in leftright scrolling where <CR> during text input didn't
+ return the cursor to the left margin.
+ + Rev the Perl interpreter code, new version from Sven Verdoolaege,
+ based on Perl 5.003.01.
+ + Fix bug in tags file pattern search introduced in 1.71.
+1.70 -> 1.71 (07/01/96)
+ + Don't include <term.h> -- neither HPUX or Solaris can cope with it.
+ + Fix bug where ^M's in the original pattern were converted into new
+ lines in the file during substitution commands.
+ + Make window resize events separate from interrupts -- too many users
+ complained.
+ + Fix bug in first-character-is-null text input semantic.
+ + Rework search routines to take a length instead of a nul-terminated
+ string for a pattern. This fixes a couple of bugs in searching, but
+ probably introduces new ones.
+ + Fix prompting the user after a write filter command, the way I did
+ it in 1.70 broke the display.
+ + Don't switch to the alternate xterm screen when entering the ex
+ text input commands from vi mode.
+ + Implement the Fg command, so can foreground a background screen into
+ a split screen.
+ + Change the fg command to match screen names using the last component
+ of the filename the full filename fails.
+1.69 -> 1.70 (06/28/96)
+ + Change the ex read command to support named pipes.
+ + Copy the EXINIT/NEXINIT strings before executing their commands so
+ we don't step on the process environment.
+ + Don't do "line modification" reports for intermediate commands
+ executed from the vi colon command line, it screws up filter
+ reads, causing nvi to prompt for the user to continue.
+ + Add "smd" as an abbreviation for showmode: HP, ICL and SCO have it.
+ + Change nvi to always prompt the user after a write filter command.
+ This matches historic practice.
+ + Fix recovery information mailed to the user to reflect the program's
+ installed name.
+ + Change configuration script to not cache option information, e.g.,
+ --disable-curses.
+ + Fix a bug where the second character of the vi [[, ]] and ZZ
+ commands could start a command mapped sequence.
+ + Fix 3 write bugs: partial writes (3,$write), were clearing the
+ modified flag, full writes using line numbers (1,$write) were
+ not, and append historically never cleared the modified flag, and
+ we didn't get that right.
+ + Shorten the "more files to edit" message so it can gang on a single
+ line, lots of people have complained. Add the number of files that
+ are left to edit, it's historic practice.
+ + Fix core dump where message catalogs collided with truncating the
+ write path. Add a new write message so the string "appended" is
+ taken from a message catalog.
+ + Fix bug where an undo followed by '.' to repeat it wouldn't work
+ if no other repeatable commands had been entered.
+ + Fix core dump when resolution of input lines' autoindent characters
+ invalidated cached display information.
+ + Set the name of the X11 xterm icon/window to "xterm" when exiting,
+ if modified based on the windowname option.
+ + Include <term.h> if it exists, fixes portability problems on IRIX
+ systems.
+1.68 -> 1.69 (06/17/96)
+ + Add the windowname edit option and code to change the icon/window
+ name for xterm's.
+ + Enhance the comment edit option to skip shell comments.
+ + Add conditional prototypes to replacement C library functions.
+ + Minor enhancements/reworking to Makefile.in, other build files.
+ + Fix bug in vi text input ^D processing, could result in cursor
+ warp to the beginning of the line.
+ + Fix leftright screen bug where the screen wasn't repainted when
+ being repainted from scratch.
+ + Update the Swedish and Dutch catalogs.
+ + Truncate paths in write commands if they don't fit on one line.
+ + Fix alternate screen bug where the screen flashed and output lost
+ when switching to/from the X11 xterm alternate screen. Fix bug
+ where nvi switched into the alternate screen during filter-read
+ commands, which doesn't match historic practice.
+ + Minor relative cursor positioning change, make cursor position
+ changes from ex real and permanent.
+1.67 -> 1.68 (06/09/96)
+ + Fix core dump when tagging out of a modified file.
+1.66 -> 1.67 (06/09/96)
+ + Convert the license to adware.
+ + Leftright scrolling tweak, don't repaint the screen as often.
+ + Change so that search warning/error messages don't appear during an
+ incremental search.
+ + Cscope fix: test for files newer than the database was reversed.
+ + Don't display ex `welcome message' if in ex batch mode.
+ + Test for vsnprintf and snprintf separately, HP 10.10 has snprintf
+ but not vsnprintf.
+ + Reverse lookup order between LC_MESSAGES and LANG.
+ + Fix Tcl/Perl core dumps in common API code to get/set options.
+ + Fix R command -- it used a DB pinned page after discarding it.
+ + Minor fixes in multiple edit buffer message handling code.
+ + Fix yk command moving to shorter line core dump.
+ + Rework message handling to try and gang more messages onto a single
+ line.
+1.65 -> 1.66 (05/18/96)
+ + Convert vi man page to historic -man macro package, and install it.
+ + Fix bug were !! on an empty line with a nonexistent command left the
+ cursor on the second character, not the first.
+ + Fix bug where line redisplay was wrong when a <tab> replaced a
+ previous <tab> in the line.
+ + Fix bug where D (d$) didn't reset the relative cursor position.
+ + Fix bug where yG incorrectly reset the relative cursor position.
+ + Fix bug where the window size couldn't be grown once it was shrunk.
+ + Fix bug where the extended edit option caused tag searches to fail.
+ + If multiple lines in the tags file with the same leading tag, build
+ a tags stack like the Cscope stack. This is the obvious extension,
+ and the way that Larry McVoy's ctags program works.
+ + Send the appropriate TI/TE sequence in the curses screen whenever
+ entering ex/vi mode. This means that :shell now shows the correct
+ screen when using xterm alternate screens.
+ + Rework the options display code to get five columns in an 80 column
+ screen.
+ + Interactive Unix V3.0 port -- mostly file name shortening, other
+ minor changes. Only preliminary, more work will be necessary.
+ + Add debugging option to not read EXINIT/.exrc information.
+ + Fix bug where re_compile printed an error message to the screen
+ when the user entered [ to an incremental search.
+ + Turn off screen beeps when incremental search is failing.
+ + Fix bug where the iclower option didn't trigger an RE recompilation.
+ + Fix bug where -t into an already locked file forced the user to wait
+ as if a startup command had failed.
+ + LynxOS port -- mostly adding <sys/types.h> even though <sys/param.h>
+ was already included.
+ + Fix ex output bug, where it appeared as if an ex command was skipped
+ due to flags not being cleared in the vs_msg() routine.
+ + Fix core dump when global command tried to switch screens.
+1.64 -> 1.65 (05/13/96)
+ + Fix cscope <blank>-matching pattern to use extended RE's, and bug
+ that kept cscope from finding patterns containing <blank>s.
+ + Fix core dumps in both leftright and folded screens when tabstops
+ edit option value was large, and tab characters occurred as the last
+ character in the logical screen.
+ + Fix core dump where the second screen of a folded line wasn't
+ displayed correctly.
+ + Fix incremental search to match the current location for strings
+ starting with \< patterns.
+ + Fix bug where margins were ignored during replay of text input.
+ + Fix bug where motion components to shorter lines could lose because
+ the relative motion flags weren't ever set. This has been broken
+ forever, but the change almost certainly breaks something else -- I
+ have no idea what.
+ + Tags display: don't print the current entry separately, display
+ them all and add a trailing asterisk for the current one.
+ + Change the cscope add command to put the directory name through
+ standard file name expansion.
+ + Fix cscope use of buffers -- search commands weren't nul-terminated.
+1.63 -> 1.64 (05/08/96)
+ + Add installation target to the Makefile.
+ + Add documentation on the new tags commands to the Vi Reference
+ Manual.
+ + Make the sidescroll edit option work again.
+ + Fix bug where messages output during startup by ex could be lost.
+ + Change ex/vi commands errors into beeps, unless the verbose edit
+ option is set -- there are too many macros that are expected to
+ eventually fail. This matches historic practice.
+ + Truncate paths in initial vi screen if they won't fit on one line.
+ + Make cursor position after filter write match historic practice.
+ + Force the user to wait if there is output and the user is leaving
+ the screen for any reason -- don't permit further ex commands.
+ + Don't use a <newline> character to scroll the screen when exiting,
+ scroll in the vi screen before endwin() is called.
+ + Fix bug where the column number could be incorrect because the old
+ screen wasn't updated after a screen split.
+ + Fix ex print routine to correctly specify print flags.
+ + Make -g/-O a separate make/configuration option.
+ + Fix bug where ex/vi messages weren't being joined.
+ + Fix bug where termcap strings were free'd twice.
+ + Fix bug where TI/TE still weren't working -- I didn't put in the
+ translation strings for BSD style curses.
+ + Fix bug where I misspelled the iclower edit option as icloser.
+1.62 -> 1.63 (04/29/96)
+ + Robustness and type/lint fixes for the Tcl interface code.
+ + Fix core dump if TERM wasn't set or terminal type was unknown.
+ + Fix bug where combining ex commands that did/did not require an
+ ex screen would overwrite the command with the want-to-continue
+ messsage.
+ + Fix bug where the screen was never resolved if the user continued
+ entering ex commands using the : character, but then backspaced
+ over the prompt to quit or tried to edit their colon command-line
+ history.
+ + Fix bug where cursor wasn't placed over the ^ placeholder character
+ when quoting using the literal-next character.
+ + Fix bug where nvi under BSD style curses wasn't sending TI/TE termcap
+ strings when suspending the process.
+ + Rename mic again, to iclower.
+ + Fix bug where 'z' commands trailing / or ? commands weren't being
+ executed.
+ + Change incremental search to leave the cursor at its last position
+ when searching for something that was never found.
+ + Fix bug where search-with-confirmation from vi mode didn't position
+ the cursor correctly after displaying the confirm message.
+ + Fix bug where the "search wrapped" message was dependent on the
+ verbose edit option, which doesn't match historic practice. Change
+ search messages to be in inverse video.
+ + Fix bug where matched showmatch character wasn't being displayed
+ before the matching character was displayed.
+ + Another cursor update bug required a change to vs_paint().
+ + Fix bug were initial line offset was wrong for the first split screen
+ (symptom is very strange column numbers and blank first line).
+ + Create filename "argument" lists when creating new screens.
+ + Fix bug where globals with associated commands that included both
+ buffer execution and other commands could fail to execute the latter.
+1.61 -> 1.62 (04/22/96)
+ + Rename the "searchci" edit option to be "mic".
+ + Fix memory corruption in global commands ending in searches.
+ + Fix text resolution bug, corrected the cursor based on the
+ first line input, not the last.
+ + Rework the readonly edit option to match historic practice.
+ + Fix several minor incremental search bugs; make incremental
+ searches work in maps.
+ + Fix long-line core dump, where an incorrect screen map could be
+ used.
+1.60 -> 1.61 (04/12/96)
+ + The cursor now ends up on the FIRST character of the put text for
+ all versions of the vi put commands, regardless of the source
+ of the text. This matches System III/V behavior and POSIX 1003.2.
+ + Fixed bug where showmatch messages were getting discarded.
+ + Minor Perl integration fixes.
+ + Integrate Cscope into the tags stack code -- major change.
+ + Fixed bug where ^T would drop core if returning to a temporary file.
+ + Changed vs_ routine to display ex output to replace tab characters
+ with spaces.
+ + Fix autoindent code to not back up past beginning of line when ^T
+ inserted into the middle of a line, i.e. offset != 0.
+ + Fix "notimeout" option, was being ignored, by a coding error.
+ + Fix showmatch code to never flash on a match if keys are waiting.
+ + Change the vi 'D' command to ignore any supplied count, matching
+ historic practice.
+ + Fix viusage for D, S, C and Y (the aliased vi commands).
+ + Fix the Perl5 configuration bug in the configuration script.
+ + Make file completion commands in empty lines work.
+ + Fix where the change to let vi use the default ex command structure
+ broke the ex specification of the script or source file name.
+ + Fix to free saved RE structures when screens exit. This is a major
+ RE change, which fixed several bugs in the handling of saved/subst
+ RE's. It's likely to have added new bugs, however.
+ + Add case-independent searching (the searchci edit option).
+ + Add incremental search (the searchincr edit option).
+ + Home the cursor when executing ex commands from vi.
+1.59 -> 1.60 (03/29/96)
+ + Fix ":w >>" core dump, make that command match historic practice.
+ + Fix autoindent bug where the length of the line was incorrectly
+ calculated.
+ + Fix cursor bug where cursor could end up at the wrong place if the
+ movement keys were entered quickly enough.
+ + Change the read/write whirling indicator to appear only every 1/4
+ second, clean up the appearance.
+ + Don't change the options real values until underlying functions
+ have returned OK -- fix "set tabstop=0" core dump.
+ + Fix resizing on Sun's: use SA_INTERRUPT to interrupt read calls.
+ + Fix two forward mark command bugs: one where it wasn't setting the
+ "favorite cursor" position because of the refresh optimization,
+ and one where it didn't have VM_RCM_SET set in the command flags
+ for some reason.
+ + Fix a bug were the 's' command on top of a <tab> didn't correctly
+ copy the buffer.
+ + Make :exusage command work for commands having optional leading
+ capital letters, e.g. Next.
+ + Previous changes broke the inital-matching-prefix code in the key
+ mapping part of v_event_get -- fix it, and fix the infinite macro
+ interrupt code at the same time.
+ + Add "cedit" edit option, so colon command-line editing is optional.
+ Change filec/cedit so that you can set them to the same character,
+ and they do cedit if in column 1, and filec otherwise.
+ + Fix "source of non-existent file" core dump.
+ + Fix bug where functions keys specified in startup information were
+ never resolved/activated.
+ + Fix v_txt bug where could infinitely loop if <escape> triggered an
+ abbreviation expansion.
+ + Move version string into VERSION file, out of ex_version.c
+1.58 -> 1.59
+ + Configuration changes, several minor bug fixes, including a few
+ core dumps. No functional changes.
+1.57 -> 1.58
+ + Fix the problem where colon command-line temporary files were
+ getting left in /tmp.
+ + Fix the configuration scripts to quit immediately if the Perl
+ or Tk/Tcl libraries are specified but not found.
+ + Several screen fixes -- the changes in 1.57 weren't as safe as
+ I thought. More specifically, the refresh-only-if-waiting change
+ caused a lot of problems. In general, fixing them should provide
+ even more speedup, but I'm nervous.
+ + Lots of changes in the configuration scripts, hopefully this is
+ just a first-round ordeal.
+ + Several other minor bug fixes.
+1.56 -> 1.57
+ + Add <esc> hook to colon commands, so you can edit colon commands.
+ + Add Perl5 interpreter.
+ + Change shell expansion code to fail if it doesn't read at least
+ one non-blank character from the shell. If the shell expansion
+ process fails, or if not at least one non-blank character, it
+ now displays an error message to the user.
+ + Rework the screen display so that it matches the historic vi screen
+ refreshes.
+ + Rework options processing: print/noprint are no longer cumulative,
+ provide more information to underlying edit options modules, move
+ O_MESG information into the screen specific code.
+ + Make file completion character settable.
+ + Rework terminal restart -- you can now use ":set term" to switch
+ terminal types. This cleaned up screen resizing considerably.
+ + Character display fix, display \177 as ^?, not in hex/octal.
+ + Tag search bug fix, don't repeat search if successful.
+ + Replace sys_siglist[] use with private sigmsg() routine.
+ + Fix core dump if illegal screenId specified to Tcl routine.
+ + Add get/set mark interface to Tcl Interpreter interface.
+ + Fix core dump if file expansion code stressed (re: filec edit option)
+ + Fix bug where filter commands in empty files couldn't find line 0.
+ + Switch to GNU autoconf 2.7 for configuration, delete nvi/PORT.
+ Many random portability fixes.
+1.55 -> 1.56 (11/26/95)
+ + Bug fix release -- generally available beta release.
+1.54 -> 1.55 (11/18/95)
+ + Bug fix release.
+ + Integrate Tcl interpreter.
+1.53 -> 1.54 (11/11/95)
+ + Bug fix release. A major change in reworking the ex commands, when
+ called from the colon command line, to match historic practice, and
+ permit them to be entered repeatedly after ex has trashed the screen.
+ + Use restartable endwin() from System V curses to implement screen
+ + suspend.
+1.52 -> 1.53 (10/29/95)
+ + Switch to using vendor's curses library for all ports.
+ + Back out the event driven version, leaving screen separation.
+ + User configuration of <escape> timeout (the escapetime edit option).
+ + Add Tcl/Tk screen support.
+ + Add file name completion (the filec edit option).
+ + Disallow access to outside applications (the secure edit option).
+1.51 -> 1.52 (7/26/95)
+ + Minor cleanups, snapshotted for SMI.
+1.50 -> 1.51 (7/05/95)
+ + Lots and lots of changes for event driven model, largely in moving
+ the boundary between the screen code and the editor up and down.
+ Private release for Rob Zimmermann @ Tartan and Bill Shannon @ SMI.
+1.49 -> 1.50 Fri Jun 9 13:56:17 1995
+ + Minor bug fixes for stability.
+ + Convert to an event driven model, with the usual Nachos Supreme
+ layering that results. This is a completely new version, nothing
+ done previously matters any more.
+1.48 -> 1.49 Wed Mar 8 10:42:17 1995
+ + Changes in 1.46 broke ^A processing.
+ + Add :previous to split screen commands.
+ + Lots o' random bug fixes -- passes purify testing again.
+1.47 -> 1.48 Thu Feb 9 18:13:29 1995
+ + Random bug fixes for 1.47.
+ + Move the FREF (file structure) list out of the screen and into
+ the global area.
+ + Change semantics to :E to more closely match :e -- ":E" joins
+ the current file, so ":E /tmp" is now the command to match the
+ historic ":split".
+1.46 -> 1.47 Wed Feb 8 19:43:41 1995
+ + All ex commands (including visual and excluding global and v)
+ are now supported inside ex global commands.
+ + Rework the append/change/insert commands to match historic
+ practice for text appended to the ex command line, and inside
+ of ex global commands.
+ + Restructure to make single-line screens work.
+ + Restructure to create curses independent screen routines.
+ + Restructure to permit Edit, Next, and Tag routines to create new
+ screens on the fly.
+ + Change hexadecimal output to be \x## instead of 0x##.
+ + Change ex commands run from vi to stay in vi mode for as long as
+ possible, i.e. until ex modifies the screen outside of the editor.
+1.45 -> 1.46 Tue Jan 24 10:22:27 1995
+ + Restructure to build as a library.
+1.44 -> 1.45 Thu Jan 12 21:33:06 1995
+ + Fix relative cursor motion to handle folded lines.
+ + Recompile the search pattern if applicable edit options change.
+ + Change +/-c command ordering to match historic practice.
+ + Rework autoindent code to always resolve preceeding <blank>
+ characters when a ^T or ^D are entered.
+ + Add the print/noprint edit options, so can now specify if
+ a character is printable.
+ + Change ex to run in canonical mode.
+ + Fix ex text input to support the number edit option.
+ + Vi text input fix for the R command to correctly restore
+ characters entered and then backspaced over.
+ + Several vi increment command fixes.
+1.43 -> 1.44
+ + Bug fix, vi was printing the last line number on the status line
+ at startup. Change to execute commands at first line set, i.e.
+ "vi -t tag -c cmd" executes cmd at the tag line, not EOF.
+1.42 -> 1.43 Sat Dec 3 13:11:32 1994
+ + Marks, SunOS signed comparison fix for 1.42.
+1.41 -> 1.42 Fri Dec 2 20:08:16 1994
+ + Make autowrite require the file not be read-only.
+ + Make the ex insert command work in empty files.
+ + Tab expansion is no longer limited to values < 20 (which matches
+ historical practice).
+ + Simplify (and fix limit detection for) the # command. It's no
+ longer possible to use the # command itself to repeat or modify
+ a previous # command, '.' is the only possibility.
+ + Lots more reworking of the ex addresses, putting ? and / into
+ the ex addressing code broke the world.
+ + Make the Put, Preserve and Print commands work (don't ask).
+ + Split stdout/stderr from shell expansions; stdout is expansion
+ text, stderr is entered on the message queue.
+1.40 -> 1.41 Fri Nov 18 16:13:52 1994
+ + Addition of a port for AUX 3.1
+ + Addition of a message catalog for Russian.
+ + Make vi ? and / commands be true ex addresses (historic practice).
+ + Display the date first in vi -r recovery list.
+1.39 -> 1.40 Mon Nov 14 10:46:56 1994
+ + Two bug fixes for 1.39; -r option and v_change core dump.
+1.38 -> 1.39 Sun Nov 13 18:04:08 1994
+ + Ex substitution with confirmation now matches historic practice
+ (except that it still runs in raw mode, not cooked).
+ + Nvi now clears the screen before painting, if repainting the
+ entire screen.
+ + Fix final cursor position for put command entering text in a
+ single line.
+ + Change to break error message lines on the last <blank> in the
+ line.
+ + Always center the current line when returning to a previously
+ edited file or moving to a tag line that's not visible on the
+ screen.
+ + Change write of the current file using an explicit name or % to
+ match the semantics of :w<CR>, not :w file<CR>.
+ + Add command aliases to vi, and remap 6 historic commands to their
+ historic counterparts: D->d$, Y->y_, S->c_, C->c$, A->$a, I->^i.
+ + Match option display to historic practice; if boolean or numeric
+ options changed to default values, not displayed by default.
+ Nvi treats string options the same way, vi always displayed any
+ string option that was changed.
+ + Added lock edit option, if not set, no file locking is done.
+ + Rework ex to permit any ex command in the EXINIT variable or
+ exrc startup files. This fixes the bug were `vi +100 file'
+ painted the screen and then moved to line 100 and repainted.
+ (Yanked to SCCS ID 9.1.)
+ + Bug fix: could report file modified more recently than it was
+ written, incorrectly.
+ + Search fix: historically, motions with deltas were not corrected
+ to the previous/next line based on the starting/stopping column.
+ + Addressing fixes: make trailing non-existent addresses work, change
+ % to be text substitution, not a unique address (to follow future
+ POSIX).
+1.37 -> 1.38 Mon Oct 24 12:51:58 1994
+ + Scrolling fix; ^B can move to nonexistent lines.
+ + Fix to vi mapped commands; <escape> characters while already in
+ command mode did not historically cause the mapped characters to
+ be flushed.
+ + Add the backup edit option, automatically version edit files.
+ + Make it possible to edit files that db can't read, i.e. edit a
+ temporary file, with the correct file name.
+ + Only anchor the last line of the file to the bottom line of the
+ screen if there's half or less of a screen between the target
+ line and the end of the file.
+ + Fix wrapmargin text allocation bug.
+ + Fix ex put command to work in any empty file.
+ + Fix global command to handle move's to line 0 correctly.
+ + Regularize the yank cursor motions, several bug fixes for historic
+ practice.
+ + Fix N and n, when used as a motion command for the ! command,
+ repeat the last bang command instead of prompting for a new
+ one.
+ + Timeout maps beginning with <escape> quickly, instead of based
+ on the keytime option.
+ + Bug fix for wraplen option, wasn't triggered for input commands.
+1.36 -> 1.37 Sun Oct 9 19:02:53 1994
+ + Change PORT directories to install patches before distribution.
+ + Fix ^A to set search direction and pattern for consistency.
+ + Fold the showdirty option into the showmode option.
+ + Ex addressing fix: change search offset and line arguments (e.g.
+ the copy command) to be ex addressing offsets, matching historic
+ practice.
+ + Ex addressing fix: support ^ as an offset/flag equivalent to -.
+ + Ex addressing fix: historically, any missing address defaulted to
+ dot, e.g. "4,,," was the same as ".,.".
+ + Ex addressing fix: historically, <blank> separated numbers were
+ additive, e.g. "3 5p" displayed line 8.
+ + Ex addressing fix: make ';' as a range delimiter match historic
+ practice.
+ + Change nvi to exit immediately if stdout isn't a terminal.
+ + Change alternate file name behavior to match historic practice,
+ make the :write command set the current file name.
+ + Text input fix; input keys from a map, with an associated count,
+ weren't historically affected by the wrapmargin value.
+ + Add wraplen option, same as wrapmargin, but from the left-hand
+ column, not the right.
+ + Make ex address .<number> be equivalent to .+<number>, i.e. the
+ '+' is understood; matches historic practice, and it's widely
+ documented for ed(1).
+ + Input mode ^V^J historically mapped into a single ^J.
+ + Minor catalog changes, fixes; don't use 's' to pluralize words.
+1.35 -> 1.36 Thu Sep 8 08:40:25 1994
+ + Don't overwrite user's maps with standard (termcap) mappings.
+ + Make \ escape kill and erase characters in vi text input mode.
+ + Fix ^D autoindent bug by resolving leading <blank>s at ^D.
+ + Rework abbreviation tests (again!) to match historic practice.
+ + Change ^D/^U default scrolling value to be based on window option
+ value, not screen lines, correct scrolling option value, both to
+ match historic practice. NOTE: System V does this differently!
+1.34 -> 1.35 Wed Aug 31 19:20:15 1994
+ + Add the historic -l option.
+ + Message catalogs.
+ + Display global messages at each flush, just in case some are there.
+ + Fix global substitute code, `\\' wasn't handled correctly.
+ + Fix abbreviation code to use <blank>s as the preceding character.
+ + Fix ruler to display logical column, not physical column.
+ + Block signals when user issues :preserve command, so no race caused
+ by SIGHUP/SIGTERM.
+1.33 -> 1.34 Wed Aug 17 14:37:32 1994 (PUBLICLY AVAILABLE VERSION)
+ + Back out sccsid string fix, it won't work on SunOS 4.1.
+1.32 -> 1.33 Wed Aug 17 09:31:41 1994 (PUBLICLY AVAILABLE VERSION)
+ + Get back 5K of data space for the sccsid strings.
+ + Fix bug where cG fix in version 1.31 broke cw cursor positioning
+ when the change command extended the line.
+ + Fix core dump in map/seq code if character larger than 7 bits.
+ + Block signals when manipulating the SCR chains.
+ + Fix memory allocation for machines with multiple pointer sizes.
+1.31 -> 1.32 Mon Aug 15 14:27:49 1994
+ + Turn off recno mmap call for Solaris 2.4/SunOS 5.4.
+1.30 -> 1.31 Sun Aug 14 13:13:35 1994
+ + Fix bug were cG on the last line of a file wasn't done in line mode,
+ and where the cursor wasn't positioned correctly after exiting text
+ insert mode.
+ + Add termcap workaround to make function keys greater than 9 work
+ correctly (or fail if old-style termcap support).
+ + Change ex/vi to not flush mapped keys on error -- this is historic
+ practice, and people depended on it.
+ + Rework vi parser so that no command including a mapped key ever
+ becomes the '.' command, matching historic practice.
+ + Make <escape> cancellation in the vi parser match POSIX 1003.2.
+ + Fix curses bug where standout string was written for each standout
+ character, and where standout mode was never exited explicitly.
+ Fix bugs in curses SF/sf and SR/sr scrolling, as seen on Sun and
+ x86 consoles.
+ + The v/global commands execute the print command by default.
+ + The number option historically applies to ex as well as vi.
+1.29 -> 1.30 Mon Aug 8 10:30:42 1994
+ + Make first read into a temporary set the file's name.
+ + Permit any key to continue scrolling or ex commands -- this
+ allows stacked colon commands, and matches historic practice.
+ + Don't output normal ! command commentary in ex silent mode.
+ + Allow +/- flags after substitute commands, make line (flag)
+ offsets from vi mode match historic practice.
+ + Return <eof> to ex immediately, even if preceded by spaces. Rework
+ ex parser to do erase the prompt instead of depending on the print
+ routines to do it. Minor fixes to the ex parser for display of
+ default and scrolling commands. MORE EX PARSER CHANGES.
+1.28 -> 1.29 Fri Aug 5 10:18:07 1994
+ + Make the abbreviated ex delete command work (:dele---###lll for
+ example, is historically legal.
+ + When autoprint fires, multiple flags may be set, use ex_print
+ directly instead of the stub routines.
+ + Change v/global commands to turn off autoprint while running.
+ + Minor changes to make the ! command display match historic output.
+ + Rework the ex parser to permit multiple command separators without
+ commands -- MAJOR CHANGE, likely to introduce all sorts of new bugs.
+ + Fix cd command to expand argument in the context of each element
+ of the cdpath option, make relative paths always relative to the
+ current directory.
+ + Rework write/quit cases for temporary files, so that user's don't
+ discard them accidentally.
+ + Check for window size changes when continuing after a suspend.
+ + Fix memory problem in svi_screen, used free'd memory.
+ + Change the ex change, insert, append commands to match historic
+ cursor positions if no data entered by the user.
+ + Change ex format flags (#, l, p) to affect future commands, not
+ just the current one, to match historic practice.
+ + Make the user's EOF character an additional scroll character in ex.
+ + Fix ex ^D scrolling to be the value of the scroll option, not half
+ the screen.
+ + Fix buffer execution to match historic practice -- bugs where the
+ '*' command didn't work, and @<carriage-return> didn't work.
+ + Fix doubled reporting of deleted lines in filters.
+ + Rework the % ` / ? ( ) N n { and ^A commands to always cut into
+ numeric buffers regardless of the location or length of the cut.
+ This matches historic practice.
+ + Fix the { command to check the current line if the cursor doesn't
+ start on the first character of the line.
+ + Do '!' expansion in the ex read command arguments, it's historic
+ practice. In addition, it sets the last '!' command.
+1.27 -> 1.28 Wed Jul 27 21:29:18 1994
+ + Add support for scrolling using the CS and SF/sf/SR/sr termcap
+ strings to the 4BSD curses.
+ + Rework of getkey() introduced a bug where command interrupt put
+ nvi into an infinite loop.
+ + Piping through a filter historically cut the replaced lines into
+ the default buffer, although not the numeric ones.
+ + Read of a filter and !! historically moved to the first nonblank
+ of the resulting cursor line (most of the time).
+ + Rework cursor motion flags, to support '!' as a motion command.
+1.26 -> 1.27 Tue Jul 26 10:27:58 1994
+ + Add the meta option, to specify characters the shell will expand.
+ + Fix the read command to match historic practice, the white space
+ and bang characters weren't getting parsed correctly.
+ + Change SIGALRM handler to save and restore errno.
+ + Change SunOS include/compat.h to include <vfork.h> so that the
+ ex/filter.c code works again.
+ + Don't put lines deleted by the ex delete command into the numeric
+ buffers, matching historic practice.
+ + Fix; if appending to a buffer, default buffer historically only
+ references the appended text, not the resulting text.
+ + Support multiple, semi-colon separated search strings, and 'z'
+ commands after search strings.
+ + Make previous context mark setting match historic practice (see
+ docs/internals/context).
+ + Fix the set command to permit whitespace between the option and
+ the question mark, fix question marks in general.
+ + Fix bug where ex error messages could be accidentally preceded
+ by a single space.
+ + Fix bug where curses reorganization could lose screen specific
+ mappings as soon as any screen exited.
+ + Fix bug in paragraph code where invalid macros could be matched.
+ Make paragraph motions stop at formfeed (^L) characters.
+ + Change 'c' to match historic practice, it cut text into numeric
+ buffers.
+1.25 -> 1.26 Tue Jul 19 17:46:24 1994
+ + Ignore SIGWINCH if the screen size is unchanged; SunOS systems
+ deliver one when a screen is uncovered.
+ + Fix: don't permit a command with a motion component to wrap due
+ to wrapscan and return to the original cursor position.
+ + Fix: ^E wasn't beeping when reaching the bottom of the file.
+ + Fix bg/fg bug where tmp file exiting caused a NULL dereference.
+ + Rework file locking code to use fcntl(2) explicitly.
+ + Fix bug in section code where invalid macros could be matched.
+ + Fix bug where line number reset by vi's Q command.
+ + Add explicit character mode designation to character mode buffers.
+ + Add <sys/ioctl.h> include to sex/sex_window.c, needed by NET/2
+ vintage systems.
+ + Change to always flush a character during suspend, 4BSD curses
+ has the optimization where it doesn't flush after a standend().
+ + Fix bug on OSF1 where <curses.h> changes the values of VERASE,
+ VKILL and VWERASE to incorrect ones.
+ + Fix bug where optarg used incorrectly in main.c.
+ + Block all signals when acting on a signal delivery.
+ + Fix recovery bug where RCV_EMAIL could fire even if there wasn't
+ a backing file; format recovery message.
+1.24 -> 1.25 Sun Jul 17 14:33:38 1994
+ + Stop allowing keyboard suspends (^Z) in insert mode, it's hard
+ to get autowrite correct, and it's not historic practice.
+ + Fix z^, z+ to match historic practice.
+ + Bug in message handling, "vi +35 non-existent_file" lost the
+ status message because the "+35" pushed onto the stack erased
+ it. For now, change so that messages aren't displayed if there
+ are keys waiting -- may need to add a "don't-erase" bit to the
+ character in the stack instead.
+ + Bug in svi_msgflush(), where error messages could come out in
+ normal video.
+1.23 -> 1.24 Sat Jul 16 18:30:18 1994
+ + Fix core dump in exf.c, where editing a non-existent file and
+ exiting could cause already free'd memory to be free'd.
+ + Clean up numerous memory errors, courtesy of Purify.
+ + Change process wait code to fail if wait fails, and not attempt
+ to interpret the wait return information.
+ + Open recovery and DB files for writing as well as reading, System
+ V (fcntl) won't let you acquire LOCK_EX locks otherwise.
+ + Fix substitute bug where could malloc 0 bytes (AIX breaks).
+ + Permit the mapping of <carriage-return>, it's historic practice.
+ + Historic vi didn't eat <blank> characters before the force
+ flag, match historic practice.
+ + Bug in ex argument parsing, corrected for literal characters
+ twice.
+ + Delete screen specific maps when the screen closes.
+ + Move to the first non-<blank> in the line on startup; historic
+ practice.
+ + Change the ex visual command to move directly to a line if no
+ trailing 'z' command.
+ + Fix "[[" and "]]" to match historic practice (yet again...).
+ + Fix "yb" and "y{" commands to update the cursor correctly.
+ + Change "~<motion>" to match the yank cursor movement semantics
+ exactly.
+ + Move all of the curses related code into sex/svi -- major rework,
+ but should help in future ports.
+ + Fix bug in split code caused by new file naming code, where would
+ drop core when a split screen exited.
+ + Change svi_ex_write to do character display translation, so that
+ messages with file names in them are displayed correctly.
+ + Display the file name on split screens instead of a divider line.
+ + Fix move bug, wasn't copying lines before putting them.
+ + Fix bug were :n dropped core if no arguments supplied.
+ + Don't quote characters in executed buffer: "ifoo<esc>" should leave
+ insert mode after the buffer is executed.
+ + Tagpop and tagpush should set the absolute mark in case only moving
+ within a file.
+ + Skip leading whitespace characters before tags and cursor word
+ searches.
+ + Fix bug in ex_global where re_conv() was allocating the temporary
+ buffer and not freeing it.
+1.22 -> 1.23: Wed Jun 29 19:22:33 1994
+ + New <sys/cdefs.h> required "inline" to change to "__inline"
+ + Fix System V curses code for new ^Z support.
+ + Fix off-by-one in the move code, avoid ":1,$mo$" with only one
+ line in the buffer.
+ + Line orientation of motion commands was remembered too long,
+ i.e. '.' command could be incorrectly marked as line oriented.
+ + Move file modification time into EXF, so it's shared across
+ split screens.
+ + Put the prev[ious] command back in, people complained.
+ + Random fixes to next/prev semantics changed in 1.22.
+ + Historically vi doesn't only move to the last address if there's
+ ANYTHING after the addresses, e.g. ":3" moves to line 3, ":3|"
+ prints line 3.
+1.21 -> 1.22: Mon Jun 27 11:01:41 1994
+ + Make the line between split screens inverse video again.
+ + Delete the prev[ious] command, it's not useful enough to keep.
+ + Rework :args/file name handling from scratch -- MAJOR CHANGE,
+ likely to introduce all sorts of new bugs.
+ + Fix RE bug where no subexpressions in the pattern but there were
+ subexpressions referenced in the replacement, e.g. "s/XXX/\1/g".
+ + Change recovery to not leave unmodified files around after a
+ crash, by using the owner 'x' bit on unmodified backup files.
+ MAJOR CHANGE, the system recovery script has to change!
+ + Change -r option to delete recovery.* files that reference non-
+ existent vi.* files.
+ + Rework recovery locking so that fcntl(2) locking will work.
+ + Fix append (upper-case) buffers, broken by cut fixes.
+ + Fix | to not set the absolute motion mark.
+ + Read $HOME/.exrc file on startup if the effective user ID is
+ root. This makes running vi while su(1)'d work correctly.
+ + Use the full pathname of the file as the recovery name, not
+ just the last component. Matches historic practice.
+ + Keep marks in empty files from being destroyed.
+ + Block all caught signals before calling the DB routines.
+ + Make the line change report match historic practice (yanked
+ lines were different than everything else).
+ + Add section on multiple screens to the reference manual.
+ + Display all messages at once, combine onto a single line if
+ possible. Delete the trailing period from all messages.
+1.20 -> 1.21: Thu May 19 12:21:58 1994
+ + Delete the -l flag from the recover mail.
+ + Send the user email if ex command :preserve executed, this matches
+ historic practice. Lots of changes to the preserve and recovery
+ code, change preserve to snapshot files (again, historic practice).
+ + Make buffers match historic practice: "add logically stores text
+ into buffer a, buffer 1, and the unnamed buffer.
+ + Print <tab> characters as ^I on the colon command line if the
+ list option set.
+ + Adjust ^F and ^B scroll values in the presence of split screens
+ and small windows.
+ + Break msg* routines out from util.c into msg.c, start thinking
+ about message catalogs.
+ + Add tildeop set option, based on stevie's option of the same name.
+ Changes the ~ command into "[count] ~ motion", i.e. ~ takes a
+ trailing motion.
+ + Chose NOT to match historic practice on cursor positioning after
+ consecutive undo commands on a single line; see vi/v_undo.c for
+ the comment.
+ + Add a one line cache so that multiple changes to the same line
+ are only counted once (e.g. "dl35p" changes one line, not 35).
+ + Rework signals some more. Block file sync signals in vi routines
+ that interface to DB, so can sync the files at interrupt time.
+ Write up all of the signal handling arguments, see signal.c.
+1.19 -> 1.20: Thu May 5 19:24:57 1994
+ + Return ^Z to synchronous handling. See the dicussion in signal.c
+ and svi_screen.c:svi_curses_init().
+ + Fix bug where line change report was wrong in util.c:msg_rpt().
+1.18 -> 1.19: Thu May 5 12:59:51 1994
+ + Block DSUSP so that ^Y isn't delivered at SIGTSTP.
+ + Fix bug -- put into an empty file leaves the cursor at 1,0,
+ not the first nonblank.
+ + Fix bug were number of lines reported for the 'P' command was
+ off-by-one.
+ + Fix bug were 0^D wasn't being handled correctly.
+ + Delete remnants of ^Z as a raw character.
+ + Fix bug where if a map was an entire colon command, it may never
+ have been displayed.
+ + Final cursor position fixes for the vi T and t commands.
+ + The ex :next command took an optional ex command as it's first
+ argument similar to the :edit commands. Match historic practice.
+1.17 -> 1.18: Wed May 4 13:57:10 1994
+ + Rework curses information in the PORT/Makefile's.
+ + Minor fixes to ^Z asynchronous code.
+1.16 -> 1.17: Wed May 4 11:15:56 1994
+ + Make ex comment handling match historic practice.
+ + Make ^Z work asynchronously, we can no longer use the SIGTSTP
+ handler in the curses library.
+1.15 -> 1.16: Mon May 2 19:42:07 1994
+ + Make the 'p' and 'P' commands support counts, i.e. "Y10p" works.
+ + Make characters that map to themselves as the first part of the
+ mapping work, it's historic practice.
+ + Fix bug where "s/./\& /" discarded the space in the replacement
+ string.
+ + Add support for up/down cursor arrows in text input mode, rework
+ left/right support to match industry practice.
+ + Fix bug were enough character remapping could corrupt memory.
+ + Delete O_REMAPMAX in favor of setting interrupts after N mapped
+ characters without a read, delete the map counter per character.
+ MAJOR CHANGE. All of the interrupt signal handling has been
+ reworked so that interrupts are always turned on instead of
+ being turned on periodically, when an interruptible operation is
+ pending.
+ + Fix bug where vi wait() was interrupted by the recovery alarm.
+ + Make +cmd's and initial commands execute with the current line
+ set to the last line of the file. This is historic practice.
+ + Change "lock failed" error message to a file status message.
+ It always fails over NFS, and making all NFS files readonly
+ isn't going to fly.
+ + Use the historic line number format, but check for overflow.
+ + Fix bug where vi command parser ignored buffers specified as
+ part of the motion command.
+ + Make [@*]buffer commands on character mode buffers match historic
+ practice.
+ + Fix bug where the cmap/chf entries of the tty structure weren't
+ being cleared when new characters were read.
+ + Fix bug where the default command motion flags were being set
+ when the command was a motion component.
+ + Fix wrapmargin bug; if appending characters, and wrapmargin breaks
+ the line, an additional space is eaten.
+1.14 -> 1.15: Fri Apr 29 07:44:57 1994
+ + Make the ex delete command work in any empty file.
+ + Fix bug where 't' command placed the cursor on the character
+ instead of to its left.
+ + ^D and ^U didn't set the scroll option value historically.
+ Note, this change means that any user set value (e.g. 15^D)
+ will be lost when splitting the screen, since the split code
+ now resets the scroll value regardless.
+ + Fix the ( command to set the absolute movement mark.
+ + Only use TIOCGWINSZ for window information if SIGWINCH signal
+ caught.
+ + Delete the -l flag, and make -r work for multiple arguments.
+ Add the ex "recover[!] file" command.
+ + Switch into ex terminal mode and use the sex routines when
+ append/change/insert called from vi mode.
+ + Make ^F and ^B match historic practice. This required a fairly
+ extensive rework of the svi scrolling code.
+ + Cursor positioning in H, M, L, G (first non-blank for 1G) wasn't
+ being done correctly. Delete the SETLFNB flag. H, M, and L stay
+ logical movements (SETNNB) and G always moves to the first nonblank.
+ + System V uses "lines" and "cols", not "li" and "co", change as
+ necessary. Check termcap function returns for errors.
+ + Fix `<character> command to do start/end of line correction,
+ and to set line mode if starting and stopping at column 0.
+ + Fix bug in delete code where dropped core if deleted in character
+ mode to an empty line. (Rework the delete code for efficiency.)
+ + Give up on SunOS 4.1.X, and use "cc" instead of /usr/5bin/cc.
+ + Protect ex_getline routine from interrupted system calls (if
+ possible, set SA_RESTART on SIGALRM, too).
+ + Fix leftright scrolling bug, when moving to a shorter line.
+ + Do validity checking on the copy, move, t command target line
+ numbers.
+ + Change for System V % pattern broke trailing flags for empty
+ replacement strings.
+ + Fix bug when RCM flags retained in the saved dot structure.
+ + Make the ex '=' command work for empty files.
+ + Fix bug where special_key array was being free'd (it's no longer
+ allocated).
+ + Matches cut in line mode only if the starting cursor is at or
+ before the first nonblank in its line, and the ending cursor is
+ at or after the last nonblank in its line.
+ + Add the :wn command, so you can write a file and switch to a new
+ file in one command.
+ + Allow only a single key as an argument to :viusage.
+ + New movement code broke filter/paragraph operations in empty
+ files ("!}date" in an empty file was dropping core).
+1.12 -> 1.14: Mon Apr 18 11:05:10 1994 (PUBLICLY AVAILABLE VERSION, 4.4BSD)
+ + Fix FILE structure leakage in the ex filter code.
+ + Rework suspend code for System V curses. Nvi has to do the
+ the work, there's no way to get curses to do it right.
+ + Revert SunOS 4.1.X ports to the distributed curses. There's
+ a bug in Sun's implementation that we can't live with.
+ + Quit immediately if row/column values are unreasonable.
+ + Fix the function keys to match vi historic behavior.
+ + Replace the echo/awk magic in the Makefile's with awk scripts.
+1.11 -> 1.12: Thu Apr 14 11:10:19 1994
+ + Fix bug where only the first vi key was checked for validity.
+ + Make 'R' continue to overwrite after a <carriage-return>.
+ + Only display the "no recovery" message once.
+ + Rework line backup code to restore the line to its previous
+ condition.
+ + Don't permit :q in a .exrc file or EXINIT variable.
+ + Fix wrapscan option bug where forward searches become backward
+ searches and do cursor correction accordingly.
+ + Change "dd" to move the cursor to the first non-blank on the line.
+ + Delete cursor attraction to the first non-blank, change non-blank
+ motions to set the most attractive cursor position instead.
+ + Fix 'r' substitute option to set the RE to the last RE, not the
+ last substitute RE.
+ + Fix 'c' and 'g' substitute options to always toggle, and fix
+ edcompatible option to not reset them.
+ + Display ex error messages in inverse video.
+ + Fix errorbells option to match historic practice.
+ + Delete fixed character display table in favor of table built based
+ on the current locale.
+ + Add ":set octal" option, that displays unknown characters as octal
+ values instead of the default hexadecimal.
+ + Make all command and text input modes interruptible.
+ + Fix ex input mode to display error messages immediately, instead
+ of waiting for the lines to be resolved.
+ + Fix bug where vi calling append could overwrite the command.
+ + Fix off-by-one in the ex print routine tab code.
+ + Fix incorrect ^D test in vi text input routines.
+ + Add autoindent support for ex text insert routines.
+ + Add System V substitute command replacement pattern semantics,
+ where '%' means the last replacement pattern.
+ + Fix bug that \ didn't escape newlines in ex commands.
+ + Regularize the names of special characters to CH_*.
+ + Change hex insert character from ^Vx<hex_char> to ^X<hex_char>
+ + Integrate System V style curses, so SunOS and Solaris ports can
+ use the native curses implementation.
+1.10 -> 1.11: Thu Mar 24 16:07:45 EST 1994 (PUBLICLY AVAILABLE VERSION)
+ + Change H, M, and L to set the absolute mark, historical practice.
+ + Fix bug in stepping through multiple tags files.
+ + Add "remapmax" option that turns off map counts so you can remap
+ infinitely. If it's off, term_key() can be interrupted from the
+ keyboard, which will cause the buffers to flush. I also dropped
+ the default max number of remaps to 50. (Only Dave Hitz's TM
+ macros and maze appear to go over that limit.)
+ + Change :mkexrc to not dump w{300,1200,9600}, lisp options.
+ + Fix backward search within a line bug.
+ + Change all the includes of "pathnames.h" to use <>'s so that the
+ PORT versions can use -I. to replace it with their own versions.
+ + Make reads and writes interruptible. Rework code that enters and
+ leaves ex for '!' and filter commands, rework all interrupt and
+ timer code.
+ + Fix core dump when user displayed option in .exrc file.
+ + Fix bug where writing empty files didn't update the saved
+ modification time.
+ + Fix bug where /pattern/ addressing was always a backward search.
+ + Fix bug triggered by autoindent of more than 32 characters, where
+ nvi wasn't checking the right TEXT length.
+ + Fix bug where joining only empty lines caused a core dump.
+1.09 -> 1.10: Sat Mar 19 15:40:29 EST 1994
+ + Fix "set all" core dump.
+1.08 -> 1.09: Sat Mar 19 10:11:14 EST 1994
+ + If the tag's file path is relative, and it doesn't exist, check
+ relative to the tag file location.
+ + Fix ~ command to free temporary buffer on error return.
+ + Create vi.ref, a first cut at a reference document for vi.
+ The manual page and the reference document only document the
+ set options, so far.
+ + Fix 1G bug not always going to the first non-blank.
+ + Upgrade PORT/regex to release alpha3.4, from Henry Spencer.
+ + Add MKS vi's "cdpath" option, supporting a cd search path.
+ + Handle if search as a motion was discarded, i.e. "d/<erase>".
+ + Change nvi to not create multiple recovery files if modifying
+ a recovered file.
+ + Decide to ignore that the cursor is before the '$' when inserting
+ in list mode. It's too hard to fix.
+1.07 -> 1.08: Wed Mar 16 07:37:36 EST 1994
+ + Leftright and big line scrolling fixes. This meant more changes
+ to the screen display code, so there may be new problems.
+ + Don't permit search-style addresses until a file has been read.
+ + "c[Ww]" command incorrectly handled the "in whitespace" case.
+ + Fix key space allocation bug triggered by cut/paste under SunOS.
+ + Ex move command got the final cursor position wrong.
+ + Delete "optimize option not implemented" message.
+ + Make the literal-next character turn off mapping for the next
+ character in text input mode.
+1.06 -> 1.07: Mon Mar 14 11:10:33 EST 1994
+ + The "wire down" change in 1.05 broke ex command parsing, there
+ wasn't a corresponding change to handle multiple K_VLNEXT chars.
+ + Fix final position for vi's 't' command.
+1.05 -> 1.06: Sun Mar 13 16:12:52 EST 1994
+ + Wire down ^D, ^H, ^W, and ^V, regardless of the user's termios
+ values.
+ + Add ^D as the ex scroll command.
+ + Support ^Q as a literal-next character.
+ + Rework abbreviations to be delimited by any !inword() character.
+ + Add options description to the manual page.
+ + Minor screen cache fix for svi_get.c.
+ + Rework beautify option support to match historical practice.
+ + Exit immediately if not reading from a tty and a command fails.
+ + Default the SunOS 4.* ports to the distributed curses, not SMI's.
+1.04 -> 1.05: Thu Mar 24 16:07:45 EST 1994
+ + Make cursor keys work in input mode.
+ + Rework screen column code in vi curses screen. MAJOR CHANGE --
+ after this, we'll be debugging curses screen presentation from
+ scratch.
+ + Explode include files in vi.h into the source files.
+1.03 -> 1.04: Sun Mar 6 14:14:16 EST 1994
+ + Make the ex move command keep the marks on the moved lines.
+ + Change resize semantics so you can set the screen size to a
+ specific value. A couple of screen fixes for the resize code.
+ + Fixes for foreground/background due to SIGWINCH.
+ + Complete rework of all of vi's cursor movements. The underlying
+ assumption in the old code was that the starting cursor position
+ was part of the range of lines cut or deleted. The command
+ "d[[" is an example where this isn't true. Change it so that all
+ motion component commands set the final cursor position separately
+ from the range, as it can't be done correctly later. This is a
+ MAJOR CHANGE -- after this change, we'll be debugging the cursor
+ positioning from scratch.
+ + Rewrite the B, b, E, e commands to use vi's getc() interface
+ instead of rolling their own.
+ + Add a second MARK structure, LMARK, which is the larger mark
+ needed by the logging and mark queue code. Everything else uses
+ the reworked MARK structure, which is simply a line/column pair.
+ + Rework cut/delete to not expect 1-past-the-end in the range, but
+ to act on text to the end of the range, inclusive.
+ + Sync on write's, to force NFS to flush.
+1.01 -> 1.03: Sun Jan 23 17:50:35 EST 1994 (PUBLICLY AVAILABLE VERSION)
+ + Tag stack fixes, was returning to the tag, not the position from
+ which the user tagged.
+ + Only use from the cursor to the end of the word in cursor word
+ searches and tags. (Matches historical vi behavior.)
+ + Fix delete-last-line bug when line number option set.
+ + Fix usage line for :split command.
+ + If O_NUMBER set, long input lines would eventually fail, the column
+ count for the second screen of long lines wasn't set correctly.
+ + Fix for [[ reaching SOF with a column longer than the first line.
+ + Fix for multiple error messages if no screen displayed.
+ + Fix :read to set alternate file name as in historical practice.
+ + Fix cut to rotate the numeric buffers if line mode flag set.
+1.00 -> 1.01: Wed Jan 12 13:37:18 EST 1994
+ + Don't put cut items into numeric buffers if cutting less than
+ parts of two lines.
+0.94 -> 1.00: Mon Jan 10 02:27:27 EST 1994
+ + Read-ahead not there; BSD tty driver problem, SunOS curses
+ problem.
+ + Global command could error if it deleted the last line of
+ the file.
+ + Change '.' to only apply to the 'u' if entered immediately
+ after the 'u' command. "1pu.u.u. is still broken, but I
+ expect that it's going to be sacrificed for multiple undo.
+ + If backward motion on a command, now move to the point; get
+ yank cursor positioning correct.
+ + Rework cut buffers to match historic practice -- yank/delete
+ numeric buffers redone sensibly, ignoring historic practice.
+0.92 -> 0.93: Mon Dec 20 19:52:14 EST 1993
+ + Christos Zoulas reimplemented the script windows using pty's,
+ which means that they now work reasonably. The down side of
+ this is that almost all ports other than 4.4BSD need to include
+ two new files, login_tty.c and pty.c from the PORT/clib directory.
+ I've added them to the Makefiles.
+ + All calloc/malloc/realloc functions now cast their pointers, for
+ SunOS -- there should be far fewer warning messages, during the
+ build. The remaining messages are where CHAR_T's meet char *'s,
+ i.e. where 8-bit clean meets strcmp.
+ + The user's argument list handling has been reworked so that there
+ is always a single consistent position for use by :next, :prev and
+ :rewind.
+ + All of the historical options are now at least accepted, although
+ not all of them are implemented. (Edcompatible, hardtabs, lisp,
+ optimize, redraw, and slowopen aren't implemented.)
+ + The RE's have been reworked so that matches of length 0 are handled
+ in the same way as vi used to handle them.
+ + Several more mapping fixes and ex parser addressing fixes.
diff --git a/usr.bin/vi/docs/ev b/contrib/nvi/docs/ev
index 144295a319f2..144295a319f2 100644
--- a/usr.bin/vi/docs/ev
+++ b/contrib/nvi/docs/ev
diff --git a/usr.bin/vi/docs/features b/contrib/nvi/docs/features
index d410722db5d6..51650f949efc 100644
--- a/usr.bin/vi/docs/features
+++ b/contrib/nvi/docs/features
@@ -1,30 +1,30 @@
-List of things that should be added at some point:
+List of things that should be added:
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-+ X11 interface.
-
-+ Message catalogs.
-
++ X11 (Tk, Motif, Xaw) interface.
++ Interpreted language (Perl, Scheme, Tcl/Rush, Python)
++ Additional ports: Windows, Windows NT, MSDOS
+ Forms editing package; use RE's to verify field contents.
-
-+ Internationalization, including wide character support.
-
-+ Make db, curses real libraries that we load against instead of
- compiling directly.
-
-+ Full editing capability on the : command line.
-
-+ Rob Pike's sam RE's.
-
-+ Filename completion. While on the subject of completion, it would be
- nice to have the completion mechanism found in tcsh version >= 6.03.
- For instance, the completion for the `:cd' command will be directories
- only. The completion for the `:set' command will be all options not
- set at that moment, and for `:set un' will be all options that are set
- at that moment. The completion for `:< count' will be the flags.
++ Internationalization, including wide character and multibyte support.
++ Support for single line window editing, including full editing
+ capability on the vi colon command line.
++ Rob Pike's sam style RE's.
++ Right-to-left and bottom to top text support.
++ Quitall command, to leave all windows. A ! will force the quit.
List of suggested features:
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
++ It would be nice to have the completion mechanism found in tcsh versions
+ >= 6.03. For instance, the completion for the `:cd' command will be
+ directories only. The completion for the `:set' command will be all
+ options not set at that moment, and for `:set un' will be all options
+ that are set at that moment. The completion for `:< count' will be the
+ flags.
+
++ Add an command-line option to initially split the screen based on the
+ number of file arguments, e.g., "nvi -a file1 file2" would initialize
+ a two edit-buffer display.
+
+ Add a "push" command that would push a file on the tags stack.
(Essentially make tags a special case of the stack, and make
the stack more general purpose.)
@@ -33,10 +33,6 @@ List of suggested features:
which allows interactive shell session, instead of just the current
:script.
-+ Add versioning based on a "set version" variable, that would
- create backup copies when the file was written back, i.e. the
- ":w" and autowrite's would copy the original.
-
+ Add tagging information to the man page so that users can display
the part of the man page that discusses the command in which they're
interested.
@@ -45,11 +41,6 @@ List of suggested features:
of the screen aren't filled except by accident, so that the text
you ask for is always concentrated in the center of the screen.
-+ Add "set searchdir" for a list of directories to look in for
- files to edit. The semantic is that ":e foo" is replaced with
- the file name that is found, so there's no confusion as to
- which file is written.
-
+ Change
:di[splay] tags -> :tags
:di[splay] screens -> :screens
diff --git a/contrib/nvi/docs/help b/contrib/nvi/docs/help
new file mode 100644
index 000000000000..81df84aa1353
--- /dev/null
+++ b/contrib/nvi/docs/help
@@ -0,0 +1,229 @@
+MOVING THE CURSOR:
+ k - cursor up ^F - page forward /<pattern><CR> - search forward
+ j - cursor down ^B - page backward ?<pattern><CR> - search backward
+ h - cursor left w - move forward a "word" n - repeat the last search
+ l - cursor right b - move backward a "word"
+
+ENTERING TEXT:
+a - append after the cursor. Use the <escape> key to return to
+i - insert before the cursor. command mode.
+o - open a new line below the cursor.
+O - open new line above the cursor.
+
+WRITING AND EXITING:
+:w<Enter> - write the file
+:q<Enter> - exit the file
+:q!<Enter> - exit without writing the file
+:#<Enter> - move to a line (e.g., :35<Enter> moves to line 35)
+
+MISCELLANEOUS:
+^G - display the file name
+ J - join two lines (use i<Enter><escape> to split a line)
+ u - undo the last change (enter . after a 'u' to undo more than one change)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+VI COMMANDS:
+ ^A search forward for cursor word
+ ^B scroll up by screens
+ ^C interrupt an operation (e.g. read, write, search)
+ ^D scroll down by half screens (setting count)
+ ^E scroll down by lines
+ ^F scroll down by screens
+ ^G file status
+ ^H move left by characters
+ ^J move down by lines
+ ^L redraw screen
+ ^M move down by lines (to first non-blank)
+ ^N move down by lines
+ ^P move up by lines
+ ^R redraw screen
+ ^T tag pop
+ ^U half page up (set count)
+ ^V input a literal character
+ ^W move to next screen
+ ^Y page up by lines
+ ^Z suspend editor
+ ^[ <escape> exit input mode, cancel partial commands
+ ^\ switch to ex mode
+ ^] tag push cursor word
+ ^^ switch to previous file
+ <space> move right by columns
+ ! filter through command(s) to motion
+ # number increment/decrement
+ $ move to last column
+ % move to match
+ & repeat substitution
+ ' move to mark (to first non-blank)
+ ( move back sentence
+ ) move forward sentence
+ + move down by lines (to first non-blank)
+ , reverse last F, f, T or t search
+ - move up by lines (to first non-blank)
+ . repeat the last command
+ / search forward
+ 0 move to first character
+ : ex command
+ ; repeat last F, f, T or t search
+ < shift lines left to motion
+ > shift lines right to motion
+ ? search backward
+ @ execute buffer
+ A append to the line
+ B move back bigword
+ C change to end-of-line
+ D delete to end-of-line
+ E move to end of bigword
+ F character in line backward search
+ G move to line
+ H move to count lines from screen top
+ I insert before first nonblank
+ J join lines
+ L move to screen bottom
+ M move to screen middle
+ N reverse last search
+ O insert above line
+ P insert before cursor from buffer
+ Q switch to ex mode
+ R replace characters
+ S substitute for the line(s)
+ T before character in line backward search
+ U Restore the current line
+ W move to next bigword
+ X delete character before cursor
+ Y copy line
+ ZZ save file and exit
+ [[ move back section
+ ]] move forward section
+ ^ move to first non-blank
+ _ move to first non-blank
+ ` move to mark
+ a append after cursor
+ b move back word
+ c change to motion
+ d delete to motion
+ e move to end of word
+ f character in line forward search
+ h move left by columns
+ i insert before cursor
+ j move down by lines
+ k move up by lines
+ l move right by columns
+ m set mark
+ n repeat last search
+ o append after line
+ p insert after cursor from buffer
+ r replace character
+ s substitute character
+ t before character in line forward search
+ u undo last change
+ w move to next word
+ x delete character
+ y copy text to motion into a cut buffer
+ z reposition the screen
+ { move back paragraph
+ | move to column
+ } move forward paragraph
+ ~ reverse case
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+EX COMMANDS:
+ ^D: scroll lines
+ !: filter lines through commands or run commands
+ #: display numbered lines
+ &: repeat the last subsitution
+ *: execute a buffer
+ <: shift lines left
+ =: display line number
+ >: shift lines right
+ @: execute a buffer
+ append: append input to a line
+ abbreviate: specify an input abbreviation
+ args: display file argument list
+ bg: background the current screen
+ change: change lines to input
+ cd: change the current directory
+ chdir: change the current directory
+ copy: copy lines elsewhere in the file
+ cscope: create a set of tags using a cscope command
+ delete: delete lines from the file
+ display: display buffers, screens or tags
+ [Ee]dit: begin editing another file
+ [Ee]x: begin editing another file
+ exusage: display ex command usage statement
+ file: display (and optionally set) file name
+ fg: switch the current screen and a backgrounded screen
+ global: execute a global command on lines matching an RE
+ help: display help statement
+ insert: insert input before a line
+ join: join lines into a single line
+ k: mark a line position
+ list: display lines in an unambiguous form
+ move: move lines elsewhere in the file
+ mark: mark a line position
+ map: map input or commands to one or more keys
+ mkexrc: write a .exrc file
+ [Nn]ext: edit (and optionally specify) the next file
+ number: change display to number lines
+ open: enter "open" mode (not implemented)
+ print: display lines
+ perl: run the perl interpreter with the command
+ perldo: run the perl interpreter with the command, on each line
+ preserve: preserve an edit session for recovery
+ [Pp]revious: edit the previous file in the file argument list
+ put: append a cut buffer to the line
+ quit: exit ex/vi
+ read: append input from a command or file to the line
+ recover: recover a saved file
+ resize: grow or shrink the current screen
+ rewind: re-edit all the files in the file argument list
+ s: substitute on lines matching an RE
+ script: run a shell in a screen
+ set: set options (use ":set all" to see all options)
+ shell: suspend editing and run a shell
+ source: read a file of ex commands
+ stop: suspend the edit session
+ suspend: suspend the edit session
+ t: copy lines elsewhere in the file
+ [Tt]ag: edit the file containing the tag
+ tagnext: move to the next tag
+ tagpop: return to the previous group of tags
+ tagprev: move to the previous tag
+ tagtop: discard all tags
+ tcl: run the tcl interpreter with the command
+ undo: undo the most recent change
+unabbreviate: delete an abbreviation
+ unmap: delete an input or command map
+ v: execute a global command on lines NOT matching an RE
+ version: display the program version information
+ visual: enter visual (vi) mode from ex mode
+ [Vv]isual: edit another file (from vi mode only)
+ viusage: display vi key usage statement
+ write: write the file
+ wn: write the file and switch to the next file
+ wq: write the file and exit
+ xit: exit
+ yank: copy lines to a cut buffer
+ z: display different screens of the file
+ ~: replace previous RE with previous replacement string,
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Edit options:
+noaltwerase filec="" nomodeline scroll=17 notildeop
+autoindent flash msgcat="./" nosearchincr timeout
+autoprint hardtabs=0 noprint="" nosecure nottywerase
+noautowrite noiclower nonumber shiftwidth=8 noverbose
+backup="" noignorecase nooctal noshowmatch warn
+nobeautify keytime=6 open noshowmode window=35
+cedit="" noleftright optimize sidescroll=16 nowindowname
+columns=80 lines=36 print="" noslowopen wraplen=0
+comment nolisp prompt nosourceany wrapmargin=0
+noedcompatible nolist readonly tabstop=8 wrapscan
+escapetime=1 lock noredraw taglength=0 nowriteany
+noerrorbells magic remap tags="tags"
+exrc matchtime=7 report=5 term="xterm"
+noextended mesg ruler noterse
+cdpath="/usr/src/local/nvi:/tmp"
+directory="/tmp"
+paragraphs="IPLPPPQPP LIpplpipbp"
+recdir="/var/tmp/vi.recover"
+sections="NHSHH HUnhsh"
+shell="/bin/csh"
+shellmeta="~{[*?$`'"\"
diff --git a/usr.bin/vi/docs/internals/autowrite b/contrib/nvi/docs/internals/autowrite
index 55cd13b8f72e..dbad6c8bae8a 100644
--- a/usr.bin/vi/docs/internals/autowrite
+++ b/contrib/nvi/docs/internals/autowrite
@@ -1,4 +1,4 @@
-# @(#)autowrite 8.2 (Berkeley) 9/28/93
+# @(#)autowrite 8.3 (Berkeley) 2/17/95
Vi autowrite behavior, the fields with *'s are "don't cares".
@@ -13,9 +13,9 @@ Command File Autowrite? Action:
^Z N * Suspend.
# This behavior is NOT identical to :edit.
-^ Y Y Write file and jump.
-^ Y N Error.
-^ N * Jump.
+^^ Y Y Write file and jump.
+^^ Y N Error.
+^^ N * Jump.
# The new nvi command ^T (:tagpop) behaves identically to ^].
# This behavior is identical to :tag, :tagpop, and :tagpush with
diff --git a/usr.bin/vi/docs/internals/context b/contrib/nvi/docs/internals/context
index 139a1c3fdb41..8b1db32768b7 100644
--- a/usr.bin/vi/docs/internals/context
+++ b/contrib/nvi/docs/internals/context
@@ -1,4 +1,4 @@
-# @(#)context 8.5 (Berkeley) 7/23/94
+# @(#)context 8.6 (Berkeley) 10/14/94
In historic vi, the previous context mark was always set:
@@ -6,7 +6,7 @@ ex address:
any number, <question-mark>, <slash>, <dollar-sign>,
<single-quote>, <backslash>
-ex commands: undo, "z.", global, vglobal
+ex commands: undo, "z.", global, v
vi commands: (, ), {, }, %, [[, ]], ^]
diff --git a/contrib/nvi/docs/internals/cscope.NOTES b/contrib/nvi/docs/internals/cscope.NOTES
new file mode 100644
index 000000000000..e0e3483d26ed
--- /dev/null
+++ b/contrib/nvi/docs/internals/cscope.NOTES
@@ -0,0 +1,142 @@
+Cscope Notes:
+
+The nvi tags structure has been reworked to handle the notion of multiple
+locations per tag. This supports cscope, which returns multiple locations
+per query. It will hopefully support ctags programs that create databases
+with multiple locations per tag as well.
+
+There is now a list of "tag queues" chained from each screen. Each tag
+queue has one or more "tag locations".
+
+ +----+ +----+ +----+ +----+
+ | EP | -> | Q1 | <-- | T1 | <-- | T2 |
+ +----+ +----+ --> +----+ --> +----+
+ |
+ +----+ +----+
+ | Q2 | <-- | T1 |
+ +----+ --> +----+
+ |
+ +----+ +----+
+ | Q3 | <-- | T1 |
+ +----+ --> +----+
+
+In the above diagram, each "Q" is a "tag queue", and each "T" is a
+tag location. Generally, the commands:
+
+ :tag create a new Q
+ ^[ create a new Q
+ :cscope find create a new Q
+ :tagnext move to the next T
+ :tagprev move to the previous T
+ :tagpop discard one or more Q's
+ ^T discard the most recent Q
+ :tagtop discard all Q's
+
+More specifically:
+
+:cs[cope] a[dd] cscope-dir
+
+ Attach to the cscope database in cscope-dir.
+
+:cs[cope] f[ind] c|d|e|f|g|i|s|t buffer|pattern
+
+ Query all attached cscopes for the pattern. The pattern is a
+ regular expression. If the pattern is a double-quote character
+ followed by a valid buffer name (e.g., "t), then the contents
+ of the named buffer are used as the pattern.
+
+ c: find callers of name
+ d: find all function calls made from name
+ e: find pattern
+ f: find files with name as substring
+ g: find definition of name
+ i: find files #including name
+ s: find all uses of name
+ t: find assignments to name
+
+ The find command pushes the current location onto the tags stack,
+ and switches to the first location resulting from the query, if
+ the query returned at least one result.
+
+:cs[cope] h[elp] [command]
+
+ List the cscope commands, or usage help on one command.
+
+:display c[onnections]
+
+ Display the list of cscope connections
+
+:display t[ags]
+
+ The tags display has been enhanced to display multiple tag
+ locations per tag query.
+
+:cs[cope] k[ill] #
+
+ Kill cscope connection number #.
+
+:cs[cope] r[eset]
+ Kill all attached cscopes. Useful if one got hung but you don't
+ know which one.
+
+:tagn[ext][!]
+
+ Move to the next tag resulting from a query.
+
+:tagpr[ev][!]
+
+ Return to the previous tag resulting from a query.
+
+:tagp[op], ^T
+
+ Return to the previous tag group (no change).
+
+:tagt[op]
+
+ Discard all tag groups (no change).
+
+Suggested maps:
+
+ " ^N: move to the next tag
+ map ^N :tagnext^M
+ " ^P: move to the previous tag
+ map ^P :tagprev^M
+
+ " Tab+letter performs a C-Scope query on the current word.
+ " C-Scope 12.9 has a text-string query (type t).
+ " C-Scope 13.3 replaces it with an assignment query; hence a==t.
+ map <tab>a "tye:csc find t"t
+ map <tab>c "tye:csc find c"t
+ map <tab>d "tye:csc find d"t
+ map <tab>e "tye:csc find e"t
+ map <tab>f "tye:csc find f"t
+ map <tab>g "tye:csc find g"t
+ map <tab>i "tye:csc find i"t
+ map <tab>s "tye:csc find s"t
+ map <tab>t "tye:csc find t"t
+
+To start nvi with an initial set of cscope directories, use the environment
+variable CSCOPE_DIRS. This variable should contain a <blank>-separated
+list of directories containing cscope databases. (This MAY be changed to
+be an edit option, I haven't really decided, yet.)
+
+Each cscope directory must contain a file named "cscope.out" which is the
+main cscope database, or nvi will not attempt to connect to a cscope to
+handle requests for that database.
+
+The file "cscope.tpath" may contain a colon-separated directory search
+path which will be used to find the files reported by cscope. If this
+cscope.tpath does not exist, then the paths are assumed to be relative to
+the cscope directory itself. This is an extension to the standard cscope,
+but seems important enough to keep.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Cscope Availability:
+
+UNIXWare System V Release 4.0 variants such as Sun Solaris 2.x
+(/opt/SUNWspro/bin) have version 11.5, and UNIXWare System V
+Release 4.1 has version 12.10 with an option for much faster
+searching.
+
+You can buy version 13.3 source with an unrestricted license
+for $400 from AT&T Software Solutions by calling +1-800-462-8146.
diff --git a/usr.bin/vi/docs/internals/gdb.script b/contrib/nvi/docs/internals/gdb.script
index 5f180edcd642..a1122343c162 100644
--- a/usr.bin/vi/docs/internals/gdb.script
+++ b/contrib/nvi/docs/internals/gdb.script
@@ -1,12 +1,13 @@
-# @(#)gdb.script 8.2 (Berkeley) 9/29/93
+# @(#)gdb.script 8.5 (Berkeley) 5/4/96
-# display the SVI screen map
+# display the VI screen map
# usage dmap(sp)
define dmap
- set $h = ((SVI_PRIVATE *)$arg0->svi_private)->h_smap
- set $t = ((SVI_PRIVATE *)$arg0->svi_private)->t_smap
+ set $h = ((VI_PRIVATE *)$arg0->vi_private)->h_smap
+ set $t = ((VI_PRIVATE *)$arg0->vi_private)->t_smap
while ($h <= $t)
- printf "lno: %d; off %d ", (int)$h->lno, (int)$h->off
+ printf "lno: %2d; soff %d coff %d ", \
+ (int)$h->lno, (int)$h->soff, (int)$h->coff
if ($h->c_ecsize == 0)
printf "flushed\n"
else
@@ -20,12 +21,13 @@ define dmap
end
end
-# display the tail of the SVI screen map
+# display the tail of the VI screen map
define tmap
- set $h = ((SVI_PRIVATE *)$arg0->svi_private)->h_smap
- set $t = ((SVI_PRIVATE *)$arg0->svi_private)->t_smap
+ set $h = ((VI_PRIVATE *)$arg0->vi_private)->h_smap
+ set $t = ((VI_PRIVATE *)$arg0->vi_private)->t_smap
while ($t >= $h)
- printf "lno: %d; off %d ", (int)$t->lno, (int)$t->off
+ printf "lno: %2d; soff %d coff %d ", \
+ (int)$t->lno, (int)$t->soff, (int)$t->coff
if ($t->c_ecsize == 0)
printf "flushed\n"
else
@@ -39,9 +41,15 @@ define tmap
end
end
-# display the SVI private structure
-define svp
- print *((SVI_PRIVATE *)sp->svi_private)
+# display the private structures
+define clp
+ print *((CL_PRIVATE *)sp->gp->cl_private)
+end
+define vip
+ print *((VI_PRIVATE *)sp->vi_private)
+end
+define exp
+ print *((EX_PRIVATE *)sp->ex_private)
end
# display the marks
diff --git a/usr.bin/vi/docs/internals/input b/contrib/nvi/docs/internals/input
index 9a7506ee2337..9a7506ee2337 100644
--- a/usr.bin/vi/docs/internals/input
+++ b/contrib/nvi/docs/internals/input
diff --git a/contrib/nvi/docs/internals/openmode b/contrib/nvi/docs/internals/openmode
new file mode 100644
index 000000000000..c64b76774b3e
--- /dev/null
+++ b/contrib/nvi/docs/internals/openmode
@@ -0,0 +1,36 @@
+ @(#)openmode 8.1 (Berkeley) 10/29/94
+
+Open mode has the following special behaviors:
+
+z, ^F, ^B:
+ If count is not specified, it shall default to the window
+ edit option - 2.
+
+ Write lines from the edit buffer starting at:
+
+ (the current line) - ((count - 2) / 2)
+
+ until:
+
+ (((count + 1) / 2) * 2) - 1
+
+ lines, or the last line in the edit buffer has been written. A
+ line consisting of the smaller of the number of columns in the
+ display divided by two or 40 ``-'' characters shall be written
+ immediately before and after the specified is written. These two
+ lines shall count against the total number of lines to be written.
+ A blank line shall be written after the last line is written.
+
+ z, ^F and ^B all behave identically.
+
+^D: Display the next scroll value lines, change the current line.
+
+^U: Change the current line, do nothing else.
+
+^E, ^Y: Do nothing.
+
+^L: Clear the screen and redisplay the current line.
+
+H, L, M:
+ Move to the first nonblank of the current line and do nothing
+ else.
diff --git a/contrib/nvi/docs/internals/quoting b/contrib/nvi/docs/internals/quoting
new file mode 100644
index 000000000000..a5fb8926a33c
--- /dev/null
+++ b/contrib/nvi/docs/internals/quoting
@@ -0,0 +1,208 @@
+# @(#)quoting 5.5 (Berkeley) 11/12/94
+
+QUOTING IN EX/VI:
+
+There are four escape characters in historic ex/vi:
+
+ \ (backslashes)
+ ^V
+ ^Q (assuming it wasn't used for IXON/IXOFF)
+ The terminal literal next character.
+
+Vi did not use the lnext character, it always used ^V (or ^Q).
+^V and ^Q were equivalent in all cases for vi.
+
+There are four different areas in ex/vi where escaping characters
+is interesting:
+
+ 1: In vi text input mode.
+ 2: In vi command mode.
+ 3: In ex command and text input modes.
+ 4: In the ex commands themselves.
+
+1: Vi text input mode (a, i, o, :colon commands, etc.):
+
+ The set of characters that users might want to escape are as follows.
+ As ^L and ^Z were not special in input mode, they are not listed.
+
+ carriage return (^M)
+ escape (^[)
+ autoindents (^D, 0, ^, ^T)
+ erase (^H)
+ word erase (^W)
+ line erase (^U)
+ newline (^J) (not historic practice)
+
+ Historic practice was that ^V was the only way to escape any
+ of these characters, and that whatever character followed
+ the ^V was taken literally, e.g. ^V^V is a single ^V. I
+ don't see any strong reason to make it possible to escape
+ ^J, so I'm going to leave that alone.
+
+ One comment regarding the autoindent characters. In historic
+ vi, if you entered "^V0^D" autoindent erasure was still
+ triggered, although it wasn't if you entered "0^V^D". In
+ nvi, if you escape either character, autoindent erasure is
+ not triggered.
+
+ Abbreviations were not performed if the non-word character
+ that triggered the abbreviation was escaped by a ^V. Input
+ maps were not triggered if any part of the map was escaped
+ by a ^V.
+
+ The historic vi implementation for the 'r' command requires
+ two leading ^V's to replace a character with a literal
+ character. This is obviously a bug, and should be fixed.
+
+2: Vi command mode
+
+ Command maps were not triggered if the second or later
+ character of a map was escaped by a ^V.
+
+ The obvious extension is that ^V should keep the next command
+ character from being mapped, so you can do ":map x xxx" and
+ then enter ^Vx to delete a single character.
+
+3: Ex command and text input modes.
+
+ As ex ran in canonical mode, there was little work that it
+ needed to do for quoting. The notable differences between
+ ex and vi are that it was possible to escape a <newline> in
+ the ex command and text input modes, and ex used the "literal
+ next" character, not control-V/control-Q.
+
+4: The ex commands:
+
+ Ex commands are delimited by '|' or newline characters.
+ Within the commands, whitespace characters delimit the
+ arguments. Backslash will generally escape any following
+ character. In the abbreviate, unabbreviate, map and unmap
+ commands, control-V escapes the next character, instead.
+
+ This is historic behavior in vi, although there are special
+ cases where it's impossible to escape a character, generally
+ a whitespace character.
+
+ Escaping characters in file names in ex commands:
+
+ :cd [directory] (directory)
+ :chdir [directory] (directory)
+ :edit [+cmd] [file] (file)
+ :ex [+cmd] [file] (file)
+ :file [file] (file)
+ :next [file ...] (file ...)
+ :read [!cmd | file] (file)
+ :source [file] (file)
+ :write [!cmd | file] (file)
+ :wq [file] (file)
+ :xit [file] (file)
+
+ Since file names are also subject to word expansion, the
+ underlying shell had better be doing the correct backslash
+ escaping. This is NOT historic behavior in vi, making it
+ impossible to insert a whitespace, newline or carriage return
+ character into a file name.
+
+4: Escaping characters in non-file arguments in ex commands:
+
+ :abbreviate word string (word, string)
+* :edit [+cmd] [file] (+cmd)
+* :ex [+cmd] [file] (+cmd)
+ :map word string (word, string)
+* :set [option ...] (option)
+* :tag string (string)
+ :unabbreviate word (word)
+ :unmap word (word)
+
+ These commands use whitespace to delimit their arguments, and use
+ ^V to escape those characters. The exceptions are starred in the
+ above list, and are discussed below.
+
+ In general, I intend to treat a ^V in any argument, followed by
+ any character, as that literal character. This will permit
+ editing of files name "foo|", for example, by using the string
+ "foo\^V|", where the literal next character protects the pipe
+ from the ex command parser and the backslash protects it from the
+ shell expansion.
+
+ This is backward compatible with historical vi, although there
+ were a number of special cases where vi wasn't consistent.
+
+4.1: The edit/ex commands:
+
+ The edit/ex commands are a special case because | symbols may
+ occur in the "+cmd" field, for example:
+
+ :edit +10|s/abc/ABC/ file.c
+
+ In addition, the edit and ex commands have historically
+ ignored literal next characters in the +cmd string, so that
+ the following command won't work.
+
+ :edit +10|s/X/^V / file.c
+
+ I intend to handle the literal next character in edit/ex consistently
+ with how it is handled in other commands.
+
+ More fun facts to know and tell:
+ The acid test for the ex/edit commands:
+
+ date > file1; date > file2
+ vi
+ :edit +1|s/./XXX/|w file1| e file2|1 | s/./XXX/|wq
+
+ No version of vi, of which I'm aware, handles it.
+
+4.2: The set command:
+
+ The set command treats ^V's as literal characters, so the
+ following command won't work. Backslashes do work in this
+ case, though, so the second version of the command does work.
+
+ set tags=tags_file1^V tags_file2
+ set tags=tags_file1\ tags_file2
+
+ I intend to continue permitting backslashes in set commands,
+ but to also permit literal next characters to work as well.
+ This is backward compatible, but will also make set
+ consistent with the other commands. I think it's unlikely
+ to break any historic .exrc's, given that there are probably
+ very few files with ^V's in their name.
+
+4.3: The tag command:
+
+ The tag command ignores ^V's and backslashes; there's no way to
+ get a space into a tag name.
+
+ I think this is a don't care, and I don't intend to fix it.
+
+5: Regular expressions:
+
+ :global /pattern/ command
+ :substitute /pattern/replace/
+ :vglobal /pattern/ command
+
+ I intend to treat a backslash in the pattern, followed by the
+ delimiter character or a backslash, as that literal character.
+
+ This is historic behavior in vi. It would get rid of a fairly
+ hard-to-explain special case if we could just use the character
+ immediately following the backslash in all cases, or, if we
+ changed nvi to permit using the literal next character as a
+ pattern escape character, but that would probably break historic
+ scripts.
+
+ There is an additional escaping issue for regular expressions.
+ Within the pattern and replacement, the '|' character did not
+ delimit ex commands. For example, the following is legal.
+
+ :substitute /|/PIPE/|s/P/XXX/
+
+ This is a special case that I will support.
+
+6: Ending anything with an escape character:
+
+ In all of the above rules, an escape character (either ^V or a
+ backslash) at the end of an argument or file name is not handled
+ specially, but used as a literal character.
+
diff --git a/contrib/nvi/docs/internals/structures b/contrib/nvi/docs/internals/structures
new file mode 100644
index 000000000000..a25c780c8e63
--- /dev/null
+++ b/contrib/nvi/docs/internals/structures
@@ -0,0 +1,68 @@
+# @(#)structures 5.4 (Berkeley) 10/4/95
+
+There are three major data structures in this package, plus a single data
+structure per screen type. The first is a single global structure (GS)
+which contains information common to all files and screens. It hold
+global things like the input key queues, and functions as a single place
+to hang things. For example, interrupt routines have to be able to find
+screen structures, and they can only do this if they have a starting
+point. The number of globals in nvi is dependent on the screen type, but
+every screen type will have at least one global, __global_list, which
+references the GS structure.
+
+The GS structure contains linked lists of screen (SCR) structures.
+Each SCR structure normally references a file (EXF) structure.
+
+The GS structure has a set of functions which update the screen and/or
+return information about the screen from the underlying screen package.
+The GS structure never goes away. The SCR structure persists over
+instances of screens, and the EXF structure persists over references to
+files.
+
+File names have different properties than files themselves, so the name
+information for a file is held in an FREF structure which is chained from
+the SCR structure.
+
+In general, functions are always passed an SCR structure, which usually
+references an underlying EXF structure. The SCR structure is necessary
+for any routine that wishes to talk to the screen, the EXF structure is
+necessary for any routine that wants to modify the file. The relationship
+between an SCR structure and its underlying EXF structure is not fixed,
+and various ex commands will substitute a new EXF in place of the current
+one, and there's no way to detect this.
+
+The naming of the structures is consistent across the program. (Macros
+even depend on it, so don't try and change it!) The global structure is
+"gp", the screen structure is "sp", and the file structure is "ep".
+
+A few other data structures:
+
+TEXT In nvi/cut.h. This structure describes a portion of a line,
+ and is used by the input routines and as the "line" part of a
+ cut buffer.
+
+CB In nvi/cut.h. A cut buffer. A cut buffer is a place to
+ hang a list of TEXT structures.
+
+CL The curses screen private data structure. Everything to
+ do standalone curses screens.
+
+MARK In nvi/mark.h. A cursor position, consisting of a line number
+ and a column number.
+
+MSG In nvi/msg.h. A chain of messages for the user.
+
+SEQ In nvi/seq.h. An abbreviation or a map entry.
+
+TK The Tcl/Tk screen private data structure. Everything to
+ do standalone Tcl/Tk screens.
+
+EXCMD In nvi/ex/ex.h. The structure that gets passed around to the
+ functions that implement the ex commands. (The main ex command
+ loop (see nvi/ex/ex.c) builds this up and then passes it to the
+ ex functions.)
+
+VICMD In nvi/vi/vi.h. The structure that gets passed around to the
+ functions that implement the vi commands. (The main vi command
+ loop (see nvi/vi/vi.c) builds this up and then passes it to the
+ vi functions.)
diff --git a/contrib/nvi/docs/interp/interp b/contrib/nvi/docs/interp/interp
new file mode 100644
index 000000000000..3da5a8f656dc
--- /dev/null
+++ b/contrib/nvi/docs/interp/interp
@@ -0,0 +1,190 @@
+# @(#)interp 8.5 (Berkeley) 10/19/96
+ Nvi Interpreter API
+
+Introduction:
+ The intention is to provide a way to graft a fairly generic extension
+ language into nvi. I think that the obvious candidates are Tcl/Rush,
+ Scheme, Python and Perl. Since the interpretation language chosen
+ is often a religious issue, the method should be as flexible as
+ possible. I don't expect to rewrite the editor in the interpreted
+ language, so that isn't a consideration.
+
+ Q: Is there any reason for nvi to support multiple interpreters in
+ a single executable?
+
+Interpreter functions in nvi:
+
+ 1: Function to get the current screen pointer.
+
+ SCR *inter_screen();
+
+ Return a pointer to the current screen.
+
+ 2: Functions to execute both ex and vi commands. The return value of the
+ function will be success/failure. The editor itself will continue to
+ handle the display of all messages and text for the foreseeable future.
+
+ int inter_vicmd(SCR *, char *cmds, size_t len);
+ int inter_excmd(SCR *, char *cmds, size_t len);
+
+ The byte string cmds, of length len, is entered into the standard
+ vi or ex parser, as if typed by the user. The characters are not
+ mapped in any way, i.e. the user's vi mappings don't apply. If
+ any error occurs, an error value is returned, and the rest of the
+ characters are discarded.
+
+ 3: Functions to handle lines of text in the file.
+
+ int inter_gline(SCR *, recno_t lno, char **lp, size_t *lenp);
+
+ Return a pointer to the text of the line lno, into the location
+ referenced by lp, and its length into the location referenced by
+ lenp.
+
+ int inter_dline(SCR *, recno_t lno);
+
+ Delete the line lno from the file.
+
+ int inter_aline(SCR *, recno_t lno, char *lp, size_t len);
+
+ Append a line consisting of the len bytes of text referenced by
+ lp to the line lno.
+
+ int inter_iline(SCR *, recno_t lno, char *lp, size_t len);
+
+ Insert a line consisting of the len bytes of text referenced by
+ lp before the line lno.
+
+ int inter_sline(SCR *, recno_t lno, char *lp, size_t len);
+
+ Replace line lno with the len bytes of text referenced by lp.
+
+ int inter_lline(SCR *, recno_t *lnop);
+
+ Return the number of the last line in the file in the location
+ referenced by lnop.
+
+ 4: Function to post an error message to the user.
+
+ int inter_msgq(SCR *, enum msgtype, char *fmt, ...);
+
+ Display the message for the user. Valid message types are:
+
+ M_BERR Error: M_ERR if verbose, else bell.
+ M_ERR Error: Display in inverse video.
+ M_INFO Info: Display in normal video.
+ M_SYSERR Error: M_ERR, using strerror(3) message.
+ M_VINFO Info: M_INFO if verbose, else ignore.
+
+ 5: Function to manipulate cut buffers.
+
+ int inter_setbuf(SCR *, CHAR_T buffer);
+
+ Create the specified buffer if it does not exist (the
+ buffer will have no contents).
+
+ int inter_getbuf(SCR *, CHAR_T buffer, TEXT **textp);
+
+ Return a pointer to the specified buffer in the location
+ referenced by textp. (Since a pointer to the real item
+ is being returned, it can be manipulated in any way the
+ interpreter chooses.)
+
+ 6: Functions to manipulate marks.
+
+ int inter_setmark(SCR *, CHAR_T name);
+
+ Create the specified mark if it does not exist (the
+ mark will have no contents).
+
+ int inter_getmark(SCR *, CHAR_T name, MARK **markp);
+
+ Return a pointer to the specified mark in the location
+ referenced by markp. (Since a pointer to the real item
+ is being returned, it can be manipulated in any way the
+ interpreter chooses.)
+
+ 7: Function to manipulate screens.
+
+ SCR *inter_iscreen();
+
+ Create a new screen, and return a pointer to it.
+
+ int inter_escreen(SCR *);
+
+ End a screen.
+
+ 8: Functions to get input from the user.
+
+ int inter_getchar(CHAR_T *chp,
+ enum maptype {NONE, INPUT, COMMAND} mapt);
+
+ Return a character from the keyboard into the location referenced
+ by chp. Mapt can be set to INPUT, COMMAND or NONE, depending on
+ what vi mappings should be applied to the character.
+
+ int inter_getline(SCR *, char *prompt, CHAR_T **linep,
+ size_t *lenp, enum maptype {NONE, INPUT, COMMAND} mapt);
+
+ Return a pointer to a line entered by the user, and its length,
+ into the locations linep and lenp. A prompt may be specified
+ by prompt, and mappings by mapt.
+
+ int inter_freeline(CHAR_T *linep);
+
+ Free the memory that was allocated by inter_getline();
+
+ 9: Function to retrieve and set the cursor.
+
+ int inter_getcursor(SCR *, MARK *mark);
+
+ Store the current cursor position in mark.
+
+ int inter_setcursor(SCR *, MARK *mark);
+
+ Set the current cursor position to mark.
+
+10: Function to return a motion command from the user.
+
+ int inter_getmotion(SCR *,
+ MARK *start, MARK *end, enum movetype {LINE, CHAR} *mt);
+
+ Nvi gets a motion command from the user and returns the starting
+ and stopping points of the movement, reordered from the beginning
+ to the end of the file. The standard rules for line/character
+ motions are applied, and returned to the interpreter through the
+ mt argument.
+
+11: Functions to return pathnames.
+
+12: Functions to return edit options.
+
+13: Nvi commands which will send text to the interpreter.
+
+ Nvi will have a new ex command "inter", which will pipe the rest of
+ the line up to the first unescaped <newline> to the interpreter, of
+ the following form:
+
+ :[address[,address]] inter [count] command
+
+ The interface from the ex command to the interpreter is a function:
+
+ int inter_ex(
+ SCR *, /* Current screen. */
+ char *cmd; /* The command. */
+ size_t len; /* The command length. */
+ MARK *start, /* Starting address for INTER_EX */
+ MARK *end, /* Ending address for INTER_EX */
+ int count); /* Count. */
+
+ Nvi will have a new vi command "*<buffer>" which will pipe the contents
+ of the named buffer to the interpreter, of the following form:
+
+ [count]*<buffer>
+
+ The interface from the vi command to the interpreter is a function:
+
+ int inter_vi(
+ SCR *, /* Current screen. */
+ CHAR_T buffer, /* Buffer. */
+ int count); /* Count. */
diff --git a/contrib/nvi/docs/interp/spell.ok b/contrib/nvi/docs/interp/spell.ok
new file mode 100644
index 000000000000..4ca990c21720
--- /dev/null
+++ b/contrib/nvi/docs/interp/spell.ok
@@ -0,0 +1,46 @@
+API
+BERR
+Mapt
+Nvi
+Perl
+SCR
+SYSERR
+Tcl
+VINFO
+aline
+callback
+chp
+cmd
+cmds
+dline
+enum
+escreen
+excmd
+freeline
+getbuf
+getcursor
+getline
+getmotion
+gline
+iline
+int
+interp
+iscreen
+lenp
+linep
+lline
+lno
+lnop
+lp
+mapt
+maptype
+movetype
+msgq
+msgtype
+nvi
+recno
+setcursor
+sline
+strerror
+textp
+vicmd
diff --git a/contrib/nvi/docs/spell.ok b/contrib/nvi/docs/spell.ok
new file mode 100644
index 000000000000..ec854ffa41b4
--- /dev/null
+++ b/contrib/nvi/docs/spell.ok
@@ -0,0 +1,173 @@
+API's
+Amiga
+Amir
+Bostic
+CFLAGS
+CR
+CTYPE
+Cscope
+Ctags
+DB
+DPURIFY
+Darren
+Ds
+Dw
+EXINIT
+Englar
+FreeBSD
+GDB
+Hiebert
+Kirkendall
+LC
+LN
+Linux
+Lite
+MSDOS
+Makefile
+Mayoff
+NEXINIT
+NVI
+NetBSD
+Neville
+Nvi
+Nvi's
+OS
+POSIX
+POSIX.2
+Perl
+PostScript
+README
+Roff
+Solaris
+SunOS
+Sven
+Tcl
+Tk
+Todo
+USD
+USD.doc
+USD:14
+USD:15
+USD:16
+UUNET
+UX
+Verdoolaege
+Vi
+Vi's
+WindowsNT
+ags
+al
+american
+api
+autowrite
+berkeley
+bitstring
+bitstring.h
+bostic
+bsd
+bugs.current
+ccil
+changelog
+cl
+clib
+cont
+cs
+cs.berkeley.edu
+cscope
+csh
+cshrc
+ctags
+darren
+db
+dbopen
+devel
+doc
+docs
+edu
+elvis
+email
+enum
+escapetime
+esr
+execl
+exrc
+exref
+fcntl
+filesystem
+free's
+ftp.cs.berkeley.edu
+gdb
+gdb.script
+gvr
+gz
+gzip'd
+hardtabs
+hiwaay
+html
+http
+ic
+iclower
+ignorecase
+il
+init
+init.tcl
+iso
+isprint
+kB
+keystrokes
+ksh
+lang
+ld
+lt
+lu
+mmap
+ncurses
+nex
+nexrc
+nul's
+nvi
+nvi's
+nvi.ALPHA.tar.gz
+nvi.tar.Z
+nvi.tar.gz
+openmode
+org
+perl
+preformatted
+ps
+queue.h
+readonly
+recover.script
+redistributable
+regex
+remapped
+setenv
+settable
+shiftwidth
+sirsi
+slowopen
+sourced
+struct
+sunsite
+svi
+tcl
+tclapi
+terminfo
+tk
+tknvi
+txt
+ucb
+unc
+uunet
+version's
+vi
+vi's
+vi.man
+vi.ref
+vi.ref.ps
+vi.ref.txt
+vitut
+writeable
+www
+xaw
+ynq
diff --git a/usr.bin/vi/docs/tutorial/vi.advanced b/contrib/nvi/docs/tutorial/vi.advanced
index f757ad19c44a..f757ad19c44a 100644
--- a/usr.bin/vi/docs/tutorial/vi.advanced
+++ b/contrib/nvi/docs/tutorial/vi.advanced
diff --git a/usr.bin/vi/docs/tutorial/vi.beginner b/contrib/nvi/docs/tutorial/vi.beginner
index 3bf35ac939f8..3bf35ac939f8 100644
--- a/usr.bin/vi/docs/tutorial/vi.beginner
+++ b/contrib/nvi/docs/tutorial/vi.beginner
diff --git a/usr.bin/vi/docs/tutorial/vi.tut.csh b/contrib/nvi/docs/tutorial/vi.tut.csh
index 01554bc4e5fd..01554bc4e5fd 100755
--- a/usr.bin/vi/docs/tutorial/vi.tut.csh
+++ b/contrib/nvi/docs/tutorial/vi.tut.csh
diff --git a/usr.bin/vi/ex/excmd.awk b/contrib/nvi/ex/ex.awk
index 289022051cdd..3ee372e14aac 100644
--- a/usr.bin/vi/ex/excmd.awk
+++ b/contrib/nvi/ex/ex.awk
@@ -1,4 +1,4 @@
-# @(#)excmd.awk 8.1 (Berkeley) 4/17/94
+# @(#)ex.awk 10.1 (Berkeley) 6/8/95
/^\/\* C_[0-9A-Z_]* \*\/$/ {
printf("#define %s %d\n", $2, cnt++);
diff --git a/contrib/nvi/ex/ex.c b/contrib/nvi/ex/ex.c
new file mode 100644
index 000000000000..f92d8f7c4f9a
--- /dev/null
+++ b/contrib/nvi/ex/ex.c
@@ -0,0 +1,2370 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex.c 10.57 (Berkeley) 10/10/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+#if defined(DEBUG) && defined(COMLOG)
+static void ex_comlog __P((SCR *, EXCMD *));
+#endif
+static EXCMDLIST const *
+ ex_comm_search __P((char *, size_t));
+static int ex_discard __P((SCR *));
+static int ex_line __P((SCR *, EXCMD *, MARK *, int *, int *));
+static int ex_load __P((SCR *));
+static void ex_unknown __P((SCR *, char *, size_t));
+
+/*
+ * ex --
+ * Main ex loop.
+ *
+ * PUBLIC: int ex __P((SCR **));
+ */
+int
+ex(spp)
+ SCR **spp;
+{
+ EX_PRIVATE *exp;
+ GS *gp;
+ MSGS *mp;
+ SCR *sp;
+ TEXT *tp;
+ u_int32_t flags;
+
+ sp = *spp;
+ gp = sp->gp;
+ exp = EXP(sp);
+
+ /* Start the ex screen. */
+ if (ex_init(sp))
+ return (1);
+
+ /* Flush any saved messages. */
+ while ((mp = gp->msgq.lh_first) != NULL) {
+ gp->scr_msg(sp, mp->mtype, mp->buf, mp->len);
+ LIST_REMOVE(mp, q);
+ free(mp->buf);
+ free(mp);
+ }
+
+ /* If reading from a file, errors should have name and line info. */
+ if (F_ISSET(gp, G_SCRIPTED)) {
+ gp->excmd.if_lno = 1;
+ gp->excmd.if_name = "script";
+ }
+
+ /*
+ * !!!
+ * Initialize the text flags. The beautify edit option historically
+ * applied to ex command input read from a file. In addition, the
+ * first time a ^H was discarded from the input, there was a message,
+ * "^H discarded", that was displayed. We don't bother.
+ */
+ LF_INIT(TXT_BACKSLASH | TXT_CNTRLD | TXT_CR);
+ for (;; ++gp->excmd.if_lno) {
+ /* Display status line and flush. */
+ if (F_ISSET(sp, SC_STATUS)) {
+ if (!F_ISSET(sp, SC_EX_SILENT))
+ msgq_status(sp, sp->lno, 0);
+ F_CLR(sp, SC_STATUS);
+ }
+ (void)ex_fflush(sp);
+
+ /* Set the flags the user can reset. */
+ if (O_ISSET(sp, O_BEAUTIFY))
+ LF_SET(TXT_BEAUTIFY);
+ if (O_ISSET(sp, O_PROMPT))
+ LF_SET(TXT_PROMPT);
+
+ /* Clear any current interrupts, and get a command. */
+ CLR_INTERRUPT(sp);
+ if (ex_txt(sp, &sp->tiq, ':', flags))
+ return (1);
+ if (INTERRUPTED(sp)) {
+ (void)ex_puts(sp, "\n");
+ (void)ex_fflush(sp);
+ continue;
+ }
+
+ /* Initialize the command structure. */
+ CLEAR_EX_PARSER(&gp->excmd);
+
+ /*
+ * If the user entered a single carriage return, send
+ * ex_cmd() a separator -- it discards single newlines.
+ */
+ tp = sp->tiq.cqh_first;
+ if (tp->len == 0) {
+ gp->excmd.cp = " "; /* __TK__ why not |? */
+ gp->excmd.clen = 1;
+ } else {
+ gp->excmd.cp = tp->lb;
+ gp->excmd.clen = tp->len;
+ }
+ F_INIT(&gp->excmd, E_NRSEP);
+
+ if (ex_cmd(sp) && F_ISSET(gp, G_SCRIPTED))
+ return (1);
+
+ if (INTERRUPTED(sp)) {
+ CLR_INTERRUPT(sp);
+ msgq(sp, M_ERR, "170|Interrupted");
+ }
+
+ /*
+ * If the last command caused a restart, or switched screens
+ * or into vi, return.
+ */
+ if (F_ISSET(gp, G_SRESTART) || F_ISSET(sp, SC_SSWITCH | SC_VI)) {
+ *spp = sp;
+ break;
+ }
+
+ /* If the last command switched files, we don't care. */
+ F_CLR(sp, SC_FSWITCH);
+
+ /*
+ * If we're exiting this screen, move to the next one. By
+ * definition, this means returning into vi, so return to the
+ * main editor loop. The ordering is careful, don't discard
+ * the contents of sp until the end.
+ */
+ if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) {
+ if (file_end(sp, NULL, F_ISSET(sp, SC_EXIT_FORCE)))
+ return (1);
+ *spp = screen_next(sp);
+ return (screen_end(sp));
+ }
+ }
+ return (0);
+}
+
+/*
+ * ex_cmd --
+ * The guts of the ex parser: parse and execute a string containing
+ * ex commands.
+ *
+ * !!!
+ * This code MODIFIES the string that gets passed in, to delete quoting
+ * characters, etc. The string cannot be readonly/text space, nor should
+ * you expect to use it again after ex_cmd() returns.
+ *
+ * !!!
+ * For the fun of it, if you want to see if a vi clone got the ex argument
+ * parsing right, try:
+ *
+ * echo 'foo|bar' > file1; echo 'foo/bar' > file2;
+ * vi
+ * :edit +1|s/|/PIPE/|w file1| e file2|1 | s/\//SLASH/|wq
+ *
+ * or: vi
+ * :set|file|append|set|file
+ *
+ * For extra credit, try them in a startup .exrc file.
+ *
+ * PUBLIC: int ex_cmd __P((SCR *));
+ */
+int
+ex_cmd(sp)
+ SCR *sp;
+{
+ enum nresult nret;
+ EX_PRIVATE *exp;
+ EXCMD *ecp;
+ GS *gp;
+ MARK cur;
+ recno_t lno;
+ size_t arg1_len, discard, len;
+ u_int32_t flags;
+ long ltmp;
+ int at_found, gv_found;
+ int ch, cnt, delim, isaddr, namelen;
+ int newscreen, notempty, tmp, vi_address;
+ char *arg1, *p, *s, *t;
+
+ gp = sp->gp;
+ exp = EXP(sp);
+
+ /*
+ * We always start running the command on the top of the stack.
+ * This means that *everything* must be resolved when we leave
+ * this function for any reason.
+ */
+loop: ecp = gp->ecq.lh_first;
+
+ /* If we're reading a command from a file, set up error information. */
+ if (ecp->if_name != NULL) {
+ gp->if_lno = ecp->if_lno;
+ gp->if_name = ecp->if_name;
+ }
+
+ /*
+ * If a move to the end of the file is scheduled for this command,
+ * do it now.
+ */
+ if (F_ISSET(ecp, E_MOVETOEND)) {
+ if (db_last(sp, &sp->lno))
+ goto rfail;
+ sp->cno = 0;
+ F_CLR(ecp, E_MOVETOEND);
+ }
+
+ /* If we found a newline, increment the count now. */
+ if (F_ISSET(ecp, E_NEWLINE)) {
+ ++gp->if_lno;
+ ++ecp->if_lno;
+ F_CLR(ecp, E_NEWLINE);
+ }
+
+ /* (Re)initialize the EXCMD structure, preserving some flags. */
+ CLEAR_EX_CMD(ecp);
+
+ /* Initialize the argument structures. */
+ if (argv_init(sp, ecp))
+ goto err;
+
+ /* Initialize +cmd, saved command information. */
+ arg1 = NULL;
+ ecp->save_cmdlen = 0;
+
+ /* Skip <blank>s, empty lines. */
+ for (notempty = 0; ecp->clen > 0; ++ecp->cp, --ecp->clen)
+ if ((ch = *ecp->cp) == '\n') {
+ ++gp->if_lno;
+ ++ecp->if_lno;
+ } else if (isblank(ch))
+ notempty = 1;
+ else
+ break;
+
+ /*
+ * !!!
+ * Permit extra colons at the start of the line. Historically,
+ * ex/vi allowed a single extra one. It's simpler not to count.
+ * The stripping is done here because, historically, any command
+ * could have preceding colons, e.g. ":g/pattern/:p" worked.
+ */
+ if (ecp->clen != 0 && ch == ':') {
+ notempty = 1;
+ while (--ecp->clen > 0 && (ch = *++ecp->cp) == ':');
+ }
+
+ /*
+ * Command lines that start with a double-quote are comments.
+ *
+ * !!!
+ * Historically, there was no escape or delimiter for a comment, e.g.
+ * :"foo|set was a single comment and nothing was output. Since nvi
+ * permits users to escape <newline> characters into command lines, we
+ * have to check for that case.
+ */
+ if (ecp->clen != 0 && ch == '"') {
+ while (--ecp->clen > 0 && *++ecp->cp != '\n');
+ if (*ecp->cp == '\n') {
+ F_SET(ecp, E_NEWLINE);
+ ++ecp->cp;
+ --ecp->clen;
+ }
+ goto loop;
+ }
+
+ /* Skip whitespace. */
+ for (; ecp->clen > 0; ++ecp->cp, --ecp->clen) {
+ ch = *ecp->cp;
+ if (!isblank(ch))
+ break;
+ }
+
+ /*
+ * The last point at which an empty line can mean do nothing.
+ *
+ * !!!
+ * Historically, in ex mode, lines containing only <blank> characters
+ * were the same as a single <carriage-return>, i.e. a default command.
+ * In vi mode, they were ignored. In .exrc files this was a serious
+ * annoyance, as vi kept trying to treat them as print commands. We
+ * ignore backward compatibility in this case, discarding lines that
+ * contain only <blank> characters from .exrc files.
+ *
+ * !!!
+ * This is where you end up when you're done a command, i.e. clen has
+ * gone to zero. Continue if there are more commands to run.
+ */
+ if (ecp->clen == 0 &&
+ (!notempty || F_ISSET(sp, SC_VI) || F_ISSET(ecp, E_BLIGNORE))) {
+ if (ex_load(sp))
+ goto rfail;
+ ecp = gp->ecq.lh_first;
+ if (ecp->clen == 0)
+ goto rsuccess;
+ goto loop;
+ }
+
+ /*
+ * Check to see if this is a command for which we may want to move
+ * the cursor back up to the previous line. (The command :1<CR>
+ * wants a <newline> separator, but the command :<CR> wants to erase
+ * the command line.) If the line is empty except for <blank>s,
+ * <carriage-return> or <eof>, we'll probably want to move up. I
+ * don't think there's any way to get <blank> characters *after* the
+ * command character, but this is the ex parser, and I've been wrong
+ * before.
+ */
+ if (F_ISSET(ecp, E_NRSEP) &&
+ ecp->clen != 0 && (ecp->clen != 1 || ecp->cp[0] != '\004'))
+ F_CLR(ecp, E_NRSEP);
+
+ /* Parse command addresses. */
+ if (ex_range(sp, ecp, &tmp))
+ goto rfail;
+ if (tmp)
+ goto err;
+
+ /*
+ * Skip <blank>s and any more colons (the command :3,5:print
+ * worked, historically).
+ */
+ for (; ecp->clen > 0; ++ecp->cp, --ecp->clen) {
+ ch = *ecp->cp;
+ if (!isblank(ch) && ch != ':')
+ break;
+ }
+
+ /*
+ * If no command, ex does the last specified of p, l, or #, and vi
+ * moves to the line. Otherwise, determine the length of the command
+ * name by looking for the first non-alphabetic character. (There
+ * are a few non-alphabetic characters in command names, but they're
+ * all single character commands.) This isn't a great test, because
+ * it means that, for the command ":e +cut.c file", we'll report that
+ * the command "cut" wasn't known. However, it makes ":e+35 file" work
+ * correctly.
+ *
+ * !!!
+ * Historically, lines with multiple adjacent (or <blank> separated)
+ * command separators were very strange. For example, the command
+ * |||<carriage-return>, when the cursor was on line 1, displayed
+ * lines 2, 3 and 5 of the file. In addition, the command " | "
+ * would only display the line after the next line, instead of the
+ * next two lines. No ideas why. It worked reasonably when executed
+ * from vi mode, and displayed lines 2, 3, and 4, so we do a default
+ * command for each separator.
+ */
+#define SINGLE_CHAR_COMMANDS "\004!#&*<=>@~"
+ newscreen = 0;
+ if (ecp->clen != 0 && ecp->cp[0] != '|' && ecp->cp[0] != '\n') {
+ if (strchr(SINGLE_CHAR_COMMANDS, *ecp->cp)) {
+ p = ecp->cp;
+ ++ecp->cp;
+ --ecp->clen;
+ namelen = 1;
+ } else {
+ for (p = ecp->cp;
+ ecp->clen > 0; --ecp->clen, ++ecp->cp)
+ if (!isalpha(*ecp->cp))
+ break;
+ if ((namelen = ecp->cp - p) == 0) {
+ msgq(sp, M_ERR, "080|Unknown command name");
+ goto err;
+ }
+ }
+
+ /*
+ * !!!
+ * Historic vi permitted flags to immediately follow any
+ * subset of the 'delete' command, but then did not permit
+ * further arguments (flag, buffer, count). Make it work.
+ * Permit further arguments for the few shreds of dignity
+ * it offers.
+ *
+ * Adding commands that start with 'd', and match "delete"
+ * up to a l, p, +, - or # character can break this code.
+ *
+ * !!!
+ * Capital letters beginning the command names ex, edit,
+ * next, previous, tag and visual (in vi mode) indicate the
+ * command should happen in a new screen.
+ */
+ switch (p[0]) {
+ case 'd':
+ for (s = p,
+ t = cmds[C_DELETE].name; *s == *t; ++s, ++t);
+ if (s[0] == 'l' || s[0] == 'p' || s[0] == '+' ||
+ s[0] == '-' || s[0] == '^' || s[0] == '#') {
+ len = (ecp->cp - p) - (s - p);
+ ecp->cp -= len;
+ ecp->clen += len;
+ ecp->rcmd = cmds[C_DELETE];
+ ecp->rcmd.syntax = "1bca1";
+ ecp->cmd = &ecp->rcmd;
+ goto skip_srch;
+ }
+ break;
+ case 'E': case 'F': case 'N': case 'P': case 'T': case 'V':
+ newscreen = 1;
+ p[0] = tolower(p[0]);
+ break;
+ }
+
+ /*
+ * Search the table for the command.
+ *
+ * !!!
+ * Historic vi permitted the mark to immediately follow the
+ * 'k' in the 'k' command. Make it work.
+ *
+ * !!!
+ * Historic vi permitted any flag to follow the s command, e.g.
+ * "s/e/E/|s|sgc3p" was legal. Make the command "sgc" work.
+ * Since the following characters all have to be flags, i.e.
+ * alphabetics, we can let the s command routine return errors
+ * if it was some illegal command string. This code will break
+ * if an "sg" or similar command is ever added. The substitute
+ * code doesn't care if it's a "cgr" flag or a "#lp" flag that
+ * follows the 's', but we limit the choices here to "cgr" so
+ * that we get unknown command messages for wrong combinations.
+ */
+ if ((ecp->cmd = ex_comm_search(p, namelen)) == NULL)
+ switch (p[0]) {
+ case 'k':
+ if (namelen == 2) {
+ ecp->cp -= namelen - 1;
+ ecp->clen += namelen - 1;
+ ecp->cmd = &cmds[C_K];
+ break;
+ }
+ goto unknown;
+ case 's':
+ for (s = p + 1, cnt = namelen; --cnt; ++s)
+ if (s[0] != 'c' &&
+ s[0] != 'g' && s[0] != 'r')
+ break;
+ if (cnt == 0) {
+ ecp->cp -= namelen - 1;
+ ecp->clen += namelen - 1;
+ ecp->rcmd = cmds[C_SUBSTITUTE];
+ ecp->rcmd.fn = ex_subagain;
+ ecp->cmd = &ecp->rcmd;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+unknown: if (newscreen)
+ p[0] = toupper(p[0]);
+ ex_unknown(sp, p, namelen);
+ goto err;
+ }
+
+ /*
+ * The visual command has a different syntax when called
+ * from ex than when called from a vi colon command. FMH.
+ * Make the change now, before we test for the newscreen
+ * semantic, so that we're testing the right one.
+ */
+skip_srch: if (ecp->cmd == &cmds[C_VISUAL_EX] && F_ISSET(sp, SC_VI))
+ ecp->cmd = &cmds[C_VISUAL_VI];
+
+ /*
+ * !!!
+ * Historic vi permitted a capital 'P' at the beginning of
+ * any command that started with 'p'. Probably wanted the
+ * P[rint] command for backward compatibility, and the code
+ * just made Preserve and Put work by accident. Nvi uses
+ * Previous to mean previous-in-a-new-screen, so be careful.
+ */
+ if (newscreen && !F_ISSET(ecp->cmd, E_NEWSCREEN) &&
+ (ecp->cmd == &cmds[C_PRINT] ||
+ ecp->cmd == &cmds[C_PRESERVE]))
+ newscreen = 0;
+
+ /* Test for a newscreen associated with this command. */
+ if (newscreen && !F_ISSET(ecp->cmd, E_NEWSCREEN))
+ goto unknown;
+
+ /* Secure means no shell access. */
+ if (F_ISSET(ecp->cmd, E_SECURE) && O_ISSET(sp, O_SECURE)) {
+ ex_emsg(sp, ecp->cmd->name, EXM_SECURE);
+ goto err;
+ }
+
+ /*
+ * Multiple < and > characters; another "feature". Note,
+ * The string passed to the underlying function may not be
+ * nul terminated in this case.
+ */
+ if ((ecp->cmd == &cmds[C_SHIFTL] && *p == '<') ||
+ (ecp->cmd == &cmds[C_SHIFTR] && *p == '>')) {
+ for (ch = *p;
+ ecp->clen > 0; --ecp->clen, ++ecp->cp)
+ if (*ecp->cp != ch)
+ break;
+ if (argv_exp0(sp, ecp, p, ecp->cp - p))
+ goto err;
+ }
+
+ /* Set the format style flags for the next command. */
+ if (ecp->cmd == &cmds[C_HASH])
+ exp->fdef = E_C_HASH;
+ else if (ecp->cmd == &cmds[C_LIST])
+ exp->fdef = E_C_LIST;
+ else if (ecp->cmd == &cmds[C_PRINT])
+ exp->fdef = E_C_PRINT;
+ F_CLR(ecp, E_USELASTCMD);
+ } else {
+ /* Print is the default command. */
+ ecp->cmd = &cmds[C_PRINT];
+
+ /* Set the saved format flags. */
+ F_SET(ecp, exp->fdef);
+
+ /*
+ * !!!
+ * If no address was specified, and it's not a global command,
+ * we up the address by one. (I have no idea why globals are
+ * exempted, but it's (ahem) historic practice.)
+ */
+ if (ecp->addrcnt == 0 && !F_ISSET(sp, SC_EX_GLOBAL)) {
+ ecp->addrcnt = 1;
+ ecp->addr1.lno = sp->lno + 1;
+ ecp->addr1.cno = sp->cno;
+ }
+
+ F_SET(ecp, E_USELASTCMD);
+ }
+
+ /*
+ * !!!
+ * Historically, the number option applied to both ex and vi. One
+ * strangeness was that ex didn't switch display formats until a
+ * command was entered, e.g. <CR>'s after the set didn't change to
+ * the new format, but :1p would.
+ */
+ if (O_ISSET(sp, O_NUMBER)) {
+ F_SET(ecp, E_OPTNUM);
+ FL_SET(ecp->iflags, E_C_HASH);
+ } else
+ F_CLR(ecp, E_OPTNUM);
+
+ /* Check for ex mode legality. */
+ if (F_ISSET(sp, SC_EX) && (F_ISSET(ecp->cmd, E_VIONLY) || newscreen)) {
+ msgq(sp, M_ERR,
+ "082|%s: command not available in ex mode", ecp->cmd->name);
+ goto err;
+ }
+
+ /* Add standard command flags. */
+ F_SET(ecp, ecp->cmd->flags);
+ if (!newscreen)
+ F_CLR(ecp, E_NEWSCREEN);
+
+ /*
+ * There are three normal termination cases for an ex command. They
+ * are the end of the string (ecp->clen), or unescaped (by <literal
+ * next> characters) <newline> or '|' characters. As we're now past
+ * possible addresses, we can determine how long the command is, so we
+ * don't have to look for all the possible terminations. Naturally,
+ * there are some exciting special cases:
+ *
+ * 1: The bang, global, v and the filter versions of the read and
+ * write commands are delimited by <newline>s (they can contain
+ * shell pipes).
+ * 2: The ex, edit, next and visual in vi mode commands all take ex
+ * commands as their first arguments.
+ * 3: The s command takes an RE as its first argument, and wants it
+ * to be specially delimited.
+ *
+ * Historically, '|' characters in the first argument of the ex, edit,
+ * next, vi visual, and s commands didn't delimit the command. And,
+ * in the filter cases for read and write, and the bang, global and v
+ * commands, they did not delimit the command at all.
+ *
+ * For example, the following commands were legal:
+ *
+ * :edit +25|s/abc/ABC/ file.c
+ * :s/|/PIPE/
+ * :read !spell % | columnate
+ * :global/pattern/p|l
+ *
+ * It's not quite as simple as it sounds, however. The command:
+ *
+ * :s/a/b/|s/c/d|set
+ *
+ * was also legal, i.e. the historic ex parser (using the word loosely,
+ * since "parser" implies some regularity of syntax) delimited the RE's
+ * based on its delimiter and not anything so irretrievably vulgar as a
+ * command syntax.
+ *
+ * Anyhow, the following code makes this all work. First, for the
+ * special cases we move past their special argument(s). Then, we
+ * do normal command processing on whatever is left. Barf-O-Rama.
+ */
+ discard = 0; /* Characters discarded from the command. */
+ arg1_len = 0;
+ ecp->save_cmd = ecp->cp;
+ if (ecp->cmd == &cmds[C_EDIT] || ecp->cmd == &cmds[C_EX] ||
+ ecp->cmd == &cmds[C_NEXT] || ecp->cmd == &cmds[C_VISUAL_VI]) {
+ /*
+ * Move to the next non-whitespace character. A '!'
+ * immediately following the command is eaten as a
+ * force flag.
+ */
+ if (ecp->clen > 0 && *ecp->cp == '!') {
+ ++ecp->cp;
+ --ecp->clen;
+ FL_SET(ecp->iflags, E_C_FORCE);
+
+ /* Reset, don't reparse. */
+ ecp->save_cmd = ecp->cp;
+ }
+ for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
+ if (!isblank(*ecp->cp))
+ break;
+ /*
+ * QUOTING NOTE:
+ *
+ * The historic implementation ignored all escape characters
+ * so there was no way to put a space or newline into the +cmd
+ * field. We do a simplistic job of fixing it by moving to the
+ * first whitespace character that isn't escaped. The escaping
+ * characters are stripped as no longer useful.
+ */
+ if (ecp->clen > 0 && *ecp->cp == '+') {
+ ++ecp->cp;
+ --ecp->clen;
+ for (arg1 = p = ecp->cp;
+ ecp->clen > 0; --ecp->clen, ++ecp->cp) {
+ ch = *ecp->cp;
+ if (IS_ESCAPE(sp, ecp, ch) &&
+ ecp->clen > 1) {
+ ++discard;
+ --ecp->clen;
+ ch = *++ecp->cp;
+ } else if (isblank(ch))
+ break;
+ *p++ = ch;
+ }
+ arg1_len = ecp->cp - arg1;
+
+ /* Reset, so the first argument isn't reparsed. */
+ ecp->save_cmd = ecp->cp;
+ }
+ } else if (ecp->cmd == &cmds[C_BANG] ||
+ ecp->cmd == &cmds[C_GLOBAL] || ecp->cmd == &cmds[C_V]) {
+ /*
+ * QUOTING NOTE:
+ *
+ * We use backslashes to escape <newline> characters, although
+ * this wasn't historic practice for the bang command. It was
+ * for the global and v commands, and it's common usage when
+ * doing text insert during the command. Escaping characters
+ * are stripped as no longer useful.
+ */
+ for (p = ecp->cp; ecp->clen > 0; --ecp->clen, ++ecp->cp) {
+ ch = *ecp->cp;
+ if (ch == '\\' && ecp->clen > 1 && ecp->cp[1] == '\n') {
+ ++discard;
+ --ecp->clen;
+ ch = *++ecp->cp;
+
+ ++gp->if_lno;
+ ++ecp->if_lno;
+ } else if (ch == '\n')
+ break;
+ *p++ = ch;
+ }
+ } else if (ecp->cmd == &cmds[C_READ] || ecp->cmd == &cmds[C_WRITE]) {
+ /*
+ * For write commands, if the next character is a <blank>, and
+ * the next non-blank character is a '!', it's a filter command
+ * and we want to eat everything up to the <newline>. For read
+ * commands, if the next non-blank character is a '!', it's a
+ * filter command and we want to eat everything up to the next
+ * <newline>. Otherwise, we're done.
+ */
+ for (tmp = 0; ecp->clen > 0; --ecp->clen, ++ecp->cp) {
+ ch = *ecp->cp;
+ if (isblank(ch))
+ tmp = 1;
+ else
+ break;
+ }
+ if (ecp->clen > 0 && ch == '!' &&
+ (ecp->cmd == &cmds[C_READ] || tmp))
+ for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
+ if (ecp->cp[0] == '\n')
+ break;
+ } else if (ecp->cmd == &cmds[C_SUBSTITUTE]) {
+ /*
+ * Move to the next non-whitespace character, we'll use it as
+ * the delimiter. If the character isn't an alphanumeric or
+ * a '|', it's the delimiter, so parse it. Otherwise, we're
+ * into something like ":s g", so use the special s command.
+ */
+ for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
+ if (!isblank(ecp->cp[0]))
+ break;
+
+ if (isalnum(ecp->cp[0]) || ecp->cp[0] == '|') {
+ ecp->rcmd = cmds[C_SUBSTITUTE];
+ ecp->rcmd.fn = ex_subagain;
+ ecp->cmd = &ecp->rcmd;
+ } else if (ecp->clen > 0) {
+ /*
+ * QUOTING NOTE:
+ *
+ * Backslashes quote delimiter characters for RE's.
+ * The backslashes are NOT removed since they'll be
+ * used by the RE code. Move to the third delimiter
+ * that's not escaped (or the end of the command).
+ */
+ delim = *ecp->cp;
+ ++ecp->cp;
+ --ecp->clen;
+ for (cnt = 2; ecp->clen > 0 &&
+ cnt != 0; --ecp->clen, ++ecp->cp)
+ if (ecp->cp[0] == '\\' &&
+ ecp->clen > 1) {
+ ++ecp->cp;
+ --ecp->clen;
+ } else if (ecp->cp[0] == delim)
+ --cnt;
+ }
+ }
+
+ /*
+ * Use normal quoting and termination rules to find the end of this
+ * command.
+ *
+ * QUOTING NOTE:
+ *
+ * Historically, vi permitted ^V's to escape <newline>'s in the .exrc
+ * file. It was almost certainly a bug, but that's what bug-for-bug
+ * compatibility means, Grasshopper. Also, ^V's escape the command
+ * delimiters. Literal next quote characters in front of the newlines,
+ * '|' characters or literal next characters are stripped as they're
+ * no longer useful.
+ */
+ vi_address = ecp->clen != 0 && ecp->cp[0] != '\n';
+ for (p = ecp->cp; ecp->clen > 0; --ecp->clen, ++ecp->cp) {
+ ch = ecp->cp[0];
+ if (IS_ESCAPE(sp, ecp, ch) && ecp->clen > 1) {
+ tmp = ecp->cp[1];
+ if (tmp == '\n' || tmp == '|') {
+ if (tmp == '\n') {
+ ++gp->if_lno;
+ ++ecp->if_lno;
+ }
+ ++discard;
+ --ecp->clen;
+ ++ecp->cp;
+ ch = tmp;
+ }
+ } else if (ch == '\n' || ch == '|') {
+ if (ch == '\n')
+ F_SET(ecp, E_NEWLINE);
+ --ecp->clen;
+ break;
+ }
+ *p++ = ch;
+ }
+
+ /*
+ * Save off the next command information, go back to the
+ * original start of the command.
+ */
+ p = ecp->cp + 1;
+ ecp->cp = ecp->save_cmd;
+ ecp->save_cmd = p;
+ ecp->save_cmdlen = ecp->clen;
+ ecp->clen = ((ecp->save_cmd - ecp->cp) - 1) - discard;
+
+ /*
+ * QUOTING NOTE:
+ *
+ * The "set tags" command historically used a backslash, not the
+ * user's literal next character, to escape whitespace. Handle
+ * it here instead of complicating the argv_exp3() code. Note,
+ * this isn't a particularly complex trap, and if backslashes were
+ * legal in set commands, this would have to be much more complicated.
+ */
+ if (ecp->cmd == &cmds[C_SET])
+ for (p = ecp->cp, len = ecp->clen; len > 0; --len, ++p)
+ if (*p == '\\')
+ *p = CH_LITERAL;
+
+ /*
+ * Set the default addresses. It's an error to specify an address for
+ * a command that doesn't take them. If two addresses are specified
+ * for a command that only takes one, lose the first one. Two special
+ * cases here, some commands take 0 or 2 addresses. For most of them
+ * (the E_ADDR2_ALL flag), 0 defaults to the entire file. For one
+ * (the `!' command, the E_ADDR2_NONE flag), 0 defaults to no lines.
+ *
+ * Also, if the file is empty, some commands want to use an address of
+ * 0, i.e. the entire file is 0 to 0, and the default first address is
+ * 0. Otherwise, an entire file is 1 to N and the default line is 1.
+ * Note, we also add the E_ADDR_ZERO flag to the command flags, for the
+ * case where the 0 address is only valid if it's a default address.
+ *
+ * Also, set a flag if we set the default addresses. Some commands
+ * (ex: z) care if the user specified an address or if we just used
+ * the current cursor.
+ */
+ switch (F_ISSET(ecp, E_ADDR1 | E_ADDR2 | E_ADDR2_ALL | E_ADDR2_NONE)) {
+ case E_ADDR1: /* One address: */
+ switch (ecp->addrcnt) {
+ case 0: /* Default cursor/empty file. */
+ ecp->addrcnt = 1;
+ F_SET(ecp, E_ADDR_DEF);
+ if (F_ISSET(ecp, E_ADDR_ZERODEF)) {
+ if (db_last(sp, &lno))
+ goto err;
+ if (lno == 0) {
+ ecp->addr1.lno = 0;
+ F_SET(ecp, E_ADDR_ZERO);
+ } else
+ ecp->addr1.lno = sp->lno;
+ } else
+ ecp->addr1.lno = sp->lno;
+ ecp->addr1.cno = sp->cno;
+ break;
+ case 1:
+ break;
+ case 2: /* Lose the first address. */
+ ecp->addrcnt = 1;
+ ecp->addr1 = ecp->addr2;
+ }
+ break;
+ case E_ADDR2_NONE: /* Zero/two addresses: */
+ if (ecp->addrcnt == 0) /* Default to nothing. */
+ break;
+ goto two_addr;
+ case E_ADDR2_ALL: /* Zero/two addresses: */
+ if (ecp->addrcnt == 0) { /* Default entire/empty file. */
+ F_SET(ecp, E_ADDR_DEF);
+ ecp->addrcnt = 2;
+ if (sp->ep == NULL)
+ ecp->addr2.lno = 0;
+ else if (db_last(sp, &ecp->addr2.lno))
+ goto err;
+ if (F_ISSET(ecp, E_ADDR_ZERODEF) &&
+ ecp->addr2.lno == 0) {
+ ecp->addr1.lno = 0;
+ F_SET(ecp, E_ADDR_ZERO);
+ } else
+ ecp->addr1.lno = 1;
+ ecp->addr1.cno = ecp->addr2.cno = 0;
+ F_SET(ecp, E_ADDR2_ALL);
+ break;
+ }
+ /* FALLTHROUGH */
+ case E_ADDR2: /* Two addresses: */
+two_addr: switch (ecp->addrcnt) {
+ case 0: /* Default cursor/empty file. */
+ ecp->addrcnt = 2;
+ F_SET(ecp, E_ADDR_DEF);
+ if (sp->lno == 1 &&
+ F_ISSET(ecp, E_ADDR_ZERODEF)) {
+ if (db_last(sp, &lno))
+ goto err;
+ if (lno == 0) {
+ ecp->addr1.lno = ecp->addr2.lno = 0;
+ F_SET(ecp, E_ADDR_ZERO);
+ } else
+ ecp->addr1.lno =
+ ecp->addr2.lno = sp->lno;
+ } else
+ ecp->addr1.lno = ecp->addr2.lno = sp->lno;
+ ecp->addr1.cno = ecp->addr2.cno = sp->cno;
+ break;
+ case 1: /* Default to first address. */
+ ecp->addrcnt = 2;
+ ecp->addr2 = ecp->addr1;
+ break;
+ case 2:
+ break;
+ }
+ break;
+ default:
+ if (ecp->addrcnt) /* Error. */
+ goto usage;
+ }
+
+ /*
+ * !!!
+ * The ^D scroll command historically scrolled the value of the scroll
+ * option or to EOF. It was an error if the cursor was already at EOF.
+ * (Leading addresses were permitted, but were then ignored.)
+ */
+ if (ecp->cmd == &cmds[C_SCROLL]) {
+ ecp->addrcnt = 2;
+ ecp->addr1.lno = sp->lno + 1;
+ ecp->addr2.lno = sp->lno + O_VAL(sp, O_SCROLL);
+ ecp->addr1.cno = ecp->addr2.cno = sp->cno;
+ if (db_last(sp, &lno))
+ goto err;
+ if (lno != 0 && lno > sp->lno && ecp->addr2.lno > lno)
+ ecp->addr2.lno = lno;
+ }
+
+ ecp->flagoff = 0;
+ for (p = ecp->cmd->syntax; *p != '\0'; ++p) {
+ /*
+ * The force flag is sensitive to leading whitespace, i.e.
+ * "next !" is different from "next!". Handle it before
+ * skipping leading <blank>s.
+ */
+ if (*p == '!') {
+ if (ecp->clen > 0 && *ecp->cp == '!') {
+ ++ecp->cp;
+ --ecp->clen;
+ FL_SET(ecp->iflags, E_C_FORCE);
+ }
+ continue;
+ }
+
+ /* Skip leading <blank>s. */
+ for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
+ if (!isblank(*ecp->cp))
+ break;
+ if (ecp->clen == 0)
+ break;
+
+ switch (*p) {
+ case '1': /* +, -, #, l, p */
+ /*
+ * !!!
+ * Historically, some flags were ignored depending
+ * on where they occurred in the command line. For
+ * example, in the command, ":3+++p--#", historic vi
+ * acted on the '#' flag, but ignored the '-' flags.
+ * It's unambiguous what the flags mean, so we just
+ * handle them regardless of the stupidity of their
+ * location.
+ */
+ for (; ecp->clen; --ecp->clen, ++ecp->cp)
+ switch (*ecp->cp) {
+ case '+':
+ ++ecp->flagoff;
+ break;
+ case '-':
+ case '^':
+ --ecp->flagoff;
+ break;
+ case '#':
+ F_CLR(ecp, E_OPTNUM);
+ FL_SET(ecp->iflags, E_C_HASH);
+ exp->fdef |= E_C_HASH;
+ break;
+ case 'l':
+ FL_SET(ecp->iflags, E_C_LIST);
+ exp->fdef |= E_C_LIST;
+ break;
+ case 'p':
+ FL_SET(ecp->iflags, E_C_PRINT);
+ exp->fdef |= E_C_PRINT;
+ break;
+ default:
+ goto end_case1;
+ }
+end_case1: break;
+ case '2': /* -, ., +, ^ */
+ case '3': /* -, ., +, ^, = */
+ for (; ecp->clen; --ecp->clen, ++ecp->cp)
+ switch (*ecp->cp) {
+ case '-':
+ FL_SET(ecp->iflags, E_C_DASH);
+ break;
+ case '.':
+ FL_SET(ecp->iflags, E_C_DOT);
+ break;
+ case '+':
+ FL_SET(ecp->iflags, E_C_PLUS);
+ break;
+ case '^':
+ FL_SET(ecp->iflags, E_C_CARAT);
+ break;
+ case '=':
+ if (*p == '3') {
+ FL_SET(ecp->iflags, E_C_EQUAL);
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ goto end_case23;
+ }
+end_case23: break;
+ case 'b': /* buffer */
+ /*
+ * !!!
+ * Historically, "d #" was a delete with a flag, not a
+ * delete into the '#' buffer. If the current command
+ * permits a flag, don't use one as a buffer. However,
+ * the 'l' and 'p' flags were legal buffer names in the
+ * historic ex, and were used as buffers, not flags.
+ */
+ if ((ecp->cp[0] == '+' || ecp->cp[0] == '-' ||
+ ecp->cp[0] == '^' || ecp->cp[0] == '#') &&
+ strchr(p, '1') != NULL)
+ break;
+ /*
+ * !!!
+ * Digits can't be buffer names in ex commands, or the
+ * command "d2" would be a delete into buffer '2', and
+ * not a two-line deletion.
+ */
+ if (!isdigit(ecp->cp[0])) {
+ ecp->buffer = *ecp->cp;
+ ++ecp->cp;
+ --ecp->clen;
+ FL_SET(ecp->iflags, E_C_BUFFER);
+ }
+ break;
+ case 'c': /* count [01+a] */
+ ++p;
+ /* Validate any signed value. */
+ if (!isdigit(*ecp->cp) && (*p != '+' ||
+ (*ecp->cp != '+' && *ecp->cp != '-')))
+ break;
+ /* If a signed value, set appropriate flags. */
+ if (*ecp->cp == '-')
+ FL_SET(ecp->iflags, E_C_COUNT_NEG);
+ else if (*ecp->cp == '+')
+ FL_SET(ecp->iflags, E_C_COUNT_POS);
+ if ((nret =
+ nget_slong(&ltmp, ecp->cp, &t, 10)) != NUM_OK) {
+ ex_badaddr(sp, NULL, A_NOTSET, nret);
+ goto err;
+ }
+ if (ltmp == 0 && *p != '0') {
+ msgq(sp, M_ERR, "083|Count may not be zero");
+ goto err;
+ }
+ ecp->clen -= (t - ecp->cp);
+ ecp->cp = t;
+
+ /*
+ * Counts as address offsets occur in commands taking
+ * two addresses. Historic vi practice was to use
+ * the count as an offset from the *second* address.
+ *
+ * Set a count flag; some underlying commands (see
+ * join) do different things with counts than with
+ * line addresses.
+ */
+ if (*p == 'a') {
+ ecp->addr1 = ecp->addr2;
+ ecp->addr2.lno = ecp->addr1.lno + ltmp - 1;
+ } else
+ ecp->count = ltmp;
+ FL_SET(ecp->iflags, E_C_COUNT);
+ break;
+ case 'f': /* file */
+ if (argv_exp2(sp, ecp, ecp->cp, ecp->clen))
+ goto err;
+ goto arg_cnt_chk;
+ case 'l': /* line */
+ /*
+ * Get a line specification.
+ *
+ * If the line was a search expression, we may have
+ * changed state during the call, and we're now
+ * searching the file. Push ourselves onto the state
+ * stack.
+ */
+ if (ex_line(sp, ecp, &cur, &isaddr, &tmp))
+ goto rfail;
+ if (tmp)
+ goto err;
+
+ /* Line specifications are always required. */
+ if (!isaddr) {
+ msgq_str(sp, M_ERR, ecp->cp,
+ "084|%s: bad line specification");
+ goto err;
+ }
+ /*
+ * The target line should exist for these commands,
+ * but 0 is legal for them as well.
+ */
+ if (cur.lno != 0 && !db_exist(sp, cur.lno)) {
+ ex_badaddr(sp, NULL, A_EOF, NUM_OK);
+ goto err;
+ }
+ ecp->lineno = cur.lno;
+ break;
+ case 'S': /* string, file exp. */
+ if (ecp->clen != 0) {
+ if (argv_exp1(sp, ecp, ecp->cp,
+ ecp->clen, ecp->cmd == &cmds[C_BANG]))
+ goto err;
+ goto addr_verify;
+ }
+ /* FALLTHROUGH */
+ case 's': /* string */
+ if (argv_exp0(sp, ecp, ecp->cp, ecp->clen))
+ goto err;
+ goto addr_verify;
+ case 'W': /* word string */
+ /*
+ * QUOTING NOTE:
+ *
+ * Literal next characters escape the following
+ * character. Quoting characters are stripped here
+ * since they are no longer useful.
+ *
+ * First there was the word.
+ */
+ for (p = t = ecp->cp;
+ ecp->clen > 0; --ecp->clen, ++ecp->cp) {
+ ch = *ecp->cp;
+ if (IS_ESCAPE(sp,
+ ecp, ch) && ecp->clen > 1) {
+ --ecp->clen;
+ *p++ = *++ecp->cp;
+ } else if (isblank(ch)) {
+ ++ecp->cp;
+ --ecp->clen;
+ break;
+ } else
+ *p++ = ch;
+ }
+ if (argv_exp0(sp, ecp, t, p - t))
+ goto err;
+
+ /* Delete intervening whitespace. */
+ for (; ecp->clen > 0;
+ --ecp->clen, ++ecp->cp) {
+ ch = *ecp->cp;
+ if (!isblank(ch))
+ break;
+ }
+ if (ecp->clen == 0)
+ goto usage;
+
+ /* Followed by the string. */
+ for (p = t = ecp->cp; ecp->clen > 0;
+ --ecp->clen, ++ecp->cp, ++p) {
+ ch = *ecp->cp;
+ if (IS_ESCAPE(sp,
+ ecp, ch) && ecp->clen > 1) {
+ --ecp->clen;
+ *p = *++ecp->cp;
+ } else
+ *p = ch;
+ }
+ if (argv_exp0(sp, ecp, t, p - t))
+ goto err;
+ goto addr_verify;
+ case 'w': /* word */
+ if (argv_exp3(sp, ecp, ecp->cp, ecp->clen))
+ goto err;
+arg_cnt_chk: if (*++p != 'N') { /* N */
+ /*
+ * If a number is specified, must either be
+ * 0 or that number, if optional, and that
+ * number, if required.
+ */
+ tmp = *p - '0';
+ if ((*++p != 'o' || exp->argsoff != 0) &&
+ exp->argsoff != tmp)
+ goto usage;
+ }
+ goto addr_verify;
+ default:
+ msgq(sp, M_ERR,
+ "085|Internal syntax table error (%s: %s)",
+ ecp->cmd->name, KEY_NAME(sp, *p));
+ }
+ }
+
+ /* Skip trailing whitespace. */
+ for (; ecp->clen > 0; --ecp->clen) {
+ ch = *ecp->cp++;
+ if (!isblank(ch))
+ break;
+ }
+
+ /*
+ * There shouldn't be anything left, and no more required fields,
+ * i.e neither 'l' or 'r' in the syntax string.
+ */
+ if (ecp->clen != 0 || strpbrk(p, "lr")) {
+usage: msgq(sp, M_ERR, "086|Usage: %s", ecp->cmd->usage);
+ goto err;
+ }
+
+ /*
+ * Verify that the addresses are legal. Check the addresses here,
+ * because this is a place where all ex addresses pass through.
+ * (They don't all pass through ex_line(), for instance.) We're
+ * assuming that any non-existent line doesn't exist because it's
+ * past the end-of-file. That's a pretty good guess.
+ *
+ * If it's a "default vi command", an address of zero is okay.
+ */
+addr_verify:
+ switch (ecp->addrcnt) {
+ case 2:
+ /*
+ * Historic ex/vi permitted commands with counts to go past
+ * EOF. So, for example, if the file only had 5 lines, the
+ * ex command "1,6>" would fail, but the command ">300"
+ * would succeed. Since we don't want to have to make all
+ * of the underlying commands handle random line numbers,
+ * fix it here.
+ */
+ if (ecp->addr2.lno == 0) {
+ if (!F_ISSET(ecp, E_ADDR_ZERO) &&
+ (F_ISSET(sp, SC_EX) ||
+ !F_ISSET(ecp, E_USELASTCMD))) {
+ ex_badaddr(sp, ecp->cmd, A_ZERO, NUM_OK);
+ goto err;
+ }
+ } else if (!db_exist(sp, ecp->addr2.lno))
+ if (FL_ISSET(ecp->iflags, E_C_COUNT)) {
+ if (db_last(sp, &lno))
+ goto err;
+ ecp->addr2.lno = lno;
+ } else {
+ ex_badaddr(sp, NULL, A_EOF, NUM_OK);
+ goto err;
+ }
+ /* FALLTHROUGH */
+ case 1:
+ if (ecp->addr1.lno == 0) {
+ if (!F_ISSET(ecp, E_ADDR_ZERO) &&
+ (F_ISSET(sp, SC_EX) ||
+ !F_ISSET(ecp, E_USELASTCMD))) {
+ ex_badaddr(sp, ecp->cmd, A_ZERO, NUM_OK);
+ goto err;
+ }
+ } else if (!db_exist(sp, ecp->addr1.lno)) {
+ ex_badaddr(sp, NULL, A_EOF, NUM_OK);
+ goto err;
+ }
+ break;
+ }
+
+ /*
+ * If doing a default command and there's nothing left on the line,
+ * vi just moves to the line. For example, ":3" and ":'a,'b" just
+ * move to line 3 and line 'b, respectively, but ":3|" prints line 3.
+ *
+ * !!!
+ * In addition, IF THE LINE CHANGES, move to the first nonblank of
+ * the line.
+ *
+ * !!!
+ * This is done before the absolute mark gets set; historically,
+ * "/a/,/b/" did NOT set vi's absolute mark, but "/a/,/b/d" did.
+ */
+ if ((F_ISSET(sp, SC_VI) || F_ISSET(ecp, E_NOPRDEF)) &&
+ F_ISSET(ecp, E_USELASTCMD) && vi_address == 0) {
+ switch (ecp->addrcnt) {
+ case 2:
+ if (sp->lno !=
+ (ecp->addr2.lno ? ecp->addr2.lno : 1)) {
+ sp->lno =
+ ecp->addr2.lno ? ecp->addr2.lno : 1;
+ sp->cno = 0;
+ (void)nonblank(sp, sp->lno, &sp->cno);
+ }
+ break;
+ case 1:
+ if (sp->lno !=
+ (ecp->addr1.lno ? ecp->addr1.lno : 1)) {
+ sp->lno =
+ ecp->addr1.lno ? ecp->addr1.lno : 1;
+ sp->cno = 0;
+ (void)nonblank(sp, sp->lno, &sp->cno);
+ }
+ break;
+ }
+ ecp->cp = ecp->save_cmd;
+ ecp->clen = ecp->save_cmdlen;
+ goto loop;
+ }
+
+ /*
+ * Set the absolute mark -- we have to set it for vi here, in case
+ * it's a compound command, e.g. ":5p|6" should set the absolute
+ * mark for vi.
+ */
+ if (F_ISSET(ecp, E_ABSMARK)) {
+ cur.lno = sp->lno;
+ cur.cno = sp->cno;
+ F_CLR(ecp, E_ABSMARK);
+ if (mark_set(sp, ABSMARK1, &cur, 1))
+ goto err;
+ }
+
+#if defined(DEBUG) && defined(COMLOG)
+ ex_comlog(sp, ecp);
+#endif
+ /* Increment the command count if not called from vi. */
+ if (F_ISSET(sp, SC_EX))
+ ++sp->ccnt;
+
+ /*
+ * If file state available, and not doing a global command,
+ * log the start of an action.
+ */
+ if (sp->ep != NULL && !F_ISSET(sp, SC_EX_GLOBAL))
+ (void)log_cursor(sp);
+
+ /*
+ * !!!
+ * There are two special commands for the purposes of this code: the
+ * default command (<carriage-return>) or the scrolling commands (^D
+ * and <EOF>) as the first non-<blank> characters in the line.
+ *
+ * If this is the first command in the command line, we received the
+ * command from the ex command loop and we're talking to a tty, and
+ * and there's nothing else on the command line, and it's one of the
+ * special commands, we move back up to the previous line, and erase
+ * the prompt character with the output. Since ex runs in canonical
+ * mode, we don't have to do anything else, a <newline> has already
+ * been echoed by the tty driver. It's OK if vi calls us -- we won't
+ * be in ex mode so we'll do nothing.
+ */
+ if (F_ISSET(ecp, E_NRSEP)) {
+ if (sp->ep != NULL &&
+ F_ISSET(sp, SC_EX) && !F_ISSET(gp, G_SCRIPTED) &&
+ (F_ISSET(ecp, E_USELASTCMD) || ecp->cmd == &cmds[C_SCROLL]))
+ gp->scr_ex_adjust(sp, EX_TERM_SCROLL);
+ F_CLR(ecp, E_NRSEP);
+ }
+
+ /*
+ * Call the underlying function for the ex command.
+ *
+ * XXX
+ * Interrupts behave like errors, for now.
+ */
+ if (ecp->cmd->fn(sp, ecp) || INTERRUPTED(sp)) {
+ if (F_ISSET(gp, G_SCRIPTED))
+ F_SET(sp, SC_EXIT_FORCE);
+ goto err;
+ }
+
+#ifdef DEBUG
+ /* Make sure no function left global temporary space locked. */
+ if (F_ISSET(gp, G_TMP_INUSE)) {
+ F_CLR(gp, G_TMP_INUSE);
+ msgq(sp, M_ERR, "087|%s: temporary buffer not released",
+ ecp->cmd->name);
+ }
+#endif
+ /*
+ * Ex displayed the number of lines modified immediately after each
+ * command, so the command "1,10d|1,10d" would display:
+ *
+ * 10 lines deleted
+ * 10 lines deleted
+ * <autoprint line>
+ *
+ * Executing ex commands from vi only reported the final modified
+ * lines message -- that's wrong enough that we don't match it.
+ */
+ if (F_ISSET(sp, SC_EX))
+ mod_rpt(sp);
+
+ /*
+ * Integrate any offset parsed by the underlying command, and make
+ * sure the referenced line exists.
+ *
+ * XXX
+ * May not match historic practice (which I've never been able to
+ * completely figure out.) For example, the '=' command from vi
+ * mode often got the offset wrong, and complained it was too large,
+ * but didn't seem to have a problem with the cursor. If anyone
+ * complains, ask them how it's supposed to work, they might know.
+ */
+ if (sp->ep != NULL && ecp->flagoff) {
+ if (ecp->flagoff < 0) {
+ if (sp->lno <= -ecp->flagoff) {
+ msgq(sp, M_ERR,
+ "088|Flag offset to before line 1");
+ goto err;
+ }
+ } else {
+ if (!NPFITS(MAX_REC_NUMBER, sp->lno, ecp->flagoff)) {
+ ex_badaddr(sp, NULL, A_NOTSET, NUM_OVER);
+ goto err;
+ }
+ if (!db_exist(sp, sp->lno + ecp->flagoff)) {
+ msgq(sp, M_ERR,
+ "089|Flag offset past end-of-file");
+ goto err;
+ }
+ }
+ sp->lno += ecp->flagoff;
+ }
+
+ /*
+ * If the command executed successfully, we may want to display a line
+ * based on the autoprint option or an explicit print flag. (Make sure
+ * that there's a line to display.) Also, the autoprint edit option is
+ * turned off for the duration of global commands.
+ */
+ if (F_ISSET(sp, SC_EX) && sp->ep != NULL && sp->lno != 0) {
+ /*
+ * The print commands have already handled the `print' flags.
+ * If so, clear them.
+ */
+ if (FL_ISSET(ecp->iflags, E_CLRFLAG))
+ FL_CLR(ecp->iflags, E_C_HASH | E_C_LIST | E_C_PRINT);
+
+ /* If hash set only because of the number option, discard it. */
+ if (F_ISSET(ecp, E_OPTNUM))
+ FL_CLR(ecp->iflags, E_C_HASH);
+
+ /*
+ * If there was an explicit flag to display the new cursor line,
+ * or autoprint is set and a change was made, display the line.
+ * If any print flags were set use them, else default to print.
+ */
+ LF_INIT(FL_ISSET(ecp->iflags, E_C_HASH | E_C_LIST | E_C_PRINT));
+ if (!LF_ISSET(E_C_HASH | E_C_LIST | E_C_PRINT | E_NOAUTO) &&
+ !F_ISSET(sp, SC_EX_GLOBAL) &&
+ O_ISSET(sp, O_AUTOPRINT) && F_ISSET(ecp, E_AUTOPRINT))
+ LF_INIT(E_C_PRINT);
+
+ if (LF_ISSET(E_C_HASH | E_C_LIST | E_C_PRINT)) {
+ cur.lno = sp->lno;
+ cur.cno = 0;
+ (void)ex_print(sp, ecp, &cur, &cur, flags);
+ }
+ }
+
+ /*
+ * If the command had an associated "+cmd", it has to be executed
+ * before we finish executing any more of this ex command. For
+ * example, consider a .exrc file that contains the following lines:
+ *
+ * :set all
+ * :edit +25 file.c|s/abc/ABC/|1
+ * :3,5 print
+ *
+ * This can happen more than once -- the historic vi simply hung or
+ * dropped core, of course. Prepend the + command back into the
+ * current command and continue. We may have to add an additional
+ * <literal next> character. We know that it will fit because we
+ * discarded at least one space and the + character.
+ */
+ if (arg1_len != 0) {
+ /*
+ * If the last character of the + command was a <literal next>
+ * character, it would be treated differently because of the
+ * append. Quote it, if necessary.
+ */
+ if (IS_ESCAPE(sp, ecp, arg1[arg1_len - 1])) {
+ *--ecp->save_cmd = CH_LITERAL;
+ ++ecp->save_cmdlen;
+ }
+
+ ecp->save_cmd -= arg1_len;
+ ecp->save_cmdlen += arg1_len;
+ memcpy(ecp->save_cmd, arg1, arg1_len);
+
+ /*
+ * Any commands executed from a +cmd are executed starting at
+ * the first column of the last line of the file -- NOT the
+ * first nonblank.) The main file startup code doesn't know
+ * that a +cmd was set, however, so it may have put us at the
+ * top of the file. (Note, this is safe because we must have
+ * switched files to get here.)
+ */
+ F_SET(ecp, E_MOVETOEND);
+ }
+
+ /* Update the current command. */
+ ecp->cp = ecp->save_cmd;
+ ecp->clen = ecp->save_cmdlen;
+
+ /*
+ * !!!
+ * If we've changed screens or underlying files, any pending global or
+ * v command, or @ buffer that has associated addresses, has to be
+ * discarded. This is historic practice for globals, and necessary for
+ * @ buffers that had associated addresses.
+ *
+ * Otherwise, if we've changed underlying files, it's not a problem,
+ * we continue with the rest of the ex command(s), operating on the
+ * new file. However, if we switch screens (either by exiting or by
+ * an explicit command), we have no way of knowing where to put output
+ * messages, and, since we don't control screens here, we could screw
+ * up the upper layers, (e.g. we could exit/reenter a screen multiple
+ * times). So, return and continue after we've got a new screen.
+ */
+ if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE | SC_FSWITCH | SC_SSWITCH)) {
+ at_found = gv_found = 0;
+ for (ecp = sp->gp->ecq.lh_first;
+ ecp != NULL; ecp = ecp->q.le_next)
+ switch (ecp->agv_flags) {
+ case 0:
+ case AGV_AT_NORANGE:
+ break;
+ case AGV_AT:
+ if (!at_found) {
+ at_found = 1;
+ msgq(sp, M_ERR,
+ "090|@ with range running when the file/screen changed");
+ }
+ break;
+ case AGV_GLOBAL:
+ case AGV_V:
+ if (!gv_found) {
+ gv_found = 1;
+ msgq(sp, M_ERR,
+ "091|Global/v command running when the file/screen changed");
+ }
+ break;
+ default:
+ abort();
+ }
+ if (at_found || gv_found)
+ goto discard;
+ if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE | SC_SSWITCH))
+ goto rsuccess;
+ }
+
+ goto loop;
+ /* NOTREACHED */
+
+err: /*
+ * On command failure, we discard keys and pending commands remaining,
+ * as well as any keys that were mapped and waiting. The save_cmdlen
+ * test is not necessarily correct. If we fail early enough we don't
+ * know if the entire string was a single command or not. Guess, as
+ * it's useful to know if commands other than the current one are being
+ * discarded.
+ */
+ if (ecp->save_cmdlen == 0)
+ for (; ecp->clen; --ecp->clen) {
+ ch = *ecp->cp++;
+ if (IS_ESCAPE(sp, ecp, ch) && ecp->clen > 1) {
+ --ecp->clen;
+ ++ecp->cp;
+ } else if (ch == '\n' || ch == '|') {
+ if (ecp->clen > 1)
+ ecp->save_cmdlen = 1;
+ break;
+ }
+ }
+ if (ecp->save_cmdlen != 0 || gp->ecq.lh_first != &gp->excmd) {
+discard: msgq(sp, M_BERR,
+ "092|Ex command failed: pending commands discarded");
+ ex_discard(sp);
+ }
+ if (v_event_flush(sp, CH_MAPPED))
+ msgq(sp, M_BERR,
+ "093|Ex command failed: mapped keys discarded");
+
+rfail: tmp = 1;
+ if (0)
+rsuccess: tmp = 0;
+
+ /* Turn off any file name error information. */
+ gp->if_name = NULL;
+
+ /* Turn off the global bit. */
+ F_CLR(sp, SC_EX_GLOBAL);
+
+ return (tmp);
+}
+
+/*
+ * ex_range --
+ * Get a line range for ex commands, or perform a vi ex address search.
+ *
+ * PUBLIC: int ex_range __P((SCR *, EXCMD *, int *));
+ */
+int
+ex_range(sp, ecp, errp)
+ SCR *sp;
+ EXCMD *ecp;
+ int *errp;
+{
+ enum { ADDR_FOUND, ADDR_NEED, ADDR_NONE } addr;
+ GS *gp;
+ EX_PRIVATE *exp;
+ MARK m;
+ int isaddr;
+
+ *errp = 0;
+
+ /*
+ * Parse comma or semi-colon delimited line specs.
+ *
+ * Semi-colon delimiters update the current address to be the last
+ * address. For example, the command
+ *
+ * :3;/pattern/ecp->cp
+ *
+ * will search for pattern from line 3. In addition, if ecp->cp
+ * is not a valid command, the current line will be left at 3, not
+ * at the original address.
+ *
+ * Extra addresses are discarded, starting with the first.
+ *
+ * !!!
+ * If any addresses are missing, they default to the current line.
+ * This was historically true for both leading and trailing comma
+ * delimited addresses as well as for trailing semicolon delimited
+ * addresses. For consistency, we make it true for leading semicolon
+ * addresses as well.
+ */
+ gp = sp->gp;
+ exp = EXP(sp);
+ for (addr = ADDR_NONE, ecp->addrcnt = 0; ecp->clen > 0;)
+ switch (*ecp->cp) {
+ case '%': /* Entire file. */
+ /* Vi ex address searches didn't permit % signs. */
+ if (F_ISSET(ecp, E_VISEARCH))
+ goto ret;
+
+ /* It's an error if the file is empty. */
+ if (sp->ep == NULL) {
+ ex_badaddr(sp, NULL, A_EMPTY, NUM_OK);
+ *errp = 1;
+ return (0);
+ }
+ /*
+ * !!!
+ * A percent character addresses all of the lines in
+ * the file. Historically, it couldn't be followed by
+ * any other address. We do it as a text substitution
+ * for simplicity. POSIX 1003.2 is expected to follow
+ * this practice.
+ *
+ * If it's an empty file, the first line is 0, not 1.
+ */
+ if (addr == ADDR_FOUND) {
+ ex_badaddr(sp, NULL, A_COMBO, NUM_OK);
+ *errp = 1;
+ return (0);
+ }
+ if (db_last(sp, &ecp->addr2.lno))
+ return (1);
+ ecp->addr1.lno = ecp->addr2.lno == 0 ? 0 : 1;
+ ecp->addr1.cno = ecp->addr2.cno = 0;
+ ecp->addrcnt = 2;
+ addr = ADDR_FOUND;
+ ++ecp->cp;
+ --ecp->clen;
+ break;
+ case ',': /* Comma delimiter. */
+ /* Vi ex address searches didn't permit commas. */
+ if (F_ISSET(ecp, E_VISEARCH))
+ goto ret;
+ /* FALLTHROUGH */
+ case ';': /* Semi-colon delimiter. */
+ if (sp->ep == NULL) {
+ ex_badaddr(sp, NULL, A_EMPTY, NUM_OK);
+ *errp = 1;
+ return (0);
+ }
+ if (addr != ADDR_FOUND)
+ switch (ecp->addrcnt) {
+ case 0:
+ ecp->addr1.lno = sp->lno;
+ ecp->addr1.cno = sp->cno;
+ ecp->addrcnt = 1;
+ break;
+ case 2:
+ ecp->addr1 = ecp->addr2;
+ /* FALLTHROUGH */
+ case 1:
+ ecp->addr2.lno = sp->lno;
+ ecp->addr2.cno = sp->cno;
+ ecp->addrcnt = 2;
+ break;
+ }
+ if (*ecp->cp == ';')
+ switch (ecp->addrcnt) {
+ case 0:
+ abort();
+ /* NOTREACHED */
+ case 1:
+ sp->lno = ecp->addr1.lno;
+ sp->cno = ecp->addr1.cno;
+ break;
+ case 2:
+ sp->lno = ecp->addr2.lno;
+ sp->cno = ecp->addr2.cno;
+ break;
+ }
+ addr = ADDR_NEED;
+ /* FALLTHROUGH */
+ case ' ': /* Whitespace. */
+ case '\t': /* Whitespace. */
+ ++ecp->cp;
+ --ecp->clen;
+ break;
+ default:
+ /* Get a line specification. */
+ if (ex_line(sp, ecp, &m, &isaddr, errp))
+ return (1);
+ if (*errp)
+ return (0);
+ if (!isaddr)
+ goto ret;
+ if (addr == ADDR_FOUND) {
+ ex_badaddr(sp, NULL, A_COMBO, NUM_OK);
+ *errp = 1;
+ return (0);
+ }
+ switch (ecp->addrcnt) {
+ case 0:
+ ecp->addr1 = m;
+ ecp->addrcnt = 1;
+ break;
+ case 1:
+ ecp->addr2 = m;
+ ecp->addrcnt = 2;
+ break;
+ case 2:
+ ecp->addr1 = ecp->addr2;
+ ecp->addr2 = m;
+ break;
+ }
+ addr = ADDR_FOUND;
+ break;
+ }
+
+ /*
+ * !!!
+ * Vi ex address searches are indifferent to order or trailing
+ * semi-colons.
+ */
+ret: if (F_ISSET(ecp, E_VISEARCH))
+ return (0);
+
+ if (addr == ADDR_NEED)
+ switch (ecp->addrcnt) {
+ case 0:
+ ecp->addr1.lno = sp->lno;
+ ecp->addr1.cno = sp->cno;
+ ecp->addrcnt = 1;
+ break;
+ case 2:
+ ecp->addr1 = ecp->addr2;
+ /* FALLTHROUGH */
+ case 1:
+ ecp->addr2.lno = sp->lno;
+ ecp->addr2.cno = sp->cno;
+ ecp->addrcnt = 2;
+ break;
+ }
+
+ if (ecp->addrcnt == 2 && ecp->addr2.lno < ecp->addr1.lno) {
+ msgq(sp, M_ERR,
+ "094|The second address is smaller than the first");
+ *errp = 1;
+ }
+ return (0);
+}
+
+/*
+ * ex_line --
+ * Get a single line address specifier.
+ *
+ * The way the "previous context" mark worked was that any "non-relative"
+ * motion set it. While ex/vi wasn't totally consistent about this, ANY
+ * numeric address, search pattern, '$', or mark reference in an address
+ * was considered non-relative, and set the value. Which should explain
+ * why we're hacking marks down here. The problem was that the mark was
+ * only set if the command was called, i.e. we have to set a flag and test
+ * it later.
+ *
+ * XXX
+ * This is probably still not exactly historic practice, although I think
+ * it's fairly close.
+ */
+static int
+ex_line(sp, ecp, mp, isaddrp, errp)
+ SCR *sp;
+ EXCMD *ecp;
+ MARK *mp;
+ int *isaddrp, *errp;
+{
+ enum nresult nret;
+ EX_PRIVATE *exp;
+ GS *gp;
+ long total, val;
+ int isneg;
+ int (*sf) __P((SCR *, MARK *, MARK *, char *, size_t, char **, u_int));
+ char *endp;
+
+ gp = sp->gp;
+ exp = EXP(sp);
+
+ *isaddrp = *errp = 0;
+ F_CLR(ecp, E_DELTA);
+
+ /* No addresses permitted until a file has been read in. */
+ if (sp->ep == NULL && strchr("$0123456789'\\/?.+-^", *ecp->cp)) {
+ ex_badaddr(sp, NULL, A_EMPTY, NUM_OK);
+ *errp = 1;
+ return (0);
+ }
+
+ switch (*ecp->cp) {
+ case '$': /* Last line in the file. */
+ *isaddrp = 1;
+ F_SET(ecp, E_ABSMARK);
+
+ mp->cno = 0;
+ if (db_last(sp, &mp->lno))
+ return (1);
+ ++ecp->cp;
+ --ecp->clen;
+ break; /* Absolute line number. */
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ *isaddrp = 1;
+ F_SET(ecp, E_ABSMARK);
+
+ if ((nret = nget_slong(&val, ecp->cp, &endp, 10)) != NUM_OK) {
+ ex_badaddr(sp, NULL, A_NOTSET, nret);
+ *errp = 1;
+ return (0);
+ }
+ if (!NPFITS(MAX_REC_NUMBER, 0, val)) {
+ ex_badaddr(sp, NULL, A_NOTSET, NUM_OVER);
+ *errp = 1;
+ return (0);
+ }
+ mp->lno = val;
+ mp->cno = 0;
+ ecp->clen -= (endp - ecp->cp);
+ ecp->cp = endp;
+ break;
+ case '\'': /* Use a mark. */
+ *isaddrp = 1;
+ F_SET(ecp, E_ABSMARK);
+
+ if (ecp->clen == 1) {
+ msgq(sp, M_ERR, "095|No mark name supplied");
+ *errp = 1;
+ return (0);
+ }
+ if (mark_get(sp, ecp->cp[1], mp, M_ERR)) {
+ *errp = 1;
+ return (0);
+ }
+ ecp->cp += 2;
+ ecp->clen -= 2;
+ break;
+ case '\\': /* Search: forward/backward. */
+ /*
+ * !!!
+ * I can't find any difference between // and \/ or between
+ * ?? and \?. Mark Horton doesn't remember there being any
+ * difference. C'est la vie.
+ */
+ if (ecp->clen < 2 ||
+ ecp->cp[1] != '/' && ecp->cp[1] != '?') {
+ msgq(sp, M_ERR, "096|\\ not followed by / or ?");
+ *errp = 1;
+ return (0);
+ }
+ ++ecp->cp;
+ --ecp->clen;
+ sf = ecp->cp[0] == '/' ? f_search : b_search;
+ goto search;
+ case '/': /* Search forward. */
+ sf = f_search;
+ goto search;
+ case '?': /* Search backward. */
+ sf = b_search;
+
+search: mp->lno = sp->lno;
+ mp->cno = sp->cno;
+ if (sf(sp, mp, mp, ecp->cp, ecp->clen, &endp,
+ SEARCH_MSG | SEARCH_PARSE | SEARCH_SET |
+ (F_ISSET(ecp, E_SEARCH_WMSG) ? SEARCH_WMSG : 0))) {
+ *errp = 1;
+ return (0);
+ }
+
+ /* Fix up the command pointers. */
+ ecp->clen -= (endp - ecp->cp);
+ ecp->cp = endp;
+
+ *isaddrp = 1;
+ F_SET(ecp, E_ABSMARK);
+ break;
+ case '.': /* Current position. */
+ *isaddrp = 1;
+ mp->cno = sp->cno;
+
+ /* If an empty file, then '.' is 0, not 1. */
+ if (sp->lno == 1) {
+ if (db_last(sp, &mp->lno))
+ return (1);
+ if (mp->lno != 0)
+ mp->lno = 1;
+ } else
+ mp->lno = sp->lno;
+
+ /*
+ * !!!
+ * Historically, .<number> was the same as .+<number>, i.e.
+ * the '+' could be omitted. (This feature is found in ed
+ * as well.)
+ */
+ if (ecp->clen > 1 && isdigit(ecp->cp[1]))
+ *ecp->cp = '+';
+ else {
+ ++ecp->cp;
+ --ecp->clen;
+ }
+ break;
+ }
+
+ /* Skip trailing <blank>s. */
+ for (; ecp->clen > 0 &&
+ isblank(ecp->cp[0]); ++ecp->cp, --ecp->clen);
+
+ /*
+ * Evaluate any offset. If no address yet found, the offset
+ * is relative to ".".
+ */
+ total = 0;
+ if (ecp->clen != 0 && (isdigit(ecp->cp[0]) ||
+ ecp->cp[0] == '+' || ecp->cp[0] == '-' ||
+ ecp->cp[0] == '^')) {
+ if (!*isaddrp) {
+ *isaddrp = 1;
+ mp->lno = sp->lno;
+ mp->cno = sp->cno;
+ }
+ /*
+ * Evaluate an offset, defined as:
+ *
+ * [+-^<blank>]*[<blank>]*[0-9]*
+ *
+ * The rough translation is any number of signs, optionally
+ * followed by numbers, or a number by itself, all <blank>
+ * separated.
+ *
+ * !!!
+ * All address offsets were additive, e.g. "2 2 3p" was the
+ * same as "7p", or, "/ZZZ/ 2" was the same as "/ZZZ/+2".
+ * Note, however, "2 /ZZZ/" was an error. It was also legal
+ * to insert signs without numbers, so "3 - 2" was legal, and
+ * equal to 4.
+ *
+ * !!!
+ * Offsets were historically permitted for any line address,
+ * e.g. the command "1,2 copy 2 2 2 2" copied lines 1,2 after
+ * line 8.
+ *
+ * !!!
+ * Offsets were historically permitted for search commands,
+ * and handled as addresses: "/pattern/2 2 2" was legal, and
+ * referenced the 6th line after pattern.
+ */
+ F_SET(ecp, E_DELTA);
+ for (;;) {
+ for (; ecp->clen > 0 && isblank(ecp->cp[0]);
+ ++ecp->cp, --ecp->clen);
+ if (ecp->clen == 0 || !isdigit(ecp->cp[0]) &&
+ ecp->cp[0] != '+' && ecp->cp[0] != '-' &&
+ ecp->cp[0] != '^')
+ break;
+ if (!isdigit(ecp->cp[0]) &&
+ !isdigit(ecp->cp[1])) {
+ total += ecp->cp[0] == '+' ? 1 : -1;
+ --ecp->clen;
+ ++ecp->cp;
+ } else {
+ if (ecp->cp[0] == '-' ||
+ ecp->cp[0] == '^') {
+ ++ecp->cp;
+ --ecp->clen;
+ isneg = 1;
+ } else
+ isneg = 0;
+
+ /* Get a signed long, add it to the total. */
+ if ((nret = nget_slong(&val,
+ ecp->cp, &endp, 10)) != NUM_OK ||
+ (nret = NADD_SLONG(sp,
+ total, val)) != NUM_OK) {
+ ex_badaddr(sp, NULL, A_NOTSET, nret);
+ *errp = 1;
+ return (0);
+ }
+ total += isneg ? -val : val;
+ ecp->clen -= (endp - ecp->cp);
+ ecp->cp = endp;
+ }
+ }
+ }
+
+ /*
+ * Any value less than 0 is an error. Make sure that the new value
+ * will fit into a recno_t.
+ */
+ if (*isaddrp && total != 0) {
+ if (total < 0) {
+ if (-total > mp->lno) {
+ msgq(sp, M_ERR,
+ "097|Reference to a line number less than 0");
+ *errp = 1;
+ return (0);
+ }
+ } else
+ if (!NPFITS(MAX_REC_NUMBER, mp->lno, total)) {
+ ex_badaddr(sp, NULL, A_NOTSET, NUM_OVER);
+ *errp = 1;
+ return (0);
+ }
+ mp->lno += total;
+ }
+ return (0);
+}
+
+
+/*
+ * ex_load --
+ * Load up the next command, which may be an @ buffer or global command.
+ */
+static int
+ex_load(sp)
+ SCR *sp;
+{
+ GS *gp;
+ EXCMD *ecp;
+ RANGE *rp;
+
+ F_CLR(sp, SC_EX_GLOBAL);
+
+ /*
+ * Lose any exhausted commands. We know that the first command
+ * can't be an AGV command, which makes things a bit easier.
+ */
+ for (gp = sp->gp;;) {
+ /*
+ * If we're back to the original structure, leave it around,
+ * but discard any allocated source name, we've returned to
+ * the beginning of the command stack.
+ */
+ if ((ecp = gp->ecq.lh_first) == &gp->excmd) {
+ if (F_ISSET(ecp, E_NAMEDISCARD)) {
+ free(ecp->if_name);
+ ecp->if_name = NULL;
+ }
+ return (0);
+ }
+
+ /*
+ * ecp->clen will be 0 for the first discarded command, but
+ * may not be 0 for subsequent ones, e.g. if the original
+ * command was ":g/xx/@a|s/b/c/", then when we discard the
+ * command pushed on the stack by the @a, we have to resume
+ * the global command which included the substitute command.
+ */
+ if (ecp->clen != 0)
+ return (0);
+
+ /*
+ * If it's an @, global or v command, we may need to continue
+ * the command on a different line.
+ */
+ if (FL_ISSET(ecp->agv_flags, AGV_ALL)) {
+ /* Discard any exhausted ranges. */
+ while ((rp = ecp->rq.cqh_first) != (void *)&ecp->rq)
+ if (rp->start > rp->stop) {
+ CIRCLEQ_REMOVE(&ecp->rq, rp, q);
+ free(rp);
+ } else
+ break;
+
+ /* If there's another range, continue with it. */
+ if (rp != (void *)&ecp->rq)
+ break;
+
+ /* If it's a global/v command, fix up the last line. */
+ if (FL_ISSET(ecp->agv_flags,
+ AGV_GLOBAL | AGV_V) && ecp->range_lno != OOBLNO)
+ if (db_exist(sp, ecp->range_lno))
+ sp->lno = ecp->range_lno;
+ else {
+ if (db_last(sp, &sp->lno))
+ return (1);
+ if (sp->lno == 0)
+ sp->lno = 1;
+ }
+ free(ecp->o_cp);
+ }
+
+ /* Discard the EXCMD. */
+ LIST_REMOVE(ecp, q);
+ free(ecp);
+ }
+
+ /*
+ * We only get here if it's an active @, global or v command. Set
+ * the current line number, and get a new copy of the command for
+ * the parser. Note, the original pointer almost certainly moved,
+ * so we have play games.
+ */
+ ecp->cp = ecp->o_cp;
+ memcpy(ecp->cp, ecp->cp + ecp->o_clen, ecp->o_clen);
+ ecp->clen = ecp->o_clen;
+ ecp->range_lno = sp->lno = rp->start++;
+
+ if (FL_ISSET(ecp->agv_flags, AGV_GLOBAL | AGV_V))
+ F_SET(sp, SC_EX_GLOBAL);
+ return (0);
+}
+
+/*
+ * ex_discard --
+ * Discard any pending ex commands.
+ */
+static int
+ex_discard(sp)
+ SCR *sp;
+{
+ GS *gp;
+ EXCMD *ecp;
+ RANGE *rp;
+
+ /*
+ * We know the first command can't be an AGV command, so we don't
+ * process it specially. We do, however, nail the command itself.
+ */
+ for (gp = sp->gp; (ecp = gp->ecq.lh_first) != &gp->excmd;) {
+ if (FL_ISSET(ecp->agv_flags, AGV_ALL)) {
+ while ((rp = ecp->rq.cqh_first) != (void *)&ecp->rq) {
+ CIRCLEQ_REMOVE(&ecp->rq, rp, q);
+ free(rp);
+ }
+ free(ecp->o_cp);
+ }
+ LIST_REMOVE(ecp, q);
+ free(ecp);
+ }
+ gp->ecq.lh_first->clen = 0;
+ return (0);
+}
+
+/*
+ * ex_unknown --
+ * Display an unknown command name.
+ */
+static void
+ex_unknown(sp, cmd, len)
+ SCR *sp;
+ char *cmd;
+ size_t len;
+{
+ size_t blen;
+ char *bp;
+
+ GET_SPACE_GOTO(sp, bp, blen, len + 1);
+ bp[len] = '\0';
+ memcpy(bp, cmd, len);
+ msgq_str(sp, M_ERR, bp, "098|The %s command is unknown");
+ FREE_SPACE(sp, bp, blen);
+
+alloc_err:
+ return;
+}
+
+/*
+ * ex_is_abbrev -
+ * The vi text input routine needs to know if ex thinks this is an
+ * [un]abbreviate command, so it can turn off abbreviations. See
+ * the usual ranting in the vi/v_txt_ev.c:txt_abbrev() routine.
+ *
+ * PUBLIC: int ex_is_abbrev __P((char *, size_t));
+ */
+int
+ex_is_abbrev(name, len)
+ char *name;
+ size_t len;
+{
+ EXCMDLIST const *cp;
+
+ return ((cp = ex_comm_search(name, len)) != NULL &&
+ (cp == &cmds[C_ABBR] || cp == &cmds[C_UNABBREVIATE]));
+}
+
+/*
+ * ex_is_unmap -
+ * The vi text input routine needs to know if ex thinks this is an
+ * unmap command, so it can turn off input mapping. See the usual
+ * ranting in the vi/v_txt_ev.c:txt_unmap() routine.
+ *
+ * PUBLIC: int ex_is_unmap __P((char *, size_t));
+ */
+int
+ex_is_unmap(name, len)
+ char *name;
+ size_t len;
+{
+ EXCMDLIST const *cp;
+
+ /*
+ * The command the vi input routines are really interested in
+ * is "unmap!", not just unmap.
+ */
+ if (name[len - 1] != '!')
+ return (0);
+ --len;
+ return ((cp = ex_comm_search(name, len)) != NULL &&
+ cp == &cmds[C_UNMAP]);
+}
+
+/*
+ * ex_comm_search --
+ * Search for a command name.
+ */
+static EXCMDLIST const *
+ex_comm_search(name, len)
+ char *name;
+ size_t len;
+{
+ EXCMDLIST const *cp;
+
+ for (cp = cmds; cp->name != NULL; ++cp) {
+ if (cp->name[0] > name[0])
+ return (NULL);
+ if (cp->name[0] != name[0])
+ continue;
+ if (!memcmp(name, cp->name, len))
+ return (cp);
+ }
+ return (NULL);
+}
+
+/*
+ * ex_badaddr --
+ * Display a bad address message.
+ *
+ * PUBLIC: void ex_badaddr
+ * PUBLIC: __P((SCR *, EXCMDLIST const *, enum badaddr, enum nresult));
+ */
+void
+ex_badaddr(sp, cp, ba, nret)
+ SCR *sp;
+ EXCMDLIST const *cp;
+ enum badaddr ba;
+ enum nresult nret;
+{
+ recno_t lno;
+
+ switch (nret) {
+ case NUM_OK:
+ break;
+ case NUM_ERR:
+ msgq(sp, M_SYSERR, NULL);
+ return;
+ case NUM_OVER:
+ msgq(sp, M_ERR, "099|Address value overflow");
+ return;
+ case NUM_UNDER:
+ msgq(sp, M_ERR, "100|Address value underflow");
+ return;
+ }
+
+ /*
+ * When encountering an address error, tell the user if there's no
+ * underlying file, that's the real problem.
+ */
+ if (sp->ep == NULL) {
+ ex_emsg(sp, cp->name, EXM_NOFILEYET);
+ return;
+ }
+
+ switch (ba) {
+ case A_COMBO:
+ msgq(sp, M_ERR, "101|Illegal address combination");
+ break;
+ case A_EOF:
+ if (db_last(sp, &lno))
+ return;
+ if (lno != 0) {
+ msgq(sp, M_ERR,
+ "102|Illegal address: only %lu lines in the file",
+ lno);
+ break;
+ }
+ /* FALLTHROUGH */
+ case A_EMPTY:
+ msgq(sp, M_ERR, "103|Illegal address: the file is empty");
+ break;
+ case A_NOTSET:
+ abort();
+ /* NOTREACHED */
+ case A_ZERO:
+ msgq(sp, M_ERR,
+ "104|The %s command doesn't permit an address of 0",
+ cp->name);
+ break;
+ }
+ return;
+}
+
+#if defined(DEBUG) && defined(COMLOG)
+/*
+ * ex_comlog --
+ * Log ex commands.
+ */
+static void
+ex_comlog(sp, ecp)
+ SCR *sp;
+ EXCMD *ecp;
+{
+ TRACE(sp, "ecmd: %s", ecp->cmd->name);
+ if (ecp->addrcnt > 0) {
+ TRACE(sp, " a1 %d", ecp->addr1.lno);
+ if (ecp->addrcnt > 1)
+ TRACE(sp, " a2: %d", ecp->addr2.lno);
+ }
+ if (ecp->lineno)
+ TRACE(sp, " line %d", ecp->lineno);
+ if (ecp->flags)
+ TRACE(sp, " flags 0x%x", ecp->flags);
+ if (F_ISSET(&exc, E_BUFFER))
+ TRACE(sp, " buffer %c", ecp->buffer);
+ if (ecp->argc)
+ for (cnt = 0; cnt < ecp->argc; ++cnt)
+ TRACE(sp, " arg %d: {%s}", cnt, ecp->argv[cnt]->bp);
+ TRACE(sp, "\n");
+}
+#endif
diff --git a/contrib/nvi/ex/ex.h b/contrib/nvi/ex/ex.h
new file mode 100644
index 000000000000..5870990b744e
--- /dev/null
+++ b/contrib/nvi/ex/ex.h
@@ -0,0 +1,228 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)ex.h 10.24 (Berkeley) 8/12/96
+ */
+
+#define PROMPTCHAR ':' /* Prompt using a colon. */
+
+typedef struct _excmdlist { /* Ex command table structure. */
+ char *name; /* Command name, underlying function. */
+ int (*fn) __P((SCR *, EXCMD *));
+
+#define E_ADDR1 0x00000001 /* One address. */
+#define E_ADDR2 0x00000002 /* Two addresses. */
+#define E_ADDR2_ALL 0x00000004 /* Zero/two addresses; zero == all. */
+#define E_ADDR2_NONE 0x00000008 /* Zero/two addresses; zero == none. */
+#define E_ADDR_ZERO 0x00000010 /* 0 is a legal addr1. */
+#define E_ADDR_ZERODEF 0x00000020 /* 0 is default addr1 of empty files. */
+#define E_AUTOPRINT 0x00000040 /* Command always sets autoprint. */
+#define E_CLRFLAG 0x00000080 /* Clear the print (#, l, p) flags. */
+#define E_NEWSCREEN 0x00000100 /* Create a new screen. */
+#define E_SECURE 0x00000200 /* Permission denied if O_SECURE set. */
+#define E_VIONLY 0x00000400 /* Meaningful only in vi. */
+#define __INUSE1 0xfffff800 /* Same name space as EX_PRIVATE. */
+ u_int16_t flags;
+
+ char *syntax; /* Syntax script. */
+ char *usage; /* Usage line. */
+ char *help; /* Help line. */
+} EXCMDLIST;
+
+#define MAXCMDNAMELEN 12 /* Longest command name. */
+extern EXCMDLIST const cmds[]; /* Table of ex commands. */
+
+/*
+ * !!!
+ * QUOTING NOTE:
+ *
+ * Historically, .exrc files and EXINIT variables could only use ^V as an
+ * escape character, neither ^Q or a user specified character worked. We
+ * enforce that here, just in case someone depends on it.
+ */
+#define IS_ESCAPE(sp, cmdp, ch) \
+ (F_ISSET(cmdp, E_VLITONLY) ? \
+ (ch) == CH_LITERAL : KEY_VAL(sp, ch) == K_VLNEXT)
+
+/*
+ * File state must be checked for each command -- any ex command may be entered
+ * at any time, and most of them won't work well if a file hasn't yet been read
+ * in. Historic vi generally took the easy way out and dropped core.
+ */
+#define NEEDFILE(sp, cmdp) { \
+ if ((sp)->ep == NULL) { \
+ ex_emsg(sp, (cmdp)->cmd->name, EXM_NOFILEYET); \
+ return (1); \
+ } \
+}
+
+/* Range structures for global and @ commands. */
+typedef struct _range RANGE;
+struct _range { /* Global command range. */
+ CIRCLEQ_ENTRY(_range) q; /* Linked list of ranges. */
+ recno_t start, stop; /* Start/stop of the range. */
+};
+
+/* Ex command structure. */
+struct _excmd {
+ LIST_ENTRY(_excmd) q; /* Linked list of commands. */
+
+ char *if_name; /* Associated file. */
+ recno_t if_lno; /* Associated line number. */
+
+ /* Clear the structure for the ex parser. */
+#define CLEAR_EX_PARSER(cmdp) \
+ memset(&((cmdp)->cp), 0, ((char *)&(cmdp)->flags - \
+ (char *)&((cmdp)->cp)) + sizeof((cmdp)->flags))
+
+ char *cp; /* Current command text. */
+ size_t clen; /* Current command length. */
+
+ char *save_cmd; /* Remaining command. */
+ size_t save_cmdlen; /* Remaining command length. */
+
+ EXCMDLIST const *cmd; /* Command: entry in command table. */
+ EXCMDLIST rcmd; /* Command: table entry/replacement. */
+
+ CIRCLEQ_HEAD(_rh, _range) rq; /* @/global range: linked list. */
+ recno_t range_lno; /* @/global range: set line number. */
+ char *o_cp; /* Original @/global command. */
+ size_t o_clen; /* Original @/global command length. */
+#define AGV_AT 0x01 /* @ buffer execution. */
+#define AGV_AT_NORANGE 0x02 /* @ buffer execution without range. */
+#define AGV_GLOBAL 0x04 /* global command. */
+#define AGV_V 0x08 /* v command. */
+#define AGV_ALL (AGV_AT | AGV_AT_NORANGE | AGV_GLOBAL | AGV_V)
+ u_int8_t agv_flags;
+
+ /* Clear the structure before each ex command. */
+#define CLEAR_EX_CMD(cmdp) { \
+ u_int32_t L__f = F_ISSET(cmdp, E_PRESERVE); \
+ memset(&((cmdp)->buffer), 0, ((char *)&(cmdp)->flags - \
+ (char *)&((cmdp)->buffer)) + sizeof((cmdp)->flags)); \
+ F_SET(cmdp, L__f); \
+}
+
+ CHAR_T buffer; /* Command: named buffer. */
+ recno_t lineno; /* Command: line number. */
+ long count; /* Command: signed count. */
+ long flagoff; /* Command: signed flag offset. */
+ int addrcnt; /* Command: addresses (0, 1 or 2). */
+ MARK addr1; /* Command: 1st address. */
+ MARK addr2; /* Command: 2nd address. */
+ ARGS **argv; /* Command: array of arguments. */
+ int argc; /* Command: count of arguments. */
+
+#define E_C_BUFFER 0x00001 /* Buffer name specified. */
+#define E_C_CARAT 0x00002 /* ^ flag. */
+#define E_C_COUNT 0x00004 /* Count specified. */
+#define E_C_COUNT_NEG 0x00008 /* Count was signed negative. */
+#define E_C_COUNT_POS 0x00010 /* Count was signed positive. */
+#define E_C_DASH 0x00020 /* - flag. */
+#define E_C_DOT 0x00040 /* . flag. */
+#define E_C_EQUAL 0x00080 /* = flag. */
+#define E_C_FORCE 0x00100 /* ! flag. */
+#define E_C_HASH 0x00200 /* # flag. */
+#define E_C_LIST 0x00400 /* l flag. */
+#define E_C_PLUS 0x00800 /* + flag. */
+#define E_C_PRINT 0x01000 /* p flag. */
+ u_int16_t iflags; /* User input information. */
+
+#define __INUSE2 0x000004ff /* Same name space as EXCMDLIST. */
+#define E_BLIGNORE 0x00000800 /* Ignore blank lines. */
+#define E_NAMEDISCARD 0x00001000 /* Free/discard the name. */
+#define E_NOAUTO 0x00002000 /* Don't do autoprint output. */
+#define E_NOPRDEF 0x00004000 /* Don't print as default. */
+#define E_NRSEP 0x00008000 /* Need to line adjust ex output. */
+#define E_OPTNUM 0x00010000 /* Number edit option affected. */
+#define E_VLITONLY 0x00020000 /* Use ^V quoting only. */
+#define E_PRESERVE 0x0003f800 /* Bits to preserve across commands. */
+
+#define E_ABSMARK 0x00040000 /* Set the absolute mark. */
+#define E_ADDR_DEF 0x00080000 /* Default addresses used. */
+#define E_DELTA 0x00100000 /* Search address with delta. */
+#define E_MODIFY 0x00200000 /* File name expansion modified arg. */
+#define E_MOVETOEND 0x00400000 /* Move to the end of the file first. */
+#define E_NEWLINE 0x00800000 /* Found ending <newline>. */
+#define E_SEARCH_WMSG 0x01000000 /* Display search-wrapped message. */
+#define E_USELASTCMD 0x02000000 /* Use the last command. */
+#define E_VISEARCH 0x04000000 /* It's really a vi search command. */
+ u_int32_t flags; /* Current flags. */
+};
+
+/* Ex private, per-screen memory. */
+typedef struct _ex_private {
+ CIRCLEQ_HEAD(_tqh, _tagq) tq; /* Tag queue. */
+ TAILQ_HEAD(_tagfh, _tagf) tagfq;/* Tag file list. */
+ LIST_HEAD(_csch, _csc) cscq; /* Cscope connection list. */
+ char *tag_last; /* Saved last tag string. */
+
+ CHAR_T *lastbcomm; /* Last bang command. */
+
+ ARGS **args; /* Command: argument list. */
+ int argscnt; /* Command: argument list count. */
+ int argsoff; /* Command: offset into arguments. */
+
+ u_int32_t fdef; /* Saved E_C_* default command flags. */
+
+ char *ibp; /* File line input buffer. */
+ size_t ibp_len; /* File line input buffer length. */
+
+ /*
+ * Buffers for the ex output. The screen/vi support doesn't do any
+ * character buffering of any kind. We do it here so that we're not
+ * calling the screen output routines on every character.
+ *
+ * XXX
+ * Change to grow dynamically.
+ */
+ char obp[1024]; /* Ex output buffer. */
+ size_t obp_len; /* Ex output buffer length. */
+
+#define EXP_CSCINIT 0x01 /* Cscope initialized. */
+ u_int8_t flags;
+} EX_PRIVATE;
+#define EXP(sp) ((EX_PRIVATE *)((sp)->ex_private))
+
+/*
+ * Filter actions:
+ *
+ * FILTER_BANG !: filter text through the utility.
+ * FILTER_RBANG !: read from the utility (without stdin).
+ * FILTER_READ read: read from the utility (with stdin).
+ * FILTER_WRITE write: write to the utility, display its output.
+ */
+enum filtertype { FILTER_BANG, FILTER_RBANG, FILTER_READ, FILTER_WRITE };
+
+/* Ex common error messages. */
+typedef enum {
+ EXM_EMPTYBUF, /* Empty buffer. */
+ EXM_FILECOUNT, /* Too many file names. */
+ EXM_NOCANON, /* No terminal interface. */
+ EXM_NOCANON_F, /* EXM_NOCANO: filter version. */
+ EXM_NOFILEYET, /* Illegal until a file read in. */
+ EXM_NOPREVBUF, /* No previous buffer specified. */
+ EXM_NOPREVRE, /* No previous RE specified. */
+ EXM_NOSUSPEND, /* No suspension. */
+ EXM_SECURE, /* Illegal if secure edit option set. */
+ EXM_SECURE_F, /* EXM_SECURE: filter version */
+ EXM_USAGE /* Standard usage message. */
+} exm_t;
+
+/* Ex address error types. */
+enum badaddr { A_COMBO, A_EMPTY, A_EOF, A_NOTSET, A_ZERO };
+
+/* Ex common tag error messages. */
+typedef enum {
+ TAG_BADLNO, /* Tag line doesn't exist. */
+ TAG_EMPTY, /* Tags stack is empty. */
+ TAG_SEARCH /* Tags search pattern wasn't found. */
+} tagmsg_t;
+
+#include "ex_def.h"
+#include "ex_extern.h"
diff --git a/contrib/nvi/ex/ex_abbrev.c b/contrib/nvi/ex/ex_abbrev.c
new file mode 100644
index 000000000000..231098ce7d25
--- /dev/null
+++ b/contrib/nvi/ex/ex_abbrev.c
@@ -0,0 +1,117 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_abbrev.c 10.7 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+/*
+ * ex_abbr -- :abbreviate [key replacement]
+ * Create an abbreviation or display abbreviations.
+ *
+ * PUBLIC: int ex_abbr __P((SCR *, EXCMD *));
+ */
+int
+ex_abbr(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ CHAR_T *p;
+ size_t len;
+
+ switch (cmdp->argc) {
+ case 0:
+ if (seq_dump(sp, SEQ_ABBREV, 0) == 0)
+ msgq(sp, M_INFO, "105|No abbreviations to display");
+ return (0);
+ case 2:
+ break;
+ default:
+ abort();
+ }
+
+ /*
+ * Check for illegal characters.
+ *
+ * !!!
+ * Another fun one, historically. See vi/v_ntext.c:txt_abbrev() for
+ * details. The bottom line is that all abbreviations have to end
+ * with a "word" character, because it's the transition from word to
+ * non-word characters that triggers the test for an abbreviation. In
+ * addition, because of the way the test is done, there can't be any
+ * transitions from word to non-word character (or vice-versa) other
+ * than between the next-to-last and last characters of the string,
+ * and there can't be any <blank> characters. Warn the user.
+ */
+ if (!inword(cmdp->argv[0]->bp[cmdp->argv[0]->len - 1])) {
+ msgq(sp, M_ERR,
+ "106|Abbreviations must end with a \"word\" character");
+ return (1);
+ }
+ for (p = cmdp->argv[0]->bp; *p != '\0'; ++p)
+ if (isblank(p[0])) {
+ msgq(sp, M_ERR,
+ "107|Abbreviations may not contain tabs or spaces");
+ return (1);
+ }
+ if (cmdp->argv[0]->len > 2)
+ for (p = cmdp->argv[0]->bp,
+ len = cmdp->argv[0]->len - 2; len; --len, ++p)
+ if (inword(p[0]) != inword(p[1])) {
+ msgq(sp, M_ERR,
+"108|Abbreviations may not mix word/non-word characters, except at the end");
+ return (1);
+ }
+
+ if (seq_set(sp, NULL, 0, cmdp->argv[0]->bp, cmdp->argv[0]->len,
+ cmdp->argv[1]->bp, cmdp->argv[1]->len, SEQ_ABBREV, SEQ_USERDEF))
+ return (1);
+
+ F_SET(sp->gp, G_ABBREV);
+ return (0);
+}
+
+/*
+ * ex_unabbr -- :unabbreviate key
+ * Delete an abbreviation.
+ *
+ * PUBLIC: int ex_unabbr __P((SCR *, EXCMD *));
+ */
+int
+ex_unabbr(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ ARGS *ap;
+
+ ap = cmdp->argv[0];
+ if (!F_ISSET(sp->gp, G_ABBREV) ||
+ seq_delete(sp, ap->bp, ap->len, SEQ_ABBREV)) {
+ msgq_str(sp, M_ERR, ap->bp,
+ "109|\"%s\" is not an abbreviation");
+ return (1);
+ }
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_append.c b/contrib/nvi/ex/ex_append.c
new file mode 100644
index 000000000000..8d89e125f51f
--- /dev/null
+++ b/contrib/nvi/ex/ex_append.c
@@ -0,0 +1,277 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_append.c 10.30 (Berkeley) 10/23/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+enum which {APPEND, CHANGE, INSERT};
+
+static int ex_aci __P((SCR *, EXCMD *, enum which));
+
+/*
+ * ex_append -- :[line] a[ppend][!]
+ * Append one or more lines of new text after the specified line,
+ * or the current line if no address is specified.
+ *
+ * PUBLIC: int ex_append __P((SCR *, EXCMD *));
+ */
+int
+ex_append(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ return (ex_aci(sp, cmdp, APPEND));
+}
+
+/*
+ * ex_change -- :[line[,line]] c[hange][!] [count]
+ * Change one or more lines to the input text.
+ *
+ * PUBLIC: int ex_change __P((SCR *, EXCMD *));
+ */
+int
+ex_change(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ return (ex_aci(sp, cmdp, CHANGE));
+}
+
+/*
+ * ex_insert -- :[line] i[nsert][!]
+ * Insert one or more lines of new text before the specified line,
+ * or the current line if no address is specified.
+ *
+ * PUBLIC: int ex_insert __P((SCR *, EXCMD *));
+ */
+int
+ex_insert(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ return (ex_aci(sp, cmdp, INSERT));
+}
+
+/*
+ * ex_aci --
+ * Append, change, insert in ex.
+ */
+static int
+ex_aci(sp, cmdp, cmd)
+ SCR *sp;
+ EXCMD *cmdp;
+ enum which cmd;
+{
+ CHAR_T *p, *t;
+ GS *gp;
+ TEXT *tp;
+ TEXTH tiq;
+ recno_t cnt, lno;
+ size_t len;
+ u_int32_t flags;
+ int need_newline;
+
+ gp = sp->gp;
+ NEEDFILE(sp, cmdp);
+
+ /*
+ * If doing a change, replace lines for as long as possible. Then,
+ * append more lines or delete remaining lines. Changes to an empty
+ * file are appends, inserts are the same as appends to the previous
+ * line.
+ *
+ * !!!
+ * Set the address to which we'll append. We set sp->lno to this
+ * address as well so that autoindent works correctly when get text
+ * from the user.
+ */
+ lno = cmdp->addr1.lno;
+ sp->lno = lno;
+ if ((cmd == CHANGE || cmd == INSERT) && lno != 0)
+ --lno;
+
+ /*
+ * !!!
+ * If the file isn't empty, cut changes into the unnamed buffer.
+ */
+ if (cmd == CHANGE && cmdp->addr1.lno != 0 &&
+ (cut(sp, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE) ||
+ del(sp, &cmdp->addr1, &cmdp->addr2, 1)))
+ return (1);
+
+ /*
+ * !!!
+ * Anything that was left after the command separator becomes part
+ * of the inserted text. Apparently, it was common usage to enter:
+ *
+ * :g/pattern/append|stuff1
+ *
+ * and append the line of text "stuff1" to the lines containing the
+ * pattern. It was also historically legal to enter:
+ *
+ * :append|stuff1
+ * stuff2
+ * .
+ *
+ * and the text on the ex command line would be appended as well as
+ * the text inserted after it. There was an historic bug however,
+ * that the user had to enter *two* terminating lines (the '.' lines)
+ * to terminate text input mode, in this case. This whole thing
+ * could be taken too far, however. Entering:
+ *
+ * :append|stuff1\
+ * stuff2
+ * stuff3
+ * .
+ *
+ * i.e. mixing and matching the forms confused the historic vi, and,
+ * not only did it take two terminating lines to terminate text input
+ * mode, but the trailing backslashes were retained on the input. We
+ * match historic practice except that we discard the backslashes.
+ *
+ * Input lines specified on the ex command line lines are separated by
+ * <newline>s. If there is a trailing delimiter an empty line was
+ * inserted. There may also be a leading delimiter, which is ignored
+ * unless it's also a trailing delimiter. It is possible to encounter
+ * a termination line, i.e. a single '.', in a global command, but not
+ * necessary if the text insert command was the last of the global
+ * commands.
+ */
+ if (cmdp->save_cmdlen != 0) {
+ for (p = cmdp->save_cmd,
+ len = cmdp->save_cmdlen; len > 0; p = t) {
+ for (t = p; len > 0 && t[0] != '\n'; ++t, --len);
+ if (t != p || len == 0) {
+ if (F_ISSET(sp, SC_EX_GLOBAL) &&
+ t - p == 1 && p[0] == '.') {
+ ++t;
+ if (len > 0)
+ --len;
+ break;
+ }
+ if (db_append(sp, 1, lno++, p, t - p))
+ return (1);
+ }
+ if (len != 0) {
+ ++t;
+ if (--len == 0 &&
+ db_append(sp, 1, lno++, "", 0))
+ return (1);
+ }
+ }
+ /*
+ * If there's any remaining text, we're in a global, and
+ * there's more command to parse.
+ *
+ * !!!
+ * We depend on the fact that non-global commands will eat the
+ * rest of the command line as text input, and before getting
+ * any text input from the user. Otherwise, we'd have to save
+ * off the command text before or during the call to the text
+ * input function below.
+ */
+ if (len != 0)
+ cmdp->save_cmd = t;
+ cmdp->save_cmdlen = len;
+ }
+
+ if (F_ISSET(sp, SC_EX_GLOBAL)) {
+ if ((sp->lno = lno) == 0 && db_exist(sp, 1))
+ sp->lno = 1;
+ return (0);
+ }
+
+ /*
+ * If not in a global command, read from the terminal.
+ *
+ * If this code is called by vi, we want to reset the terminal and use
+ * ex's line get routine. It actually works fine if we use vi's get
+ * routine, but it doesn't look as nice. Maybe if we had a separate
+ * window or something, but getting a line at a time looks awkward.
+ * However, depending on the screen that we're using, that may not
+ * be possible.
+ */
+ if (F_ISSET(sp, SC_VI)) {
+ if (gp->scr_screen(sp, SC_EX)) {
+ ex_emsg(sp, cmdp->cmd->name, EXM_NOCANON);
+ return (1);
+ }
+
+ /* If we're still in the vi screen, move out explicitly. */
+ need_newline = !F_ISSET(sp, SC_SCR_EXWROTE);
+ F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
+ if (need_newline)
+ (void)ex_puts(sp, "\n");
+
+ /*
+ * !!!
+ * Users of historical versions of vi sometimes get confused
+ * when they enter append mode, and can't seem to get out of
+ * it. Give them an informational message.
+ */
+ (void)ex_puts(sp,
+ msg_cat(sp, "273|Entering ex input mode.", NULL));
+ (void)ex_puts(sp, "\n");
+ (void)ex_fflush(sp);
+ }
+
+ /*
+ * Set input flags; the ! flag turns off autoindent for append,
+ * change and insert.
+ */
+ LF_INIT(TXT_DOTTERM | TXT_NUMBER);
+ if (!FL_ISSET(cmdp->iflags, E_C_FORCE) && O_ISSET(sp, O_AUTOINDENT))
+ LF_SET(TXT_AUTOINDENT);
+ if (O_ISSET(sp, O_BEAUTIFY))
+ LF_SET(TXT_BEAUTIFY);
+
+ /*
+ * This code can't use the common screen TEXTH structure (sp->tiq),
+ * as it may already be in use, e.g. ":append|s/abc/ABC/" would fail
+ * as we are only halfway through the text when the append code fires.
+ * Use a local structure instead. (The ex code would have to use a
+ * local structure except that we're guaranteed to finish remaining
+ * characters in the common TEXTH structure when they were inserted
+ * into the file, above.)
+ */
+ memset(&tiq, 0, sizeof(TEXTH));
+ CIRCLEQ_INIT(&tiq);
+
+ if (ex_txt(sp, &tiq, 0, flags))
+ return (1);
+
+ for (cnt = 0, tp = tiq.cqh_first;
+ tp != (TEXT *)&tiq; ++cnt, tp = tp->q.cqe_next)
+ if (db_append(sp, 1, lno++, tp->lb, tp->len))
+ return (1);
+
+ /*
+ * Set sp->lno to the final line number value (correcting for a
+ * possible 0 value) as that's historically correct for the final
+ * line value, whether or not the user entered any text.
+ */
+ if ((sp->lno = lno) == 0 && db_exist(sp, 1))
+ sp->lno = 1;
+
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_args.c b/contrib/nvi/ex/ex_args.c
new file mode 100644
index 000000000000..bc37109fc130
--- /dev/null
+++ b/contrib/nvi/ex/ex_args.c
@@ -0,0 +1,327 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_args.c 10.16 (Berkeley) 7/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+static int ex_N_next __P((SCR *, EXCMD *));
+
+/*
+ * ex_next -- :next [+cmd] [files]
+ * Edit the next file, optionally setting the list of files.
+ *
+ * !!!
+ * The :next command behaved differently from the :rewind command in
+ * historic vi. See nvi/docs/autowrite for details, but the basic
+ * idea was that it ignored the force flag if the autowrite flag was
+ * set. This implementation handles them all identically.
+ *
+ * PUBLIC: int ex_next __P((SCR *, EXCMD *));
+ */
+int
+ex_next(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ ARGS **argv;
+ FREF *frp;
+ int noargs;
+ char **ap;
+
+ /* Check for file to move to. */
+ if (cmdp->argc == 0 && (sp->cargv == NULL || sp->cargv[1] == NULL)) {
+ msgq(sp, M_ERR, "111|No more files to edit");
+ return (1);
+ }
+
+ if (F_ISSET(cmdp, E_NEWSCREEN)) {
+ /* By default, edit the next file in the old argument list. */
+ if (cmdp->argc == 0) {
+ if (argv_exp0(sp,
+ cmdp, sp->cargv[1], strlen(sp->cargv[1])))
+ return (1);
+ return (ex_edit(sp, cmdp));
+ }
+ return (ex_N_next(sp, cmdp));
+ }
+
+ /* Check modification. */
+ if (file_m1(sp,
+ FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
+ return (1);
+
+ /* Any arguments are a replacement file list. */
+ if (cmdp->argc) {
+ /* Free the current list. */
+ if (!F_ISSET(sp, SC_ARGNOFREE) && sp->argv != NULL) {
+ for (ap = sp->argv; *ap != NULL; ++ap)
+ free(*ap);
+ free(sp->argv);
+ }
+ F_CLR(sp, SC_ARGNOFREE | SC_ARGRECOVER);
+ sp->cargv = NULL;
+
+ /* Create a new list. */
+ CALLOC_RET(sp,
+ sp->argv, char **, cmdp->argc + 1, sizeof(char *));
+ for (ap = sp->argv,
+ argv = cmdp->argv; argv[0]->len != 0; ++ap, ++argv)
+ if ((*ap =
+ v_strdup(sp, argv[0]->bp, argv[0]->len)) == NULL)
+ return (1);
+ *ap = NULL;
+
+ /* Switch to the first file. */
+ sp->cargv = sp->argv;
+ if ((frp = file_add(sp, *sp->cargv)) == NULL)
+ return (1);
+ noargs = 0;
+
+ /* Display a file count with the welcome message. */
+ F_SET(sp, SC_STATUS_CNT);
+ } else {
+ if ((frp = file_add(sp, sp->cargv[1])) == NULL)
+ return (1);
+ if (F_ISSET(sp, SC_ARGRECOVER))
+ F_SET(frp, FR_RECOVER);
+ noargs = 1;
+ }
+
+ if (file_init(sp, frp, NULL, FS_SETALT |
+ (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
+ return (1);
+ if (noargs)
+ ++sp->cargv;
+
+ F_SET(sp, SC_FSWITCH);
+ return (0);
+}
+
+/*
+ * ex_N_next --
+ * New screen version of ex_next.
+ */
+static int
+ex_N_next(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ SCR *new;
+ FREF *frp;
+
+ /* Get a new screen. */
+ if (screen_init(sp->gp, sp, &new))
+ return (1);
+ if (vs_split(sp, new, 0)) {
+ (void)screen_end(new);
+ return (1);
+ }
+
+ /* Get a backing file. */
+ if ((frp = file_add(new, cmdp->argv[0]->bp)) == NULL ||
+ file_init(new, frp, NULL,
+ (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0))) {
+ (void)vs_discard(new, NULL);
+ (void)screen_end(new);
+ return (1);
+ }
+
+ /* The arguments are a replacement file list. */
+ new->cargv = new->argv = ex_buildargv(sp, cmdp, NULL);
+
+ /* Display a file count with the welcome message. */
+ F_SET(new, SC_STATUS_CNT);
+
+ /* Set up the switch. */
+ sp->nextdisp = new;
+ F_SET(sp, SC_SSWITCH);
+
+ return (0);
+}
+
+/*
+ * ex_prev -- :prev
+ * Edit the previous file.
+ *
+ * PUBLIC: int ex_prev __P((SCR *, EXCMD *));
+ */
+int
+ex_prev(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ FREF *frp;
+
+ if (sp->cargv == sp->argv) {
+ msgq(sp, M_ERR, "112|No previous files to edit");
+ return (1);
+ }
+
+ if (F_ISSET(cmdp, E_NEWSCREEN)) {
+ if (argv_exp0(sp, cmdp, sp->cargv[-1], strlen(sp->cargv[-1])))
+ return (1);
+ return (ex_edit(sp, cmdp));
+ }
+
+ if (file_m1(sp,
+ FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
+ return (1);
+
+ if ((frp = file_add(sp, sp->cargv[-1])) == NULL)
+ return (1);
+
+ if (file_init(sp, frp, NULL, FS_SETALT |
+ (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
+ return (1);
+ --sp->cargv;
+
+ F_SET(sp, SC_FSWITCH);
+ return (0);
+}
+
+/*
+ * ex_rew -- :rew
+ * Re-edit the list of files.
+ *
+ * !!!
+ * Historic practice was that all files would start editing at the beginning
+ * of the file. We don't get this right because we may have multiple screens
+ * and we can't clear the FR_CURSORSET bit for a single screen. I don't see
+ * anyone noticing, but if they do, we'll have to put information into the SCR
+ * structure so we can keep track of it.
+ *
+ * PUBLIC: int ex_rew __P((SCR *, EXCMD *));
+ */
+int
+ex_rew(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ FREF *frp;
+
+ /*
+ * !!!
+ * Historic practice -- you can rewind to the current file.
+ */
+ if (sp->argv == NULL) {
+ msgq(sp, M_ERR, "113|No previous files to rewind");
+ return (1);
+ }
+
+ if (file_m1(sp,
+ FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
+ return (1);
+
+ /* Switch to the first one. */
+ sp->cargv = sp->argv;
+ if ((frp = file_add(sp, *sp->cargv)) == NULL)
+ return (1);
+ if (file_init(sp, frp, NULL, FS_SETALT |
+ (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
+ return (1);
+
+ /* Switch and display a file count with the welcome message. */
+ F_SET(sp, SC_FSWITCH | SC_STATUS_CNT);
+
+ return (0);
+}
+
+/*
+ * ex_args -- :args
+ * Display the list of files.
+ *
+ * PUBLIC: int ex_args __P((SCR *, EXCMD *));
+ */
+int
+ex_args(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ GS *gp;
+ int cnt, col, len, sep;
+ char **ap;
+
+ if (sp->argv == NULL) {
+ (void)msgq(sp, M_ERR, "114|No file list to display");
+ return (0);
+ }
+
+ gp = sp->gp;
+ col = len = sep = 0;
+ for (cnt = 1, ap = sp->argv; *ap != NULL; ++ap) {
+ col += len = strlen(*ap) + sep + (ap == sp->cargv ? 2 : 0);
+ if (col >= sp->cols - 1) {
+ col = len;
+ sep = 0;
+ (void)ex_puts(sp, "\n");
+ } else if (cnt != 1) {
+ sep = 1;
+ (void)ex_puts(sp, " ");
+ }
+ ++cnt;
+
+ (void)ex_printf(sp, "%s%s%s", ap == sp->cargv ? "[" : "",
+ *ap, ap == sp->cargv ? "]" : "");
+ if (INTERRUPTED(sp))
+ break;
+ }
+ (void)ex_puts(sp, "\n");
+ return (0);
+}
+
+/*
+ * ex_buildargv --
+ * Build a new file argument list.
+ *
+ * PUBLIC: char **ex_buildargv __P((SCR *, EXCMD *, char *));
+ */
+char **
+ex_buildargv(sp, cmdp, name)
+ SCR *sp;
+ EXCMD *cmdp;
+ char *name;
+{
+ ARGS **argv;
+ int argc;
+ char **ap, **s_argv;
+
+ argc = cmdp == NULL ? 1 : cmdp->argc;
+ CALLOC(sp, s_argv, char **, argc + 1, sizeof(char *));
+ if ((ap = s_argv) == NULL)
+ return (NULL);
+
+ if (cmdp == NULL) {
+ if ((*ap = v_strdup(sp, name, strlen(name))) == NULL)
+ return (NULL);
+ ++ap;
+ } else
+ for (argv = cmdp->argv; argv[0]->len != 0; ++ap, ++argv)
+ if ((*ap =
+ v_strdup(sp, argv[0]->bp, argv[0]->len)) == NULL)
+ return (NULL);
+ *ap = NULL;
+ return (s_argv);
+}
diff --git a/usr.bin/vi/ex/ex_argv.c b/contrib/nvi/ex/ex_argv.c
index f93aa76e3039..cc5a201bea26 100644
--- a/usr.bin/vi/ex/ex_argv.c
+++ b/contrib/nvi/ex/ex_argv.c
@@ -1,76 +1,50 @@
/*-
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)ex_argv.c 8.36 (Berkeley) 8/4/94";
+static const char sccsid[] = "@(#)ex_argv.c 10.26 (Berkeley) 9/20/96";
#endif /* not lint */
#include <sys/types.h>
#include <sys/queue.h>
-#include <sys/time.h>
#include <bitstring.h>
#include <ctype.h>
+#include <dirent.h>
#include <errno.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
#include <unistd.h>
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
+#include "../common/common.h"
static int argv_alloc __P((SCR *, size_t));
-static int argv_fexp __P((SCR *, EXCMDARG *,
- char *, size_t, char *, size_t *, char **, size_t *, int));
+static int argv_comp __P((const void *, const void *));
+static int argv_fexp __P((SCR *, EXCMD *,
+ char *, size_t, char *, size_t *, char **, size_t *, int));
+static int argv_lexp __P((SCR *, EXCMD *, char *));
static int argv_sexp __P((SCR *, char **, size_t *, size_t *));
/*
* argv_init --
* Build a prototype arguments list.
+ *
+ * PUBLIC: int argv_init __P((SCR *, EXCMD *));
*/
int
-argv_init(sp, ep, excp)
+argv_init(sp, excp)
SCR *sp;
- EXF *ep;
- EXCMDARG *excp;
+ EXCMD *excp;
{
EX_PRIVATE *exp;
@@ -86,12 +60,13 @@ argv_init(sp, ep, excp)
/*
* argv_exp0 --
* Append a string to the argument list.
+ *
+ * PUBLIC: int argv_exp0 __P((SCR *, EXCMD *, char *, size_t));
*/
int
-argv_exp0(sp, ep, excp, cmd, cmdlen)
+argv_exp0(sp, excp, cmd, cmdlen)
SCR *sp;
- EXF *ep;
- EXCMDARG *excp;
+ EXCMD *excp;
char *cmd;
size_t cmdlen;
{
@@ -99,7 +74,7 @@ argv_exp0(sp, ep, excp, cmd, cmdlen)
exp = EXP(sp);
argv_alloc(sp, cmdlen);
- memmove(exp->args[exp->argsoff]->bp, cmd, cmdlen);
+ memcpy(exp->args[exp->argsoff]->bp, cmd, cmdlen);
exp->args[exp->argsoff]->bp[cmdlen] = '\0';
exp->args[exp->argsoff]->len = cmdlen;
++exp->argsoff;
@@ -112,12 +87,13 @@ argv_exp0(sp, ep, excp, cmd, cmdlen)
* argv_exp1 --
* Do file name expansion on a string, and append it to the
* argument list.
+ *
+ * PUBLIC: int argv_exp1 __P((SCR *, EXCMD *, char *, size_t, int));
*/
int
-argv_exp1(sp, ep, excp, cmd, cmdlen, is_bang)
+argv_exp1(sp, excp, cmd, cmdlen, is_bang)
SCR *sp;
- EXF *ep;
- EXCMDARG *excp;
+ EXCMD *excp;
char *cmd;
size_t cmdlen;
int is_bang;
@@ -145,8 +121,8 @@ argv_exp1(sp, ep, excp, cmd, cmdlen, is_bang)
} else
goto ret;
- (void)argv_exp0(sp, ep, excp, bp, len);
-
+ (void)argv_exp0(sp, excp, bp, len);
+
ret: FREE_SPACE(sp, bp, blen);
return (0);
}
@@ -155,15 +131,15 @@ ret: FREE_SPACE(sp, bp, blen);
* argv_exp2 --
* Do file name and shell expansion on a string, and append it to
* the argument list.
+ *
+ * PUBLIC: int argv_exp2 __P((SCR *, EXCMD *, char *, size_t));
*/
int
-argv_exp2(sp, ep, excp, cmd, cmdlen, is_bang)
+argv_exp2(sp, excp, cmd, cmdlen)
SCR *sp;
- EXF *ep;
- EXCMDARG *excp;
+ EXCMD *excp;
char *cmd;
size_t cmdlen;
- int is_bang;
{
size_t blen, len, n;
int rval;
@@ -173,7 +149,7 @@ argv_exp2(sp, ep, excp, cmd, cmdlen, is_bang)
#define SHELLECHO "echo "
#define SHELLOFFSET (sizeof(SHELLECHO) - 1)
- memmove(bp, SHELLECHO, SHELLOFFSET);
+ memcpy(bp, SHELLECHO, SHELLOFFSET);
p = bp + SHELLOFFSET;
len = SHELLOFFSET;
@@ -181,7 +157,7 @@ argv_exp2(sp, ep, excp, cmd, cmdlen, is_bang)
TRACE(sp, "file_argv: {%.*s}\n", (int)cmdlen, cmd);
#endif
- if (argv_fexp(sp, excp, cmd, cmdlen, p, &len, &bp, &blen, is_bang)) {
+ if (argv_fexp(sp, excp, cmd, cmdlen, p, &len, &bp, &blen, 0)) {
rval = 1;
goto err;
}
@@ -202,37 +178,63 @@ argv_exp2(sp, ep, excp, cmd, cmdlen, is_bang)
*
* To avoid a function call per character, we do a first pass through
* the meta characters looking for characters that aren't expected
- * to be there.
+ * to be there, and then we can ignore them in the user's argument.
*/
- for (p = mp = O_STR(sp, O_META); *p != '\0'; ++p)
- if (isblank(*p) || isalnum(*p))
- break;
- if (*p != '\0') {
- for (p = bp, n = len; n > 0; --n, ++p)
- if (strchr(mp, *p) != NULL)
+ if (opts_empty(sp, O_SHELL, 1) || opts_empty(sp, O_SHELLMETA, 1))
+ n = 0;
+ else {
+ for (p = mp = O_STR(sp, O_SHELLMETA); *p != '\0'; ++p)
+ if (isblank(*p) || isalnum(*p))
break;
- } else
- for (p = bp, n = len; n > 0; --n, ++p)
- if (!isblank(*p) &&
- !isalnum(*p) && strchr(mp, *p) != NULL)
- break;
- if (n > 0) {
+ p = bp + SHELLOFFSET;
+ n = len - SHELLOFFSET;
+ if (*p != '\0') {
+ for (; n > 0; --n, ++p)
+ if (strchr(mp, *p) != NULL)
+ break;
+ } else
+ for (; n > 0; --n, ++p)
+ if (!isblank(*p) &&
+ !isalnum(*p) && strchr(mp, *p) != NULL)
+ break;
+ }
+
+ /*
+ * If we found a meta character in the string, fork a shell to expand
+ * it. Unfortunately, this is comparatively slow. Historically, it
+ * didn't matter much, since users don't enter meta characters as part
+ * of pathnames that frequently. The addition of filename completion
+ * broke that assumption because it's easy to use. As a result, lots
+ * folks have complained that the expansion code is too slow. So, we
+ * detect filename completion as a special case, and do it internally.
+ * Note that this code assumes that the <asterisk> character is the
+ * match-anything meta character. That feels safe -- if anyone writes
+ * a shell that doesn't follow that convention, I'd suggest giving them
+ * a festive hot-lead enema.
+ */
+ switch (n) {
+ case 0:
+ p = bp + SHELLOFFSET;
+ len -= SHELLOFFSET;
+ rval = argv_exp3(sp, excp, p, len);
+ break;
+ case 1:
+ if (*p == '*') {
+ *p = '\0';
+ rval = argv_lexp(sp, excp, bp + SHELLOFFSET);
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
if (argv_sexp(sp, &bp, &blen, &len)) {
rval = 1;
goto err;
}
p = bp;
- } else {
- p = bp + SHELLOFFSET;
- len -= SHELLOFFSET;
+ rval = argv_exp3(sp, excp, p, len);
+ break;
}
-#if defined(DEBUG) && 0
- TRACE(sp, "after shell: %d: {%s}\n", len, bp);
-#endif
-
- rval = argv_exp3(sp, ep, excp, p, len);
-
err: FREE_SPACE(sp, bp, blen);
return (rval);
}
@@ -241,12 +243,13 @@ err: FREE_SPACE(sp, bp, blen);
* argv_exp3 --
* Take a string and break it up into an argv, which is appended
* to the argument list.
+ *
+ * PUBLIC: int argv_exp3 __P((SCR *, EXCMD *, char *, size_t));
*/
int
-argv_exp3(sp, ep, excp, cmd, cmdlen)
+argv_exp3(sp, excp, cmd, cmdlen)
SCR *sp;
- EXF *ep;
- EXCMDARG *excp;
+ EXCMD *excp;
char *cmd;
size_t cmdlen;
{
@@ -276,7 +279,7 @@ argv_exp3(sp, ep, excp, cmd, cmdlen)
*/
for (ap = cmd, len = 0; cmdlen > 0; ++cmd, --cmdlen, ++len) {
ch = *cmd;
- if (IS_ESCAPE(sp, ch) && cmdlen > 1) {
+ if (IS_ESCAPE(sp, excp, ch) && cmdlen > 1) {
++cmd;
--cmdlen;
} else if (isblank(ch))
@@ -294,7 +297,7 @@ argv_exp3(sp, ep, excp, cmd, cmdlen)
off = exp->argsoff;
exp->args[off]->len = len;
for (p = exp->args[off]->bp; len > 0; --len, *p++ = *ap++)
- if (IS_ESCAPE(sp, *ap))
+ if (IS_ESCAPE(sp, excp, *ap))
++ap;
*p = '\0';
}
@@ -315,14 +318,14 @@ argv_exp3(sp, ep, excp, cmd, cmdlen)
static int
argv_fexp(sp, excp, cmd, cmdlen, p, lenp, bpp, blenp, is_bang)
SCR *sp;
- EXCMDARG *excp;
+ EXCMD *excp;
char *cmd, *p, **bpp;
size_t cmdlen, *lenp, *blenp;
int is_bang;
{
EX_PRIVATE *exp;
char *bp, *t;
- size_t blen, len, tlen;
+ size_t blen, len, off, tlen;
/* Replace file name characters. */
for (bp = *bpp, blen = *blenp, len = *lenp; cmdlen > 0; --cmdlen, ++cmd)
@@ -333,37 +336,43 @@ argv_fexp(sp, excp, cmd, cmdlen, p, lenp, bpp, blenp, is_bang)
exp = EXP(sp);
if (exp->lastbcomm == NULL) {
msgq(sp, M_ERR,
- "No previous command to replace \"!\"");
+ "115|No previous command to replace \"!\"");
return (1);
}
len += tlen = strlen(exp->lastbcomm);
+ off = p - bp;
ADD_SPACE_RET(sp, bp, blen, len);
- memmove(p, exp->lastbcomm, tlen);
+ p = bp + off;
+ memcpy(p, exp->lastbcomm, tlen);
p += tlen;
F_SET(excp, E_MODIFY);
break;
case '%':
if ((t = sp->frp->name) == NULL) {
msgq(sp, M_ERR,
- "No filename to substitute for %%");
+ "116|No filename to substitute for %%");
return (1);
}
tlen = strlen(t);
len += tlen;
+ off = p - bp;
ADD_SPACE_RET(sp, bp, blen, len);
- memmove(p, t, tlen);
+ p = bp + off;
+ memcpy(p, t, tlen);
p += tlen;
F_SET(excp, E_MODIFY);
break;
case '#':
if ((t = sp->alt_name) == NULL) {
msgq(sp, M_ERR,
- "No filename to substitute for #");
+ "117|No filename to substitute for #");
return (1);
}
len += tlen = strlen(t);
+ off = p - bp;
ADD_SPACE_RET(sp, bp, blen, len);
- memmove(p, t, tlen);
+ p = bp + off;
+ memcpy(p, t, tlen);
p += tlen;
F_SET(excp, E_MODIFY);
break;
@@ -374,20 +383,25 @@ argv_fexp(sp, excp, cmd, cmdlen, p, lenp, bpp, blenp, is_bang)
* Strip any backslashes that protected the file
* expansion characters.
*/
- if (cmdlen > 1 && (cmd[1] == '%' || cmd[1] == '#')) {
+ if (cmdlen > 1 &&
+ (cmd[1] == '%' || cmd[1] == '#' || cmd[1] == '!')) {
++cmd;
--cmdlen;
}
/* FALLTHROUGH */
default:
ins_ch: ++len;
+ off = p - bp;
ADD_SPACE_RET(sp, bp, blen, len);
+ p = bp + off;
*p++ = *cmd;
}
/* Nul termination. */
++len;
+ off = p - bp;
ADD_SPACE_RET(sp, bp, blen, len);
+ p = bp + off;
*p = '\0';
/* Return the new string length, buffer, buffer length. */
@@ -424,7 +438,7 @@ argv_alloc(sp, len)
(void)argv_free(sp);
goto mem;
}
- memset(&exp->args[off], 0, INCREMENT * sizeof(ARGS *));
+ memset(&exp->args[exp->argscnt], 0, INCREMENT * sizeof(ARGS *));
exp->argscnt = cnt;
}
@@ -465,6 +479,8 @@ mem: msgq(sp, M_SYSERR, NULL);
/*
* argv_free --
* Free up argument structures.
+ *
+ * PUBLIC: int argv_free __P((SCR *));
*/
int
argv_free(sp)
@@ -480,9 +496,9 @@ argv_free(sp)
continue;
if (F_ISSET(exp->args[off], A_ALLOCATED))
free(exp->args[off]->bp);
- FREE(exp->args[off], sizeof(ARGS));
+ free(exp->args[off]);
}
- FREE(exp->args, exp->argscnt * sizeof(ARGS *));
+ free(exp->args);
}
exp->args = NULL;
exp->argscnt = 0;
@@ -491,6 +507,105 @@ argv_free(sp)
}
/*
+ * argv_lexp --
+ * Find all file names matching the prefix and append them to the
+ * buffer.
+ */
+static int
+argv_lexp(sp, excp, path)
+ SCR *sp;
+ EXCMD *excp;
+ char *path;
+{
+ struct dirent *dp;
+ DIR *dirp;
+ EX_PRIVATE *exp;
+ int off;
+ size_t dlen, len, nlen;
+ char *dname, *name, *p;
+
+ exp = EXP(sp);
+
+ /* Set up the name and length for comparison. */
+ if ((p = strrchr(path, '/')) == NULL) {
+ dname = ".";
+ dlen = 0;
+ name = path;
+ } else {
+ if (p == path) {
+ dname = "/";
+ dlen = 1;
+ } else {
+ *p = '\0';
+ dname = path;
+ dlen = strlen(path);
+ }
+ name = p + 1;
+ }
+ nlen = strlen(name);
+
+ /*
+ * XXX
+ * We don't use the d_namlen field, it's not portable enough; we
+ * assume that d_name is nul terminated, instead.
+ */
+ if ((dirp = opendir(dname)) == NULL) {
+ msgq_str(sp, M_SYSERR, dname, "%s");
+ return (1);
+ }
+ for (off = exp->argsoff; (dp = readdir(dirp)) != NULL;) {
+ if (nlen == 0) {
+ if (dp->d_name[0] == '.')
+ continue;
+ len = strlen(dp->d_name);
+ } else {
+ len = strlen(dp->d_name);
+ if (len < nlen || memcmp(dp->d_name, name, nlen))
+ continue;
+ }
+
+ /* Directory + name + slash + null. */
+ argv_alloc(sp, dlen + len + 2);
+ p = exp->args[exp->argsoff]->bp;
+ if (dlen != 0) {
+ memcpy(p, dname, dlen);
+ p += dlen;
+ if (dlen > 1 || dname[0] != '/')
+ *p++ = '/';
+ }
+ memcpy(p, dp->d_name, len + 1);
+ exp->args[exp->argsoff]->len = dlen + len + 1;
+ ++exp->argsoff;
+ excp->argv = exp->args;
+ excp->argc = exp->argsoff;
+ }
+ closedir(dirp);
+
+ if (off == exp->argsoff) {
+ /*
+ * If we didn't find a match, complain that the expansion
+ * failed. We can't know for certain that's the error, but
+ * it's a good guess, and it matches historic practice.
+ */
+ msgq(sp, M_ERR, "304|Shell expansion failed");
+ return (1);
+ }
+ qsort(exp->args + off, exp->argsoff - off, sizeof(ARGS *), argv_comp);
+ return (0);
+}
+
+/*
+ * argv_comp --
+ * Alphabetic comparison.
+ */
+static int
+argv_comp(a, b)
+ const void *a, *b;
+{
+ return (strcmp((char *)(*(ARGS **)a)->bp, (char *)(*(ARGS **)b)->bp));
+}
+
+/*
* argv_sexp --
* Fork a shell, pipe a command through it, and read the output into
* a buffer.
@@ -501,14 +616,19 @@ argv_sexp(sp, bpp, blenp, lenp)
char **bpp;
size_t *blenp, *lenp;
{
+ enum { SEXP_ERR, SEXP_EXPANSION_ERR, SEXP_OK } rval;
FILE *ifp;
pid_t pid;
size_t blen, len;
- int ch, rval, output[2];
+ int ch, std_output[2];
char *bp, *p, *sh, *sh_path;
- bp = *bpp;
- blen = *blenp;
+ /* Secure means no shell access. */
+ if (O_ISSET(sp, O_SECURE)) {
+ msgq(sp, M_ERR,
+"289|Shell expansions not supported when the secure edit option is set");
+ return (1);
+ }
sh_path = O_STR(sp, O_SHELL);
if ((sh = strrchr(sh_path, '/')) == NULL)
@@ -516,64 +636,70 @@ argv_sexp(sp, bpp, blenp, lenp)
else
++sh;
+ /* Local copies of the buffer variables. */
+ bp = *bpp;
+ blen = *blenp;
+
/*
- * There are two different processes running through this code.
- * They are named the utility and the parent. The utility reads
- * from standard input and writes to the parent. The parent reads
- * from the utility and writes into the buffer. The parent reads
- * from output[0], and the utility writes to output[1].
+ * There are two different processes running through this code, named
+ * the utility (the shell) and the parent. The utility reads standard
+ * input and writes standard output and standard error output. The
+ * parent writes to the utility, reads its standard output and ignores
+ * its standard error output. Historically, the standard error output
+ * was discarded by vi, as it produces a lot of noise when file patterns
+ * don't match.
+ *
+ * The parent reads std_output[0], and the utility writes std_output[1].
*/
- if (pipe(output) < 0) {
+ ifp = NULL;
+ std_output[0] = std_output[1] = -1;
+ if (pipe(std_output) < 0) {
msgq(sp, M_SYSERR, "pipe");
return (1);
}
- if ((ifp = fdopen(output[0], "r")) == NULL) {
+ if ((ifp = fdopen(std_output[0], "r")) == NULL) {
msgq(sp, M_SYSERR, "fdopen");
goto err;
}
/*
- * Do the minimal amount of work possible, the shell is going
- * to run briefly and then exit. Hopefully.
+ * Do the minimal amount of work possible, the shell is going to run
+ * briefly and then exit. We sincerely hope.
*/
- SIGBLOCK(sp->gp);
switch (pid = vfork()) {
case -1: /* Error. */
- SIGUNBLOCK(sp->gp);
-
msgq(sp, M_SYSERR, "vfork");
-err: (void)close(output[0]);
- (void)close(output[1]);
+err: if (ifp != NULL)
+ (void)fclose(ifp);
+ else if (std_output[0] != -1)
+ close(std_output[0]);
+ if (std_output[1] != -1)
+ close(std_output[0]);
return (1);
case 0: /* Utility. */
- /* The utility has default signal behavior. */
- sig_end();
-
- /* Redirect stdout/stderr to the write end of the pipe. */
- (void)dup2(output[1], STDOUT_FILENO);
- (void)dup2(output[1], STDERR_FILENO);
+ /* Redirect stdout to the write end of the pipe. */
+ (void)dup2(std_output[1], STDOUT_FILENO);
/* Close the utility's file descriptors. */
- (void)close(output[0]);
- (void)close(output[1]);
+ (void)close(std_output[0]);
+ (void)close(std_output[1]);
+ (void)close(STDERR_FILENO);
- /* Assumes that all shells have -c. */
+ /*
+ * XXX
+ * Assume that all shells have -c.
+ */
execl(sh_path, sh, "-c", bp, NULL);
- msgq(sp, M_ERR,
- "Error: execl: %s: %s", sh_path, strerror(errno));
+ msgq_str(sp, M_SYSERR, sh_path, "118|Error: execl: %s");
_exit(127);
default: /* Parent. */
- SIGUNBLOCK(sp->gp);
-
- /* Close the pipe end the parent won't use. */
- (void)close(output[1]);
+ /* Close the pipe ends the parent won't use. */
+ (void)close(std_output[1]);
break;
}
- rval = 0;
-
/*
- * Copy process output into a buffer.
+ * Copy process standard output into a buffer.
*
* !!!
* Historic vi apparently discarded leading \n and \r's from
@@ -583,27 +709,48 @@ err: (void)close(output[0]);
for (p = bp, len = 0, ch = EOF;
(ch = getc(ifp)) != EOF; *p++ = ch, --blen, ++len)
if (blen < 5) {
- ADD_SPACE_GOTO(sp, bp, blen, *blenp * 2);
+ ADD_SPACE_GOTO(sp, bp, *blenp, *blenp * 2);
p = bp + len;
blen = *blenp - len;
}
/* Delete the final newline, nul terminate the string. */
if (p > bp && (p[-1] == '\n' || p[-1] == '\r')) {
+ --p;
--len;
- *--p = '\0';
- } else
- *p = '\0';
+ }
+ *p = '\0';
*lenp = len;
+ *bpp = bp; /* *blenp is already updated. */
- if (ferror(ifp)) {
- msgq(sp, M_ERR, "I/O error: %s", sh);
-binc_err: rval = 1;
- }
- (void)fclose(ifp);
+ if (ferror(ifp))
+ goto ioerr;
+ if (fclose(ifp)) {
+ioerr: msgq_str(sp, M_ERR, sh, "119|I/O error: %s");
+alloc_err: rval = SEXP_ERR;
+ } else
+ rval = SEXP_OK;
- *bpp = bp; /* *blenp is already updated. */
+ /*
+ * Wait for the process. If the shell process fails (e.g., "echo $q"
+ * where q wasn't a defined variable) or if the returned string has
+ * no characters or only blank characters, (e.g., "echo $5"), complain
+ * that the shell expansion failed. We can't know for certain that's
+ * the error, but it's a good guess, and it matches historic practice.
+ * This won't catch "echo foo_$5", but that's not a common error and
+ * historic vi didn't catch it either.
+ */
+ if (proc_wait(sp, (long)pid, sh, 1, 0))
+ rval = SEXP_EXPANSION_ERR;
+
+ for (p = bp; len; ++p, --len)
+ if (!isblank(*p))
+ break;
+ if (len == 0)
+ rval = SEXP_EXPANSION_ERR;
+
+ if (rval == SEXP_EXPANSION_ERR)
+ msgq(sp, M_ERR, "304|Shell expansion failed");
- /* Wait for the process. */
- return (proc_wait(sp, (long)pid, sh, 0) || rval);
+ return (rval == SEXP_OK ? 0 : 1);
}
diff --git a/contrib/nvi/ex/ex_at.c b/contrib/nvi/ex/ex_at.c
new file mode 100644
index 000000000000..e9c6c592d60b
--- /dev/null
+++ b/contrib/nvi/ex/ex_at.c
@@ -0,0 +1,126 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_at.c 10.12 (Berkeley) 9/15/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_at -- :@[@ | buffer]
+ * :*[* | buffer]
+ *
+ * Execute the contents of the buffer.
+ *
+ * PUBLIC: int ex_at __P((SCR *, EXCMD *));
+ */
+int
+ex_at(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ CB *cbp;
+ CHAR_T name;
+ EXCMD *ecp;
+ RANGE *rp;
+ TEXT *tp;
+ size_t len;
+ char *p;
+
+ /*
+ * !!!
+ * Historically, [@*]<carriage-return> and [@*][@*] executed the most
+ * recently executed buffer in ex mode.
+ */
+ name = FL_ISSET(cmdp->iflags, E_C_BUFFER) ? cmdp->buffer : '@';
+ if (name == '@' || name == '*') {
+ if (!F_ISSET(sp, SC_AT_SET)) {
+ ex_emsg(sp, NULL, EXM_NOPREVBUF);
+ return (1);
+ }
+ name = sp->at_lbuf;
+ }
+ sp->at_lbuf = name;
+ F_SET(sp, SC_AT_SET);
+
+ CBNAME(sp, cbp, name);
+ if (cbp == NULL) {
+ ex_emsg(sp, KEY_NAME(sp, name), EXM_EMPTYBUF);
+ return (1);
+ }
+
+ /*
+ * !!!
+ * Historically the @ command took a range of lines, and the @ buffer
+ * was executed once per line. The historic vi could be trashed by
+ * this because it didn't notice if the underlying file changed, or,
+ * for that matter, if there were no more lines on which to operate.
+ * For example, take a 10 line file, load "%delete" into a buffer,
+ * and enter :8,10@<buffer>.
+ *
+ * The solution is a bit tricky. If the user specifies a range, take
+ * the same approach as for global commands, and discard the command
+ * if exit or switch to a new file/screen. If the user doesn't specify
+ * the range, continue to execute after a file/screen switch, which
+ * means @ buffers are still useful in a multi-screen environment.
+ */
+ CALLOC_RET(sp, ecp, EXCMD *, 1, sizeof(EXCMD));
+ CIRCLEQ_INIT(&ecp->rq);
+ CALLOC_RET(sp, rp, RANGE *, 1, sizeof(RANGE));
+ rp->start = cmdp->addr1.lno;
+ if (F_ISSET(cmdp, E_ADDR_DEF)) {
+ rp->stop = rp->start;
+ FL_SET(ecp->agv_flags, AGV_AT_NORANGE);
+ } else {
+ rp->stop = cmdp->addr2.lno;
+ FL_SET(ecp->agv_flags, AGV_AT);
+ }
+ CIRCLEQ_INSERT_HEAD(&ecp->rq, rp, q);
+
+ /*
+ * Buffers executed in ex mode or from the colon command line in vi
+ * were ex commands. We can't push it on the terminal queue, since
+ * it has to be executed immediately, and we may be in the middle of
+ * an ex command already. Push the command on the ex command stack.
+ * Build two copies of the command. We need two copies because the
+ * ex parser may step on the command string when it's parsing it.
+ */
+ for (len = 0, tp = cbp->textq.cqh_last;
+ tp != (void *)&cbp->textq; tp = tp->q.cqe_prev)
+ len += tp->len + 1;
+
+ MALLOC_RET(sp, ecp->cp, char *, len * 2);
+ ecp->o_cp = ecp->cp;
+ ecp->o_clen = len;
+ ecp->cp[len] = '\0';
+
+ /* Copy the buffer into the command space. */
+ for (p = ecp->cp + len, tp = cbp->textq.cqh_last;
+ tp != (void *)&cbp->textq; tp = tp->q.cqe_prev) {
+ memcpy(p, tp->lb, tp->len);
+ p += tp->len;
+ *p++ = '\n';
+ }
+
+ LIST_INSERT_HEAD(&sp->gp->ecq, ecp, q);
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_bang.c b/contrib/nvi/ex/ex_bang.c
new file mode 100644
index 000000000000..25f3f7732ab0
--- /dev/null
+++ b/contrib/nvi/ex/ex_bang.c
@@ -0,0 +1,186 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_bang.c 10.33 (Berkeley) 9/23/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+/*
+ * ex_bang -- :[line [,line]] ! command
+ *
+ * Pass the rest of the line after the ! character to the program named by
+ * the O_SHELL option.
+ *
+ * Historical vi did NOT do shell expansion on the arguments before passing
+ * them, only file name expansion. This means that the O_SHELL program got
+ * "$t" as an argument if that is what the user entered. Also, there's a
+ * special expansion done for the bang command. Any exclamation points in
+ * the user's argument are replaced by the last, expanded ! command.
+ *
+ * There's some fairly amazing slop in this routine to make the different
+ * ways of getting here display the right things. It took a long time to
+ * get it right (wrong?), so be careful.
+ *
+ * PUBLIC: int ex_bang __P((SCR *, EXCMD *));
+ */
+int
+ex_bang(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ enum filtertype ftype;
+ ARGS *ap;
+ EX_PRIVATE *exp;
+ MARK rm;
+ recno_t lno;
+ int rval;
+ const char *msg;
+
+ ap = cmdp->argv[0];
+ if (ap->len == 0) {
+ ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+ return (1);
+ }
+
+ /* Set the "last bang command" remembered value. */
+ exp = EXP(sp);
+ if (exp->lastbcomm != NULL)
+ free(exp->lastbcomm);
+ if ((exp->lastbcomm = strdup(ap->bp)) == NULL) {
+ msgq(sp, M_SYSERR, NULL);
+ return (1);
+ }
+
+ /*
+ * If the command was modified by the expansion, it was historically
+ * redisplayed.
+ */
+ if (F_ISSET(cmdp, E_MODIFY) && !F_ISSET(sp, SC_EX_SILENT)) {
+ /*
+ * Display the command if modified. Historic ex/vi displayed
+ * the command if it was modified due to file name and/or bang
+ * expansion. If piping lines in vi, it would be immediately
+ * overwritten by any error or line change reporting.
+ */
+ if (F_ISSET(sp, SC_VI))
+ vs_update(sp, "!", ap->bp);
+ else {
+ (void)ex_printf(sp, "!%s\n", ap->bp);
+ (void)ex_fflush(sp);
+ }
+ }
+
+ /*
+ * If no addresses were specified, run the command. If there's an
+ * underlying file, it's been modified and autowrite is set, write
+ * the file back. If the file has been modified, autowrite is not
+ * set and the warn option is set, tell the user about the file.
+ */
+ if (cmdp->addrcnt == 0) {
+ msg = NULL;
+ if (sp->ep != NULL && F_ISSET(sp->ep, F_MODIFIED))
+ if (O_ISSET(sp, O_AUTOWRITE)) {
+ if (file_aw(sp, FS_ALL))
+ return (0);
+ } else if (O_ISSET(sp, O_WARN) &&
+ !F_ISSET(sp, SC_EX_SILENT))
+ msg = msg_cat(sp,
+ "303|File modified since last write.",
+ NULL);
+
+ /* If we're still in a vi screen, move out explicitly. */
+ (void)ex_exec_proc(sp,
+ cmdp, ap->bp, msg, !F_ISSET(sp, SC_EX | SC_SCR_EXWROTE));
+ }
+
+ /*
+ * If addresses were specified, pipe lines from the file through the
+ * command.
+ *
+ * Historically, vi lines were replaced by both the stdout and stderr
+ * lines of the command, but ex lines by only the stdout lines. This
+ * makes no sense to me, so nvi makes it consistent for both, and
+ * matches vi's historic behavior.
+ */
+ else {
+ NEEDFILE(sp, cmdp);
+
+ /* Autoprint is set historically, even if the command fails. */
+ F_SET(cmdp, E_AUTOPRINT);
+
+ /*
+ * !!!
+ * Historical vi permitted "!!" in an empty file. When this
+ * happens, we arrive here with two addresses of 1,1 and a
+ * bad attitude. The simple solution is to turn it into a
+ * FILTER_READ operation, with the exception that stdin isn't
+ * opened for the utility, and the cursor position isn't the
+ * same. The only historic glitch (I think) is that we don't
+ * put an empty line into the default cut buffer, as historic
+ * vi did. Imagine, if you can, my disappointment.
+ */
+ ftype = FILTER_BANG;
+ if (cmdp->addr1.lno == 1 && cmdp->addr2.lno == 1) {
+ if (db_last(sp, &lno))
+ return (1);
+ if (lno == 0) {
+ cmdp->addr1.lno = cmdp->addr2.lno = 0;
+ ftype = FILTER_RBANG;
+ }
+ }
+ rval = ex_filter(sp, cmdp,
+ &cmdp->addr1, &cmdp->addr2, &rm, ap->bp, ftype);
+
+ /*
+ * If in vi mode, move to the first nonblank.
+ *
+ * !!!
+ * Historic vi wasn't consistent in this area -- if you used
+ * a forward motion it moved to the first nonblank, but if you
+ * did a backward motion it didn't. And, if you followed a
+ * backward motion with a forward motion, it wouldn't move to
+ * the nonblank for either. Going to the nonblank generally
+ * seems more useful and consistent, so we do it.
+ */
+ sp->lno = rm.lno;
+ if (F_ISSET(sp, SC_VI)) {
+ sp->cno = 0;
+ (void)nonblank(sp, sp->lno, &sp->cno);
+ } else
+ sp->cno = rm.cno;
+ }
+
+ /* Ex terminates with a bang, even if the command fails. */
+ if (!F_ISSET(sp, SC_VI) && !F_ISSET(sp, SC_EX_SILENT))
+ (void)ex_puts(sp, "!\n");
+
+ /*
+ * XXX
+ * The ! commands never return an error, so that autoprint always
+ * happens in the ex parser.
+ */
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_cd.c b/contrib/nvi/ex/ex_cd.c
new file mode 100644
index 000000000000..3307c7b6306b
--- /dev/null
+++ b/contrib/nvi/ex/ex_cd.c
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_cd.c 10.10 (Berkeley) 8/12/96";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_cd -- :cd[!] [directory]
+ * Change directories.
+ *
+ * PUBLIC: int ex_cd __P((SCR *, EXCMD *));
+ */
+int
+ex_cd(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ struct passwd *pw;
+ ARGS *ap;
+ CHAR_T savech;
+ char *dir, *p, *t; /* XXX: END OF THE STACK, DON'T TRUST GETCWD. */
+ char buf[MAXPATHLEN * 2];
+
+ /*
+ * !!!
+ * Historic practice is that the cd isn't attempted if the file has
+ * been modified, unless its name begins with a leading '/' or the
+ * force flag is set.
+ */
+ if (F_ISSET(sp->ep, F_MODIFIED) &&
+ !FL_ISSET(cmdp->iflags, E_C_FORCE) && sp->frp->name[0] != '/') {
+ msgq(sp, M_ERR,
+ "120|File modified since last complete write; write or use ! to override");
+ return (1);
+ }
+
+ switch (cmdp->argc) {
+ case 0:
+ /* If no argument, change to the user's home directory. */
+ if ((dir = getenv("HOME")) == NULL) {
+ if ((pw = getpwuid(getuid())) == NULL ||
+ pw->pw_dir == NULL || pw->pw_dir[0] == '\0') {
+ msgq(sp, M_ERR,
+ "121|Unable to find home directory location");
+ return (1);
+ }
+ dir = pw->pw_dir;
+ }
+ break;
+ case 1:
+ dir = cmdp->argv[0]->bp;
+ break;
+ default:
+ abort();
+ }
+
+ /*
+ * Try the current directory first. If this succeeds, don't display
+ * a message, vi didn't historically, and it should be obvious to the
+ * user where they are.
+ */
+ if (!chdir(dir))
+ return (0);
+
+ /*
+ * If moving to the user's home directory, or, the path begins with
+ * "/", "./" or "../", it's the only place we try.
+ */
+ if (cmdp->argc == 0 ||
+ (ap = cmdp->argv[0])->bp[0] == '/' ||
+ ap->len == 1 && ap->bp[0] == '.' ||
+ ap->len >= 2 && ap->bp[0] == '.' && ap->bp[1] == '.' &&
+ (ap->bp[2] == '/' || ap->bp[2] == '\0'))
+ goto err;
+
+ /* Try the O_CDPATH option values. */
+ for (p = t = O_STR(sp, O_CDPATH);; ++p)
+ if (*p == '\0' || *p == ':') {
+ /*
+ * Empty strings specify ".". The only way to get an
+ * empty string is a leading colon, colons in a row,
+ * or a trailing colon. Or, to put it the other way,
+ * if the length is 1 or less, then we're dealing with
+ * ":XXX", "XXX::XXXX" , "XXX:", or "". Since we've
+ * already tried dot, we ignore tham all.
+ */
+ if (t < p - 1) {
+ savech = *p;
+ *p = '\0';
+ (void)snprintf(buf,
+ sizeof(buf), "%s/%s", t, dir);
+ *p = savech;
+ if (!chdir(buf)) {
+ if (getcwd(buf, sizeof(buf)) != NULL)
+ msgq_str(sp, M_INFO, buf, "122|New current directory: %s");
+ return (0);
+ }
+ }
+ t = p + 1;
+ if (*p == '\0')
+ break;
+ }
+
+err: msgq_str(sp, M_SYSERR, dir, "%s");
+ return (1);
+}
diff --git a/usr.bin/vi/ex/excmd.c b/contrib/nvi/ex/ex_cmd.c
index 384576862348..8f7fc8da7a13 100644
--- a/usr.bin/vi/ex/excmd.c
+++ b/contrib/nvi/ex/ex_cmd.c
@@ -1,56 +1,26 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)excmd.c 8.58 (Berkeley) 8/9/94";
+static const char sccsid[] = "@(#)ex_cmd.c 10.20 (Berkeley) 10/10/96";
#endif /* not lint */
#include <sys/types.h>
#include <sys/queue.h>
-#include <sys/time.h>
#include <bitstring.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
-#include <termios.h>
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
+#include "../common/common.h"
/*
* This array maps ex command names to command functions.
@@ -80,22 +50,22 @@ static char sccsid[] = "@(#)excmd.c 8.58 (Berkeley) 8/9/94";
*/
EXCMDLIST const cmds[] = {
/* C_SCROLL */
- {"\004", ex_pr, E_ADDR2|E_NORC,
+ {"\004", ex_pr, E_ADDR2,
"",
"^D",
"scroll lines"},
/* C_BANG */
- {"!", ex_bang, E_ADDR2_NONE|E_NORC,
+ {"!", ex_bang, E_ADDR2_NONE | E_SECURE,
"S",
"[line [,line]] ! command",
"filter lines through commands or run commands"},
/* C_HASH */
- {"#", ex_number, E_ADDR2|E_F_PRCLEAR|E_NORC,
+ {"#", ex_number, E_ADDR2|E_CLRFLAG,
"ca1",
"[line [,line]] # [count] [l]",
"display numbered lines"},
/* C_SUBAGAIN */
- {"&", ex_subagain, E_ADDR2|E_NORC,
+ {"&", ex_subagain, E_ADDR2,
"s",
"[line [,line]] & [cgr] [count] [#lp]",
"repeat the last subsitution"},
@@ -105,147 +75,147 @@ EXCMDLIST const cmds[] = {
"* [buffer]",
"execute a buffer"},
/* C_SHIFTL */
- {"<", ex_shiftl, E_ADDR2|E_AUTOPRINT|E_NORC,
+ {"<", ex_shiftl, E_ADDR2|E_AUTOPRINT,
"ca1",
"[line [,line]] <[<...] [count] [flags]",
"shift lines left"},
/* C_EQUAL */
- {"=", ex_equal, E_ADDR1|E_NORC|E_ZERO|E_ZERODEF,
+ {"=", ex_equal, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
"1",
"[line] = [flags]",
"display line number"},
/* C_SHIFTR */
- {">", ex_shiftr, E_ADDR2|E_AUTOPRINT|E_NORC,
+ {">", ex_shiftr, E_ADDR2|E_AUTOPRINT,
"ca1",
"[line [,line]] >[>...] [count] [flags]",
"shift lines right"},
/* C_AT */
- {"@", ex_at, 0,
+ {"@", ex_at, E_ADDR2,
"b",
"@ [buffer]",
"execute a buffer"},
/* C_APPEND */
- {"append", ex_append, E_ADDR1|E_NORC|E_ZERO|E_ZERODEF,
+ {"append", ex_append, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
"!",
"[line] a[ppend][!]",
"append input to a line"},
/* C_ABBR */
- {"abbreviate", ex_abbr, E_NOGLOBAL,
+ {"abbreviate", ex_abbr, 0,
"W",
"ab[brev] [word replace]",
"specify an input abbreviation"},
/* C_ARGS */
- {"args", ex_args, E_NOGLOBAL|E_NORC,
+ {"args", ex_args, 0,
"",
"ar[gs]",
"display file argument list"},
/* C_BG */
- {"bg", ex_bg, E_NOGLOBAL|E_NORC,
+ {"bg", ex_bg, E_VIONLY,
"",
"bg",
- "background the current screen"},
+ "put a foreground screen into the background"},
/* C_CHANGE */
- {"change", ex_change, E_ADDR2|E_NORC|E_ZERODEF,
+ {"change", ex_change, E_ADDR2|E_ADDR_ZERODEF,
"!ca",
"[line [,line]] c[hange][!] [count]",
"change lines to input"},
/* C_CD */
- {"cd", ex_cd, E_NOGLOBAL,
+ {"cd", ex_cd, 0,
"!f1o",
"cd[!] [directory]",
"change the current directory"},
/* C_CHDIR */
- {"chdir", ex_cd, E_NOGLOBAL,
+ {"chdir", ex_cd, 0,
"!f1o",
"chd[ir][!] [directory]",
"change the current directory"},
/* C_COPY */
- {"copy", ex_copy, E_ADDR2|E_AUTOPRINT|E_NORC,
+ {"copy", ex_copy, E_ADDR2|E_AUTOPRINT,
"l1",
"[line [,line]] co[py] line [flags]",
"copy lines elsewhere in the file"},
+/* C_CSCOPE */
+ {"cscope", ex_cscope, 0,
+ "!s",
+ "cs[cope] command [args]",
+ "create a set of tags using a cscope command"},
/*
* !!!
* Adding new commands starting with 'd' may break the delete command code
* in ex_cmd() (the ex parser). Read through the comments there, first.
*/
/* C_DELETE */
- {"delete", ex_delete, E_ADDR2|E_AUTOPRINT|E_NORC,
+ {"delete", ex_delete, E_ADDR2|E_AUTOPRINT,
"bca1",
"[line [,line]] d[elete][flags] [buffer] [count] [flags]",
"delete lines from the file"},
/* C_DISPLAY */
- {"display", ex_display, E_NOGLOBAL|E_NORC,
+ {"display", ex_display, 0,
"w1r",
- "display b[uffers] | s[creens] | t[ags]",
- "display buffers, screens or tags"},
-/* C_DIGRAPH */
- {"digraph", ex_digraph, E_NOGLOBAL|E_NOPERM|E_NORC,
- "",
- "digraph",
- "specify digraphs (not implemented)"},
+ "display b[uffers] | c[onnections] | s[creens] | t[ags]",
+ "display buffers, connections, screens or tags"},
/* C_EDIT */
- {"edit", ex_edit, E_NOGLOBAL|E_NORC,
+ {"edit", ex_edit, E_NEWSCREEN,
"f1o",
- "e[dit][!] [+cmd] [file]",
+ "[Ee][dit][!] [+cmd] [file]",
"begin editing another file"},
/* C_EX */
- {"ex", ex_edit, E_NOGLOBAL|E_NORC,
+ {"ex", ex_edit, E_NEWSCREEN,
"f1o",
- "ex[!] [+cmd] [file]",
+ "[Ee]x[!] [+cmd] [file]",
"begin editing another file"},
/* C_EXUSAGE */
- {"exusage", ex_usage, E_NOGLOBAL|E_NORC,
+ {"exusage", ex_usage, 0,
"w1o",
"[exu]sage [command]",
"display ex command usage statement"},
/* C_FILE */
- {"file", ex_file, E_NOGLOBAL|E_NORC,
+ {"file", ex_file, 0,
"f1o",
"f[ile] [name]",
"display (and optionally set) file name"},
/* C_FG */
- {"fg", ex_fg, E_NOGLOBAL|E_NORC,
+ {"fg", ex_fg, E_NEWSCREEN|E_VIONLY,
"f1o",
- "fg [file]",
- "switch the current screen and a backgrounded screen"},
+ "[Ff]g [file]",
+ "bring a backgrounded screen into the foreground"},
/* C_GLOBAL */
- {"global", ex_global, E_ADDR2_ALL|E_NOGLOBAL|E_NORC,
+ {"global", ex_global, E_ADDR2_ALL,
"!s",
"[line [,line]] g[lobal][!] [;/]RE[;/] [commands]",
"execute a global command on lines matching an RE"},
/* C_HELP */
- {"help", ex_help, E_NOGLOBAL|E_NORC,
+ {"help", ex_help, 0,
"",
"he[lp]",
"display help statement"},
/* C_INSERT */
- {"insert", ex_insert, E_ADDR1|E_NORC,
+ {"insert", ex_insert, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
"!",
"[line] i[nsert][!]",
"insert input before a line"},
/* C_JOIN */
- {"join", ex_join, E_ADDR2|E_AUTOPRINT|E_NORC,
+ {"join", ex_join, E_ADDR2|E_AUTOPRINT,
"!ca1",
"[line [,line]] j[oin][!] [count] [flags]",
"join lines into a single line"},
/* C_K */
- {"k", ex_mark, E_ADDR1|E_NORC,
+ {"k", ex_mark, E_ADDR1,
"w1r",
"[line] k key",
"mark a line position"},
/* C_LIST */
- {"list", ex_list, E_ADDR2|E_F_PRCLEAR|E_NORC,
+ {"list", ex_list, E_ADDR2|E_CLRFLAG,
"ca1",
"[line [,line]] l[ist] [count] [#]",
"display lines in an unambiguous form"},
/* C_MOVE */
- {"move", ex_move, E_ADDR2|E_AUTOPRINT|E_NORC,
+ {"move", ex_move, E_ADDR2|E_AUTOPRINT,
"l",
"[line [,line]] m[ove] line",
"move lines elsewhere in the file"},
/* C_MARK */
- {"mark", ex_mark, E_ADDR1|E_NORC,
+ {"mark", ex_mark, E_ADDR1,
"w1r",
"[line] ma[rk] key",
"mark a line position"},
@@ -255,17 +225,17 @@ EXCMDLIST const cmds[] = {
"map[!] [keys replace]",
"map input or commands to one or more keys"},
/* C_MKEXRC */
- {"mkexrc", ex_mkexrc, E_NOGLOBAL|E_NORC,
+ {"mkexrc", ex_mkexrc, 0,
"!f1r",
"mkexrc[!] file",
"write a .exrc file"},
/* C_NEXT */
- {"next", ex_next, E_NOGLOBAL|E_NORC,
+ {"next", ex_next, E_NEWSCREEN,
"!fN",
- "n[ext][!] [+cmd] [file ...]",
+ "[Nn][ext][!] [+cmd] [file ...]",
"edit (and optionally specify) the next file"},
/* C_NUMBER */
- {"number", ex_number, E_ADDR2|E_F_PRCLEAR|E_NORC,
+ {"number", ex_number, E_ADDR2|E_CLRFLAG,
"ca1",
"[line [,line]] nu[mber] [count] [l]",
"change display to number lines"},
@@ -275,182 +245,211 @@ EXCMDLIST const cmds[] = {
"[line] o[pen] [/RE/] [flags]",
"enter \"open\" mode (not implemented)"},
/* C_PRINT */
- {"print", ex_pr, E_ADDR2|E_F_PRCLEAR|E_NORC,
+ {"print", ex_pr, E_ADDR2|E_CLRFLAG,
"ca1",
"[line [,line]] p[rint] [count] [#l]",
"display lines"},
+/* C_PERLCMD */
+ {"perl", ex_perl, E_ADDR2_ALL|E_ADDR_ZERO|
+ E_ADDR_ZERODEF|E_SECURE,
+ "s",
+ "pe[rl] cmd",
+ "run the perl interpreter with the command"},
+/* C_PERLDOCMD */
+ {"perldo", ex_perl, E_ADDR2_ALL|E_ADDR_ZERO|
+ E_ADDR_ZERODEF|E_SECURE,
+ "s",
+ "perld[o] cmd",
+ "run the perl interpreter with the command, on each line"},
/* C_PRESERVE */
- {"preserve", ex_preserve, E_NOGLOBAL|E_NORC,
+ {"preserve", ex_preserve, 0,
"",
"pre[serve]",
"preserve an edit session for recovery"},
/* C_PREVIOUS */
- {"previous", ex_prev, E_NOGLOBAL|E_NORC,
+ {"previous", ex_prev, E_NEWSCREEN,
"!",
- "prev[ious][!]",
+ "[Pp]rev[ious][!]",
"edit the previous file in the file argument list"},
/* C_PUT */
- {"put", ex_put, E_ADDR1|E_AUTOPRINT|E_NORC|E_ZERO,
+ {"put", ex_put,
+ E_ADDR1|E_AUTOPRINT|E_ADDR_ZERO|E_ADDR_ZERODEF,
"b",
"[line] pu[t] [buffer]",
"append a cut buffer to the line"},
/* C_QUIT */
- {"quit", ex_quit, E_NOGLOBAL|E_NORC,
+ {"quit", ex_quit, 0,
"!",
"q[uit][!]",
"exit ex/vi"},
/* C_READ */
- {"read", ex_read, E_ADDR1|E_NORC|E_ZERO|E_ZERODEF,
+ {"read", ex_read, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
"s",
"[line] r[ead] [!cmd | [file]]",
"append input from a command or file to the line"},
/* C_RECOVER */
- {"recover", ex_recover, E_NOGLOBAL|E_NORC,
+ {"recover", ex_recover, 0,
"!f1r",
"recover[!] file",
"recover a saved file"},
/* C_RESIZE */
- {"resize", ex_resize, E_NOGLOBAL|E_NORC,
+ {"resize", ex_resize, E_VIONLY,
"c+",
"resize [+-]rows",
"grow or shrink the current screen"},
/* C_REWIND */
- {"rewind", ex_rew, E_NOGLOBAL|E_NORC,
+ {"rewind", ex_rew, 0,
"!",
"rew[ind][!]",
"re-edit all the files in the file argument list"},
+/*
+ * !!!
+ * Adding new commands starting with 's' may break the substitute command code
+ * in ex_cmd() (the ex parser). Read through the comments there, first.
+ */
/* C_SUBSTITUTE */
- {"substitute", ex_substitute, E_ADDR2|E_NORC,
+ {"s", ex_s, E_ADDR2,
"s",
-"[line [,line]] s[ubstitute] [[/;]RE[/;]/repl[/;] [cgr] [count] [#lp]]",
+ "[line [,line]] s [[/;]RE[/;]repl[/;] [cgr] [count] [#lp]]",
"substitute on lines matching an RE"},
/* C_SCRIPT */
- {"script", ex_script, E_NOGLOBAL|E_NORC,
+ {"script", ex_script, E_SECURE,
"!f1o",
"sc[ript][!] [file]",
"run a shell in a screen"},
/* C_SET */
- {"set", ex_set, E_NOGLOBAL,
+ {"set", ex_set, 0,
"wN",
"se[t] [option[=[value]]...] [nooption ...] [option? ...] [all]",
"set options (use \":set all\" to see all options)"},
/* C_SHELL */
- {"shell", ex_shell, E_NOGLOBAL|E_NORC,
+ {"shell", ex_shell, E_SECURE,
"",
"sh[ell]",
"suspend editing and run a shell"},
/* C_SOURCE */
- {"source", ex_source, E_NOGLOBAL,
+ {"source", ex_source, 0,
"f1r",
"so[urce] file",
"read a file of ex commands"},
-/* C_SPLIT */
- {"split", ex_split, E_NOGLOBAL|E_NORC,
- "fNo",
- "sp[lit] [file ...]",
- "split the current screen into two screens"},
/* C_STOP */
- {"stop", ex_stop, E_NOGLOBAL|E_NORC,
+ {"stop", ex_stop, E_SECURE,
"!",
"st[op][!]",
"suspend the edit session"},
/* C_SUSPEND */
- {"suspend", ex_stop, E_NOGLOBAL|E_NORC,
+ {"suspend", ex_stop, E_SECURE,
"!",
"su[spend][!]",
"suspend the edit session"},
/* C_T */
- {"t", ex_copy, E_ADDR2|E_AUTOPRINT|E_NORC,
+ {"t", ex_copy, E_ADDR2|E_AUTOPRINT,
"l1",
"[line [,line]] t line [flags]",
"copy lines elsewhere in the file"},
/* C_TAG */
- {"tag", ex_tagpush, E_NOGLOBAL,
+ {"tag", ex_tag_push, E_NEWSCREEN,
"!w1o",
- "ta[g][!] [string]",
+ "[Tt]a[g][!] [string]",
"edit the file containing the tag"},
+/* C_TAGNEXT */
+ {"tagnext", ex_tag_next, 0,
+ "!",
+ "tagn[ext][!]",
+ "move to the next tag"},
/* C_TAGPOP */
- {"tagpop", ex_tagpop, E_NOGLOBAL|E_NORC,
+ {"tagpop", ex_tag_pop, 0,
"!w1o",
"tagp[op][!] [number | file]",
- "return to a previous tag"},
+ "return to the previous group of tags"},
+/* C_TAGPREV */
+ {"tagprev", ex_tag_prev, 0,
+ "!",
+ "tagpr[ev][!]",
+ "move to the previous tag"},
/* C_TAGTOP */
- {"tagtop", ex_tagtop, E_NOGLOBAL|E_NORC,
+ {"tagtop", ex_tag_top, 0,
"!",
"tagt[op][!]",
- "return to the first tag"},
+ "discard all tags"},
+/* C_TCLCMD */
+ {"tcl", ex_tcl, E_ADDR2_ALL|E_ADDR_ZERO|
+ E_ADDR_ZERODEF|E_SECURE,
+ "s",
+ "tc[l] cmd",
+ "run the tcl interpreter with the command"},
/* C_UNDO */
- {"undo", ex_undo, E_AUTOPRINT|E_NOGLOBAL|E_NORC,
+ {"undo", ex_undo, E_AUTOPRINT,
"",
"u[ndo]",
"undo the most recent change"},
/* C_UNABBREVIATE */
- {"unabbreviate",ex_unabbr, E_NOGLOBAL,
+ {"unabbreviate",ex_unabbr, 0,
"w1r",
"una[bbrev] word",
"delete an abbreviation"},
/* C_UNMAP */
- {"unmap", ex_unmap, E_NOGLOBAL,
+ {"unmap", ex_unmap, 0,
"!w1r",
"unm[ap][!] word",
"delete an input or command map"},
-/* C_VGLOBAL */
- {"vglobal", ex_vglobal, E_ADDR2_ALL|E_NOGLOBAL|E_NORC,
+/* C_V */
+ {"v", ex_v, E_ADDR2_ALL,
"s",
- "[line [,line]] v[global] [;/]RE[;/] [commands]",
+ "[line [,line]] v [;/]RE[;/] [commands]",
"execute a global command on lines NOT matching an RE"},
/* C_VERSION */
- {"version", ex_version, E_NOGLOBAL|E_NORC,
+ {"version", ex_version, 0,
"",
"version",
"display the program version information"},
/* C_VISUAL_EX */
- {"visual", ex_visual, E_ADDR1|E_NOGLOBAL|E_NORC|E_ZERODEF,
+ {"visual", ex_visual, E_ADDR1|E_ADDR_ZERODEF,
"2c11",
"[line] vi[sual] [-|.|+|^] [window_size] [flags]",
"enter visual (vi) mode from ex mode"},
/* C_VISUAL_VI */
- {"visual", ex_edit, E_NOGLOBAL|E_NORC,
+ {"visual", ex_edit, E_NEWSCREEN,
"f1o",
- "vi[sual][!] [+cmd] [file]",
+ "[Vv]i[sual][!] [+cmd] [file]",
"edit another file (from vi mode only)"},
/* C_VIUSAGE */
- {"viusage", ex_viusage, E_NOGLOBAL|E_NORC,
+ {"viusage", ex_viusage, 0,
"w1o",
"[viu]sage [key]",
"display vi key usage statement"},
/* C_WRITE */
- {"write", ex_write, E_ADDR2_ALL|E_NOGLOBAL|E_NORC|E_ZERODEF,
+ {"write", ex_write, E_ADDR2_ALL|E_ADDR_ZERODEF,
"!s",
- "[line [,line]] w[rite][!] [!cmd | [>>] [file]]",
+ "[line [,line]] w[rite][!] [ !cmd | [>>] [file]]",
"write the file"},
/* C_WN */
- {"wn", ex_wn, E_ADDR2_ALL|E_NOGLOBAL|E_NORC|E_ZERODEF,
+ {"wn", ex_wn, E_ADDR2_ALL|E_ADDR_ZERODEF,
"!s",
"[line [,line]] wn[!] [>>] [file]",
"write the file and switch to the next file"},
/* C_WQ */
- {"wq", ex_wq, E_ADDR2_ALL|E_NOGLOBAL|E_NORC|E_ZERODEF,
+ {"wq", ex_wq, E_ADDR2_ALL|E_ADDR_ZERODEF,
"!s",
"[line [,line]] wq[!] [>>] [file]",
"write the file and exit"},
/* C_XIT */
- {"xit", ex_xit, E_ADDR2_ALL|E_NOGLOBAL|E_NORC|E_ZERODEF,
+ {"xit", ex_xit, E_ADDR2_ALL|E_ADDR_ZERODEF,
"!f1o",
"[line [,line]] x[it][!] [file]",
"exit"},
/* C_YANK */
- {"yank", ex_yank, E_ADDR2|E_NORC,
+ {"yank", ex_yank, E_ADDR2,
"bca",
"[line [,line]] ya[nk] [buffer] [count]",
"copy lines to a cut buffer"},
/* C_Z */
- {"z", ex_z, E_ADDR1|E_NOGLOBAL|E_NORC,
+ {"z", ex_z, E_ADDR1,
"3c01",
"[line] z [-|.|+|^|=] [count] [flags]",
"display different screens of the file"},
/* C_SUBTILDE */
- {"~", ex_subtilde, E_ADDR2|E_NORC,
+ {"~", ex_subtilde, E_ADDR2,
"s",
"[line [,line]] ~ [cgr] [count] [#lp]",
"replace previous RE with previous replacement string,"},
diff --git a/contrib/nvi/ex/ex_cscope.c b/contrib/nvi/ex/ex_cscope.c
new file mode 100644
index 000000000000..c2fa0a5c454b
--- /dev/null
+++ b/contrib/nvi/ex/ex_cscope.c
@@ -0,0 +1,1057 @@
+/*-
+ * Copyright (c) 1994, 1996
+ * Rob Mayoff. All rights reserved.
+ * Copyright (c) 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_cscope.c 10.13 (Berkeley) 9/15/96";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/types.h> /* XXX: param.h may not have included types.h */
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "pathnames.h"
+#include "tag.h"
+
+#define CSCOPE_DBFILE "cscope.out"
+#define CSCOPE_PATHS "cscope.tpath"
+
+/*
+ * 0name find all uses of name
+ * 1name find definition of name
+ * 2name find all function calls made from name
+ * 3name find callers of name
+ * 4string find text string (cscope 12.9)
+ * 4name find assignments to name (cscope 13.3)
+ * 5pattern change pattern -- NOT USED
+ * 6pattern find pattern
+ * 7name find files with name as substring
+ * 8name find files #including name
+ */
+#define FINDHELP "\
+find c|d|e|f|g|i|s|t buffer|pattern\n\
+ c: find callers of name\n\
+ d: find all function calls made from name\n\
+ e: find pattern\n\
+ f: find files with name as substring\n\
+ g: find definition of name\n\
+ i: find files #including name\n\
+ s: find all uses of name\n\
+ t: find assignments to name"
+
+static int cscope_add __P((SCR *, EXCMD *, char *));
+static int cscope_find __P((SCR *, EXCMD*, char *));
+static int cscope_help __P((SCR *, EXCMD *, char *));
+static int cscope_kill __P((SCR *, EXCMD *, char *));
+static int cscope_reset __P((SCR *, EXCMD *, char *));
+
+typedef struct _cc {
+ char *name;
+ int (*function) __P((SCR *, EXCMD *, char *));
+ char *help_msg;
+ char *usage_msg;
+} CC;
+
+static CC const cscope_cmds[] = {
+ { "add", cscope_add,
+ "Add a new cscope database", "add file | directory" },
+ { "find", cscope_find,
+ "Query the databases for a pattern", FINDHELP },
+ { "help", cscope_help,
+ "Show help for cscope commands", "help [command]" },
+ { "kill", cscope_kill,
+ "Kill a cscope connection", "kill number" },
+ { "reset", cscope_reset,
+ "Discard all current cscope connections", "reset" },
+ { NULL }
+};
+
+static TAGQ *create_cs_cmd __P((SCR *, char *, size_t *));
+static int csc_help __P((SCR *, char *));
+static void csc_file __P((SCR *,
+ CSC *, char *, char **, size_t *, int *));
+static int get_paths __P((SCR *, CSC *));
+static CC const *lookup_ccmd __P((char *));
+static int parse __P((SCR *, CSC *, TAGQ *, int *));
+static int read_prompt __P((SCR *, CSC *));
+static int run_cscope __P((SCR *, CSC *, char *));
+static int start_cscopes __P((SCR *, EXCMD *));
+static int terminate __P((SCR *, CSC *, int));
+
+/*
+ * ex_cscope --
+ * Perform an ex cscope.
+ *
+ * PUBLIC: int ex_cscope __P((SCR *, EXCMD *));
+ */
+int
+ex_cscope(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ CC const *ccp;
+ EX_PRIVATE *exp;
+ int i;
+ char *cmd, *p;
+
+ /* Initialize the default cscope directories. */
+ exp = EXP(sp);
+ if (!F_ISSET(exp, EXP_CSCINIT) && start_cscopes(sp, cmdp))
+ return (1);
+ F_SET(exp, EXP_CSCINIT);
+
+ /* Skip leading whitespace. */
+ for (p = cmdp->argv[0]->bp, i = cmdp->argv[0]->len; i > 0; --i, ++p)
+ if (!isspace(*p))
+ break;
+ if (i == 0)
+ goto usage;
+
+ /* Skip the command to any arguments. */
+ for (cmd = p; i > 0; --i, ++p)
+ if (isspace(*p))
+ break;
+ if (*p != '\0') {
+ *p++ = '\0';
+ for (; *p && isspace(*p); ++p);
+ }
+
+ if ((ccp = lookup_ccmd(cmd)) == NULL) {
+usage: msgq(sp, M_ERR, "309|Use \"cscope help\" for help");
+ return (1);
+ }
+
+ /* Call the underlying function. */
+ return (ccp->function(sp, cmdp, p));
+}
+
+/*
+ * start_cscopes --
+ * Initialize the cscope package.
+ */
+static int
+start_cscopes(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ size_t blen, len;
+ char *bp, *cscopes, *p, *t;
+
+ /*
+ * EXTENSION #1:
+ *
+ * If the CSCOPE_DIRS environment variable is set, we treat it as a
+ * list of cscope directories that we're using, similar to the tags
+ * edit option.
+ *
+ * XXX
+ * This should probably be an edit option, although that implies that
+ * we start/stop cscope processes periodically, instead of once when
+ * the editor starts.
+ */
+ if ((cscopes = getenv("CSCOPE_DIRS")) == NULL)
+ return (0);
+ len = strlen(cscopes);
+ GET_SPACE_RET(sp, bp, blen, len);
+ memcpy(bp, cscopes, len + 1);
+
+ for (cscopes = t = bp; (p = strsep(&t, "\t :")) != NULL;)
+ if (*p != '\0')
+ (void)cscope_add(sp, cmdp, p);
+
+ FREE_SPACE(sp, bp, blen);
+ return (0);
+}
+
+/*
+ * cscope_add --
+ * The cscope add command.
+ */
+static int
+cscope_add(sp, cmdp, dname)
+ SCR *sp;
+ EXCMD *cmdp;
+ char *dname;
+{
+ struct stat sb;
+ EX_PRIVATE *exp;
+ CSC *csc;
+ size_t len;
+ int cur_argc;
+ char *dbname, path[MAXPATHLEN];
+
+ exp = EXP(sp);
+
+ /*
+ * 0 additional args: usage.
+ * 1 additional args: matched a file.
+ * >1 additional args: object, too many args.
+ */
+ cur_argc = cmdp->argc;
+ if (argv_exp2(sp, cmdp, dname, strlen(dname)))
+ return (1);
+ if (cmdp->argc == cur_argc) {
+ (void)csc_help(sp, "add");
+ return (1);
+ }
+ if (cmdp->argc == cur_argc + 1)
+ dname = cmdp->argv[cur_argc]->bp;
+ else {
+ ex_emsg(sp, dname, EXM_FILECOUNT);
+ return (1);
+ }
+
+ /*
+ * The user can specify a specific file (so they can have multiple
+ * Cscope databases in a single directory) or a directory. If the
+ * file doesn't exist, we're done. If it's a directory, append the
+ * standard database file name and try again. Store the directory
+ * name regardless so that we can use it as a base for searches.
+ */
+ if (stat(dname, &sb)) {
+ msgq(sp, M_SYSERR, dname);
+ return (1);
+ }
+ if (S_ISDIR(sb.st_mode)) {
+ (void)snprintf(path, sizeof(path),
+ "%s/%s", dname, CSCOPE_DBFILE);
+ if (stat(path, &sb)) {
+ msgq(sp, M_SYSERR, path);
+ return (1);
+ }
+ dbname = CSCOPE_DBFILE;
+ } else if ((dbname = strrchr(dname, '/')) != NULL)
+ *dbname++ = '\0';
+
+ /* Allocate a cscope connection structure and initialize its fields. */
+ len = strlen(dname);
+ CALLOC_RET(sp, csc, CSC *, 1, sizeof(CSC) + len);
+ csc->dname = csc->buf;
+ csc->dlen = len;
+ memcpy(csc->dname, dname, len);
+ csc->mtime = sb.st_mtime;
+
+ /* Get the search paths for the cscope. */
+ if (get_paths(sp, csc))
+ goto err;
+
+ /* Start the cscope process. */
+ if (run_cscope(sp, csc, dbname))
+ goto err;
+
+ /*
+ * Add the cscope connection to the screen's list. From now on,
+ * on error, we have to call terminate, which expects the csc to
+ * be on the chain.
+ */
+ LIST_INSERT_HEAD(&exp->cscq, csc, q);
+
+ /* Read the initial prompt from the cscope to make sure it's okay. */
+ if (read_prompt(sp, csc)) {
+ terminate(sp, csc, 0);
+ return (1);
+ }
+
+ return (0);
+
+err: free(csc);
+ return (1);
+}
+
+/*
+ * get_paths --
+ * Get the directories to search for the files associated with this
+ * cscope database.
+ */
+static int
+get_paths(sp, csc)
+ SCR *sp;
+ CSC *csc;
+{
+ struct stat sb;
+ int fd, nentries;
+ size_t len;
+ char *p, **pathp, buf[MAXPATHLEN * 2];
+
+ /*
+ * EXTENSION #2:
+ *
+ * If there's a cscope directory with a file named CSCOPE_PATHS, it
+ * contains a colon-separated list of paths in which to search for
+ * files returned by cscope.
+ *
+ * XXX
+ * These paths are absolute paths, and not relative to the cscope
+ * directory. To fix this, rewrite the each path using the cscope
+ * directory as a prefix.
+ */
+ (void)snprintf(buf, sizeof(buf), "%s/%s", csc->dname, CSCOPE_PATHS);
+ if (stat(buf, &sb) == 0) {
+ /* Read in the CSCOPE_PATHS file. */
+ len = sb.st_size;
+ MALLOC_RET(sp, csc->pbuf, char *, len + 1);
+ if ((fd = open(buf, O_RDONLY, 0)) < 0 ||
+ read(fd, csc->pbuf, len) != len) {
+ msgq_str(sp, M_SYSERR, buf, "%s");
+ if (fd >= 0)
+ (void)close(fd);
+ return (1);
+ }
+ (void)close(fd);
+ csc->pbuf[len] = '\0';
+
+ /* Count up the entries. */
+ for (nentries = 0, p = csc->pbuf; *p != '\0'; ++p)
+ if (p[0] == ':' && p[1] != '\0')
+ ++nentries;
+
+ /* Build an array of pointers to the paths. */
+ CALLOC_GOTO(sp,
+ csc->paths, char **, nentries + 1, sizeof(char **));
+ for (pathp = csc->paths, p = strtok(csc->pbuf, ":");
+ p != NULL; p = strtok(NULL, ":"))
+ *pathp++ = p;
+ return (0);
+ }
+
+ /*
+ * If the CSCOPE_PATHS file doesn't exist, we look for files
+ * relative to the cscope directory.
+ */
+ if ((csc->pbuf = strdup(csc->dname)) == NULL) {
+ msgq(sp, M_SYSERR, NULL);
+ return (1);
+ }
+ CALLOC_GOTO(sp, csc->paths, char **, 2, sizeof(char *));
+ csc->paths[0] = csc->pbuf;
+ return (0);
+
+alloc_err:
+ if (csc->pbuf != NULL) {
+ free(csc->pbuf);
+ csc->pbuf = NULL;
+ }
+ return (1);
+}
+
+/*
+ * run_cscope --
+ * Fork off the cscope process.
+ */
+static int
+run_cscope(sp, csc, dbname)
+ SCR *sp;
+ CSC *csc;
+ char *dbname;
+{
+ int to_cs[2], from_cs[2];
+ char cmd[MAXPATHLEN * 2];
+
+ /*
+ * Cscope reads from to_cs[0] and writes to from_cs[1]; vi reads from
+ * from_cs[0] and writes to to_cs[1].
+ */
+ to_cs[0] = to_cs[1] = from_cs[0] = from_cs[0] = -1;
+ if (pipe(to_cs) < 0 || pipe(from_cs) < 0) {
+ msgq(sp, M_SYSERR, "pipe");
+ goto err;
+ }
+ switch (csc->pid = vfork()) {
+ case -1:
+ msgq(sp, M_SYSERR, "vfork");
+err: if (to_cs[0] != -1)
+ (void)close(to_cs[0]);
+ if (to_cs[1] != -1)
+ (void)close(to_cs[1]);
+ if (from_cs[0] != -1)
+ (void)close(from_cs[0]);
+ if (from_cs[1] != -1)
+ (void)close(from_cs[1]);
+ return (1);
+ case 0: /* child: run cscope. */
+ (void)dup2(to_cs[0], STDIN_FILENO);
+ (void)dup2(from_cs[1], STDOUT_FILENO);
+ (void)dup2(from_cs[1], STDERR_FILENO);
+
+ /* Close unused file descriptors. */
+ (void)close(to_cs[1]);
+ (void)close(from_cs[0]);
+
+ /* Run the cscope command. */
+#define CSCOPE_CMD_FMT "cd '%s' && exec cscope -dl -f %s"
+ (void)snprintf(cmd, sizeof(cmd),
+ CSCOPE_CMD_FMT, csc->dname, dbname);
+ (void)execl(_PATH_BSHELL, "sh", "-c", cmd, NULL);
+ msgq_str(sp, M_SYSERR, cmd, "execl: %s");
+ _exit (127);
+ /* NOTREACHED */
+ default: /* parent. */
+ /* Close unused file descriptors. */
+ (void)close(to_cs[0]);
+ (void)close(from_cs[1]);
+
+ /*
+ * Save the file descriptors for later duplication, and
+ * reopen as streams.
+ */
+ csc->to_fd = to_cs[1];
+ csc->to_fp = fdopen(to_cs[1], "w");
+ csc->from_fd = from_cs[0];
+ csc->from_fp = fdopen(from_cs[0], "r");
+ break;
+ }
+ return (0);
+}
+
+/*
+ * cscope_find --
+ * The cscope find command.
+ */
+static int
+cscope_find(sp, cmdp, pattern)
+ SCR *sp;
+ EXCMD *cmdp;
+ char *pattern;
+{
+ CSC *csc, *csc_next;
+ EX_PRIVATE *exp;
+ FREF *frp;
+ TAGQ *rtqp, *tqp;
+ TAG *rtp;
+ recno_t lno;
+ size_t cno, search;
+ int force, istmp, matches;
+
+ exp = EXP(sp);
+
+ /* Check for connections. */
+ if (exp->cscq.lh_first == NULL) {
+ msgq(sp, M_ERR, "310|No cscope connections running");
+ return (1);
+ }
+
+ /*
+ * Allocate all necessary memory before doing anything hard. If the
+ * tags stack is empty, we'll need the `local context' TAGQ structure
+ * later.
+ */
+ rtp = NULL;
+ rtqp = NULL;
+ if (exp->tq.cqh_first == (void *)&exp->tq) {
+ /* Initialize the `local context' tag queue structure. */
+ CALLOC_GOTO(sp, rtqp, TAGQ *, 1, sizeof(TAGQ));
+ CIRCLEQ_INIT(&rtqp->tagq);
+
+ /* Initialize and link in its tag structure. */
+ CALLOC_GOTO(sp, rtp, TAG *, 1, sizeof(TAG));
+ CIRCLEQ_INSERT_HEAD(&rtqp->tagq, rtp, q);
+ rtqp->current = rtp;
+ }
+
+ /* Create the cscope command. */
+ if ((tqp = create_cs_cmd(sp, pattern, &search)) == NULL)
+ goto err;
+
+ /*
+ * Stick the current context in a convenient place, we'll lose it
+ * when we switch files.
+ */
+ frp = sp->frp;
+ lno = sp->lno;
+ cno = sp->cno;
+ istmp = F_ISSET(sp->frp, FR_TMPFILE) && !F_ISSET(cmdp, E_NEWSCREEN);
+
+ /* Search all open connections for a match. */
+ matches = 0;
+ for (csc = exp->cscq.lh_first; csc != NULL; csc = csc_next) {
+ /* Copy csc->q.lh_next here in case csc is killed. */
+ csc_next = csc->q.le_next;
+
+ /*
+ * Send the command to the cscope program. (We skip the
+ * first two bytes of the command, because we stored the
+ * search cscope command character and a leading space
+ * there.)
+ */
+ (void)fprintf(csc->to_fp, "%d%s\n", search, tqp->tag + 2);
+ (void)fflush(csc->to_fp);
+
+ /* Read the output. */
+ if (parse(sp, csc, tqp, &matches)) {
+ if (rtqp != NULL)
+ free(rtqp);
+ tagq_free(sp, tqp);
+ return (1);
+ }
+ }
+
+ if (matches == 0) {
+ msgq(sp, M_INFO, "278|No matches for query");
+ return (0);
+ }
+
+ tqp->current = tqp->tagq.cqh_first;
+
+ /* Try to switch to the first tag. */
+ force = FL_ISSET(cmdp->iflags, E_C_FORCE);
+ if (F_ISSET(cmdp, E_NEWSCREEN)) {
+ if (ex_tag_Nswitch(sp, tqp->current, force))
+ goto err;
+
+ /* Everything else gets done in the new screen. */
+ sp = sp->nextdisp;
+ exp = EXP(sp);
+ } else
+ if (ex_tag_nswitch(sp, tqp->current, force))
+ goto err;
+
+ /*
+ * If this is the first tag, put a `current location' queue entry
+ * in place, so we can pop all the way back to the current mark.
+ * Note, it doesn't point to much of anything, it's a placeholder.
+ */
+ if (exp->tq.cqh_first == (void *)&exp->tq) {
+ CIRCLEQ_INSERT_HEAD(&exp->tq, rtqp, q);
+ } else
+ rtqp = exp->tq.cqh_first;
+
+ /* Link the current TAGQ structure into place. */
+ CIRCLEQ_INSERT_HEAD(&exp->tq, tqp, q);
+
+ (void)cscope_search(sp, tqp, tqp->current);
+
+ /*
+ * Move the current context from the temporary save area into the
+ * right structure.
+ *
+ * If we were in a temporary file, we don't have a context to which
+ * we can return, so just make it be the same as what we're moving
+ * to. It will be a little odd that ^T doesn't change anything, but
+ * I don't think it's a big deal.
+ */
+ if (istmp) {
+ rtqp->current->frp = sp->frp;
+ rtqp->current->lno = sp->lno;
+ rtqp->current->cno = sp->cno;
+ } else {
+ rtqp->current->frp = frp;
+ rtqp->current->lno = lno;
+ rtqp->current->cno = cno;
+ }
+
+ return (0);
+
+err:
+alloc_err:
+ if (rtqp != NULL)
+ free(rtqp);
+ if (rtp != NULL)
+ free(rtp);
+ return (1);
+}
+
+/*
+ * create_cs_cmd --
+ * Build a cscope command, creating and initializing the base TAGQ.
+ */
+static TAGQ *
+create_cs_cmd(sp, pattern, searchp)
+ SCR *sp;
+ char *pattern;
+ size_t *searchp;
+{
+ CB *cbp;
+ TAGQ *tqp;
+ size_t tlen;
+ char *p;
+
+ /*
+ * Cscope supports a "change pattern" command which we never use,
+ * cscope command 5. Set CSCOPE_QUERIES[5] to " " since the user
+ * can't pass " " as the first character of pattern. That way the
+ * user can't ask for pattern 5 so we don't need any special-case
+ * code.
+ */
+#define CSCOPE_QUERIES "sgdct efi"
+
+ if (pattern == NULL)
+ goto usage;
+
+ /* Skip leading blanks, check for command character. */
+ for (; isblank(pattern[0]); ++pattern);
+ if (pattern[0] == '\0' || !isblank(pattern[1]))
+ goto usage;
+ for (*searchp = 0, p = CSCOPE_QUERIES;
+ *p != '\0' && *p != pattern[0]; ++*searchp, ++p);
+ if (*p == '\0') {
+ msgq(sp, M_ERR,
+ "311|%s: unknown search type: use one of %s",
+ KEY_NAME(sp, pattern[0]), CSCOPE_QUERIES);
+ return (NULL);
+ }
+
+ /* Skip <blank> characters to the pattern. */
+ for (p = pattern + 1; *p != '\0' && isblank(*p); ++p);
+ if (*p == '\0') {
+usage: (void)csc_help(sp, "find");
+ return (NULL);
+ }
+
+ /* The user can specify the contents of a buffer as the pattern. */
+ cbp = NULL;
+ if (p[0] == '"' && p[1] != '\0' && p[2] == '\0')
+ CBNAME(sp, cbp, p[1]);
+ if (cbp != NULL) {
+ p = cbp->textq.cqh_first->lb;
+ tlen = cbp->textq.cqh_first->len;
+ } else
+ tlen = strlen(p);
+
+ /* Allocate and initialize the TAGQ structure. */
+ CALLOC(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + tlen + 3);
+ if (tqp == NULL)
+ return (NULL);
+ CIRCLEQ_INIT(&tqp->tagq);
+ tqp->tag = tqp->buf;
+ tqp->tag[0] = pattern[0];
+ tqp->tag[1] = ' ';
+ tqp->tlen = tlen + 2;
+ memcpy(tqp->tag + 2, p, tlen);
+ tqp->tag[tlen + 2] = '\0';
+ F_SET(tqp, TAG_CSCOPE);
+
+ return (tqp);
+}
+
+/*
+ * parse --
+ * Parse the cscope output.
+ */
+static int
+parse(sp, csc, tqp, matchesp)
+ SCR *sp;
+ CSC *csc;
+ TAGQ *tqp;
+ int *matchesp;
+{
+ TAG *tp;
+ recno_t slno;
+ size_t dlen, nlen, slen;
+ int ch, i, isolder, nlines;
+ char *dname, *name, *search, *p, *t, dummy[2], buf[2048];
+
+ for (;;) {
+ if (!fgets(buf, sizeof(buf), csc->from_fp))
+ goto io_err;
+
+ /*
+ * If the database is out of date, or there's some other
+ * problem, cscope will output error messages before the
+ * number-of-lines output. Display/discard any output
+ * that doesn't match what we want.
+ */
+#define CSCOPE_NLINES_FMT "cscope: %d lines%1[\n]"
+ if (sscanf(buf, CSCOPE_NLINES_FMT, &nlines, dummy) == 2)
+ break;
+ if ((p = strchr(buf, '\n')) != NULL)
+ *p = '\0';
+ msgq(sp, M_ERR, "%s: \"%s\"", csc->dname, buf);
+ }
+
+ while (nlines--) {
+ if (fgets(buf, sizeof(buf), csc->from_fp) == NULL)
+ goto io_err;
+
+ /* If the line's too long for the buffer, discard it. */
+ if ((p = strchr(buf, '\n')) == NULL) {
+ while ((ch = getc(csc->from_fp)) != EOF && ch != '\n');
+ continue;
+ }
+ *p = '\0';
+
+ /*
+ * The cscope output is in the following format:
+ *
+ * <filename> <context> <line number> <pattern>
+ *
+ * Figure out how long everything is so we can allocate in one
+ * swell foop, but discard anything that looks wrong.
+ */
+ for (p = buf, i = 0;
+ i < 3 && (t = strsep(&p, "\t ")) != NULL; ++i)
+ switch (i) {
+ case 0: /* Filename. */
+ name = t;
+ nlen = strlen(name);
+ break;
+ case 1: /* Context. */
+ break;
+ case 2: /* Line number. */
+ slno = (recno_t)atol(t);
+ break;
+ }
+ if (i != 3 || p == NULL || t == NULL)
+ continue;
+
+ /* The rest of the string is the search pattern. */
+ search = p;
+ slen = strlen(p);
+
+ /* Resolve the file name. */
+ csc_file(sp, csc, name, &dname, &dlen, &isolder);
+
+ /*
+ * If the file is older than the cscope database, that is,
+ * the database was built since the file was last modified,
+ * or there wasn't a search string, use the line number.
+ */
+ if (isolder || strcmp(search, "<unknown>") == 0) {
+ search = NULL;
+ slen = 0;
+ }
+
+ /*
+ * Allocate and initialize a tag structure plus the variable
+ * length cscope information that follows it.
+ */
+ CALLOC_RET(sp, tp,
+ TAG *, 1, sizeof(TAG) + dlen + 2 + nlen + 1 + slen + 1);
+ tp->fname = tp->buf;
+ if (dlen != 0) {
+ memcpy(tp->fname, dname, dlen);
+ tp->fname[dlen] = '/';
+ ++dlen;
+ }
+ memcpy(tp->fname + dlen, name, nlen + 1);
+ tp->fnlen = dlen + nlen;
+ tp->slno = slno;
+ if (slen != 0) {
+ tp->search = tp->fname + tp->fnlen + 1;
+ memcpy(tp->search, search, (tp->slen = slen) + 1);
+ }
+ CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
+
+ ++*matchesp;
+ }
+
+ (void)read_prompt(sp, csc);
+ return (0);
+
+io_err: if (feof(csc->from_fp))
+ errno = EIO;
+ msgq_str(sp, M_SYSERR, "%s", csc->dname);
+ terminate(sp, csc, 0);
+ return (1);
+}
+
+/*
+ * csc_file --
+ * Search for the right path to this file.
+ */
+static void
+csc_file(sp, csc, name, dirp, dlenp, isolderp)
+ SCR *sp;
+ CSC *csc;
+ char *name, **dirp;
+ size_t *dlenp;
+ int *isolderp;
+{
+ struct stat sb;
+ char **pp, buf[MAXPATHLEN];
+
+ /*
+ * Check for the file in all of the listed paths. If we don't
+ * find it, we simply return it unchanged. We have to do this
+ * now, even though it's expensive, because if the user changes
+ * directories, we can't change our minds as to where the file
+ * lives.
+ */
+ for (pp = csc->paths; *pp != NULL; ++pp) {
+ (void)snprintf(buf, sizeof(buf), "%s/%s", *pp, name);
+ if (stat(buf, &sb) == 0) {
+ *dirp = *pp;
+ *dlenp = strlen(*pp);
+ *isolderp = sb.st_mtime < csc->mtime;
+ return;
+ }
+ }
+ *dlenp = 0;
+}
+
+/*
+ * cscope_help --
+ * The cscope help command.
+ */
+static int
+cscope_help(sp, cmdp, subcmd)
+ SCR *sp;
+ EXCMD *cmdp;
+ char *subcmd;
+{
+ return (csc_help(sp, subcmd));
+}
+
+/*
+ * csc_help --
+ * Display help/usage messages.
+ */
+static int
+csc_help(sp, cmd)
+ SCR *sp;
+ char *cmd;
+{
+ CC const *ccp;
+
+ if (cmd != NULL && *cmd != '\0')
+ if ((ccp = lookup_ccmd(cmd)) == NULL) {
+ ex_printf(sp,
+ "%s doesn't match any cscope command\n", cmd);
+ return (1);
+ } else {
+ ex_printf(sp,
+ "Command: %s (%s)\n", ccp->name, ccp->help_msg);
+ ex_printf(sp, " Usage: %s\n", ccp->usage_msg);
+ return (0);
+ }
+
+ ex_printf(sp, "cscope commands:\n");
+ for (ccp = cscope_cmds; ccp->name != NULL; ++ccp)
+ ex_printf(sp, " %*s: %s\n", 5, ccp->name, ccp->help_msg);
+ return (0);
+}
+
+/*
+ * cscope_kill --
+ * The cscope kill command.
+ */
+static int
+cscope_kill(sp, cmdp, cn)
+ SCR *sp;
+ EXCMD *cmdp;
+ char *cn;
+{
+ return (terminate(sp, NULL, atoi(cn)));
+}
+
+/*
+ * terminate --
+ * Detach from a cscope process.
+ */
+static int
+terminate(sp, csc, n)
+ SCR *sp;
+ CSC *csc;
+ int n;
+{
+ EX_PRIVATE *exp;
+ int i, pstat;
+
+ exp = EXP(sp);
+
+ /*
+ * We either get a csc structure or a number. If not provided a
+ * csc structure, find the right one.
+ */
+ if (csc == NULL) {
+ if (n < 1)
+ goto badno;
+ for (i = 1, csc = exp->cscq.lh_first;
+ csc != NULL; csc = csc->q.le_next, i++)
+ if (i == n)
+ break;
+ if (csc == NULL) {
+badno: msgq(sp, M_ERR, "312|%d: no such cscope session", n);
+ return (1);
+ }
+ }
+
+ /*
+ * XXX
+ * Theoretically, we have the only file descriptors to the process,
+ * so closing them should let it exit gracefully, deleting temporary
+ * files, etc. The original vi cscope integration sent the cscope
+ * connection a SIGTERM signal, so I'm not sure if closing the file
+ * descriptors is sufficient.
+ */
+ if (csc->from_fp != NULL)
+ (void)fclose(csc->from_fp);
+ if (csc->to_fp != NULL)
+ (void)fclose(csc->to_fp);
+ (void)waitpid(csc->pid, &pstat, 0);
+
+ /* Discard cscope connection information. */
+ LIST_REMOVE(csc, q);
+ if (csc->pbuf != NULL)
+ free(csc->pbuf);
+ if (csc->paths != NULL)
+ free(csc->paths);
+ free(csc);
+ return (0);
+}
+
+/*
+ * cscope_reset --
+ * The cscope reset command.
+ */
+static int
+cscope_reset(sp, cmdp, notusedp)
+ SCR *sp;
+ EXCMD *cmdp;
+ char *notusedp;
+{
+ EX_PRIVATE *exp;
+
+ for (exp = EXP(sp); exp->cscq.lh_first != NULL;)
+ if (cscope_kill(sp, cmdp, "1"))
+ return (1);
+ return (0);
+}
+
+/*
+ * cscope_display --
+ * Display current connections.
+ *
+ * PUBLIC: int cscope_display __P((SCR *));
+ */
+int
+cscope_display(sp)
+ SCR *sp;
+{
+ EX_PRIVATE *exp;
+ CSC *csc;
+ int i;
+
+ exp = EXP(sp);
+ if (exp->cscq.lh_first == NULL) {
+ ex_printf(sp, "No cscope connections.\n");
+ return (0);
+ }
+ for (i = 1,
+ csc = exp->cscq.lh_first; csc != NULL; ++i, csc = csc->q.le_next)
+ ex_printf(sp,
+ "%2d %s (process %lu)\n", i, csc->dname, (u_long)csc->pid);
+ return (0);
+}
+
+/*
+ * cscope_search --
+ * Search a file for a cscope entry.
+ *
+ * PUBLIC: int cscope_search __P((SCR *, TAGQ *, TAG *));
+ */
+int
+cscope_search(sp, tqp, tp)
+ SCR *sp;
+ TAGQ *tqp;
+ TAG *tp;
+{
+ MARK m;
+
+ /* If we don't have a search pattern, use the line number. */
+ if (tp->search == NULL) {
+ if (!db_exist(sp, tp->slno)) {
+ tag_msg(sp, TAG_BADLNO, tqp->tag);
+ return (1);
+ }
+ m.lno = tp->slno;
+ } else {
+ /*
+ * Search for the tag; cheap fallback for C functions
+ * if the name is the same but the arguments have changed.
+ */
+ m.lno = 1;
+ m.cno = 0;
+ if (f_search(sp, &m, &m,
+ tp->search, tp->slen, NULL, SEARCH_CSCOPE | SEARCH_FILE)) {
+ tag_msg(sp, TAG_SEARCH, tqp->tag);
+ return (1);
+ }
+
+ /*
+ * !!!
+ * Historically, tags set the search direction if it wasn't
+ * already set.
+ */
+ if (sp->searchdir == NOTSET)
+ sp->searchdir = FORWARD;
+ }
+
+ /*
+ * !!!
+ * Tags move to the first non-blank, NOT the search pattern start.
+ */
+ sp->lno = m.lno;
+ sp->cno = 0;
+ (void)nonblank(sp, sp->lno, &sp->cno);
+ return (0);
+}
+
+
+/*
+ * lookup_ccmd --
+ * Return a pointer to the command structure.
+ */
+static CC const *
+lookup_ccmd(name)
+ char *name;
+{
+ CC const *ccp;
+ size_t len;
+
+ len = strlen(name);
+ for (ccp = cscope_cmds; ccp->name != NULL; ++ccp)
+ if (strncmp(name, ccp->name, len) == 0)
+ return (ccp);
+ return (NULL);
+}
+
+/*
+ * read_prompt --
+ * Read a prompt from cscope.
+ */
+static int
+read_prompt(sp, csc)
+ SCR *sp;
+ CSC *csc;
+{
+ int ch;
+
+#define CSCOPE_PROMPT ">> "
+ for (;;) {
+ while ((ch =
+ getc(csc->from_fp)) != EOF && ch != CSCOPE_PROMPT[0]);
+ if (ch == EOF) {
+ terminate(sp, csc, 0);
+ return (1);
+ }
+ if (getc(csc->from_fp) != CSCOPE_PROMPT[1])
+ continue;
+ if (getc(csc->from_fp) != CSCOPE_PROMPT[2])
+ continue;
+ break;
+ }
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_delete.c b/contrib/nvi/ex/ex_delete.c
new file mode 100644
index 000000000000..58734bbcfce4
--- /dev/null
+++ b/contrib/nvi/ex/ex_delete.c
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_delete.c 10.9 (Berkeley) 10/23/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_delete: [line [,line]] d[elete] [buffer] [count] [flags]
+ *
+ * Delete lines from the file.
+ *
+ * PUBLIC: int ex_delete __P((SCR *, EXCMD *));
+ */
+int
+ex_delete(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ recno_t lno;
+
+ NEEDFILE(sp, cmdp);
+
+ /*
+ * !!!
+ * Historically, lines deleted in ex were not placed in the numeric
+ * buffers. We follow historic practice so that we don't overwrite
+ * vi buffers accidentally.
+ */
+ if (cut(sp,
+ FL_ISSET(cmdp->iflags, E_C_BUFFER) ? &cmdp->buffer : NULL,
+ &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE))
+ return (1);
+
+ /* Delete the lines. */
+ if (del(sp, &cmdp->addr1, &cmdp->addr2, 1))
+ return (1);
+
+ /* Set the cursor to the line after the last line deleted. */
+ sp->lno = cmdp->addr1.lno;
+
+ /* Or the last line in the file if deleted to the end of the file. */
+ if (db_last(sp, &lno))
+ return (1);
+ if (sp->lno > lno)
+ sp->lno = lno;
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_display.c b/contrib/nvi/ex/ex_display.c
new file mode 100644
index 000000000000..75315170f95e
--- /dev/null
+++ b/contrib/nvi/ex/ex_display.c
@@ -0,0 +1,145 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_display.c 10.12 (Berkeley) 4/10/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "tag.h"
+
+static int bdisplay __P((SCR *));
+static void db __P((SCR *, CB *, CHAR_T *));
+
+/*
+ * ex_display -- :display b[uffers] | c[onnections] | s[creens] | t[ags]
+ *
+ * Display cscope connections, buffers, tags or screens.
+ *
+ * PUBLIC: int ex_display __P((SCR *, EXCMD *));
+ */
+int
+ex_display(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ switch (cmdp->argv[0]->bp[0]) {
+ case 'b':
+#undef ARG
+#define ARG "buffers"
+ if (cmdp->argv[0]->len >= sizeof(ARG) ||
+ memcmp(cmdp->argv[0]->bp, ARG, cmdp->argv[0]->len))
+ break;
+ return (bdisplay(sp));
+ case 'c':
+#undef ARG
+#define ARG "connections"
+ if (cmdp->argv[0]->len >= sizeof(ARG) ||
+ memcmp(cmdp->argv[0]->bp, ARG, cmdp->argv[0]->len))
+ break;
+ return (cscope_display(sp));
+ case 's':
+#undef ARG
+#define ARG "screens"
+ if (cmdp->argv[0]->len >= sizeof(ARG) ||
+ memcmp(cmdp->argv[0]->bp, ARG, cmdp->argv[0]->len))
+ break;
+ return (ex_sdisplay(sp));
+ case 't':
+#undef ARG
+#define ARG "tags"
+ if (cmdp->argv[0]->len >= sizeof(ARG) ||
+ memcmp(cmdp->argv[0]->bp, ARG, cmdp->argv[0]->len))
+ break;
+ return (ex_tag_display(sp));
+ }
+ ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+ return (1);
+}
+
+/*
+ * bdisplay --
+ *
+ * Display buffers.
+ */
+static int
+bdisplay(sp)
+ SCR *sp;
+{
+ CB *cbp;
+
+ if (sp->gp->cutq.lh_first == NULL && sp->gp->dcbp == NULL) {
+ msgq(sp, M_INFO, "123|No cut buffers to display");
+ return (0);
+ }
+
+ /* Display regular cut buffers. */
+ for (cbp = sp->gp->cutq.lh_first; cbp != NULL; cbp = cbp->q.le_next) {
+ if (isdigit(cbp->name))
+ continue;
+ if (cbp->textq.cqh_first != (void *)&cbp->textq)
+ db(sp, cbp, NULL);
+ if (INTERRUPTED(sp))
+ return (0);
+ }
+ /* Display numbered buffers. */
+ for (cbp = sp->gp->cutq.lh_first; cbp != NULL; cbp = cbp->q.le_next) {
+ if (!isdigit(cbp->name))
+ continue;
+ if (cbp->textq.cqh_first != (void *)&cbp->textq)
+ db(sp, cbp, NULL);
+ if (INTERRUPTED(sp))
+ return (0);
+ }
+ /* Display default buffer. */
+ if ((cbp = sp->gp->dcbp) != NULL)
+ db(sp, cbp, "default buffer");
+ return (0);
+}
+
+/*
+ * db --
+ * Display a buffer.
+ */
+static void
+db(sp, cbp, name)
+ SCR *sp;
+ CB *cbp;
+ CHAR_T *name;
+{
+ CHAR_T *p;
+ GS *gp;
+ TEXT *tp;
+ size_t len;
+
+ gp = sp->gp;
+ (void)ex_printf(sp, "********** %s%s\n",
+ name == NULL ? KEY_NAME(sp, cbp->name) : name,
+ F_ISSET(cbp, CB_LMODE) ? " (line mode)" : " (character mode)");
+ for (tp = cbp->textq.cqh_first;
+ tp != (void *)&cbp->textq; tp = tp->q.cqe_next) {
+ for (len = tp->len, p = tp->lb; len--; ++p) {
+ (void)ex_puts(sp, KEY_NAME(sp, *p));
+ if (INTERRUPTED(sp))
+ return;
+ }
+ (void)ex_puts(sp, "\n");
+ }
+}
diff --git a/contrib/nvi/ex/ex_edit.c b/contrib/nvi/ex/ex_edit.c
new file mode 100644
index 000000000000..8b18e0f0bbca
--- /dev/null
+++ b/contrib/nvi/ex/ex_edit.c
@@ -0,0 +1,153 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_edit.c 10.10 (Berkeley) 4/27/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+static int ex_N_edit __P((SCR *, EXCMD *, FREF *, int));
+
+/*
+ * ex_edit -- :e[dit][!] [+cmd] [file]
+ * :ex[!] [+cmd] [file]
+ * :vi[sual][!] [+cmd] [file]
+ *
+ * Edit a file; if none specified, re-edit the current file. The third
+ * form of the command can only be executed while in vi mode. See the
+ * hack in ex.c:ex_cmd().
+ *
+ * !!!
+ * Historic vi didn't permit the '+' command form without specifying
+ * a file name as well. This seems unreasonable, so we support it
+ * regardless.
+ *
+ * PUBLIC: int ex_edit __P((SCR *, EXCMD *));
+ */
+int
+ex_edit(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ FREF *frp;
+ int attach, setalt;
+
+ switch (cmdp->argc) {
+ case 0:
+ /*
+ * If the name has been changed, we edit that file, not the
+ * original name. If the user was editing a temporary file
+ * (or wasn't editing any file), create another one. The
+ * reason for not reusing temporary files is that there is
+ * special exit processing of them, and reuse is tricky.
+ */
+ frp = sp->frp;
+ if (sp->ep == NULL || F_ISSET(frp, FR_TMPFILE)) {
+ if ((frp = file_add(sp, NULL)) == NULL)
+ return (1);
+ attach = 0;
+ } else
+ attach = 1;
+ setalt = 0;
+ break;
+ case 1:
+ if ((frp = file_add(sp, cmdp->argv[0]->bp)) == NULL)
+ return (1);
+ attach = 0;
+ setalt = 1;
+ set_alt_name(sp, cmdp->argv[0]->bp);
+ break;
+ default:
+ abort();
+ }
+
+ if (F_ISSET(cmdp, E_NEWSCREEN))
+ return (ex_N_edit(sp, cmdp, frp, attach));
+
+ /*
+ * Check for modifications.
+ *
+ * !!!
+ * Contrary to POSIX 1003.2-1992, autowrite did not affect :edit.
+ */
+ if (file_m2(sp, FL_ISSET(cmdp->iflags, E_C_FORCE)))
+ return (1);
+
+ /* Switch files. */
+ if (file_init(sp, frp, NULL, (setalt ? FS_SETALT : 0) |
+ (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
+ return (1);
+
+ F_SET(sp, SC_FSWITCH);
+ return (0);
+}
+
+/*
+ * ex_N_edit --
+ * New screen version of ex_edit.
+ */
+static int
+ex_N_edit(sp, cmdp, frp, attach)
+ SCR *sp;
+ EXCMD *cmdp;
+ FREF *frp;
+ int attach;
+{
+ SCR *new;
+
+ /* Get a new screen. */
+ if (screen_init(sp->gp, sp, &new))
+ return (1);
+ if (vs_split(sp, new, 0)) {
+ (void)screen_end(new);
+ return (1);
+ }
+
+ /* Get a backing file. */
+ if (attach) {
+ /* Copy file state, keep the screen and cursor the same. */
+ new->ep = sp->ep;
+ ++new->ep->refcnt;
+
+ new->frp = frp;
+ new->frp->flags = sp->frp->flags;
+
+ new->lno = sp->lno;
+ new->cno = sp->cno;
+ } else if (file_init(new, frp, NULL,
+ (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0))) {
+ (void)vs_discard(new, NULL);
+ (void)screen_end(new);
+ return (1);
+ }
+
+ /* Create the argument list. */
+ new->cargv = new->argv = ex_buildargv(sp, NULL, frp->name);
+
+ /* Set up the switch. */
+ sp->nextdisp = new;
+ F_SET(sp, SC_SSWITCH);
+
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_equal.c b/contrib/nvi/ex/ex_equal.c
new file mode 100644
index 000000000000..565df66bd0a9
--- /dev/null
+++ b/contrib/nvi/ex/ex_equal.c
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_equal.c 10.10 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_equal -- :address =
+ *
+ * PUBLIC: int ex_equal __P((SCR *, EXCMD *));
+ */
+int
+ex_equal(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ recno_t lno;
+
+ NEEDFILE(sp, cmdp);
+
+ /*
+ * Print out the line number matching the specified address,
+ * or the number of the last line in the file if no address
+ * specified.
+ *
+ * !!!
+ * Historically, ":0=" displayed 0, and ":=" or ":1=" in an
+ * empty file displayed 1. Until somebody complains loudly,
+ * we're going to do it right. The tables in excmd.c permit
+ * lno to get away with any address from 0 to the end of the
+ * file, which, in an empty file, is 0.
+ */
+ if (F_ISSET(cmdp, E_ADDR_DEF)) {
+ if (db_last(sp, &lno))
+ return (1);
+ } else
+ lno = cmdp->addr1.lno;
+
+ (void)ex_printf(sp, "%ld\n", lno);
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_file.c b/contrib/nvi/ex/ex_file.c
new file mode 100644
index 000000000000..3492f9c7bf0d
--- /dev/null
+++ b/contrib/nvi/ex/ex_file.c
@@ -0,0 +1,80 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_file.c 10.12 (Berkeley) 7/12/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_file -- :f[ile] [name]
+ * Change the file's name and display the status line.
+ *
+ * PUBLIC: int ex_file __P((SCR *, EXCMD *));
+ */
+int
+ex_file(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ CHAR_T *p;
+ FREF *frp;
+
+ NEEDFILE(sp, cmdp);
+
+ switch (cmdp->argc) {
+ case 0:
+ break;
+ case 1:
+ frp = sp->frp;
+
+ /* Make sure can allocate enough space. */
+ if ((p = v_strdup(sp,
+ cmdp->argv[0]->bp, cmdp->argv[0]->len)) == NULL)
+ return (1);
+
+ /* If already have a file name, it becomes the alternate. */
+ if (!F_ISSET(frp, FR_TMPFILE))
+ set_alt_name(sp, frp->name);
+
+ /* Free the previous name. */
+ free(frp->name);
+ frp->name = p;
+
+ /*
+ * The file has a real name, it's no longer a temporary,
+ * clear the temporary file flags.
+ */
+ F_CLR(frp, FR_TMPEXIT | FR_TMPFILE);
+
+ /* Have to force a write if the file exists, next time. */
+ F_SET(frp, FR_NAMECHANGE);
+
+ /* Notify the screen. */
+ (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+ break;
+ default:
+ abort();
+ }
+ msgq_status(sp, sp->lno, MSTAT_SHOWLAST);
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_filter.c b/contrib/nvi/ex/ex_filter.c
new file mode 100644
index 000000000000..2e86e58b3ba2
--- /dev/null
+++ b/contrib/nvi/ex/ex_filter.c
@@ -0,0 +1,316 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_filter.c 10.34 (Berkeley) 10/23/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+static int filter_ldisplay __P((SCR *, FILE *));
+
+/*
+ * ex_filter --
+ * Run a range of lines through a filter utility and optionally
+ * replace the original text with the stdout/stderr output of
+ * the utility.
+ *
+ * PUBLIC: int ex_filter __P((SCR *,
+ * PUBLIC: EXCMD *, MARK *, MARK *, MARK *, char *, enum filtertype));
+ */
+int
+ex_filter(sp, cmdp, fm, tm, rp, cmd, ftype)
+ SCR *sp;
+ EXCMD *cmdp;
+ MARK *fm, *tm, *rp;
+ char *cmd;
+ enum filtertype ftype;
+{
+ FILE *ifp, *ofp;
+ pid_t parent_writer_pid, utility_pid;
+ recno_t nread;
+ int input[2], output[2], rval;
+ char *name;
+
+ rval = 0;
+
+ /* Set return cursor position, which is never less than line 1. */
+ *rp = *fm;
+ if (rp->lno == 0)
+ rp->lno = 1;
+
+ /* We're going to need a shell. */
+ if (opts_empty(sp, O_SHELL, 0))
+ return (1);
+
+ /*
+ * There are three different processes running through this code.
+ * They are the utility, the parent-writer and the parent-reader.
+ * The parent-writer is the process that writes from the file to
+ * the utility, the parent reader is the process that reads from
+ * the utility.
+ *
+ * Input and output are named from the utility's point of view.
+ * The utility reads from input[0] and the parent(s) write to
+ * input[1]. The parent(s) read from output[0] and the utility
+ * writes to output[1].
+ *
+ * !!!
+ * Historically, in the FILTER_READ case, the utility reads from
+ * the terminal (e.g. :r! cat works). Otherwise open up utility
+ * input pipe.
+ */
+ ofp = NULL;
+ input[0] = input[1] = output[0] = output[1] = -1;
+ if (ftype != FILTER_READ && pipe(input) < 0) {
+ msgq(sp, M_SYSERR, "pipe");
+ goto err;
+ }
+
+ /* Open up utility output pipe. */
+ if (pipe(output) < 0) {
+ msgq(sp, M_SYSERR, "pipe");
+ goto err;
+ }
+ if ((ofp = fdopen(output[0], "r")) == NULL) {
+ msgq(sp, M_SYSERR, "fdopen");
+ goto err;
+ }
+
+ /* Fork off the utility process. */
+ switch (utility_pid = vfork()) {
+ case -1: /* Error. */
+ msgq(sp, M_SYSERR, "vfork");
+err: if (input[0] != -1)
+ (void)close(input[0]);
+ if (input[1] != -1)
+ (void)close(input[1]);
+ if (ofp != NULL)
+ (void)fclose(ofp);
+ else if (output[0] != -1)
+ (void)close(output[0]);
+ if (output[1] != -1)
+ (void)close(output[1]);
+ return (1);
+ case 0: /* Utility. */
+ /*
+ * Redirect stdin from the read end of the input pipe, and
+ * redirect stdout/stderr to the write end of the output pipe.
+ *
+ * !!!
+ * Historically, ex only directed stdout into the input pipe,
+ * letting stderr come out on the terminal as usual. Vi did
+ * not, directing both stdout and stderr into the input pipe.
+ * We match that practice in both ex and vi for consistency.
+ */
+ if (input[0] != -1)
+ (void)dup2(input[0], STDIN_FILENO);
+ (void)dup2(output[1], STDOUT_FILENO);
+ (void)dup2(output[1], STDERR_FILENO);
+
+ /* Close the utility's file descriptors. */
+ if (input[0] != -1)
+ (void)close(input[0]);
+ if (input[1] != -1)
+ (void)close(input[1]);
+ (void)close(output[0]);
+ (void)close(output[1]);
+
+ if ((name = strrchr(O_STR(sp, O_SHELL), '/')) == NULL)
+ name = O_STR(sp, O_SHELL);
+ else
+ ++name;
+
+ execl(O_STR(sp, O_SHELL), name, "-c", cmd, NULL);
+ msgq_str(sp, M_SYSERR, O_STR(sp, O_SHELL), "execl: %s");
+ _exit (127);
+ /* NOTREACHED */
+ default: /* Parent-reader, parent-writer. */
+ /* Close the pipe ends neither parent will use. */
+ if (input[0] != -1)
+ (void)close(input[0]);
+ (void)close(output[1]);
+ break;
+ }
+
+ /*
+ * FILTER_RBANG, FILTER_READ:
+ *
+ * Reading is the simple case -- we don't need a parent writer,
+ * so the parent reads the output from the read end of the output
+ * pipe until it finishes, then waits for the child. Ex_readfp
+ * appends to the MARK, and closes ofp.
+ *
+ * For FILTER_RBANG, there is nothing to write to the utility.
+ * Make sure it doesn't wait forever by closing its standard
+ * input.
+ *
+ * !!!
+ * Set the return cursor to the last line read in for FILTER_READ.
+ * Historically, this behaves differently from ":r file" command,
+ * which leaves the cursor at the first line read in. Check to
+ * make sure that it's not past EOF because we were reading into an
+ * empty file.
+ */
+ if (ftype == FILTER_RBANG || ftype == FILTER_READ) {
+ if (ftype == FILTER_RBANG)
+ (void)close(input[1]);
+
+ if (ex_readfp(sp, "filter", ofp, fm, &nread, 1))
+ rval = 1;
+ sp->rptlines[L_ADDED] += nread;
+ if (ftype == FILTER_READ)
+ if (fm->lno == 0)
+ rp->lno = nread;
+ else
+ rp->lno += nread;
+ goto uwait;
+ }
+
+ /*
+ * FILTER_BANG, FILTER_WRITE
+ *
+ * Here we need both a reader and a writer. Temporary files are
+ * expensive and we'd like to avoid disk I/O. Using pipes has the
+ * obvious starvation conditions. It's done as follows:
+ *
+ * fork
+ * child
+ * write lines out
+ * exit
+ * parent
+ * FILTER_BANG:
+ * read lines into the file
+ * delete old lines
+ * FILTER_WRITE
+ * read and display lines
+ * wait for child
+ *
+ * XXX
+ * We get away without locking the underlying database because we know
+ * that none of the records that we're reading will be modified until
+ * after we've read them. This depends on the fact that the current
+ * B+tree implementation doesn't balance pages or similar things when
+ * it inserts new records. When the DB code has locking, we should
+ * treat vi as if it were multiple applications sharing a database, and
+ * do the required locking. If necessary a work-around would be to do
+ * explicit locking in the line.c:db_get() code, based on the flag set
+ * here.
+ */
+ F_SET(sp->ep, F_MULTILOCK);
+ switch (parent_writer_pid = fork()) {
+ case -1: /* Error. */
+ msgq(sp, M_SYSERR, "fork");
+ (void)close(input[1]);
+ (void)close(output[0]);
+ rval = 1;
+ break;
+ case 0: /* Parent-writer. */
+ /*
+ * Write the selected lines to the write end of the input
+ * pipe. This instance of ifp is closed by ex_writefp.
+ */
+ (void)close(output[0]);
+ if ((ifp = fdopen(input[1], "w")) == NULL)
+ _exit (1);
+ _exit(ex_writefp(sp, "filter", ifp, fm, tm, NULL, NULL, 1));
+
+ /* NOTREACHED */
+ default: /* Parent-reader. */
+ (void)close(input[1]);
+ if (ftype == FILTER_WRITE) {
+ /*
+ * Read the output from the read end of the output
+ * pipe and display it. Filter_ldisplay closes ofp.
+ */
+ if (filter_ldisplay(sp, ofp))
+ rval = 1;
+ } else {
+ /*
+ * Read the output from the read end of the output
+ * pipe. Ex_readfp appends to the MARK and closes
+ * ofp.
+ */
+ if (ex_readfp(sp, "filter", ofp, tm, &nread, 1))
+ rval = 1;
+ sp->rptlines[L_ADDED] += nread;
+ }
+
+ /* Wait for the parent-writer. */
+ if (proc_wait(sp,
+ (long)parent_writer_pid, "parent-writer", 0, 1))
+ rval = 1;
+
+ /* Delete any lines written to the utility. */
+ if (rval == 0 && ftype == FILTER_BANG &&
+ (cut(sp, NULL, fm, tm, CUT_LINEMODE) ||
+ del(sp, fm, tm, 1))) {
+ rval = 1;
+ break;
+ }
+
+ /*
+ * If the filter had no output, we may have just deleted
+ * the cursor. Don't do any real error correction, we'll
+ * try and recover later.
+ */
+ if (rp->lno > 1 && !db_exist(sp, rp->lno))
+ --rp->lno;
+ break;
+ }
+ F_CLR(sp->ep, F_MULTILOCK);
+
+ /*
+ * !!!
+ * Ignore errors on vi file reads, to make reads prettier. It's
+ * completely inconsistent, and historic practice.
+ */
+uwait: return (proc_wait(sp, (long)utility_pid, cmd,
+ ftype == FILTER_READ && F_ISSET(sp, SC_VI) ? 1 : 0, 0) || rval);
+}
+
+/*
+ * filter_ldisplay --
+ * Display output from a utility.
+ *
+ * !!!
+ * Historically, the characters were passed unmodified to the terminal.
+ * We use the ex print routines to make sure they're printable.
+ */
+static int
+filter_ldisplay(sp, fp)
+ SCR *sp;
+ FILE *fp;
+{
+ size_t len;
+
+ EX_PRIVATE *exp;
+
+ for (exp = EXP(sp); !ex_getline(sp, fp, &len) && !INTERRUPTED(sp);)
+ if (ex_ldisplay(sp, exp->ibp, len, 0, 0))
+ break;
+ if (ferror(fp))
+ msgq(sp, M_SYSERR, "filter read");
+ (void)fclose(fp);
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_global.c b/contrib/nvi/ex/ex_global.c
new file mode 100644
index 000000000000..aba9dc5fabe3
--- /dev/null
+++ b/contrib/nvi/ex/ex_global.c
@@ -0,0 +1,328 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_global.c 10.22 (Berkeley) 10/10/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+enum which {GLOBAL, V};
+
+static int ex_g_setup __P((SCR *, EXCMD *, enum which));
+
+/*
+ * ex_global -- [line [,line]] g[lobal][!] /pattern/ [commands]
+ * Exec on lines matching a pattern.
+ *
+ * PUBLIC: int ex_global __P((SCR *, EXCMD *));
+ */
+int
+ex_global(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ return (ex_g_setup(sp,
+ cmdp, FL_ISSET(cmdp->iflags, E_C_FORCE) ? V : GLOBAL));
+}
+
+/*
+ * ex_v -- [line [,line]] v /pattern/ [commands]
+ * Exec on lines not matching a pattern.
+ *
+ * PUBLIC: int ex_v __P((SCR *, EXCMD *));
+ */
+int
+ex_v(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ return (ex_g_setup(sp, cmdp, V));
+}
+
+/*
+ * ex_g_setup --
+ * Ex global and v commands.
+ */
+static int
+ex_g_setup(sp, cmdp, cmd)
+ SCR *sp;
+ EXCMD *cmdp;
+ enum which cmd;
+{
+ CHAR_T *ptrn, *p, *t;
+ EXCMD *ecp;
+ MARK abs;
+ RANGE *rp;
+ busy_t btype;
+ recno_t start, end;
+ regex_t *re;
+ regmatch_t match[1];
+ size_t len;
+ int cnt, delim, eval;
+ char *dbp;
+
+ NEEDFILE(sp, cmdp);
+
+ if (F_ISSET(sp, SC_EX_GLOBAL)) {
+ msgq(sp, M_ERR,
+ "124|The %s command can't be used as part of a global or v command",
+ cmdp->cmd->name);
+ return (1);
+ }
+
+ /*
+ * Skip leading white space. Historic vi allowed any non-alphanumeric
+ * to serve as the global command delimiter.
+ */
+ if (cmdp->argc == 0)
+ goto usage;
+ for (p = cmdp->argv[0]->bp; isblank(*p); ++p);
+ if (*p == '\0' || isalnum(*p) ||
+ *p == '\\' || *p == '|' || *p == '\n') {
+usage: ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+ return (1);
+ }
+ delim = *p++;
+
+ /*
+ * Get the pattern string, toss escaped characters.
+ *
+ * QUOTING NOTE:
+ * Only toss an escaped character if it escapes a delimiter.
+ */
+ for (ptrn = t = p;;) {
+ if (p[0] == '\0' || p[0] == delim) {
+ if (p[0] == delim)
+ ++p;
+ /*
+ * !!!
+ * Nul terminate the pattern string -- it's passed
+ * to regcomp which doesn't understand anything else.
+ */
+ *t = '\0';
+ break;
+ }
+ if (p[0] == '\\')
+ if (p[1] == delim)
+ ++p;
+ else if (p[1] == '\\')
+ *t++ = *p++;
+ *t++ = *p++;
+ }
+
+ /* If the pattern string is empty, use the last one. */
+ if (*ptrn == '\0') {
+ if (sp->re == NULL) {
+ ex_emsg(sp, NULL, EXM_NOPREVRE);
+ return (1);
+ }
+
+ /* Re-compile the RE if necessary. */
+ if (!F_ISSET(sp, SC_RE_SEARCH) && re_compile(sp,
+ sp->re, sp->re_len, NULL, NULL, &sp->re_c, RE_C_SEARCH))
+ return (1);
+ } else {
+ /* Compile the RE. */
+ if (re_compile(sp, ptrn, t - ptrn,
+ &sp->re, &sp->re_len, &sp->re_c, RE_C_SEARCH))
+ return (1);
+
+ /*
+ * Set saved RE. Historic practice is that globals set
+ * direction as well as the RE.
+ */
+ sp->searchdir = FORWARD;
+ }
+ re = &sp->re_c;
+
+ /* The global commands always set the previous context mark. */
+ abs.lno = sp->lno;
+ abs.cno = sp->cno;
+ if (mark_set(sp, ABSMARK1, &abs, 1))
+ return (1);
+
+ /* Get an EXCMD structure. */
+ CALLOC_RET(sp, ecp, EXCMD *, 1, sizeof(EXCMD));
+ CIRCLEQ_INIT(&ecp->rq);
+
+ /*
+ * Get a copy of the command string; the default command is print.
+ * Don't worry about a set of <blank>s with no command, that will
+ * default to print in the ex parser. We need to have two copies
+ * because the ex parser may step on the command string when it's
+ * parsing it.
+ */
+ if ((len = cmdp->argv[0]->len - (p - cmdp->argv[0]->bp)) == 0) {
+ p = "pp";
+ len = 1;
+ }
+
+ MALLOC_RET(sp, ecp->cp, char *, len * 2);
+ ecp->o_cp = ecp->cp;
+ ecp->o_clen = len;
+ memcpy(ecp->cp + len, p, len);
+ ecp->range_lno = OOBLNO;
+ FL_SET(ecp->agv_flags, cmd == GLOBAL ? AGV_GLOBAL : AGV_V);
+ LIST_INSERT_HEAD(&sp->gp->ecq, ecp, q);
+
+ /*
+ * For each line... The semantics of global matching are that we first
+ * have to decide which lines are going to get passed to the command,
+ * and then pass them to the command, ignoring other changes. There's
+ * really no way to do this in a single pass, since arbitrary line
+ * creation, deletion and movement can be done in the ex command. For
+ * example, a good vi clone test is ":g/X/mo.-3", or "g/X/.,.+1d".
+ * What we do is create linked list of lines that are tracked through
+ * each ex command. There's a callback routine which the DB interface
+ * routines call when a line is created or deleted. This doesn't help
+ * the layering much.
+ */
+ btype = BUSY_ON;
+ cnt = INTERRUPT_CHECK;
+ for (start = cmdp->addr1.lno,
+ end = cmdp->addr2.lno; start <= end; ++start) {
+ if (cnt-- == 0) {
+ if (INTERRUPTED(sp)) {
+ LIST_REMOVE(ecp, q);
+ free(ecp->cp);
+ free(ecp);
+ break;
+ }
+ search_busy(sp, btype);
+ btype = BUSY_UPDATE;
+ cnt = INTERRUPT_CHECK;
+ }
+ if (db_get(sp, start, DBG_FATAL, &dbp, &len))
+ return (1);
+ match[0].rm_so = 0;
+ match[0].rm_eo = len;
+ switch (eval =
+ regexec(&sp->re_c, dbp, 0, match, REG_STARTEND)) {
+ case 0:
+ if (cmd == V)
+ continue;
+ break;
+ case REG_NOMATCH:
+ if (cmd == GLOBAL)
+ continue;
+ break;
+ default:
+ re_error(sp, eval, &sp->re_c);
+ break;
+ }
+
+ /* If follows the last entry, extend the last entry's range. */
+ if ((rp = ecp->rq.cqh_last) != (void *)&ecp->rq &&
+ rp->stop == start - 1) {
+ ++rp->stop;
+ continue;
+ }
+
+ /* Allocate a new range, and append it to the list. */
+ CALLOC(sp, rp, RANGE *, 1, sizeof(RANGE));
+ if (rp == NULL)
+ return (1);
+ rp->start = rp->stop = start;
+ CIRCLEQ_INSERT_TAIL(&ecp->rq, rp, q);
+ }
+ search_busy(sp, BUSY_OFF);
+ return (0);
+}
+
+/*
+ * ex_g_insdel --
+ * Update the ranges based on an insertion or deletion.
+ *
+ * PUBLIC: int ex_g_insdel __P((SCR *, lnop_t, recno_t));
+ */
+int
+ex_g_insdel(sp, op, lno)
+ SCR *sp;
+ lnop_t op;
+ recno_t lno;
+{
+ EXCMD *ecp;
+ RANGE *nrp, *rp;
+
+ /* All insert/append operations are done as inserts. */
+ if (op == LINE_APPEND)
+ abort();
+
+ if (op == LINE_RESET)
+ return (0);
+
+ for (ecp = sp->gp->ecq.lh_first; ecp != NULL; ecp = ecp->q.le_next) {
+ if (!FL_ISSET(ecp->agv_flags, AGV_AT | AGV_GLOBAL | AGV_V))
+ continue;
+ for (rp = ecp->rq.cqh_first; rp != (void *)&ecp->rq; rp = nrp) {
+ nrp = rp->q.cqe_next;
+
+ /* If range less than the line, ignore it. */
+ if (rp->stop < lno)
+ continue;
+
+ /*
+ * If range greater than the line, decrement or
+ * increment the range.
+ */
+ if (rp->start > lno) {
+ if (op == LINE_DELETE) {
+ --rp->start;
+ --rp->stop;
+ } else {
+ ++rp->start;
+ ++rp->stop;
+ }
+ continue;
+ }
+
+ /*
+ * Lno is inside the range, decrement the end point
+ * for deletion, and split the range for insertion.
+ * In the latter case, since we're inserting a new
+ * element, neither range can be exhausted.
+ */
+ if (op == LINE_DELETE) {
+ if (rp->start > --rp->stop) {
+ CIRCLEQ_REMOVE(&ecp->rq, rp, q);
+ free(rp);
+ }
+ } else {
+ CALLOC_RET(sp, nrp, RANGE *, 1, sizeof(RANGE));
+ nrp->start = lno + 1;
+ nrp->stop = rp->stop + 1;
+ rp->stop = lno - 1;
+ CIRCLEQ_INSERT_AFTER(&ecp->rq, rp, nrp, q);
+ rp = nrp;
+ }
+ }
+
+ /*
+ * If the command deleted/inserted lines, the cursor moves to
+ * the line after the deleted/inserted line.
+ */
+ ecp->range_lno = lno;
+ }
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_init.c b/contrib/nvi/ex/ex_init.c
new file mode 100644
index 000000000000..6a78416a3344
--- /dev/null
+++ b/contrib/nvi/ex/ex_init.c
@@ -0,0 +1,417 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_init.c 10.26 (Berkeley) 8/12/96";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/types.h> /* XXX: param.h may not have included types.h */
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "tag.h"
+#include "pathnames.h"
+
+enum rc { NOEXIST, NOPERM, RCOK };
+static enum rc exrc_isok __P((SCR *, struct stat *, char *, int, int));
+
+static int ex_run_file __P((SCR *, char *));
+
+/*
+ * ex_screen_copy --
+ * Copy ex screen.
+ *
+ * PUBLIC: int ex_screen_copy __P((SCR *, SCR *));
+ */
+int
+ex_screen_copy(orig, sp)
+ SCR *orig, *sp;
+{
+ EX_PRIVATE *oexp, *nexp;
+
+ /* Create the private ex structure. */
+ CALLOC_RET(orig, nexp, EX_PRIVATE *, 1, sizeof(EX_PRIVATE));
+ sp->ex_private = nexp;
+
+ /* Initialize queues. */
+ CIRCLEQ_INIT(&nexp->tq);
+ TAILQ_INIT(&nexp->tagfq);
+ LIST_INIT(&nexp->cscq);
+
+ if (orig == NULL) {
+ } else {
+ oexp = EXP(orig);
+
+ if (oexp->lastbcomm != NULL &&
+ (nexp->lastbcomm = strdup(oexp->lastbcomm)) == NULL) {
+ msgq(sp, M_SYSERR, NULL);
+ return(1);
+ }
+ if (ex_tag_copy(orig, sp))
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * ex_screen_end --
+ * End a vi screen.
+ *
+ * PUBLIC: int ex_screen_end __P((SCR *));
+ */
+int
+ex_screen_end(sp)
+ SCR *sp;
+{
+ EX_PRIVATE *exp;
+ int rval;
+
+ if ((exp = EXP(sp)) == NULL)
+ return (0);
+
+ rval = 0;
+
+ /* Close down script connections. */
+ if (F_ISSET(sp, SC_SCRIPT) && sscr_end(sp))
+ rval = 1;
+
+ if (argv_free(sp))
+ rval = 1;
+
+ if (exp->ibp != NULL)
+ free(exp->ibp);
+
+ if (exp->lastbcomm != NULL)
+ free(exp->lastbcomm);
+
+ if (ex_tag_free(sp))
+ rval = 1;
+
+ /* Free private memory. */
+ free(exp);
+ sp->ex_private = NULL;
+
+ return (rval);
+}
+
+/*
+ * ex_optchange --
+ * Handle change of options for ex.
+ *
+ * PUBLIC: int ex_optchange __P((SCR *, int, char *, u_long *));
+ */
+int
+ex_optchange(sp, offset, str, valp)
+ SCR *sp;
+ int offset;
+ char *str;
+ u_long *valp;
+{
+ switch (offset) {
+ case O_TAGS:
+ return (ex_tagf_alloc(sp, str));
+ }
+ return (0);
+}
+
+/*
+ * ex_exrc --
+ * Read the EXINIT environment variable and the startup exrc files,
+ * and execute their commands.
+ *
+ * PUBLIC: int ex_exrc __P((SCR *));
+ */
+int
+ex_exrc(sp)
+ SCR *sp;
+{
+ struct stat hsb, lsb;
+ char *p, path[MAXPATHLEN];
+
+ /*
+ * Source the system, environment, $HOME and local .exrc values.
+ * Vi historically didn't check $HOME/.exrc if the environment
+ * variable EXINIT was set. This is all done before the file is
+ * read in, because things in the .exrc information can set, for
+ * example, the recovery directory.
+ *
+ * !!!
+ * While nvi can handle any of the options settings of historic vi,
+ * the converse is not true. Since users are going to have to have
+ * files and environmental variables that work with both, we use nvi
+ * versions of both the $HOME and local startup files if they exist,
+ * otherwise the historic ones.
+ *
+ * !!!
+ * For a discussion of permissions and when what .exrc files are
+ * read, see the comment above the exrc_isok() function below.
+ *
+ * !!!
+ * If the user started the historic of vi in $HOME, vi read the user's
+ * .exrc file twice, as $HOME/.exrc and as ./.exrc. We avoid this, as
+ * it's going to make some commands behave oddly, and I can't imagine
+ * anyone depending on it.
+ */
+ switch (exrc_isok(sp, &hsb, _PATH_SYSEXRC, 1, 0)) {
+ case NOEXIST:
+ case NOPERM:
+ break;
+ case RCOK:
+ if (ex_run_file(sp, _PATH_SYSEXRC))
+ return (1);
+ break;
+ }
+
+ /* Run the commands. */
+ if (EXCMD_RUNNING(sp->gp))
+ (void)ex_cmd(sp);
+ if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE))
+ return (0);
+
+ if ((p = getenv("NEXINIT")) != NULL) {
+ if (ex_run_str(sp, "NEXINIT", p, strlen(p), 1, 0))
+ return (1);
+ } else if ((p = getenv("EXINIT")) != NULL) {
+ if (ex_run_str(sp, "EXINIT", p, strlen(p), 1, 0))
+ return (1);
+ } else if ((p = getenv("HOME")) != NULL && *p) {
+ (void)snprintf(path, sizeof(path), "%s/%s", p, _PATH_NEXRC);
+ switch (exrc_isok(sp, &hsb, path, 0, 1)) {
+ case NOEXIST:
+ (void)snprintf(path,
+ sizeof(path), "%s/%s", p, _PATH_EXRC);
+ if (exrc_isok(sp,
+ &hsb, path, 0, 1) == RCOK && ex_run_file(sp, path))
+ return (1);
+ break;
+ case NOPERM:
+ break;
+ case RCOK:
+ if (ex_run_file(sp, path))
+ return (1);
+ break;
+ }
+ }
+
+ /* Run the commands. */
+ if (EXCMD_RUNNING(sp->gp))
+ (void)ex_cmd(sp);
+ if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE))
+ return (0);
+
+ /* Previous commands may have set the exrc option. */
+ if (O_ISSET(sp, O_EXRC)) {
+ switch (exrc_isok(sp, &lsb, _PATH_NEXRC, 0, 0)) {
+ case NOEXIST:
+ if (exrc_isok(sp, &lsb, _PATH_EXRC, 0, 0) == RCOK &&
+ (lsb.st_dev != hsb.st_dev ||
+ lsb.st_ino != hsb.st_ino) &&
+ ex_run_file(sp, _PATH_EXRC))
+ return (1);
+ break;
+ case NOPERM:
+ break;
+ case RCOK:
+ if ((lsb.st_dev != hsb.st_dev ||
+ lsb.st_ino != hsb.st_ino) &&
+ ex_run_file(sp, _PATH_NEXRC))
+ return (1);
+ break;
+ }
+ /* Run the commands. */
+ if (EXCMD_RUNNING(sp->gp))
+ (void)ex_cmd(sp);
+ if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE))
+ return (0);
+ }
+
+ return (0);
+}
+
+/*
+ * ex_run_file --
+ * Set up a file of ex commands to run.
+ */
+static int
+ex_run_file(sp, name)
+ SCR *sp;
+ char *name;
+{
+ ARGS *ap[2], a;
+ EXCMD cmd;
+
+ ex_cinit(&cmd, C_SOURCE, 0, OOBLNO, OOBLNO, 0, ap);
+ ex_cadd(&cmd, &a, name, strlen(name));
+ return (ex_source(sp, &cmd));
+}
+
+/*
+ * ex_run_str --
+ * Set up a string of ex commands to run.
+ *
+ * PUBLIC: int ex_run_str __P((SCR *, char *, char *, size_t, int, int));
+ */
+int
+ex_run_str(sp, name, str, len, ex_flags, nocopy)
+ SCR *sp;
+ char *name, *str;
+ size_t len;
+ int ex_flags, nocopy;
+{
+ GS *gp;
+ EXCMD *ecp;
+
+ gp = sp->gp;
+ if (EXCMD_RUNNING(gp)) {
+ CALLOC_RET(sp, ecp, EXCMD *, 1, sizeof(EXCMD));
+ LIST_INSERT_HEAD(&gp->ecq, ecp, q);
+ } else
+ ecp = &gp->excmd;
+
+ F_INIT(ecp,
+ ex_flags ? E_BLIGNORE | E_NOAUTO | E_NOPRDEF | E_VLITONLY : 0);
+
+ if (nocopy)
+ ecp->cp = str;
+ else
+ if ((ecp->cp = v_strdup(sp, str, len)) == NULL)
+ return (1);
+ ecp->clen = len;
+
+ if (name == NULL)
+ ecp->if_name = NULL;
+ else {
+ if ((ecp->if_name = v_strdup(sp, name, strlen(name))) == NULL)
+ return (1);
+ ecp->if_lno = 1;
+ F_SET(ecp, E_NAMEDISCARD);
+ }
+
+ return (0);
+}
+
+/*
+ * exrc_isok --
+ * Check a .exrc file for source-ability.
+ *
+ * !!!
+ * Historically, vi read the $HOME and local .exrc files if they were owned
+ * by the user's real ID, or the "sourceany" option was set, regardless of
+ * any other considerations. We no longer support the sourceany option as
+ * it's a security problem of mammoth proportions. We require the system
+ * .exrc file to be owned by root, the $HOME .exrc file to be owned by the
+ * user's effective ID (or that the user's effective ID be root) and the
+ * local .exrc files to be owned by the user's effective ID. In all cases,
+ * the file cannot be writeable by anyone other than its owner.
+ *
+ * In O'Reilly ("Learning the VI Editor", Fifth Ed., May 1992, page 106),
+ * it notes that System V release 3.2 and later has an option "[no]exrc".
+ * The behavior is that local .exrc files are read only if the exrc option
+ * is set. The default for the exrc option was off, so, by default, local
+ * .exrc files were not read. The problem this was intended to solve was
+ * that System V permitted users to give away files, so there's no possible
+ * ownership or writeability test to ensure that the file is safe.
+ *
+ * POSIX 1003.2-1992 standardized exrc as an option. It required the exrc
+ * option to be off by default, thus local .exrc files are not to be read
+ * by default. The Rationale noted (incorrectly) that this was a change
+ * to historic practice, but correctly noted that a default of off improves
+ * system security. POSIX also required that vi check the effective user
+ * ID instead of the real user ID, which is why we've switched from historic
+ * practice.
+ *
+ * We initialize the exrc variable to off. If it's turned on by the system
+ * or $HOME .exrc files, and the local .exrc file passes the ownership and
+ * writeability tests, then we read it. This breaks historic 4BSD practice,
+ * but it gives us a measure of security on systems where users can give away
+ * files.
+ */
+static enum rc
+exrc_isok(sp, sbp, path, rootown, rootid)
+ SCR *sp;
+ struct stat *sbp;
+ char *path;
+ int rootown, rootid;
+{
+ enum { ROOTOWN, OWN, WRITER } etype;
+ uid_t euid;
+ int nf1, nf2;
+ char *a, *b, buf[MAXPATHLEN];
+
+ /* Check for the file's existence. */
+ if (stat(path, sbp))
+ return (NOEXIST);
+
+ /* Check ownership permissions. */
+ euid = geteuid();
+ if (!(rootown && sbp->st_uid == 0) &&
+ !(rootid && euid == 0) && sbp->st_uid != euid) {
+ etype = rootown ? ROOTOWN : OWN;
+ goto denied;
+ }
+
+ /* Check writeability. */
+ if (sbp->st_mode & (S_IWGRP | S_IWOTH)) {
+ etype = WRITER;
+ goto denied;
+ }
+ return (RCOK);
+
+denied: a = msg_print(sp, path, &nf1);
+ if (strchr(path, '/') == NULL && getcwd(buf, sizeof(buf)) != NULL) {
+ b = msg_print(sp, buf, &nf2);
+ switch (etype) {
+ case ROOTOWN:
+ msgq(sp, M_ERR,
+ "125|%s/%s: not sourced: not owned by you or root",
+ b, a);
+ break;
+ case OWN:
+ msgq(sp, M_ERR,
+ "126|%s/%s: not sourced: not owned by you", b, a);
+ break;
+ case WRITER:
+ msgq(sp, M_ERR,
+ "127|%s/%s: not sourced: writeable by a user other than the owner", b, a);
+ break;
+ }
+ if (nf2)
+ FREE_SPACE(sp, b, 0);
+ } else
+ switch (etype) {
+ case ROOTOWN:
+ msgq(sp, M_ERR,
+ "128|%s: not sourced: not owned by you or root", a);
+ break;
+ case OWN:
+ msgq(sp, M_ERR,
+ "129|%s: not sourced: not owned by you", a);
+ break;
+ case WRITER:
+ msgq(sp, M_ERR,
+ "130|%s: not sourced: writeable by a user other than the owner", a);
+ break;
+ }
+
+ if (nf1)
+ FREE_SPACE(sp, a, 0);
+ return (NOPERM);
+}
diff --git a/usr.bin/vi/ex/ex_join.c b/contrib/nvi/ex/ex_join.c
index d561f0a5bd61..c26c4243178a 100644
--- a/usr.bin/vi/ex/ex_join.c
+++ b/contrib/nvi/ex/ex_join.c
@@ -1,81 +1,54 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)ex_join.c 8.12 (Berkeley) 5/21/94";
+static const char sccsid[] = "@(#)ex_join.c 10.10 (Berkeley) 9/15/96";
#endif /* not lint */
#include <sys/types.h>
#include <sys/queue.h>
-#include <sys/time.h>
#include <bitstring.h>
#include <ctype.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-#include "vi.h"
-#include "excmd.h"
+#include "../common/common.h"
/*
* ex_join -- :[line [,line]] j[oin][!] [count] [flags]
* Join lines.
+ *
+ * PUBLIC: int ex_join __P((SCR *, EXCMD *));
*/
int
-ex_join(sp, ep, cmdp)
+ex_join(sp, cmdp)
SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+ EXCMD *cmdp;
{
recno_t from, to;
size_t blen, clen, len, tlen;
int echar, extra, first;
char *bp, *p, *tbp;
+ NEEDFILE(sp, cmdp);
+
from = cmdp->addr1.lno;
to = cmdp->addr2.lno;
/* Check for no lines to join. */
- if ((p = file_gline(sp, ep, from + 1, &len)) == NULL) {
- msgq(sp, M_ERR, "No following lines to join");
+ if (!db_exist(sp, from + 1)) {
+ msgq(sp, M_ERR, "131|No following lines to join");
return (1);
}
@@ -85,7 +58,7 @@ ex_join(sp, ep, cmdp)
* The count for the join command was off-by-one,
* historically, to other counts for other commands.
*/
- if (F_ISSET(cmdp, E_COUNT))
+ if (FL_ISSET(cmdp->iflags, E_C_COUNT))
++cmdp->addr2.lno;
/*
@@ -102,7 +75,7 @@ ex_join(sp, ep, cmdp)
* Get next line. Historic versions of vi allowed "10J" while
* less than 10 lines from the end-of-file, so we do too.
*/
- if ((p = file_gline(sp, ep, from, &len)) == NULL) {
+ if (db_get(sp, from, 0, &p, &len)) {
cmdp->addr2.lno = from - 1;
break;
}
@@ -127,13 +100,17 @@ ex_join(sp, ep, cmdp)
* If the current line ends with whitespace, strip leading
* whitespace from the joined line.
* If the next line starts with a ), do nothing.
- * If the current line ends with ., ? or !, insert two spaces.
+ * If the current line ends with ., insert two spaces.
* Else, insert one space.
*
+ * One change -- add ? and ! to the list of characters for
+ * which we insert two spaces. I expect that POSIX 1003.2
+ * will require this as well.
+ *
* Echar is the last character in the last line joined.
*/
extra = 0;
- if (!first && !F_ISSET(cmdp, E_FORCE)) {
+ if (!first && !FL_ISSET(cmdp->iflags, E_C_FORCE)) {
if (isblank(echar))
for (; len && isblank(*p); --len, ++p);
else if (p[0] != ')') {
@@ -149,7 +126,7 @@ ex_join(sp, ep, cmdp)
}
if (len != 0) {
- memmove(tbp, p, len);
+ memcpy(tbp, p, len);
tbp += len;
clen += len;
echar = p[len - 1];
@@ -185,11 +162,11 @@ ex_join(sp, ep, cmdp)
/* Delete the joined lines. */
for (from = cmdp->addr1.lno, to = cmdp->addr2.lno; to > from; --to)
- if (file_dline(sp, ep, to))
+ if (db_delete(sp, to))
goto err;
/* If the original line changed, reset it. */
- if (!first && file_sline(sp, ep, from, bp, tbp - bp)) {
+ if (!first && db_set(sp, from, bp, tbp - bp)) {
err: FREE_SPACE(sp, bp, blen);
return (1);
}
diff --git a/contrib/nvi/ex/ex_map.c b/contrib/nvi/ex/ex_map.c
new file mode 100644
index 000000000000..bc2cf0855919
--- /dev/null
+++ b/contrib/nvi/ex/ex_map.c
@@ -0,0 +1,121 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_map.c 10.9 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_map -- :map[!] [input] [replacement]
+ * Map a key/string or display mapped keys.
+ *
+ * Historical note:
+ * Historic vi maps were fairly bizarre, and likely to differ in
+ * very subtle and strange ways from this implementation. Two
+ * things worth noting are that vi would often hang or drop core
+ * if the map was strange enough (ex: map X "xy$@x^V), or, simply
+ * not work. One trick worth remembering is that if you put a
+ * mark at the start of the map, e.g. map X mx"xy ...), or if you
+ * put the map in a .exrc file, things would often work much better.
+ * No clue why.
+ *
+ * PUBLIC: int ex_map __P((SCR *, EXCMD *));
+ */
+int
+ex_map(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ seq_t stype;
+ CHAR_T *input, *p;
+
+ stype = FL_ISSET(cmdp->iflags, E_C_FORCE) ? SEQ_INPUT : SEQ_COMMAND;
+
+ switch (cmdp->argc) {
+ case 0:
+ if (seq_dump(sp, stype, 1) == 0)
+ msgq(sp, M_INFO, stype == SEQ_INPUT ?
+ "132|No input map entries" :
+ "133|No command map entries");
+ return (0);
+ case 2:
+ input = cmdp->argv[0]->bp;
+ break;
+ default:
+ abort();
+ }
+
+ /*
+ * If the mapped string is #[0-9]* (and wasn't quoted) then store the
+ * function key mapping. If the screen specific routine has been set,
+ * call it as well. Note, the SEQ_FUNCMAP type is persistent across
+ * screen types, maybe the next screen type will get it right.
+ */
+ if (input[0] == '#' && isdigit(input[1])) {
+ for (p = input + 2; isdigit(*p); ++p);
+ if (p[0] != '\0')
+ goto nofunc;
+
+ if (seq_set(sp, NULL, 0, input, cmdp->argv[0]->len,
+ cmdp->argv[1]->bp, cmdp->argv[1]->len, stype,
+ SEQ_FUNCMAP | SEQ_USERDEF))
+ return (1);
+ return (sp->gp->scr_fmap == NULL ? 0 :
+ sp->gp->scr_fmap(sp, stype, input, cmdp->argv[0]->len,
+ cmdp->argv[1]->bp, cmdp->argv[1]->len));
+ }
+
+ /* Some single keys may not be remapped in command mode. */
+nofunc: if (stype == SEQ_COMMAND && input[1] == '\0')
+ switch (KEY_VAL(sp, input[0])) {
+ case K_COLON:
+ case K_ESCAPE:
+ case K_NL:
+ msgq(sp, M_ERR,
+ "134|The %s character may not be remapped",
+ KEY_NAME(sp, input[0]));
+ return (1);
+ }
+ return (seq_set(sp, NULL, 0, input, cmdp->argv[0]->len,
+ cmdp->argv[1]->bp, cmdp->argv[1]->len, stype, SEQ_USERDEF));
+}
+
+/*
+ * ex_unmap -- (:unmap[!] key)
+ * Unmap a key.
+ *
+ * PUBLIC: int ex_unmap __P((SCR *, EXCMD *));
+ */
+int
+ex_unmap(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ if (seq_delete(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len,
+ FL_ISSET(cmdp->iflags, E_C_FORCE) ? SEQ_INPUT : SEQ_COMMAND)) {
+ msgq_str(sp, M_INFO,
+ cmdp->argv[0]->bp, "135|\"%s\" isn't currently mapped");
+ return (1);
+ }
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_mark.c b/contrib/nvi/ex/ex_mark.c
new file mode 100644
index 000000000000..08ad8c2aa30b
--- /dev/null
+++ b/contrib/nvi/ex/ex_mark.c
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_mark.c 10.8 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_mark -- :mark char
+ * :k char
+ * Mark lines.
+ *
+ *
+ * PUBLIC: int ex_mark __P((SCR *, EXCMD *));
+ */
+int
+ex_mark(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ NEEDFILE(sp, cmdp);
+
+ if (cmdp->argv[0]->len != 1) {
+ msgq(sp, M_ERR, "136|Mark names must be a single character");
+ return (1);
+ }
+ return (mark_set(sp, cmdp->argv[0]->bp[0], &cmdp->addr1, 1));
+}
diff --git a/contrib/nvi/ex/ex_mkexrc.c b/contrib/nvi/ex/ex_mkexrc.c
new file mode 100644
index 000000000000..0eb15d408cf7
--- /dev/null
+++ b/contrib/nvi/ex/ex_mkexrc.c
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_mkexrc.c 10.11 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "pathnames.h"
+
+/*
+ * ex_mkexrc -- :mkexrc[!] [file]
+ *
+ * Create (or overwrite) a .exrc file with the current info.
+ *
+ * PUBLIC: int ex_mkexrc __P((SCR *, EXCMD *));
+ */
+int
+ex_mkexrc(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ struct stat sb;
+ FILE *fp;
+ int fd, sverrno;
+ char *fname;
+
+ switch (cmdp->argc) {
+ case 0:
+ fname = _PATH_EXRC;
+ break;
+ case 1:
+ fname = cmdp->argv[0]->bp;
+ set_alt_name(sp, fname);
+ break;
+ default:
+ abort();
+ }
+
+ if (!FL_ISSET(cmdp->iflags, E_C_FORCE) && !stat(fname, &sb)) {
+ msgq_str(sp, M_ERR, fname,
+ "137|%s exists, not written; use ! to override");
+ return (1);
+ }
+
+ /* Create with max permissions of rw-r--r--. */
+ if ((fd = open(fname, O_CREAT | O_TRUNC | O_WRONLY,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
+ msgq_str(sp, M_SYSERR, fname, "%s");
+ return (1);
+ }
+
+ if ((fp = fdopen(fd, "w")) == NULL) {
+ sverrno = errno;
+ (void)close(fd);
+ goto e2;
+ }
+
+ if (seq_save(sp, fp, "abbreviate ", SEQ_ABBREV) || ferror(fp))
+ goto e1;
+ if (seq_save(sp, fp, "map ", SEQ_COMMAND) || ferror(fp))
+ goto e1;
+ if (seq_save(sp, fp, "map! ", SEQ_INPUT) || ferror(fp))
+ goto e1;
+ if (opts_save(sp, fp) || ferror(fp))
+ goto e1;
+ if (fclose(fp)) {
+ sverrno = errno;
+ goto e2;
+ }
+
+ msgq_str(sp, M_INFO, fname, "138|New exrc file: %s");
+ return (0);
+
+e1: sverrno = errno;
+ (void)fclose(fp);
+e2: errno = sverrno;
+ msgq_str(sp, M_SYSERR, fname, "%s");
+ return (1);
+}
diff --git a/usr.bin/vi/ex/ex_move.c b/contrib/nvi/ex/ex_move.c
index 98225089d321..d6e45c373964 100644
--- a/usr.bin/vi/ex/ex_move.c
+++ b/contrib/nvi/ex/ex_move.c
@@ -1,68 +1,39 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)ex_move.c 8.17 (Berkeley) 8/8/94";
+static const char sccsid[] = "@(#)ex_move.c 10.10 (Berkeley) 9/15/96";
#endif /* not lint */
#include <sys/types.h>
#include <sys/queue.h>
-#include <sys/time.h>
#include <bitstring.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
+#include "../common/common.h"
/*
* ex_copy -- :[line [,line]] co[py] line [flags]
* Copy selected lines.
+ *
+ * PUBLIC: int ex_copy __P((SCR *, EXCMD *));
*/
int
-ex_copy(sp, ep, cmdp)
+ex_copy(sp, cmdp)
SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+ EXCMD *cmdp;
{
CB cb;
MARK fm1, fm2, m, tm;
@@ -71,6 +42,8 @@ ex_copy(sp, ep, cmdp)
rval = 0;
+ NEEDFILE(sp, cmdp);
+
/*
* It's possible to copy things into the area that's being
* copied, e.g. "2,5copy3" is legitimate. Save the text to
@@ -81,7 +54,7 @@ ex_copy(sp, ep, cmdp)
memset(&cb, 0, sizeof(cb));
CIRCLEQ_INIT(&cb.textq);
for (cnt = fm1.lno; cnt <= fm2.lno; ++cnt)
- if (cut_line(sp, ep, cnt, 0, 0, &cb)) {
+ if (cut_line(sp, cnt, 0, 0, &cb)) {
rval = 1;
goto err;
}
@@ -90,7 +63,7 @@ ex_copy(sp, ep, cmdp)
/* Put the text into place. */
tm.lno = cmdp->lineno;
tm.cno = 0;
- if (put(sp, ep, &cb, NULL, &tm, &m, 1))
+ if (put(sp, &cb, NULL, &tm, &m, 1))
rval = 1;
else {
/*
@@ -109,12 +82,13 @@ err: text_lfree(&cb.textq);
/*
* ex_move -- :[line [,line]] mo[ve] line
* Move selected lines.
+ *
+ * PUBLIC: int ex_move __P((SCR *, EXCMD *));
*/
int
-ex_move(sp, ep, cmdp)
+ex_move(sp, cmdp)
SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+ EXCMD *cmdp;
{
LMARK *lmp;
MARK fm1, fm2;
@@ -123,6 +97,8 @@ ex_move(sp, ep, cmdp)
int mark_reset;
char *bp, *p;
+ NEEDFILE(sp, cmdp);
+
/*
* It's not possible to move things into the area that's being
* moved.
@@ -130,7 +106,7 @@ ex_move(sp, ep, cmdp)
fm1 = cmdp->addr1;
fm2 = cmdp->addr2;
if (cmdp->lineno >= fm1.lno && cmdp->lineno <= fm2.lno) {
- msgq(sp, M_ERR, "Destination line is inside move range");
+ msgq(sp, M_ERR, "139|Destination line is inside move range");
return (1);
}
@@ -150,12 +126,12 @@ ex_move(sp, ep, cmdp)
/* Log the old positions of the marks. */
mark_reset = 0;
- for (lmp = ep->marks.lh_first; lmp != NULL; lmp = lmp->q.le_next)
+ for (lmp = sp->ep->marks.lh_first; lmp != NULL; lmp = lmp->q.le_next)
if (lmp->name != ABSMARK1 &&
lmp->lno >= fl && lmp->lno <= tl) {
mark_reset = 1;
F_CLR(lmp, MARK_USERSET);
- (void)log_mark(sp, ep, lmp);
+ (void)log_mark(sp, lmp);
}
/* Get memory for the copy. */
@@ -167,39 +143,39 @@ ex_move(sp, ep, cmdp)
mfl = tl - diff;
mtl = tl;
for (cnt = diff; cnt--;) {
- if ((p = file_gline(sp, ep, fl, &len)) == NULL)
+ if (db_get(sp, fl, DBG_FATAL, &p, &len))
return (1);
BINC_RET(sp, bp, blen, len);
- memmove(bp, p, len);
- if (file_aline(sp, ep, 1, tl, bp, len))
+ memcpy(bp, p, len);
+ if (db_append(sp, 1, tl, bp, len))
return (1);
if (mark_reset)
- for (lmp = ep->marks.lh_first;
+ for (lmp = sp->ep->marks.lh_first;
lmp != NULL; lmp = lmp->q.le_next)
if (lmp->name != ABSMARK1 &&
lmp->lno == fl)
lmp->lno = tl + 1;
- if (file_dline(sp, ep, fl))
+ if (db_delete(sp, fl))
return (1);
}
} else { /* Destination < source. */
mfl = tl;
mtl = tl + diff;
for (cnt = diff; cnt--;) {
- if ((p = file_gline(sp, ep, fl, &len)) == NULL)
+ if (db_get(sp, fl, DBG_FATAL, &p, &len))
return (1);
BINC_RET(sp, bp, blen, len);
- memmove(bp, p, len);
- if (file_aline(sp, ep, 1, tl++, bp, len))
+ memcpy(bp, p, len);
+ if (db_append(sp, 1, tl++, bp, len))
return (1);
if (mark_reset)
- for (lmp = ep->marks.lh_first;
+ for (lmp = sp->ep->marks.lh_first;
lmp != NULL; lmp = lmp->q.le_next)
if (lmp->name != ABSMARK1 &&
lmp->lno == fl)
lmp->lno = tl;
++fl;
- if (file_dline(sp, ep, fl))
+ if (db_delete(sp, fl))
return (1);
}
}
@@ -210,11 +186,11 @@ ex_move(sp, ep, cmdp)
/* Log the new positions of the marks. */
if (mark_reset)
- for (lmp = ep->marks.lh_first;
+ for (lmp = sp->ep->marks.lh_first;
lmp != NULL; lmp = lmp->q.le_next)
if (lmp->name != ABSMARK1 &&
lmp->lno >= mfl && lmp->lno <= mtl)
- (void)log_mark(sp, ep, lmp);
+ (void)log_mark(sp, lmp);
sp->rptlines[L_MOVED] += diff;
diff --git a/contrib/nvi/ex/ex_open.c b/contrib/nvi/ex/ex_open.c
new file mode 100644
index 000000000000..afffaeb2202d
--- /dev/null
+++ b/contrib/nvi/ex/ex_open.c
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_open.c 10.7 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_open -- :[line] o[pen] [/pattern/] [flags]
+ *
+ * Switch to single line "open" mode.
+ *
+ * PUBLIC: int ex_open __P((SCR *, EXCMD *));
+ */
+int
+ex_open(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ /* If open option off, disallow open command. */
+ if (!O_ISSET(sp, O_OPEN)) {
+ msgq(sp, M_ERR,
+ "140|The open command requires that the open option be set");
+ return (1);
+ }
+
+ msgq(sp, M_ERR, "141|The open command is not yet implemented");
+ return (1);
+}
diff --git a/contrib/nvi/ex/ex_perl.c b/contrib/nvi/ex/ex_perl.c
new file mode 100644
index 000000000000..e620352ab518
--- /dev/null
+++ b/contrib/nvi/ex/ex_perl.c
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ * Copyright (c) 1995
+ * George V. Neville-Neil. All rights reserved.
+ * Copyright (c) 1996
+ * Sven Verdoolaege. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_perl.c 8.10 (Berkeley) 9/15/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_perl -- :[line [,line]] perl [command]
+ * Run a command through the perl interpreter.
+ *
+ * ex_perldo -- :[line [,line]] perldo [command]
+ * Run a set of lines through the perl interpreter.
+ *
+ * PUBLIC: int ex_perl __P((SCR*, EXCMD *));
+ */
+int
+ex_perl(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+#ifdef HAVE_PERL_INTERP
+ CHAR_T *p;
+ size_t len;
+
+ /* Skip leading white space. */
+ if (cmdp->argc != 0)
+ for (p = cmdp->argv[0]->bp,
+ len = cmdp->argv[0]->len; len > 0; --len, ++p)
+ if (!isblank(*p))
+ break;
+ if (cmdp->argc == 0 || len == 0) {
+ ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+ return (1);
+ }
+ return (cmdp->cmd == &cmds[C_PERLCMD] ?
+ perl_ex_perl(sp, p, len, cmdp->addr1.lno, cmdp->addr2.lno) :
+ perl_ex_perldo(sp, p, len, cmdp->addr1.lno, cmdp->addr2.lno));
+#else
+ msgq(sp, M_ERR, "306|Vi was not loaded with a Perl interpreter");
+ return (1);
+#endif
+}
diff --git a/contrib/nvi/ex/ex_preserve.c b/contrib/nvi/ex/ex_preserve.c
new file mode 100644
index 000000000000..5614c88d753a
--- /dev/null
+++ b/contrib/nvi/ex/ex_preserve.c
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_preserve.c 10.12 (Berkeley) 4/27/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_preserve -- :pre[serve]
+ * Push the file to recovery.
+ *
+ * PUBLIC: int ex_preserve __P((SCR *, EXCMD *));
+ */
+int
+ex_preserve(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ recno_t lno;
+
+ NEEDFILE(sp, cmdp);
+
+ if (!F_ISSET(sp->ep, F_RCV_ON)) {
+ msgq(sp, M_ERR, "142|Preservation of this file not possible");
+ return (1);
+ }
+
+ /* If recovery not initialized, do so. */
+ if (F_ISSET(sp->ep, F_FIRSTMODIFY) && rcv_init(sp))
+ return (1);
+
+ /* Force the file to be read in, in case it hasn't yet. */
+ if (db_last(sp, &lno))
+ return (1);
+
+ /* Sync to disk. */
+ if (rcv_sync(sp, RCV_SNAPSHOT))
+ return (1);
+
+ msgq(sp, M_INFO, "143|File preserved");
+ return (0);
+}
+
+/*
+ * ex_recover -- :rec[over][!] file
+ * Recover the file.
+ *
+ * PUBLIC: int ex_recover __P((SCR *, EXCMD *));
+ */
+int
+ex_recover(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ ARGS *ap;
+ FREF *frp;
+
+ ap = cmdp->argv[0];
+
+ /* Set the alternate file name. */
+ set_alt_name(sp, ap->bp);
+
+ /*
+ * Check for modifications. Autowrite did not historically
+ * affect :recover.
+ */
+ if (file_m2(sp, FL_ISSET(cmdp->iflags, E_C_FORCE)))
+ return (1);
+
+ /* Get a file structure for the file. */
+ if ((frp = file_add(sp, ap->bp)) == NULL)
+ return (1);
+
+ /* Set the recover bit. */
+ F_SET(frp, FR_RECOVER);
+
+ /* Switch files. */
+ if (file_init(sp, frp, NULL, FS_SETALT |
+ (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
+ return (1);
+
+ F_SET(sp, SC_FSWITCH);
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_print.c b/contrib/nvi/ex/ex_print.c
new file mode 100644
index 000000000000..4218e08e0978
--- /dev/null
+++ b/contrib/nvi/ex/ex_print.c
@@ -0,0 +1,352 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_print.c 10.18 (Berkeley) 5/12/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "../common/common.h"
+
+static int ex_prchars __P((SCR *, const char *, size_t *, size_t, u_int, int));
+
+/*
+ * ex_list -- :[line [,line]] l[ist] [count] [flags]
+ *
+ * Display the addressed lines such that the output is unambiguous.
+ *
+ * PUBLIC: int ex_list __P((SCR *, EXCMD *));
+ */
+int
+ex_list(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ if (ex_print(sp, cmdp,
+ &cmdp->addr1, &cmdp->addr2, cmdp->iflags | E_C_LIST))
+ return (1);
+ sp->lno = cmdp->addr2.lno;
+ sp->cno = cmdp->addr2.cno;
+ return (0);
+}
+
+/*
+ * ex_number -- :[line [,line]] nu[mber] [count] [flags]
+ *
+ * Display the addressed lines with a leading line number.
+ *
+ * PUBLIC: int ex_number __P((SCR *, EXCMD *));
+ */
+int
+ex_number(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ if (ex_print(sp, cmdp,
+ &cmdp->addr1, &cmdp->addr2, cmdp->iflags | E_C_HASH))
+ return (1);
+ sp->lno = cmdp->addr2.lno;
+ sp->cno = cmdp->addr2.cno;
+ return (0);
+}
+
+/*
+ * ex_pr -- :[line [,line]] p[rint] [count] [flags]
+ *
+ * Display the addressed lines.
+ *
+ * PUBLIC: int ex_pr __P((SCR *, EXCMD *));
+ */
+int
+ex_pr(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ if (ex_print(sp, cmdp, &cmdp->addr1, &cmdp->addr2, cmdp->iflags))
+ return (1);
+ sp->lno = cmdp->addr2.lno;
+ sp->cno = cmdp->addr2.cno;
+ return (0);
+}
+
+/*
+ * ex_print --
+ * Print the selected lines.
+ *
+ * PUBLIC: int ex_print __P((SCR *, EXCMD *, MARK *, MARK *, u_int32_t));
+ */
+int
+ex_print(sp, cmdp, fp, tp, flags)
+ SCR *sp;
+ EXCMD *cmdp;
+ MARK *fp, *tp;
+ u_int32_t flags;
+{
+ GS *gp;
+ recno_t from, to;
+ size_t col, len;
+ char *p, buf[10];
+
+ NEEDFILE(sp, cmdp);
+
+ gp = sp->gp;
+ for (from = fp->lno, to = tp->lno; from <= to; ++from) {
+ col = 0;
+
+ /*
+ * Display the line number. The %6 format is specified
+ * by POSIX 1003.2, and is almost certainly large enough.
+ * Check, though, just in case.
+ */
+ if (LF_ISSET(E_C_HASH)) {
+ if (from <= 999999) {
+ snprintf(buf, sizeof(buf), "%6ld ", from);
+ p = buf;
+ } else
+ p = "TOOBIG ";
+ if (ex_prchars(sp, p, &col, 8, 0, 0))
+ return (1);
+ }
+
+ /*
+ * Display the line. The format for E_C_PRINT isn't very good,
+ * especially in handling end-of-line tabs, but they're almost
+ * backward compatible.
+ */
+ if (db_get(sp, from, DBG_FATAL, &p, &len))
+ return (1);
+
+ if (len == 0 && !LF_ISSET(E_C_LIST))
+ (void)ex_puts(sp, "\n");
+ else if (ex_ldisplay(sp, p, len, col, flags))
+ return (1);
+
+ if (INTERRUPTED(sp))
+ break;
+ }
+ return (0);
+}
+
+/*
+ * ex_ldisplay --
+ * Display a line without any preceding number.
+ *
+ * PUBLIC: int ex_ldisplay __P((SCR *, const char *, size_t, size_t, u_int));
+ */
+int
+ex_ldisplay(sp, p, len, col, flags)
+ SCR *sp;
+ const char *p;
+ size_t len, col;
+ u_int flags;
+{
+ if (len > 0 && ex_prchars(sp, p, &col, len, LF_ISSET(E_C_LIST), 0))
+ return (1);
+ if (!INTERRUPTED(sp) && LF_ISSET(E_C_LIST)) {
+ p = "$";
+ if (ex_prchars(sp, p, &col, 1, LF_ISSET(E_C_LIST), 0))
+ return (1);
+ }
+ if (!INTERRUPTED(sp))
+ (void)ex_puts(sp, "\n");
+ return (0);
+}
+
+/*
+ * ex_scprint --
+ * Display a line for the substitute with confirmation routine.
+ *
+ * PUBLIC: int ex_scprint __P((SCR *, MARK *, MARK *));
+ */
+int
+ex_scprint(sp, fp, tp)
+ SCR *sp;
+ MARK *fp, *tp;
+{
+ const char *p;
+ size_t col, len;
+
+ col = 0;
+ if (O_ISSET(sp, O_NUMBER)) {
+ p = " ";
+ if (ex_prchars(sp, p, &col, 8, 0, 0))
+ return (1);
+ }
+
+ if (db_get(sp, fp->lno, DBG_FATAL, (char **)&p, &len))
+ return (1);
+
+ if (ex_prchars(sp, p, &col, fp->cno, 0, ' '))
+ return (1);
+ p += fp->cno;
+ if (ex_prchars(sp,
+ p, &col, tp->cno == fp->cno ? 1 : tp->cno - fp->cno, 0, '^'))
+ return (1);
+ if (INTERRUPTED(sp))
+ return (1);
+ p = "[ynq]"; /* XXX: should be msg_cat. */
+ if (ex_prchars(sp, p, &col, 5, 0, 0))
+ return (1);
+ (void)ex_fflush(sp);
+ return (0);
+}
+
+/*
+ * ex_prchars --
+ * Local routine to dump characters to the screen.
+ */
+static int
+ex_prchars(sp, p, colp, len, flags, repeatc)
+ SCR *sp;
+ const char *p;
+ size_t *colp, len;
+ u_int flags;
+ int repeatc;
+{
+ CHAR_T ch, *kp;
+ GS *gp;
+ size_t col, tlen, ts;
+
+ if (O_ISSET(sp, O_LIST))
+ LF_SET(E_C_LIST);
+ gp = sp->gp;
+ ts = O_VAL(sp, O_TABSTOP);
+ for (col = *colp; len--;)
+ if ((ch = *p++) == '\t' && !LF_ISSET(E_C_LIST))
+ for (tlen = ts - col % ts;
+ col < sp->cols && tlen--; ++col) {
+ (void)ex_printf(sp,
+ "%c", repeatc ? repeatc : ' ');
+ if (INTERRUPTED(sp))
+ goto intr;
+ }
+ else {
+ kp = KEY_NAME(sp, ch);
+ tlen = KEY_LEN(sp, ch);
+ if (!repeatc && col + tlen < sp->cols) {
+ (void)ex_puts(sp, kp);
+ col += tlen;
+ } else
+ for (; tlen--; ++kp, ++col) {
+ if (col == sp->cols) {
+ col = 0;
+ (void)ex_puts(sp, "\n");
+ }
+ (void)ex_printf(sp,
+ "%c", repeatc ? repeatc : *kp);
+ if (INTERRUPTED(sp))
+ goto intr;
+ }
+ }
+intr: *colp = col;
+ return (0);
+}
+
+/*
+ * ex_printf --
+ * Ex's version of printf.
+ *
+ * PUBLIC: int ex_printf __P((SCR *, const char *, ...));
+ */
+int
+#ifdef __STDC__
+ex_printf(SCR *sp, const char *fmt, ...)
+#else
+ex_printf(sp, fmt, va_alist)
+ SCR *sp;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ EX_PRIVATE *exp;
+ va_list ap;
+ size_t n;
+
+ exp = EXP(sp);
+
+#ifdef __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ exp->obp_len += n = vsnprintf(exp->obp + exp->obp_len,
+ sizeof(exp->obp) - exp->obp_len, fmt, ap);
+ va_end(ap);
+
+ /* Flush when reach a <newline> or half the buffer. */
+ if (exp->obp[exp->obp_len - 1] == '\n' ||
+ exp->obp_len > sizeof(exp->obp) / 2)
+ (void)ex_fflush(sp);
+ return (n);
+}
+
+/*
+ * ex_puts --
+ * Ex's version of puts.
+ *
+ * PUBLIC: int ex_puts __P((SCR *, const char *));
+ */
+int
+ex_puts(sp, str)
+ SCR *sp;
+ const char *str;
+{
+ EX_PRIVATE *exp;
+ int doflush, n;
+
+ exp = EXP(sp);
+
+ /* Flush when reach a <newline> or the end of the buffer. */
+ for (doflush = n = 0; *str != '\0'; ++n) {
+ if (exp->obp_len > sizeof(exp->obp))
+ (void)ex_fflush(sp);
+ if ((exp->obp[exp->obp_len++] = *str++) == '\n')
+ doflush = 1;
+ }
+ if (doflush)
+ (void)ex_fflush(sp);
+ return (n);
+}
+
+/*
+ * ex_fflush --
+ * Ex's version of fflush.
+ *
+ * PUBLIC: int ex_fflush __P((SCR *sp));
+ */
+int
+ex_fflush(sp)
+ SCR *sp;
+{
+ EX_PRIVATE *exp;
+
+ exp = EXP(sp);
+
+ if (exp->obp_len != 0) {
+ sp->gp->scr_msg(sp, M_NONE, exp->obp, exp->obp_len);
+ exp->obp_len = 0;
+ }
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_put.c b/contrib/nvi/ex/ex_put.c
new file mode 100644
index 000000000000..2facb03f0fb5
--- /dev/null
+++ b/contrib/nvi/ex/ex_put.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_put.c 10.7 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_put -- [line] pu[t] [buffer]
+ * Append a cut buffer into the file.
+ *
+ * PUBLIC: int ex_put __P((SCR *, EXCMD *));
+ */
+int
+ex_put(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ MARK m;
+
+ NEEDFILE(sp, cmdp);
+
+ m.lno = sp->lno;
+ m.cno = sp->cno;
+ if (put(sp, NULL,
+ FL_ISSET(cmdp->iflags, E_C_BUFFER) ? &cmdp->buffer : NULL,
+ &cmdp->addr1, &m, 1))
+ return (1);
+ sp->lno = m.lno;
+ sp->cno = m.cno;
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_quit.c b/contrib/nvi/ex/ex_quit.c
new file mode 100644
index 000000000000..705fa1a64ade
--- /dev/null
+++ b/contrib/nvi/ex/ex_quit.c
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_quit.c 10.7 (Berkeley) 4/27/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_quit -- :quit[!]
+ * Quit.
+ *
+ * PUBLIC: int ex_quit __P((SCR *, EXCMD *));
+ */
+int
+ex_quit(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ int force;
+
+ force = FL_ISSET(cmdp->iflags, E_C_FORCE);
+
+ /* Check for file modifications, or more files to edit. */
+ if (file_m2(sp, force) || ex_ncheck(sp, force))
+ return (1);
+
+ F_SET(sp, force ? SC_EXIT_FORCE : SC_EXIT);
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_read.c b/contrib/nvi/ex/ex_read.c
new file mode 100644
index 000000000000..78296ff28ca6
--- /dev/null
+++ b/contrib/nvi/ex/ex_read.c
@@ -0,0 +1,360 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_read.c 10.38 (Berkeley) 8/12/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+/*
+ * ex_read -- :read [file]
+ * :read [!cmd]
+ * Read from a file or utility.
+ *
+ * !!!
+ * Historical vi wouldn't undo a filter read, for no apparent reason.
+ *
+ * PUBLIC: int ex_read __P((SCR *, EXCMD *));
+ */
+int
+ex_read(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ enum { R_ARG, R_EXPANDARG, R_FILTER } which;
+ struct stat sb;
+ CHAR_T *arg, *name;
+ EX_PRIVATE *exp;
+ FILE *fp;
+ FREF *frp;
+ GS *gp;
+ MARK rm;
+ recno_t nlines;
+ size_t arglen;
+ int argc, rval;
+ char *p;
+
+ gp = sp->gp;
+
+ /*
+ * 0 args: read the current pathname.
+ * 1 args: check for "read !arg".
+ */
+ switch (cmdp->argc) {
+ case 0:
+ which = R_ARG;
+ break;
+ case 1:
+ arg = cmdp->argv[0]->bp;
+ arglen = cmdp->argv[0]->len;
+ if (*arg == '!') {
+ ++arg;
+ --arglen;
+ which = R_FILTER;
+
+ /* Secure means no shell access. */
+ if (O_ISSET(sp, O_SECURE)) {
+ ex_emsg(sp, cmdp->cmd->name, EXM_SECURE_F);
+ return (1);
+ }
+ } else
+ which = R_EXPANDARG;
+ break;
+ default:
+ abort();
+ /* NOTREACHED */
+ }
+
+ /* Load a temporary file if no file being edited. */
+ if (sp->ep == NULL) {
+ if ((frp = file_add(sp, NULL)) == NULL)
+ return (1);
+ if (file_init(sp, frp, NULL, 0))
+ return (1);
+ }
+
+ switch (which) {
+ case R_FILTER:
+ /*
+ * File name and bang expand the user's argument. If
+ * we don't get an additional argument, it's illegal.
+ */
+ argc = cmdp->argc;
+ if (argv_exp1(sp, cmdp, arg, arglen, 1))
+ return (1);
+ if (argc == cmdp->argc) {
+ ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+ return (1);
+ }
+ argc = cmdp->argc - 1;
+
+ /* Set the last bang command. */
+ exp = EXP(sp);
+ if (exp->lastbcomm != NULL)
+ free(exp->lastbcomm);
+ if ((exp->lastbcomm =
+ strdup(cmdp->argv[argc]->bp)) == NULL) {
+ msgq(sp, M_SYSERR, NULL);
+ return (1);
+ }
+
+ /*
+ * Vi redisplayed the user's argument if it changed, ex
+ * always displayed a !, plus the user's argument if it
+ * changed.
+ */
+ if (F_ISSET(sp, SC_VI)) {
+ if (F_ISSET(cmdp, E_MODIFY))
+ (void)vs_update(sp, "!", cmdp->argv[argc]->bp);
+ } else {
+ if (F_ISSET(cmdp, E_MODIFY))
+ (void)ex_printf(sp,
+ "!%s\n", cmdp->argv[argc]->bp);
+ else
+ (void)ex_puts(sp, "!\n");
+ (void)ex_fflush(sp);
+ }
+
+ /*
+ * Historically, filter reads as the first ex command didn't
+ * wait for the user. If SC_SCR_EXWROTE not already set, set
+ * the don't-wait flag.
+ */
+ if (!F_ISSET(sp, SC_SCR_EXWROTE))
+ F_SET(sp, SC_EX_WAIT_NO);
+
+ /*
+ * Switch into ex canonical mode. The reason to restore the
+ * original terminal modes for read filters is so that users
+ * can do things like ":r! cat /dev/tty".
+ *
+ * !!!
+ * We do not output an extra <newline>, so that we don't touch
+ * the screen on a normal read.
+ */
+ if (F_ISSET(sp, SC_VI)) {
+ if (gp->scr_screen(sp, SC_EX)) {
+ ex_emsg(sp, cmdp->cmd->name, EXM_NOCANON_F);
+ return (1);
+ }
+ /*
+ * !!!
+ * Historically, the read command doesn't switch to
+ * the alternate X11 xterm screen, if doing a filter
+ * read -- don't set SA_ALTERNATE.
+ */
+ F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
+ }
+
+ if (ex_filter(sp, cmdp, &cmdp->addr1,
+ NULL, &rm, cmdp->argv[argc]->bp, FILTER_READ))
+ return (1);
+
+ /* The filter version of read set the autoprint flag. */
+ F_SET(cmdp, E_AUTOPRINT);
+
+ /*
+ * If in vi mode, move to the first nonblank. Might have
+ * switched into ex mode, so saved the original SC_VI value.
+ */
+ sp->lno = rm.lno;
+ if (F_ISSET(sp, SC_VI)) {
+ sp->cno = 0;
+ (void)nonblank(sp, sp->lno, &sp->cno);
+ }
+ return (0);
+ case R_ARG:
+ name = sp->frp->name;
+ break;
+ case R_EXPANDARG:
+ if (argv_exp2(sp, cmdp, arg, arglen))
+ return (1);
+ /*
+ * 0 args: impossible.
+ * 1 args: impossible (I hope).
+ * 2 args: read it.
+ * >2 args: object, too many args.
+ *
+ * The 1 args case depends on the argv_sexp() function refusing
+ * to return success without at least one non-blank character.
+ */
+ switch (cmdp->argc) {
+ case 0:
+ case 1:
+ abort();
+ /* NOTREACHED */
+ case 2:
+ name = cmdp->argv[1]->bp;
+ /*
+ * !!!
+ * Historically, the read and write commands renamed
+ * "unnamed" files, or, if the file had a name, set
+ * the alternate file name.
+ */
+ if (F_ISSET(sp->frp, FR_TMPFILE) &&
+ !F_ISSET(sp->frp, FR_EXNAMED)) {
+ if ((p = v_strdup(sp, cmdp->argv[1]->bp,
+ cmdp->argv[1]->len)) != NULL) {
+ free(sp->frp->name);
+ sp->frp->name = p;
+ }
+ /*
+ * The file has a real name, it's no longer a
+ * temporary, clear the temporary file flags.
+ */
+ F_CLR(sp->frp, FR_TMPEXIT | FR_TMPFILE);
+ F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED);
+
+ /* Notify the screen. */
+ (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+ } else
+ set_alt_name(sp, name);
+ break;
+ default:
+ ex_emsg(sp, cmdp->argv[0]->bp, EXM_FILECOUNT);
+ return (1);
+
+ }
+ break;
+ }
+
+ /*
+ * !!!
+ * Historically, vi did not permit reads from non-regular files, nor
+ * did it distinguish between "read !" and "read!", so there was no
+ * way to "force" it. We permit reading from named pipes too, since
+ * they didn't exist when the original implementation of vi was done
+ * and they seem a reasonable addition.
+ */
+ if ((fp = fopen(name, "r")) == NULL || fstat(fileno(fp), &sb)) {
+ msgq_str(sp, M_SYSERR, name, "%s");
+ return (1);
+ }
+ if (!S_ISFIFO(sb.st_mode) && !S_ISREG(sb.st_mode)) {
+ (void)fclose(fp);
+ msgq(sp, M_ERR,
+ "145|Only regular files and named pipes may be read");
+ return (1);
+ }
+
+ /* Try and get a lock. */
+ if (file_lock(sp, NULL, NULL, fileno(fp), 0) == LOCK_UNAVAIL)
+ msgq(sp, M_ERR, "146|%s: read lock was unavailable", name);
+
+ rval = ex_readfp(sp, name, fp, &cmdp->addr1, &nlines, 0);
+
+ /*
+ * In vi, set the cursor to the first line read in, if anything read
+ * in, otherwise, the address. (Historic vi set it to the line after
+ * the address regardless, but since that line may not exist we don't
+ * bother.)
+ *
+ * In ex, set the cursor to the last line read in, if anything read in,
+ * otherwise, the address.
+ */
+ if (F_ISSET(sp, SC_VI)) {
+ sp->lno = cmdp->addr1.lno;
+ if (nlines)
+ ++sp->lno;
+ } else
+ sp->lno = cmdp->addr1.lno + nlines;
+ return (rval);
+}
+
+/*
+ * ex_readfp --
+ * Read lines into the file.
+ *
+ * PUBLIC: int ex_readfp __P((SCR *, char *, FILE *, MARK *, recno_t *, int));
+ */
+int
+ex_readfp(sp, name, fp, fm, nlinesp, silent)
+ SCR *sp;
+ char *name;
+ FILE *fp;
+ MARK *fm;
+ recno_t *nlinesp;
+ int silent;
+{
+ EX_PRIVATE *exp;
+ GS *gp;
+ recno_t lcnt, lno;
+ size_t len;
+ u_long ccnt; /* XXX: can't print off_t portably. */
+ int nf, rval;
+ char *p;
+
+ gp = sp->gp;
+ exp = EXP(sp);
+
+ /*
+ * Add in the lines from the output. Insertion starts at the line
+ * following the address.
+ */
+ ccnt = 0;
+ lcnt = 0;
+ p = "147|Reading...";
+ for (lno = fm->lno; !ex_getline(sp, fp, &len); ++lno, ++lcnt) {
+ if ((lcnt + 1) % INTERRUPT_CHECK == 0) {
+ if (INTERRUPTED(sp))
+ break;
+ if (!silent) {
+ gp->scr_busy(sp, p,
+ p == NULL ? BUSY_UPDATE : BUSY_ON);
+ p = NULL;
+ }
+ }
+ if (db_append(sp, 1, lno, exp->ibp, len))
+ goto err;
+ ccnt += len;
+ }
+
+ if (ferror(fp) || fclose(fp))
+ goto err;
+
+ /* Return the number of lines read in. */
+ if (nlinesp != NULL)
+ *nlinesp = lcnt;
+
+ if (!silent) {
+ p = msg_print(sp, name, &nf);
+ msgq(sp, M_INFO,
+ "148|%s: %lu lines, %lu characters", p, lcnt, ccnt);
+ if (nf)
+ FREE_SPACE(sp, p, 0);
+ }
+
+ rval = 0;
+ if (0) {
+err: msgq_str(sp, M_SYSERR, name, "%s");
+ (void)fclose(fp);
+ rval = 1;
+ }
+
+ if (!silent)
+ gp->scr_busy(sp, NULL, BUSY_OFF);
+ return (rval);
+}
diff --git a/contrib/nvi/ex/ex_screen.c b/contrib/nvi/ex/ex_screen.c
new file mode 100644
index 000000000000..9bc5bf04b06a
--- /dev/null
+++ b/contrib/nvi/ex/ex_screen.c
@@ -0,0 +1,138 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_screen.c 10.11 (Berkeley) 6/29/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+/*
+ * ex_bg -- :bg
+ * Hide the screen.
+ *
+ * PUBLIC: int ex_bg __P((SCR *, EXCMD *));
+ */
+int
+ex_bg(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ return (vs_bg(sp));
+}
+
+/*
+ * ex_fg -- :fg [file]
+ * Show the screen.
+ *
+ * PUBLIC: int ex_fg __P((SCR *, EXCMD *));
+ */
+int
+ex_fg(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ SCR *nsp;
+ int newscreen;
+
+ newscreen = F_ISSET(cmdp, E_NEWSCREEN);
+ if (vs_fg(sp, &nsp, cmdp->argc ? cmdp->argv[0]->bp : NULL, newscreen))
+ return (1);
+
+ /* Set up the switch. */
+ if (newscreen) {
+ sp->nextdisp = nsp;
+ F_SET(sp, SC_SSWITCH);
+ }
+ return (0);
+}
+
+/*
+ * ex_resize -- :resize [+-]rows
+ * Change the screen size.
+ *
+ * PUBLIC: int ex_resize __P((SCR *, EXCMD *));
+ */
+int
+ex_resize(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ adj_t adj;
+
+ switch (FL_ISSET(cmdp->iflags,
+ E_C_COUNT | E_C_COUNT_NEG | E_C_COUNT_POS)) {
+ case E_C_COUNT:
+ adj = A_SET;
+ break;
+ case E_C_COUNT | E_C_COUNT_NEG:
+ adj = A_DECREASE;
+ break;
+ case E_C_COUNT | E_C_COUNT_POS:
+ adj = A_INCREASE;
+ break;
+ default:
+ ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+ return (1);
+ }
+ return (vs_resize(sp, cmdp->count, adj));
+}
+
+/*
+ * ex_sdisplay --
+ * Display the list of screens.
+ *
+ * PUBLIC: int ex_sdisplay __P((SCR *));
+ */
+int
+ex_sdisplay(sp)
+ SCR *sp;
+{
+ GS *gp;
+ SCR *tsp;
+ int cnt, col, len, sep;
+
+ gp = sp->gp;
+ if ((tsp = gp->hq.cqh_first) == (void *)&gp->hq) {
+ msgq(sp, M_INFO, "149|No background screens to display");
+ return (0);
+ }
+
+ col = len = sep = 0;
+ for (cnt = 1; tsp != (void *)&gp->hq && !INTERRUPTED(sp);
+ tsp = tsp->q.cqe_next) {
+ col += len = strlen(tsp->frp->name) + sep;
+ if (col >= sp->cols - 1) {
+ col = len;
+ sep = 0;
+ (void)ex_puts(sp, "\n");
+ } else if (cnt != 1) {
+ sep = 1;
+ (void)ex_puts(sp, " ");
+ }
+ (void)ex_puts(sp, tsp->frp->name);
+ ++cnt;
+ }
+ if (!INTERRUPTED(sp))
+ (void)ex_puts(sp, "\n");
+ return (0);
+}
diff --git a/usr.bin/vi/ex/ex_script.c b/contrib/nvi/ex/ex_script.c
index 59586f1e1765..9ca6d60060d9 100644
--- a/usr.bin/vi/ex/ex_script.c
+++ b/contrib/nvi/ex/ex_script.c
@@ -1,103 +1,82 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * This code is derived from software contributed to Berkeley by
+ * Brian Hirt.
*
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)ex_script.c 8.17 (Berkeley) 7/23/94";
+static const char sccsid[] = "@(#)ex_script.c 10.30 (Berkeley) 9/24/96";
#endif /* not lint */
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/queue.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <sys/stat.h>
+#ifdef HAVE_SYS5_PTY
+#include <sys/stropts.h>
+#endif
#include <sys/time.h>
#include <sys/wait.h>
#include <bitstring.h>
#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h> /* XXX: OSF/1 bug: include before <grp.h> */
+#include <grp.h>
#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
+#include "../common/common.h"
+#include "../vi/vi.h"
#include "script.h"
+#include "pathnames.h"
-/*
- * XXX
- */
-int openpty __P((int *, int *, char *, struct termios *, struct winsize *));
-
-static int sscr_getprompt __P((SCR *, EXF *));
-static int sscr_init __P((SCR *, EXF *));
-static int sscr_matchprompt __P((SCR *, char *, size_t, size_t *));
-static int sscr_setprompt __P((SCR *, char *, size_t));
+static void sscr_check __P((SCR *));
+static int sscr_getprompt __P((SCR *));
+static int sscr_init __P((SCR *));
+static int sscr_insert __P((SCR *));
+static int sscr_matchprompt __P((SCR *, char *, size_t, size_t *));
+static int sscr_pty __P((int *, int *, char *, struct termios *, void *));
+static int sscr_setprompt __P((SCR *, char *, size_t));
/*
* ex_script -- : sc[ript][!] [file]
- *
* Switch to script mode.
+ *
+ * PUBLIC: int ex_script __P((SCR *, EXCMD *));
*/
int
-ex_script(sp, ep, cmdp)
+ex_script(sp, cmdp)
SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+ EXCMD *cmdp;
{
/* Vi only command. */
- if (!IN_VI_MODE(sp)) {
+ if (!F_ISSET(sp, SC_VI)) {
msgq(sp, M_ERR,
- "The script command is only available in vi mode");
+ "150|The script command is only available in vi mode");
return (1);
}
/* Switch to the new file. */
- if (cmdp->argc != 0 && ex_edit(sp, ep, cmdp))
+ if (cmdp->argc != 0 && ex_edit(sp, cmdp))
return (1);
- /*
- * Create the shell, figure out the prompt.
- *
- * !!!
- * The files just switched, use sp->ep.
- */
- if (sscr_init(sp, sp->ep))
+ /* Create the shell, figure out the prompt. */
+ if (sscr_init(sp))
return (1);
return (0);
@@ -108,13 +87,16 @@ ex_script(sp, ep, cmdp)
* Create a pty setup for a shell.
*/
static int
-sscr_init(sp, ep)
+sscr_init(sp)
SCR *sp;
- EXF *ep;
{
SCRIPT *sc;
char *sh, *sh_path;
+ /* We're going to need a shell. */
+ if (opts_empty(sp, O_SHELL, 0))
+ return (1);
+
MALLOC_RET(sp, sc, SCRIPT *, sizeof(SCRIPT));
sp->script = sc;
sc->sh_prompt = NULL;
@@ -137,26 +119,32 @@ sscr_init(sp, ep)
sc->sh_term.c_oflag &= ~OPOST;
sc->sh_term.c_cflag &= ~(ECHO|ECHOE|ECHONL|ECHOK);
+#ifdef TIOCGWINSZ
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &sc->sh_win) == -1) {
msgq(sp, M_SYSERR, "tcgetattr");
goto err;
}
- if (openpty(&sc->sh_master,
+ if (sscr_pty(&sc->sh_master,
&sc->sh_slave, sc->sh_name, &sc->sh_term, &sc->sh_win) == -1) {
- msgq(sp, M_SYSERR, "openpty");
+ msgq(sp, M_SYSERR, "pty");
goto err;
}
+#else
+ if (sscr_pty(&sc->sh_master,
+ &sc->sh_slave, sc->sh_name, &sc->sh_term, NULL) == -1) {
+ msgq(sp, M_SYSERR, "pty");
+ goto err;
+ }
+#endif
/*
+ * __TK__ huh?
* Don't use vfork() here, because the signal semantics differ from
* implementation to implementation.
*/
- SIGBLOCK(sp->gp);
switch (sc->sh_pid = fork()) {
case -1: /* Error. */
- SIGUNBLOCK(sp->gp);
-
msgq(sp, M_SYSERR, "fork");
err: if (sc->sh_master != -1)
(void)close(sc->sh_master);
@@ -164,16 +152,13 @@ err: if (sc->sh_master != -1)
(void)close(sc->sh_slave);
return (1);
case 0: /* Utility. */
- /* The utility has default signal behavior. */
- sig_end();
-
/*
* XXX
* So that shells that do command line editing turn it off.
*/
- (void)putenv("TERM=emacs");
- (void)putenv("TERMCAP=emacs:");
- (void)putenv("EMACS=t");
+ (void)setenv("TERM", "emacs", 1);
+ (void)setenv("TERMCAP", "emacs:", 1);
+ (void)setenv("EMACS", "t", 1);
(void)setsid();
#ifdef TIOCSCTTY
@@ -198,20 +183,18 @@ err: if (sc->sh_master != -1)
else
++sh;
execl(sh_path, sh, "-i", NULL);
- msgq(sp, M_ERR,
- "Error: execl: %s: %s", sh_path, strerror(errno));
+ msgq_str(sp, M_SYSERR, sh_path, "execl: %s");
_exit(127);
default: /* Parent. */
- SIGUNBLOCK(sp->gp);
break;
}
- if (sscr_getprompt(sp, ep))
+ if (sscr_getprompt(sp))
return (1);
- F_SET(sp, S_REDRAW | S_SCRIPT);
+ F_SET(sp, SC_SCRIPT);
+ F_SET(sp->gp, G_SCRWIN);
return (0);
-
}
/*
@@ -220,9 +203,8 @@ err: if (sc->sh_master != -1)
* carriage return comes; set the prompt from that line.
*/
static int
-sscr_getprompt(sp, ep)
+sscr_getprompt(sp)
SCR *sp;
- EXF *ep;
{
struct timeval tv;
CHAR_T *endp, *p, *t, buf[1024];
@@ -271,8 +253,8 @@ more: len = sizeof(buf) - (endp - buf);
for (p = t = buf; p < endp; ++p) {
value = KEY_VAL(sp, *p);
if (value == K_CR || value == K_NL) {
- if (file_lline(sp, ep, &lline) ||
- file_aline(sp, ep, 0, lline, t, p - t))
+ if (db_last(sp, &lline) ||
+ db_append(sp, 0, lline, t, p - t))
goto prompterr;
t = p + 1;
}
@@ -302,8 +284,7 @@ more: len = sizeof(buf) - (endp - buf);
endp = buf;
/* Append the line into the file. */
- if (file_lline(sp, ep, &lline) ||
- file_aline(sp, ep, 0, lline, buf, llen)) {
+ if (db_last(sp, &lline) || db_append(sp, 0, lline, buf, llen)) {
prompterr: sscr_end(sp);
return (1);
}
@@ -314,26 +295,25 @@ prompterr: sscr_end(sp);
/*
* sscr_exec --
* Take a line and hand it off to the shell.
+ *
+ * PUBLIC: int sscr_exec __P((SCR *, recno_t));
*/
int
-sscr_exec(sp, ep, lno)
+sscr_exec(sp, lno)
SCR *sp;
- EXF *ep;
recno_t lno;
{
SCRIPT *sc;
recno_t last_lno;
size_t blen, len, last_len, tlen;
- int matchprompt, nw, rval;
+ int isempty, matchprompt, nw, rval;
char *bp, *p;
/* If there's a prompt on the last line, append the command. */
- if (file_lline(sp, ep, &last_lno))
+ if (db_last(sp, &last_lno))
return (1);
- if ((p = file_gline(sp, ep, last_lno, &last_len)) == NULL) {
- GETLINE_ERR(sp, last_lno);
+ if (db_get(sp, last_lno, DBG_FATAL, &p, &last_len))
return (1);
- }
if (sscr_matchprompt(sp, p, last_len, &tlen) && tlen == 0) {
matchprompt = 1;
GET_SPACE_RET(sp, bp, blen, last_len + 128);
@@ -342,13 +322,9 @@ sscr_exec(sp, ep, lno)
matchprompt = 0;
/* Get something to execute. */
- if ((p = file_gline(sp, ep, lno, &len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- goto err1;
- if (lno == 0)
+ if (db_eget(sp, lno, &p, &len, &isempty)) {
+ if (isempty)
goto empty;
- else
- GETLINE_ERR(sp, lno);
goto err1;
}
@@ -359,7 +335,7 @@ sscr_exec(sp, ep, lno)
/* Delete any prompt. */
if (sscr_matchprompt(sp, p, len, &tlen)) {
if (tlen == len) {
-empty: msgq(sp, M_BERR, "Nothing to execute");
+empty: msgq(sp, M_BERR, "151|No command to execute");
goto err1;
}
p += (len - tlen);
@@ -381,7 +357,7 @@ err2: if (nw == 0)
if (matchprompt) {
ADD_SPACE_RET(sp, bp, blen, last_len + len);
memmove(bp + last_len, p, len);
- if (file_sline(sp, ep, last_lno, bp, last_len + len))
+ if (db_set(sp, last_lno, bp, last_len + len))
err1: rval = 1;
}
if (matchprompt)
@@ -391,16 +367,65 @@ err1: rval = 1;
/*
* sscr_input --
- * Take a line from the shell and insert it into the file.
+ * Read any waiting shell input.
+ *
+ * PUBLIC: int sscr_input __P((SCR *));
*/
int
sscr_input(sp)
SCR *sp;
{
+ GS *gp;
+ struct timeval poll;
+ fd_set rdfd;
+ int maxfd;
+
+ gp = sp->gp;
+
+loop: maxfd = 0;
+ FD_ZERO(&rdfd);
+ poll.tv_sec = 0;
+ poll.tv_usec = 0;
+
+ /* Set up the input mask. */
+ for (sp = gp->dq.cqh_first; sp != (void *)&gp->dq; sp = sp->q.cqe_next)
+ if (F_ISSET(sp, SC_SCRIPT)) {
+ FD_SET(sp->script->sh_master, &rdfd);
+ if (sp->script->sh_master > maxfd)
+ maxfd = sp->script->sh_master;
+ }
+
+ /* Check for input. */
+ switch (select(maxfd + 1, &rdfd, NULL, NULL, &poll)) {
+ case -1:
+ msgq(sp, M_SYSERR, "select");
+ return (1);
+ case 0:
+ return (0);
+ default:
+ break;
+ }
+
+ /* Read the input. */
+ for (sp = gp->dq.cqh_first; sp != (void *)&gp->dq; sp = sp->q.cqe_next)
+ if (F_ISSET(sp, SC_SCRIPT) &&
+ FD_ISSET(sp->script->sh_master, &rdfd) && sscr_insert(sp))
+ return (1);
+ goto loop;
+}
+
+/*
+ * sscr_insert --
+ * Take a line from the shell and insert it into the file.
+ */
+static int
+sscr_insert(sp)
+ SCR *sp;
+{
struct timeval tv;
CHAR_T *endp, *p, *t;
- EXF *ep;
SCRIPT *sc;
+ fd_set rdfd;
recno_t lno;
size_t blen, len, tlen;
u_int value;
@@ -408,8 +433,7 @@ sscr_input(sp)
char *bp;
/* Find out where the end of the file is. */
- ep = sp->ep;
- if (file_lline(sp, ep, &lno))
+ if (db_last(sp, &lno))
return (1);
#define MINREAD 1024
@@ -422,7 +446,6 @@ sscr_input(sp)
more: switch (nr = read(sc->sh_master, endp, MINREAD)) {
case 0: /* EOF; shell just exited. */
sscr_end(sp);
- F_CLR(sp, S_SCRIPT);
rval = 0;
goto ret;
case -1: /* Error or interrupt. */
@@ -438,7 +461,7 @@ more: switch (nr = read(sc->sh_master, endp, MINREAD)) {
value = KEY_VAL(sp, *p);
if (value == K_CR || value == K_NL) {
len = p - t;
- if (file_aline(sp, ep, 1, lno++, t, len))
+ if (db_append(sp, 1, lno++, t, len))
goto ret;
t = p + 1;
}
@@ -455,10 +478,10 @@ more: switch (nr = read(sc->sh_master, endp, MINREAD)) {
if (!sscr_matchprompt(sp, t, len, &tlen) || tlen != 0) {
tv.tv_sec = 0;
tv.tv_usec = 100000;
- FD_SET(sc->sh_master, &sp->rdfd);
- FD_CLR(STDIN_FILENO, &sp->rdfd);
+ FD_ZERO(&rdfd);
+ FD_SET(sc->sh_master, &rdfd);
if (select(sc->sh_master + 1,
- &sp->rdfd, NULL, NULL, &tv) == 1) {
+ &rdfd, NULL, NULL, &tv) == 1) {
memmove(bp, t, len);
endp = bp + len;
goto more;
@@ -466,14 +489,14 @@ more: switch (nr = read(sc->sh_master, endp, MINREAD)) {
}
if (sscr_setprompt(sp, t, len))
return (1);
- if (file_aline(sp, ep, 1, lno++, t, len))
+ if (db_append(sp, 1, lno++, t, len))
goto ret;
}
/* The cursor moves to EOF. */
sp->lno = lno;
sp->cno = len ? len - 1 : 0;
- rval = sp->s_refresh(sp, ep);
+ rval = vs_refresh(sp, 1);
ret: FREE_SPACE(sp, bp, blen);
return (rval);
@@ -488,14 +511,14 @@ ret: FREE_SPACE(sp, bp, blen);
static int
sscr_setprompt(sp, buf, len)
SCR *sp;
- char* buf;
+ char *buf;
size_t len;
{
SCRIPT *sc;
sc = sp->script;
if (sc->sh_prompt)
- FREE(sc->sh_prompt, sc->sh_prompt_len);
+ free(sc->sh_prompt);
MALLOC(sp, sc->sh_prompt, char *, len + 1);
if (sc->sh_prompt == NULL) {
sscr_end(sp);
@@ -550,19 +573,21 @@ sscr_matchprompt(sp, lp, line_len, lenp)
/*
* sscr_end --
* End the pipe to a shell.
+ *
+ * PUBLIC: int sscr_end __P((SCR *));
*/
int
sscr_end(sp)
SCR *sp;
{
SCRIPT *sc;
- int rval;
if ((sc = sp->script) == NULL)
return (0);
- /* Turn off the script flag. */
- F_CLR(sp, S_SCRIPT);
+ /* Turn off the script flags. */
+ F_CLR(sp, SC_SCRIPT);
+ sscr_check(sp);
/* Close down the parent's file descriptors. */
if (sc->sh_master != -1)
@@ -571,12 +596,203 @@ sscr_end(sp)
(void)close(sc->sh_slave);
/* This should have killed the child. */
- rval = proc_wait(sp, (long)sc->sh_pid, "script-shell", 0);
+ (void)proc_wait(sp, (long)sc->sh_pid, "script-shell", 0, 0);
/* Free memory. */
- FREE(sc->sh_prompt, sc->sh_prompt_len);
- FREE(sc, sizeof(SCRIPT));
+ free(sc->sh_prompt);
+ free(sc);
sp->script = NULL;
- return (rval);
+ return (0);
+}
+
+/*
+ * sscr_check --
+ * Set/clear the global scripting bit.
+ */
+static void
+sscr_check(sp)
+ SCR *sp;
+{
+ GS *gp;
+
+ gp = sp->gp;
+ for (sp = gp->dq.cqh_first; sp != (void *)&gp->dq; sp = sp->q.cqe_next)
+ if (F_ISSET(sp, SC_SCRIPT)) {
+ F_SET(gp, G_SCRWIN);
+ return;
+ }
+ F_CLR(gp, G_SCRWIN);
+}
+
+#ifdef HAVE_SYS5_PTY
+static int ptys_open __P((int, char *));
+static int ptym_open __P((char *));
+
+static int
+sscr_pty(amaster, aslave, name, termp, winp)
+ int *amaster, *aslave;
+ char *name;
+ struct termios *termp;
+ void *winp;
+{
+ int master, slave, ttygid;
+
+ /* open master terminal */
+ if ((master = ptym_open(name)) < 0) {
+ errno = ENOENT; /* out of ptys */
+ return (-1);
+ }
+
+ /* open slave terminal */
+ if ((slave = ptys_open(master, name)) >= 0) {
+ *amaster = master;
+ *aslave = slave;
+ } else {
+ errno = ENOENT; /* out of ptys */
+ return (-1);
+ }
+
+ if (termp)
+ (void) tcsetattr(slave, TCSAFLUSH, termp);
+#ifdef TIOCSWINSZ
+ if (winp != NULL)
+ (void) ioctl(slave, TIOCSWINSZ, (struct winsize *)winp);
+#endif
+ return (0);
+}
+
+/*
+ * ptym_open --
+ * This function opens a master pty and returns the file descriptor
+ * to it. pts_name is also returned which is the name of the slave.
+ */
+static int
+ptym_open(pts_name)
+ char *pts_name;
+{
+ int fdm;
+ char *ptr, *ptsname();
+
+ strcpy(pts_name, _PATH_SYSV_PTY);
+ if ((fdm = open(pts_name, O_RDWR)) < 0 )
+ return (-1);
+
+ if (grantpt(fdm) < 0) {
+ close(fdm);
+ return (-2);
+ }
+
+ if (unlockpt(fdm) < 0) {
+ close(fdm);
+ return (-3);
+ }
+
+ if (unlockpt(fdm) < 0) {
+ close(fdm);
+ return (-3);
+ }
+
+ /* get slave's name */
+ if ((ptr = ptsname(fdm)) == NULL) {
+ close(fdm);
+ return (-3);
+ }
+ strcpy(pts_name, ptr);
+ return (fdm);
+}
+
+/*
+ * ptys_open --
+ * This function opens the slave pty.
+ */
+static int
+ptys_open(fdm, pts_name)
+ int fdm;
+ char *pts_name;
+{
+ int fds;
+
+ if ((fds = open(pts_name, O_RDWR)) < 0) {
+ close(fdm);
+ return (-5);
+ }
+
+ if (ioctl(fds, I_PUSH, "ptem") < 0) {
+ close(fds);
+ close(fdm);
+ return (-6);
+ }
+
+ if (ioctl(fds, I_PUSH, "ldterm") < 0) {
+ close(fds);
+ close(fdm);
+ return (-7);
+ }
+
+ if (ioctl(fds, I_PUSH, "ttcompat") < 0) {
+ close(fds);
+ close(fdm);
+ return (-8);
+ }
+
+ return (fds);
+}
+
+#else /* !HAVE_SYS5_PTY */
+
+static int
+sscr_pty(amaster, aslave, name, termp, winp)
+ int *amaster, *aslave;
+ char *name;
+ struct termios *termp;
+ void *winp;
+{
+ static char line[] = "/dev/ptyXX";
+ register char *cp1, *cp2;
+ register int master, slave, ttygid;
+ struct group *gr;
+
+ if ((gr = getgrnam("tty")) != NULL)
+ ttygid = gr->gr_gid;
+ else
+ ttygid = -1;
+
+ for (cp1 = "pqrs"; *cp1; cp1++) {
+ line[8] = *cp1;
+ for (cp2 = "0123456789abcdef"; *cp2; cp2++) {
+ line[5] = 'p';
+ line[9] = *cp2;
+ if ((master = open(line, O_RDWR, 0)) == -1) {
+ if (errno == ENOENT)
+ return (-1); /* out of ptys */
+ } else {
+ line[5] = 't';
+ (void) chown(line, getuid(), ttygid);
+ (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
+#ifdef HAVE_REVOKE
+ (void) revoke(line);
+#endif
+ if ((slave = open(line, O_RDWR, 0)) != -1) {
+ *amaster = master;
+ *aslave = slave;
+ if (name)
+ strcpy(name, line);
+ if (termp)
+ (void) tcsetattr(slave,
+ TCSAFLUSH, termp);
+#ifdef TIOCSWINSZ
+ if (winp)
+ (void) ioctl(slave, TIOCSWINSZ,
+ (char *)winp);
+#endif
+ return (0);
+ }
+ (void) close(master);
+ }
+ }
+ }
+ errno = ENOENT; /* out of ptys */
+ return (-1);
}
+#endif /* HAVE_SYS5_PTY */
diff --git a/contrib/nvi/ex/ex_set.c b/contrib/nvi/ex/ex_set.c
new file mode 100644
index 000000000000..11e929764242
--- /dev/null
+++ b/contrib/nvi/ex/ex_set.c
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_set.c 10.7 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_set -- :set
+ * Ex set option.
+ *
+ * PUBLIC: int ex_set __P((SCR *, EXCMD *));
+ */
+int
+ex_set(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ switch(cmdp->argc) {
+ case 0:
+ opts_dump(sp, CHANGED_DISPLAY);
+ break;
+ default:
+ if (opts_set(sp, cmdp->argv, cmdp->cmd->usage))
+ return (1);
+ break;
+ }
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_shell.c b/contrib/nvi/ex/ex_shell.c
new file mode 100644
index 000000000000..95168033a13f
--- /dev/null
+++ b/contrib/nvi/ex/ex_shell.c
@@ -0,0 +1,378 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_shell.c 10.38 (Berkeley) 8/19/96";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/wait.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+static const char *sigmsg __P((int));
+
+/*
+ * ex_shell -- :sh[ell]
+ * Invoke the program named in the SHELL environment variable
+ * with the argument -i.
+ *
+ * PUBLIC: int ex_shell __P((SCR *, EXCMD *));
+ */
+int
+ex_shell(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ int rval;
+ char buf[MAXPATHLEN];
+
+ /* We'll need a shell. */
+ if (opts_empty(sp, O_SHELL, 0))
+ return (1);
+
+ /*
+ * XXX
+ * Assumes all shells use -i.
+ */
+ (void)snprintf(buf, sizeof(buf), "%s -i", O_STR(sp, O_SHELL));
+
+ /* Restore the window name. */
+ (void)sp->gp->scr_rename(sp, NULL, 0);
+
+ /* If we're still in a vi screen, move out explicitly. */
+ rval = ex_exec_proc(sp, cmdp, buf, NULL, !F_ISSET(sp, SC_SCR_EXWROTE));
+
+ /* Set the window name. */
+ (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+
+ /*
+ * !!!
+ * Historically, vi didn't require a continue message after the
+ * return of the shell. Match it.
+ */
+ F_SET(sp, SC_EX_WAIT_NO);
+
+ return (rval);
+}
+
+/*
+ * ex_exec_proc --
+ * Run a separate process.
+ *
+ * PUBLIC: int ex_exec_proc __P((SCR *, EXCMD *, char *, const char *, int));
+ */
+int
+ex_exec_proc(sp, cmdp, cmd, msg, need_newline)
+ SCR *sp;
+ EXCMD *cmdp;
+ char *cmd;
+ const char *msg;
+ int need_newline;
+{
+ GS *gp;
+ const char *name;
+ pid_t pid;
+
+ gp = sp->gp;
+
+ /* We'll need a shell. */
+ if (opts_empty(sp, O_SHELL, 0))
+ return (1);
+
+ /* Enter ex mode. */
+ if (F_ISSET(sp, SC_VI)) {
+ if (gp->scr_screen(sp, SC_EX)) {
+ ex_emsg(sp, cmdp->cmd->name, EXM_NOCANON);
+ return (1);
+ }
+ (void)gp->scr_attr(sp, SA_ALTERNATE, 0);
+ F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
+ }
+
+ /* Put out additional newline, message. */
+ if (need_newline)
+ (void)ex_puts(sp, "\n");
+ if (msg != NULL) {
+ (void)ex_puts(sp, msg);
+ (void)ex_puts(sp, "\n");
+ }
+ (void)ex_fflush(sp);
+
+ switch (pid = vfork()) {
+ case -1: /* Error. */
+ msgq(sp, M_SYSERR, "vfork");
+ return (1);
+ case 0: /* Utility. */
+ if ((name = strrchr(O_STR(sp, O_SHELL), '/')) == NULL)
+ name = O_STR(sp, O_SHELL);
+ else
+ ++name;
+ execl(O_STR(sp, O_SHELL), name, "-c", cmd, NULL);
+ msgq_str(sp, M_SYSERR, O_STR(sp, O_SHELL), "execl: %s");
+ _exit(127);
+ /* NOTREACHED */
+ default: /* Parent. */
+ return (proc_wait(sp, (long)pid, cmd, 0, 0));
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * proc_wait --
+ * Wait for one of the processes.
+ *
+ * !!!
+ * The pid_t type varies in size from a short to a long depending on the
+ * system. It has to be cast into something or the standard promotion
+ * rules get you. I'm using a long based on the belief that nobody is
+ * going to make it unsigned and it's unlikely to be a quad.
+ *
+ * PUBLIC: int proc_wait __P((SCR *, long, const char *, int, int));
+ */
+int
+proc_wait(sp, pid, cmd, silent, okpipe)
+ SCR *sp;
+ long pid;
+ const char *cmd;
+ int silent, okpipe;
+{
+ size_t len;
+ int nf, pstat;
+ char *p;
+
+ /* Wait for the utility, ignoring interruptions. */
+ for (;;) {
+ errno = 0;
+ if (waitpid((pid_t)pid, &pstat, 0) != -1)
+ break;
+ if (errno != EINTR) {
+ msgq(sp, M_SYSERR, "waitpid");
+ return (1);
+ }
+ }
+
+ /*
+ * Display the utility's exit status. Ignore SIGPIPE from the
+ * parent-writer, as that only means that the utility chose to
+ * exit before reading all of its input.
+ */
+ if (WIFSIGNALED(pstat) && (!okpipe || WTERMSIG(pstat) != SIGPIPE)) {
+ for (; isblank(*cmd); ++cmd);
+ p = msg_print(sp, cmd, &nf);
+ len = strlen(p);
+ msgq(sp, M_ERR, "%.*s%s: received signal: %s%s",
+ MIN(len, 20), p, len > 20 ? " ..." : "",
+ sigmsg(WTERMSIG(pstat)),
+ WCOREDUMP(pstat) ? "; core dumped" : "");
+ if (nf)
+ FREE_SPACE(sp, p, 0);
+ return (1);
+ }
+
+ if (WIFEXITED(pstat) && WEXITSTATUS(pstat)) {
+ /*
+ * Remain silent for "normal" errors when doing shell file
+ * name expansions, they almost certainly indicate nothing
+ * more than a failure to match.
+ *
+ * Remain silent for vi read filter errors. It's historic
+ * practice.
+ */
+ if (!silent) {
+ for (; isblank(*cmd); ++cmd);
+ p = msg_print(sp, cmd, &nf);
+ len = strlen(p);
+ msgq(sp, M_ERR, "%.*s%s: exited with status %d",
+ MIN(len, 20), p, len > 20 ? " ..." : "",
+ WEXITSTATUS(pstat));
+ if (nf)
+ FREE_SPACE(sp, p, 0);
+ }
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * XXX
+ * The sys_siglist[] table in the C library has this information, but there's
+ * no portable way to get to it. (Believe me, I tried.)
+ */
+typedef struct _sigs {
+ int number; /* signal number */
+ char *message; /* related message */
+} SIGS;
+
+SIGS const sigs[] = {
+#ifdef SIGABRT
+ SIGABRT, "Abort trap",
+#endif
+#ifdef SIGALRM
+ SIGALRM, "Alarm clock",
+#endif
+#ifdef SIGBUS
+ SIGBUS, "Bus error",
+#endif
+#ifdef SIGCLD
+ SIGCLD, "Child exited or stopped",
+#endif
+#ifdef SIGCHLD
+ SIGCHLD, "Child exited",
+#endif
+#ifdef SIGCONT
+ SIGCONT, "Continued",
+#endif
+#ifdef SIGDANGER
+ SIGDANGER, "System crash imminent",
+#endif
+#ifdef SIGEMT
+ SIGEMT, "EMT trap",
+#endif
+#ifdef SIGFPE
+ SIGFPE, "Floating point exception",
+#endif
+#ifdef SIGGRANT
+ SIGGRANT, "HFT monitor mode granted",
+#endif
+#ifdef SIGHUP
+ SIGHUP, "Hangup",
+#endif
+#ifdef SIGILL
+ SIGILL, "Illegal instruction",
+#endif
+#ifdef SIGINFO
+ SIGINFO, "Information request",
+#endif
+#ifdef SIGINT
+ SIGINT, "Interrupt",
+#endif
+#ifdef SIGIO
+ SIGIO, "I/O possible",
+#endif
+#ifdef SIGIOT
+ SIGIOT, "IOT trap",
+#endif
+#ifdef SIGKILL
+ SIGKILL, "Killed",
+#endif
+#ifdef SIGLOST
+ SIGLOST, "Record lock",
+#endif
+#ifdef SIGMIGRATE
+ SIGMIGRATE, "Migrate process to another CPU",
+#endif
+#ifdef SIGMSG
+ SIGMSG, "HFT input data pending",
+#endif
+#ifdef SIGPIPE
+ SIGPIPE, "Broken pipe",
+#endif
+#ifdef SIGPOLL
+ SIGPOLL, "I/O possible",
+#endif
+#ifdef SIGPRE
+ SIGPRE, "Programming error",
+#endif
+#ifdef SIGPROF
+ SIGPROF, "Profiling timer expired",
+#endif
+#ifdef SIGPWR
+ SIGPWR, "Power failure imminent",
+#endif
+#ifdef SIGRETRACT
+ SIGRETRACT, "HFT monitor mode retracted",
+#endif
+#ifdef SIGQUIT
+ SIGQUIT, "Quit",
+#endif
+#ifdef SIGSAK
+ SIGSAK, "Secure Attention Key",
+#endif
+#ifdef SIGSEGV
+ SIGSEGV, "Segmentation fault",
+#endif
+#ifdef SIGSOUND
+ SIGSOUND, "HFT sound sequence completed",
+#endif
+#ifdef SIGSTOP
+ SIGSTOP, "Suspended (signal)",
+#endif
+#ifdef SIGSYS
+ SIGSYS, "Bad system call",
+#endif
+#ifdef SIGTERM
+ SIGTERM, "Terminated",
+#endif
+#ifdef SIGTRAP
+ SIGTRAP, "Trace/BPT trap",
+#endif
+#ifdef SIGTSTP
+ SIGTSTP, "Suspended",
+#endif
+#ifdef SIGTTIN
+ SIGTTIN, "Stopped (tty input)",
+#endif
+#ifdef SIGTTOU
+ SIGTTOU, "Stopped (tty output)",
+#endif
+#ifdef SIGURG
+ SIGURG, "Urgent I/O condition",
+#endif
+#ifdef SIGUSR1
+ SIGUSR1, "User defined signal 1",
+#endif
+#ifdef SIGUSR2
+ SIGUSR2, "User defined signal 2",
+#endif
+#ifdef SIGVTALRM
+ SIGVTALRM, "Virtual timer expired",
+#endif
+#ifdef SIGWINCH
+ SIGWINCH, "Window size changes",
+#endif
+#ifdef SIGXCPU
+ SIGXCPU, "Cputime limit exceeded",
+#endif
+#ifdef SIGXFSZ
+ SIGXFSZ, "Filesize limit exceeded",
+#endif
+};
+
+/*
+ * sigmsg --
+ * Return a pointer to a message describing a signal.
+ */
+static const char *
+sigmsg(signo)
+ int signo;
+{
+ static char buf[40];
+ const SIGS *sigp;
+ int n;
+
+ for (n = 0,
+ sigp = &sigs[0]; n < sizeof(sigs) / sizeof(sigs[0]); ++n, ++sigp)
+ if (sigp->number == signo)
+ return (sigp->message);
+ (void)snprintf(buf, sizeof(buf), "Unknown signal: %d", signo);
+ return (buf);
+}
diff --git a/usr.bin/vi/ex/ex_shift.c b/contrib/nvi/ex/ex_shift.c
index 41cb557d7c58..83bd36d12a7d 100644
--- a/usr.bin/vi/ex/ex_shift.c
+++ b/contrib/nvi/ex/ex_shift.c
@@ -1,85 +1,67 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)ex_shift.c 8.14 (Berkeley) 3/14/94";
+static const char sccsid[] = "@(#)ex_shift.c 10.11 (Berkeley) 9/15/96";
#endif /* not lint */
#include <sys/types.h>
#include <sys/queue.h>
-#include <sys/time.h>
#include <bitstring.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-#include "vi.h"
-#include "excmd.h"
+#include "../common/common.h"
enum which {LEFT, RIGHT};
-static int shift __P((SCR *, EXF *, EXCMDARG *, enum which));
+static int shift __P((SCR *, EXCMD *, enum which));
+/*
+ * ex_shiftl -- :<[<...]
+ *
+ *
+ * PUBLIC: int ex_shiftl __P((SCR *, EXCMD *));
+ */
int
-ex_shiftl(sp, ep, cmdp)
+ex_shiftl(sp, cmdp)
SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+ EXCMD *cmdp;
{
- return (shift(sp, ep, cmdp, LEFT));
+ return (shift(sp, cmdp, LEFT));
}
+/*
+ * ex_shiftr -- :>[>...]
+ *
+ * PUBLIC: int ex_shiftr __P((SCR *, EXCMD *));
+ */
int
-ex_shiftr(sp, ep, cmdp)
+ex_shiftr(sp, cmdp)
SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+ EXCMD *cmdp;
{
- return (shift(sp, ep, cmdp, RIGHT));
+ return (shift(sp, cmdp, RIGHT));
}
+/*
+ * shift --
+ * Ex shift support.
+ */
static int
-shift(sp, ep, cmdp, rl)
+shift(sp, cmdp, rl)
SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+ EXCMD *cmdp;
enum which rl;
{
recno_t from, to;
@@ -87,11 +69,17 @@ shift(sp, ep, cmdp, rl)
int curset;
char *p, *bp, *tbp;
+ NEEDFILE(sp, cmdp);
+
if (O_VAL(sp, O_SHIFTWIDTH) == 0) {
- msgq(sp, M_INFO, "shiftwidth option set to 0");
+ msgq(sp, M_INFO, "152|shiftwidth option set to 0");
return (0);
}
+ /* Copy the lines being shifted into the unnamed buffer. */
+ if (cut(sp, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE))
+ return (1);
+
/*
* The historic version of vi permitted the user to string any number
* of '>' or '<' characters together, resulting in an indent of the
@@ -109,7 +97,7 @@ shift(sp, ep, cmdp, rl)
curset = 0;
for (from = cmdp->addr1.lno, to = cmdp->addr2.lno; from <= to; ++from) {
- if ((p = file_gline(sp, ep, from, &len)) == NULL)
+ if (db_get(sp, from, DBG_FATAL, &p, &len))
goto err;
if (!len) {
if (sp->lno == from)
@@ -158,10 +146,10 @@ shift(sp, ep, cmdp, rl)
*tbp++ = ' ';
/* Add the original line. */
- memmove(tbp, p + oldidx, len - oldidx);
+ memcpy(tbp, p + oldidx, len - oldidx);
/* Set the replacement line. */
- if (file_sline(sp, ep, from, bp, (tbp + (len - oldidx)) - bp)) {
+ if (db_set(sp, from, bp, (tbp + (len - oldidx)) - bp)) {
err: FREE_SPACE(sp, bp, blen);
return (1);
}
@@ -193,12 +181,11 @@ err: FREE_SPACE(sp, bp, blen);
if (!curset) {
sp->lno = to;
sp->cno = 0;
- (void)nonblank(sp, ep, to, &sp->cno);
+ (void)nonblank(sp, to, &sp->cno);
}
FREE_SPACE(sp, bp, blen);
- sp->rptlines[rl == RIGHT ? L_RSHIFT : L_LSHIFT] +=
- cmdp->addr2.lno - cmdp->addr1.lno + 1;
+ sp->rptlines[L_SHIFT] += cmdp->addr2.lno - cmdp->addr1.lno + 1;
return (0);
}
diff --git a/contrib/nvi/ex/ex_source.c b/contrib/nvi/ex/ex_source.c
new file mode 100644
index 000000000000..b52c527716fd
--- /dev/null
+++ b/contrib/nvi/ex/ex_source.c
@@ -0,0 +1,85 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_source.c 10.12 (Berkeley) 8/10/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_source -- :source file
+ * Execute ex commands from a file.
+ *
+ * PUBLIC: int ex_source __P((SCR *, EXCMD *));
+ */
+int
+ex_source(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ struct stat sb;
+ int fd, len;
+ char *bp, *name;
+
+ name = cmdp->argv[0]->bp;
+ if ((fd = open(name, O_RDONLY, 0)) < 0 || fstat(fd, &sb))
+ goto err;
+
+ /*
+ * XXX
+ * I'd like to test to see if the file is too large to malloc. Since
+ * we don't know what size or type off_t's or size_t's are, what the
+ * largest unsigned integral type is, or what random insanity the local
+ * C compiler will perpetrate, doing the comparison in a portable way
+ * is flatly impossible. So, put an fairly unreasonable limit on it,
+ * I don't want to be dropping core here.
+ */
+#define MEGABYTE 1048576
+ if (sb.st_size > MEGABYTE) {
+ errno = ENOMEM;
+ goto err;
+ }
+
+ MALLOC(sp, bp, char *, (size_t)sb.st_size + 1);
+ if (bp == NULL) {
+ (void)close(fd);
+ return (1);
+ }
+ bp[sb.st_size] = '\0';
+
+ /* Read the file into memory. */
+ len = read(fd, bp, (int)sb.st_size);
+ (void)close(fd);
+ if (len == -1 || len != sb.st_size) {
+ if (len != sb.st_size)
+ errno = EIO;
+ free(bp);
+err: msgq_str(sp, M_SYSERR, name, "%s");
+ return (1);
+ }
+
+ /* Put it on the ex queue. */
+ return (ex_run_str(sp, name, bp, (size_t)sb.st_size, 1, 1));
+}
diff --git a/contrib/nvi/ex/ex_stop.c b/contrib/nvi/ex/ex_stop.c
new file mode 100644
index 000000000000..bc55fd24ccb7
--- /dev/null
+++ b/contrib/nvi/ex/ex_stop.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_stop.c 10.10 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_stop -- :stop[!]
+ * :suspend[!]
+ * Suspend execution.
+ *
+ * PUBLIC: int ex_stop __P((SCR *, EXCMD *));
+ */
+int
+ex_stop(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ int allowed;
+
+ /* For some strange reason, the force flag turns off autowrite. */
+ if (!FL_ISSET(cmdp->iflags, E_C_FORCE) && file_aw(sp, FS_ALL))
+ return (1);
+
+ if (sp->gp->scr_suspend(sp, &allowed))
+ return (1);
+ if (!allowed)
+ ex_emsg(sp, NULL, EXM_NOSUSPEND);
+ return (0);
+}
diff --git a/usr.bin/vi/ex/ex_subst.c b/contrib/nvi/ex/ex_subst.c
index 54b6ee85097e..0ebb81dd58e7 100644
--- a/usr.bin/vi/ex/ex_subst.c
+++ b/contrib/nvi/ex/ex_subst.c
@@ -1,38 +1,16 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)ex_subst.c 8.57 (Berkeley) 8/7/94";
+static const char sccsid[] = "@(#)ex_subst.c 10.37 (Berkeley) 9/15/96";
#endif /* not lint */
#include <sys/types.h>
@@ -43,44 +21,41 @@ static char sccsid[] = "@(#)ex_subst.c 8.57 (Berkeley) 8/7/94";
#include <ctype.h>
#include <errno.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
#include <unistd.h>
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
+#include "../common/common.h"
+#include "../vi/vi.h"
#define SUB_FIRST 0x01 /* The 'r' flag isn't reasonable. */
#define SUB_MUSTSETR 0x02 /* The 'r' flag is required. */
-static __inline int regsub __P((SCR *, char *,
- char **, size_t *, size_t *, regmatch_t [10]));
-static int substitute __P((SCR *, EXF *,
- EXCMDARG *, char *, regex_t *, u_int));
+static int re_conv __P((SCR *, char **, size_t *, int *));
+static int re_cscope_conv __P((SCR *, char **, size_t *, int *));
+static int re_sub __P((SCR *,
+ char *, char **, size_t *, size_t *, regmatch_t [10]));
+static int re_tag_conv __P((SCR *, char **, size_t *, int *));
+static int s __P((SCR *, EXCMD *, char *, regex_t *, u_int));
/*
- * ex_substitute --
+ * ex_s --
* [line [,line]] s[ubstitute] [[/;]pat[/;]/repl[/;] [cgr] [count] [#lp]]
*
* Substitute on lines matching a pattern.
+ *
+ * PUBLIC: int ex_s __P((SCR *, EXCMD *));
*/
int
-ex_substitute(sp, ep, cmdp)
+ex_s(sp, cmdp)
SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+ EXCMD *cmdp;
{
- regex_t *re, lre;
+ regex_t *re;
size_t blen, len;
u_int flags;
- int delim, eval, reflags, replaced;
+ int delim;
char *bp, *ptrn, *rep, *p, *t;
/*
@@ -94,17 +69,19 @@ ex_substitute(sp, ep, cmdp)
* If the arguments are empty, it's the same as &, i.e. we
* repeat the last substitution.
*/
+ if (cmdp->argc == 0)
+ goto subagain;
for (p = cmdp->argv[0]->bp,
len = cmdp->argv[0]->len; len > 0; --len, ++p) {
if (!isblank(*p))
break;
}
if (len == 0)
- return (ex_subagain(sp, ep, cmdp));
+subagain: return (ex_subagain(sp, cmdp));
+
delim = *p++;
- if (isalnum(delim))
- return (substitute(sp, ep,
- cmdp, p, &sp->subre, SUB_MUSTSETR));
+ if (isalnum(delim) || delim == '\\')
+ return (s(sp, cmdp, p, &sp->subre_c, SUB_MUSTSETR));
/*
* !!!
@@ -112,9 +89,9 @@ ex_substitute(sp, ep, cmdp)
* state of the 'c' and 'g' suffices.
*/
sp->c_suffix = sp->g_suffix = 0;
-
+
/*
- * Get the pattern string, toss escaped characters.
+ * Get the pattern string, toss escaping characters.
*
* !!!
* Historic vi accepted any of the following forms:
@@ -126,10 +103,10 @@ ex_substitute(sp, ep, cmdp)
*
* QUOTING NOTE:
*
- * Only toss an escape character if it escapes a delimiter.
+ * Only toss an escaping character if it escapes a delimiter.
* This means that "s/A/\\\\f" replaces "A" with "\\f". It
* would be nice to be more regular, i.e. for each layer of
- * escaping a single escape character is removed, but that's
+ * escaping a single escaping character is removed, but that's
* not how the historic vi worked.
*/
for (ptrn = t = p;;) {
@@ -157,59 +134,42 @@ ex_substitute(sp, ep, cmdp)
* last substitution RE).
*/
if (*ptrn == '\0') {
- if (!F_ISSET(sp, S_SRE_SET)) {
- msgq(sp, M_ERR, "No previous regular expression");
+ if (sp->re == NULL) {
+ ex_emsg(sp, NULL, EXM_NOPREVRE);
return (1);
}
- re = &sp->sre;
- flags = 0;
- } else {
- /* Set RE flags. */
- reflags = 0;
- if (O_ISSET(sp, O_EXTENDED))
- reflags |= REG_EXTENDED;
- if (O_ISSET(sp, O_IGNORECASE))
- reflags |= REG_ICASE;
- /* Convert vi-style RE's to POSIX 1003.2 RE's. */
- if (re_conv(sp, &ptrn, &replaced))
+ /* Re-compile the RE if necessary. */
+ if (!F_ISSET(sp, SC_RE_SEARCH) && re_compile(sp,
+ sp->re, sp->re_len, NULL, NULL, &sp->re_c, RE_C_SEARCH))
return (1);
-
- /* Compile the RE. */
- eval = regcomp(&lre, (char *)ptrn, reflags);
-
- /* Free up any allocated memory. */
- if (replaced)
- FREE_SPACE(sp, ptrn, 0);
-
- if (eval) {
- re_error(sp, eval, &lre);
- return (1);
- }
-
+ flags = 0;
+ } else {
/*
- * Set saved RE.
- *
* !!!
- * Historic practice is that substitutes set the search
- * direction as well as both substitute and search RE's.
+ * Compile the RE. Historic practice is that substitutes set
+ * the search direction as well as both substitute and search
+ * RE's. We compile the RE twice, as we don't want to bother
+ * ref counting the pattern string and (opaque) structure.
*/
- sp->searchdir = FORWARD;
- sp->sre = lre;
- F_SET(sp, S_SRE_SET);
- sp->subre = lre;
- F_SET(sp, S_SUBRE_SET);
-
- re = &lre;
+ if (re_compile(sp, ptrn, t - ptrn,
+ &sp->re, &sp->re_len, &sp->re_c, RE_C_SEARCH))
+ return (1);
+ if (re_compile(sp, ptrn, t - ptrn,
+ &sp->subre, &sp->subre_len, &sp->subre_c, RE_C_SUBST))
+ return (1);
+
flags = SUB_FIRST;
+ sp->searchdir = FORWARD;
}
+ re = &sp->re_c;
/*
* Get the replacement string.
*
* The special character & (\& if O_MAGIC not set) matches the
* entire RE. No handling of & is required here, it's done by
- * regsub().
+ * re_sub().
*
* The special character ~ (\~ if O_MAGIC not set) inserts the
* previous replacement string into this replacement string.
@@ -219,7 +179,7 @@ ex_substitute(sp, ep, cmdp)
*
* QUOTING NOTE:
*
- * Only toss an escape character if it escapes a delimiter or
+ * Only toss an escaping character if it escapes a delimiter or
* if O_MAGIC is set and it escapes a tilde.
*
* !!!
@@ -232,7 +192,7 @@ ex_substitute(sp, ep, cmdp)
if (p[0] == delim)
++p;
if (sp->repl != NULL)
- FREE(sp->repl, sp->repl_len);
+ free(sp->repl);
sp->repl = NULL;
sp->repl_len = 0;
} else if (p[0] == '%' && (p[1] == '\0' || p[1] == delim))
@@ -262,7 +222,7 @@ ex_substitute(sp, ep, cmdp)
}
} else if (p[0] == '~' && O_ISSET(sp, O_MAGIC)) {
tilde: ++p;
- memmove(t, sp->repl, sp->repl_len);
+ memcpy(t, sp->repl, sp->repl_len);
t += sp->repl_len;
len += sp->repl_len;
continue;
@@ -278,11 +238,11 @@ tilde: ++p;
FREE_SPACE(sp, bp, blen);
return (1);
}
- memmove(sp->repl, bp, len);
+ memcpy(sp->repl, bp, len);
}
FREE_SPACE(sp, bp, blen);
}
- return (substitute(sp, ep, cmdp, p, re, flags));
+ return (s(sp, cmdp, p, re, flags));
}
/*
@@ -290,18 +250,23 @@ tilde: ++p;
* [line [,line]] & [cgr] [count] [#lp]]
*
* Substitute using the last substitute RE and replacement pattern.
+ *
+ * PUBLIC: int ex_subagain __P((SCR *, EXCMD *));
*/
int
-ex_subagain(sp, ep, cmdp)
+ex_subagain(sp, cmdp)
SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+ EXCMD *cmdp;
{
- if (!F_ISSET(sp, S_SUBRE_SET)) {
- msgq(sp, M_ERR, "No previous regular expression");
+ if (sp->subre == NULL) {
+ ex_emsg(sp, NULL, EXM_NOPREVRE);
return (1);
}
- return (substitute(sp, ep, cmdp, cmdp->argv[0]->bp, &sp->subre, 0));
+ if (!F_ISSET(sp, SC_RE_SUBST) && re_compile(sp,
+ sp->subre, sp->subre_len, NULL, NULL, &sp->subre_c, RE_C_SUBST))
+ return (1);
+ return (s(sp,
+ cmdp, cmdp->argc ? cmdp->argv[0]->bp : NULL, &sp->subre_c, 0));
}
/*
@@ -309,26 +274,36 @@ ex_subagain(sp, ep, cmdp)
* [line [,line]] ~ [cgr] [count] [#lp]]
*
* Substitute using the last RE and last substitute replacement pattern.
+ *
+ * PUBLIC: int ex_subtilde __P((SCR *, EXCMD *));
*/
int
-ex_subtilde(sp, ep, cmdp)
+ex_subtilde(sp, cmdp)
SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+ EXCMD *cmdp;
{
- if (!F_ISSET(sp, S_SRE_SET)) {
- msgq(sp, M_ERR, "No previous regular expression");
+ if (sp->re == NULL) {
+ ex_emsg(sp, NULL, EXM_NOPREVRE);
return (1);
}
- return (substitute(sp, ep, cmdp, cmdp->argv[0]->bp, &sp->sre, 0));
+ if (!F_ISSET(sp, SC_RE_SEARCH) && re_compile(sp,
+ sp->re, sp->re_len, NULL, NULL, &sp->re_c, RE_C_SEARCH))
+ return (1);
+ return (s(sp,
+ cmdp, cmdp->argc ? cmdp->argv[0]->bp : NULL, &sp->re_c, 0));
}
/*
+ * s --
+ * Do the substitution. This stuff is *really* tricky. There are lots of
+ * special cases, and general nastiness. Don't mess with it unless you're
+ * pretty confident.
+ *
* The nasty part of the substitution is what happens when the replacement
* string contains newlines. It's a bit tricky -- consider the information
* that has to be retained for "s/f\(o\)o/^M\1^M\1/". The solution here is
* to build a set of newline offsets which we use to break the line up later,
- * when the replacement is done. Don't change it unless you're pretty damned
+ * when the replacement is done. Don't change it unless you're *damned*
* confident.
*/
#define NEEDNEWLINE(sp) { \
@@ -352,7 +327,7 @@ ex_subtilde(sp, ep, cmdp)
return (1); \
} \
} \
- memmove(lb + lbclen, l, len); \
+ memcpy(lb + lbclen, l, len); \
lbclen += len; \
}
@@ -368,37 +343,38 @@ ex_subtilde(sp, ep, cmdp)
} \
}
-/*
- * substitute --
- * Do the substitution. This stuff is *really* tricky. There are
- * lots of special cases, and general nastiness. Don't mess with it
- * unless you're pretty confident.
- */
static int
-substitute(sp, ep, cmdp, s, re, flags)
+s(sp, cmdp, s, re, flags)
SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+ EXCMD *cmdp;
char *s;
regex_t *re;
u_int flags;
{
+ EVENT ev;
MARK from, to;
- recno_t elno, lno;
+ TEXTH tiq;
+ recno_t elno, lno, slno;
regmatch_t match[10];
- size_t blen, cnt, last, lbclen, lblen, len, llen, offset, saved_offset;
+ size_t blen, cnt, last, lbclen, lblen, len, llen;
+ size_t offset, saved_offset, scno;
int cflag, lflag, nflag, pflag, rflag;
int didsub, do_eol_match, eflags, empty_ok, eval;
int linechanged, matched, quit, rval;
char *bp, *lb;
+ NEEDFILE(sp, cmdp);
+
+ slno = sp->lno;
+ scno = sp->cno;
+
/*
* !!!
* Historically, the 'g' and 'c' suffices were always toggled as flags,
* so ":s/A/B/" was the same as ":s/A/B/ccgg". If O_EDCOMPATIBLE was
* not set, they were initialized to 0 for all substitute commands. If
* O_EDCOMPATIBLE was set, they were initialized to 0 only if the user
- * specified substitute/replacement patterns (see ex_substitute()).
+ * specified substitute/replacement patterns (see ex_s()).
*/
if (!O_ISSET(sp, O_EDCOMPATIBLE))
sp->c_suffix = sp->g_suffix = 0;
@@ -420,6 +396,8 @@ substitute(sp, ep, cmdp, s, re, flags)
* usage statement doesn't reflect this.)
*/
cflag = lflag = nflag = pflag = rflag = 0;
+ if (s == NULL)
+ goto noargs;
for (lno = OOBLNO; *s != '\0'; ++s)
switch (*s) {
case ' ':
@@ -441,9 +419,9 @@ substitute(sp, ep, cmdp, s, re, flags)
--s;
if (errno == ERANGE) {
if (lno == LONG_MAX)
- msgq(sp, M_ERR, "Count overflow");
+ msgq(sp, M_ERR, "153|Count overflow");
else if (lno == LONG_MIN)
- msgq(sp, M_ERR, "Count underflow");
+ msgq(sp, M_ERR, "154|Count underflow");
else
msgq(sp, M_SYSERR, NULL);
return (1);
@@ -454,12 +432,21 @@ substitute(sp, ep, cmdp, s, re, flags)
*/
cmdp->addr1.lno = cmdp->addr2.lno;
cmdp->addr2.lno += lno - 1;
+ if (!db_exist(sp, cmdp->addr2.lno) &&
+ db_last(sp, &cmdp->addr2.lno))
+ return (1);
break;
case '#':
nflag = 1;
break;
case 'c':
sp->c_suffix = !sp->c_suffix;
+
+ /* Ex text structure initialization. */
+ if (F_ISSET(sp, SC_EX)) {
+ memset(&tiq, 0, sizeof(TEXTH));
+ CIRCLEQ_INIT(&tiq);
+ }
break;
case 'g':
sp->g_suffix = !sp->g_suffix;
@@ -473,29 +460,28 @@ substitute(sp, ep, cmdp, s, re, flags)
case 'r':
if (LF_ISSET(SUB_FIRST)) {
msgq(sp, M_ERR,
- "Regular expression specified; r flag meaningless");
+ "155|Regular expression specified; r flag meaningless");
return (1);
}
- if (!F_ISSET(sp, S_SRE_SET)) {
- msgq(sp, M_ERR,
- "No previous regular expression");
+ if (!F_ISSET(sp, SC_RE_SEARCH)) {
+ ex_emsg(sp, NULL, EXM_NOPREVRE);
return (1);
}
rflag = 1;
- re = &sp->sre;
+ re = &sp->re_c;
break;
default:
goto usage;
}
if (*s != '\0' || !rflag && LF_ISSET(SUB_MUSTSETR)) {
-usage: msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage);
+usage: ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
return (1);
}
- if (IN_VI_MODE(sp) && sp->c_suffix && (lflag || nflag || pflag)) {
+noargs: if (F_ISSET(sp, SC_VI) && sp->c_suffix && (lflag || nflag || pflag)) {
msgq(sp, M_ERR,
- "The #, l and p flags may not be combined with the c flag in vi mode");
+"156|The #, l and p flags may not be combined with the c flag in vi mode");
return (1);
}
@@ -514,17 +500,12 @@ usage: msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage);
elno = cmdp->addr2.lno; !quit && lno <= elno; ++lno) {
/* Someone's unhappy, time to stop. */
- if (INTERRUPTED(sp)) {
- if (!F_ISSET(sp, S_GLOBAL))
- msgq(sp, M_INFO, "Interrupted");
+ if (INTERRUPTED(sp))
break;
- }
/* Get the line. */
- if ((s = file_gline(sp, ep, lno, &llen)) == NULL) {
- GETLINE_ERR(sp, lno);
- goto ret1;
- }
+ if (db_get(sp, lno, DBG_FATAL, &s, &llen))
+ goto err;
/*
* Make a local copy if doing confirmation -- when calling
@@ -535,7 +516,7 @@ usage: msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage);
GET_SPACE_RET(sp, bp, blen, llen);
} else
ADD_SPACE_RET(sp, bp, blen, llen);
- memmove(bp, s, llen);
+ memcpy(bp, s, llen);
s = bp;
}
@@ -585,7 +566,7 @@ nextmatch: match[0].rm_so = 0;
goto endmatch;
if (eval != 0) {
re_error(sp, eval, re);
- goto ret1;
+ goto err;
}
matched = 1;
@@ -628,53 +609,95 @@ nextmatch: match[0].rm_so = 0;
* Set the cursor position for confirmation. Note,
* if we matched on a '$', the cursor may be past
* the end of line.
- *
- * XXX
- * We may want to "fix" this in the confirm routine,
- * if the confirm routine should be able to display
- * a cursor past EOL.
*/
from.lno = to.lno = lno;
from.cno = match[0].rm_so + offset;
- to.cno = match[0].rm_eo;
+ to.cno = match[0].rm_eo + offset;
+ /*
+ * Both ex and vi have to correct for a change before
+ * the first character in the line.
+ */
if (llen == 0)
from.cno = to.cno = 0;
- else {
+ if (F_ISSET(sp, SC_VI)) {
+ /*
+ * Only vi has to correct for a change after
+ * the last character in the line.
+ *
+ * XXX
+ * It would be nice to change the vi code so
+ * that we could display a cursor past EOL.
+ */
if (to.cno >= llen)
to.cno = llen - 1;
if (from.cno >= llen)
from.cno = llen - 1;
+
+ sp->lno = from.lno;
+ sp->cno = from.cno;
+ if (vs_refresh(sp, 1))
+ goto err;
+
+ vs_update(sp, msg_cat(sp,
+ "169|Confirm change? [n]", NULL), NULL);
+
+ if (v_event_get(sp, &ev, 0, 0))
+ goto err;
+ switch (ev.e_event) {
+ case E_CHARACTER:
+ break;
+ case E_EOF:
+ case E_ERR:
+ case E_INTERRUPT:
+ goto lquit;
+ default:
+ v_event_err(sp, &ev);
+ goto lquit;
+ }
+ } else {
+ if (ex_print(sp, cmdp, &from, &to, 0) ||
+ ex_scprint(sp, &from, &to))
+ goto lquit;
+ if (ex_txt(sp, &tiq, 0, TXT_CR))
+ goto err;
+ ev.e_c = tiq.cqh_first->lb[0];
}
- switch (sp->s_confirm(sp, ep, &from, &to)) {
- case CONF_YES:
+
+ switch (ev.e_c) {
+ case CH_YES:
break;
- case CONF_NO:
+ default:
+ case CH_NO:
didsub = 0;
BUILD(sp, s +offset, match[0].rm_eo);
goto skip;
- case CONF_QUIT:
- /* Set the quit flag. */
- quit = 1;
-
- /* If interruptible, pass the info back. */
- if (F_ISSET(sp, S_INTERRUPTIBLE))
- F_SET(sp, S_INTERRUPTED);
+ case CH_QUIT:
+ /* Set the quit/interrupted flags. */
+lquit: quit = 1;
+ F_SET(sp->gp, G_INTERRUPTED);
/*
- * If any changes, resolve them, otherwise
- * return to the main loop.
+ * Resolve any changes, then return to (and
+ * exit from) the main loop.
*/
goto endmatch;
}
}
+ /*
+ * Set the cursor to the last position changed, converting
+ * from 1-based to 0-based.
+ */
+ sp->lno = lno;
+ sp->cno = match[0].rm_so;
+
/* Copy the bytes before the match into the build buffer. */
BUILD(sp, s + offset, match[0].rm_so);
/* Substitute the matching bytes. */
didsub = 1;
- if (regsub(sp, s + offset, &lb, &lbclen, &lblen, match))
- goto ret1;
+ if (re_sub(sp, s + offset, &lb, &lbclen, &lblen, match))
+ goto err;
/* Set the change flag so we know this line was modified. */
linechanged = 1;
@@ -710,9 +733,9 @@ skip: offset += match[0].rm_eo;
if (sp->newl_cnt) {
for (cnt = 0;
cnt < sp->newl_cnt; ++cnt, ++lno, ++elno) {
- if (file_iline(sp, ep, lno,
+ if (db_insert(sp, lno,
lb + last, sp->newl[cnt] - last))
- goto ret1;
+ goto err;
last = sp->newl[cnt] + 1;
++sp->rptlines[L_ADDED];
}
@@ -722,14 +745,12 @@ skip: offset += match[0].rm_eo;
}
/* Store and retrieve the line. */
- if (file_sline(sp, ep, lno, lb + last, lbclen))
- goto ret1;
- if ((s = file_gline(sp, ep, lno, &llen)) == NULL) {
- GETLINE_ERR(sp, lno);
- goto ret1;
- }
+ if (db_set(sp, lno, lb + last, lbclen))
+ goto err;
+ if (db_get(sp, lno, DBG_FATAL, &s, &llen))
+ goto err;
ADD_SPACE_RET(sp, bp, blen, llen)
- memmove(bp, s, llen);
+ memcpy(bp, s, llen);
s = bp;
len = llen - offset;
@@ -778,9 +799,9 @@ endmatch: if (!linechanged)
if (sp->newl_cnt) {
for (cnt = 0;
cnt < sp->newl_cnt; ++cnt, ++lno, ++elno) {
- if (file_iline(sp, ep,
+ if (db_insert(sp,
lno, lb + last, sp->newl[cnt] - last))
- goto ret1;
+ goto err;
last = sp->newl[cnt] + 1;
++sp->rptlines[L_ADDED];
}
@@ -789,8 +810,8 @@ endmatch: if (!linechanged)
}
/* Store the changed line. */
- if (file_sline(sp, ep, lno, lb + last, lbclen))
- goto ret1;
+ if (db_set(sp, lno, lb + last, lbclen))
+ goto err;
/* Update changed line counter. */
if (sp->rptlchange != lno) {
@@ -808,50 +829,50 @@ endmatch: if (!linechanged)
from.lno = to.lno = lno;
from.cno = to.cno = 0;
if (lflag)
- ex_print(sp, ep, &from, &to, E_F_LIST);
+ (void)ex_print(sp, cmdp, &from, &to, E_C_LIST);
if (nflag)
- ex_print(sp, ep, &from, &to, E_F_HASH);
+ (void)ex_print(sp, cmdp, &from, &to, E_C_HASH);
if (pflag)
- ex_print(sp, ep, &from, &to, E_F_PRINT);
+ (void)ex_print(sp, cmdp, &from, &to, E_C_PRINT);
}
-
- if (!sp->c_suffix)
- sp->lno = lno;
-
- /*
- * !!!
- * Move the cursor to the last line changed.
- */
- if (!sp->c_suffix)
- sp->lno = lno;
}
/*
* !!!
- * Move the cursor to the first non-blank of the last line change.
+ * Historically, vi attempted to leave the cursor at the same place if
+ * the substitution was done at the current cursor position. Otherwise
+ * it moved it to the first non-blank of the last line changed. There
+ * were some problems: for example, :s/$/foo/ with the cursor on the
+ * last character of the line left the cursor on the last character, or
+ * the & command with multiple occurrences of the matching string in the
+ * line usually left the cursor in a fairly random position.
*
- * XXX
- * This is NOT backward compatible with historic vi, which always
- * moved to the last line actually changed.
+ * We try to do the same thing, with the exception that if the user is
+ * doing substitution with confirmation, we move to the last line about
+ * which the user was consulted, as opposed to the last line that they
+ * actually changed. This prevents a screen flash if the user doesn't
+ * change many of the possible lines.
*/
- if (!sp->c_suffix) {
+ if (!sp->c_suffix && (sp->lno != slno || sp->cno != scno)) {
sp->cno = 0;
- (void)nonblank(sp, ep, sp->lno, &sp->cno);
+ (void)nonblank(sp, sp->lno, &sp->cno);
}
/*
* If not in a global command, and nothing matched, say so.
* Else, if none of the lines displayed, put something up.
*/
+ rval = 0;
if (!matched) {
- if (!F_ISSET(sp, S_GLOBAL))
- msgq(sp, M_INFO, "No match found");
+ if (!F_ISSET(sp, SC_EX_GLOBAL)) {
+ msgq(sp, M_ERR, "157|No match found");
+ goto err;
+ }
} else if (!lflag && !nflag && !pflag)
- F_SET(EXP(sp), EX_AUTOPRINT);
+ F_SET(cmdp, E_AUTOPRINT);
- rval = 0;
if (0) {
-ret1: rval = 1;
+err: rval = 1;
}
if (bp != NULL)
@@ -862,11 +883,448 @@ ret1: rval = 1;
}
/*
- * regsub --
+ * re_compile --
+ * Compile the RE.
+ *
+ * PUBLIC: int re_compile __P((SCR *,
+ * PUBLIC: char *, size_t, char **, size_t *, regex_t *, u_int));
+ */
+int
+re_compile(sp, ptrn, plen, ptrnp, lenp, rep, flags)
+ SCR *sp;
+ char *ptrn, **ptrnp;
+ size_t plen, *lenp;
+ regex_t *rep;
+ u_int flags;
+{
+ size_t len;
+ int reflags, replaced, rval;
+ char *p;
+
+ /* Set RE flags. */
+ reflags = 0;
+ if (!LF_ISSET(RE_C_CSCOPE | RE_C_TAG)) {
+ if (O_ISSET(sp, O_EXTENDED))
+ reflags |= REG_EXTENDED;
+ if (O_ISSET(sp, O_IGNORECASE))
+ reflags |= REG_ICASE;
+ if (O_ISSET(sp, O_ICLOWER)) {
+ for (p = ptrn, len = plen; len > 0; ++p, --len)
+ if (isupper(*p))
+ break;
+ if (len == 0)
+ reflags |= REG_ICASE;
+ }
+ }
+
+ /* If we're replacing a saved value, clear the old one. */
+ if (LF_ISSET(RE_C_SEARCH) && F_ISSET(sp, SC_RE_SEARCH)) {
+ regfree(&sp->re_c);
+ F_CLR(sp, SC_RE_SEARCH);
+ }
+ if (LF_ISSET(RE_C_SUBST) && F_ISSET(sp, SC_RE_SUBST)) {
+ regfree(&sp->subre_c);
+ F_CLR(sp, SC_RE_SUBST);
+ }
+
+ /*
+ * If we're saving the string, it's a pattern we haven't seen before,
+ * so convert the vi-style RE's to POSIX 1003.2 RE's. Save a copy for
+ * later recompilation. Free any previously saved value.
+ */
+ if (ptrnp != NULL) {
+ if (LF_ISSET(RE_C_CSCOPE)) {
+ if (re_cscope_conv(sp, &ptrn, &plen, &replaced))
+ return (1);
+ /*
+ * XXX
+ * Currently, the match-any-<blank> expression used in
+ * re_cscope_conv() requires extended RE's. This may
+ * not be right or safe.
+ */
+ reflags |= REG_EXTENDED;
+ } else if (LF_ISSET(RE_C_TAG)) {
+ if (re_tag_conv(sp, &ptrn, &plen, &replaced))
+ return (1);
+ } else
+ if (re_conv(sp, &ptrn, &plen, &replaced))
+ return (1);
+
+ /* Discard previous pattern. */
+ if (*ptrnp != NULL) {
+ free(*ptrnp);
+ *ptrnp = NULL;
+ }
+ if (lenp != NULL)
+ *lenp = plen;
+
+ /*
+ * Copy the string into allocated memory.
+ *
+ * XXX
+ * Regcomp isn't 8-bit clean, so the pattern is nul-terminated
+ * for now. There's just no other solution.
+ */
+ MALLOC(sp, *ptrnp, char *, plen + 1);
+ if (*ptrnp != NULL) {
+ memcpy(*ptrnp, ptrn, plen);
+ (*ptrnp)[plen] = '\0';
+ }
+
+ /* Free up conversion-routine-allocated memory. */
+ if (replaced)
+ FREE_SPACE(sp, ptrn, 0);
+
+ if (*ptrnp == NULL)
+ return (1);
+
+ ptrn = *ptrnp;
+ }
+
+ /*
+ * XXX
+ * Regcomp isn't 8-bit clean, so we just lost if the pattern
+ * contained a nul. Bummer!
+ */
+ if ((rval = regcomp(rep, ptrn, /* plen, */ reflags)) != 0) {
+ if (!LF_ISSET(RE_C_SILENT))
+ re_error(sp, rval, rep);
+ return (1);
+ }
+
+ if (LF_ISSET(RE_C_SEARCH))
+ F_SET(sp, SC_RE_SEARCH);
+ if (LF_ISSET(RE_C_SUBST))
+ F_SET(sp, SC_RE_SUBST);
+
+ return (0);
+}
+
+/*
+ * re_conv --
+ * Convert vi's regular expressions into something that the
+ * the POSIX 1003.2 RE functions can handle.
+ *
+ * There are three conversions we make to make vi's RE's (specifically
+ * the global, search, and substitute patterns) work with POSIX RE's.
+ *
+ * 1: If O_MAGIC is not set, strip backslashes from the magic character
+ * set (.[*~) that have them, and add them to the ones that don't.
+ * 2: If O_MAGIC is not set, the string "\~" is replaced with the text
+ * from the last substitute command's replacement string. If O_MAGIC
+ * is set, it's the string "~".
+ * 3: The pattern \<ptrn\> does "word" searches, convert it to use the
+ * new RE escapes.
+ *
+ * !!!/XXX
+ * This doesn't exactly match the historic behavior of vi because we do
+ * the ~ substitution before calling the RE engine, so magic characters
+ * in the replacement string will be expanded by the RE engine, and they
+ * weren't historically. It's a bug.
+ */
+static int
+re_conv(sp, ptrnp, plenp, replacedp)
+ SCR *sp;
+ char **ptrnp;
+ size_t *plenp;
+ int *replacedp;
+{
+ size_t blen, len, needlen;
+ int magic;
+ char *bp, *p, *t;
+
+ /*
+ * First pass through, we figure out how much space we'll need.
+ * We do it in two passes, on the grounds that most of the time
+ * the user is doing a search and won't have magic characters.
+ * That way we can skip most of the memory allocation and copies.
+ */
+ magic = 0;
+ for (p = *ptrnp, len = *plenp, needlen = 0; len > 0; ++p, --len)
+ switch (*p) {
+ case '\\':
+ if (len > 1) {
+ --len;
+ switch (*++p) {
+ case '<':
+ magic = 1;
+ needlen += sizeof(RE_WSTART);
+ break;
+ case '>':
+ magic = 1;
+ needlen += sizeof(RE_WSTOP);
+ break;
+ case '~':
+ if (!O_ISSET(sp, O_MAGIC)) {
+ magic = 1;
+ needlen += sp->repl_len;
+ }
+ break;
+ case '.':
+ case '[':
+ case '*':
+ if (!O_ISSET(sp, O_MAGIC)) {
+ magic = 1;
+ needlen += 1;
+ }
+ break;
+ default:
+ needlen += 2;
+ }
+ } else
+ needlen += 1;
+ break;
+ case '~':
+ if (O_ISSET(sp, O_MAGIC)) {
+ magic = 1;
+ needlen += sp->repl_len;
+ }
+ break;
+ case '.':
+ case '[':
+ case '*':
+ if (!O_ISSET(sp, O_MAGIC)) {
+ magic = 1;
+ needlen += 2;
+ }
+ break;
+ default:
+ needlen += 1;
+ break;
+ }
+
+ if (!magic) {
+ *replacedp = 0;
+ return (0);
+ }
+
+ /* Get enough memory to hold the final pattern. */
+ *replacedp = 1;
+ GET_SPACE_RET(sp, bp, blen, needlen);
+
+ for (p = *ptrnp, len = *plenp, t = bp; len > 0; ++p, --len)
+ switch (*p) {
+ case '\\':
+ if (len > 1) {
+ --len;
+ switch (*++p) {
+ case '<':
+ memcpy(t,
+ RE_WSTART, sizeof(RE_WSTART) - 1);
+ t += sizeof(RE_WSTART) - 1;
+ break;
+ case '>':
+ memcpy(t,
+ RE_WSTOP, sizeof(RE_WSTOP) - 1);
+ t += sizeof(RE_WSTOP) - 1;
+ break;
+ case '~':
+ if (O_ISSET(sp, O_MAGIC))
+ *t++ = '~';
+ else {
+ memcpy(t,
+ sp->repl, sp->repl_len);
+ t += sp->repl_len;
+ }
+ break;
+ case '.':
+ case '[':
+ case '*':
+ if (O_ISSET(sp, O_MAGIC))
+ *t++ = '\\';
+ *t++ = *p;
+ break;
+ default:
+ *t++ = '\\';
+ *t++ = *p;
+ }
+ } else
+ *t++ = '\\';
+ break;
+ case '~':
+ if (O_ISSET(sp, O_MAGIC)) {
+ memcpy(t, sp->repl, sp->repl_len);
+ t += sp->repl_len;
+ } else
+ *t++ = '~';
+ break;
+ case '.':
+ case '[':
+ case '*':
+ if (!O_ISSET(sp, O_MAGIC))
+ *t++ = '\\';
+ *t++ = *p;
+ break;
+ default:
+ *t++ = *p;
+ break;
+ }
+
+ *ptrnp = bp;
+ *plenp = t - bp;
+ return (0);
+}
+
+/*
+ * re_tag_conv --
+ * Convert a tags search path into something that the POSIX
+ * 1003.2 RE functions can handle.
+ */
+static int
+re_tag_conv(sp, ptrnp, plenp, replacedp)
+ SCR *sp;
+ char **ptrnp;
+ size_t *plenp;
+ int *replacedp;
+{
+ size_t blen, len;
+ int lastdollar;
+ char *bp, *p, *t;
+
+ len = *plenp;
+
+ /* Max memory usage is 2 times the length of the string. */
+ *replacedp = 1;
+ GET_SPACE_RET(sp, bp, blen, len * 2);
+
+ p = *ptrnp;
+ t = bp;
+
+ /* If the last character is a '/' or '?', we just strip it. */
+ if (len > 0 && (p[len - 1] == '/' || p[len - 1] == '?'))
+ --len;
+
+ /* If the next-to-last or last character is a '$', it's magic. */
+ if (len > 0 && p[len - 1] == '$') {
+ --len;
+ lastdollar = 1;
+ } else
+ lastdollar = 0;
+
+ /* If the first character is a '/' or '?', we just strip it. */
+ if (len > 0 && (p[0] == '/' || p[0] == '?')) {
+ ++p;
+ --len;
+ }
+
+ /* If the first or second character is a '^', it's magic. */
+ if (p[0] == '^') {
+ *t++ = *p++;
+ --len;
+ }
+
+ /*
+ * Escape every other magic character we can find, meanwhile stripping
+ * the backslashes ctags inserts when escaping the search delimiter
+ * characters.
+ */
+ for (; len > 0; --len) {
+ if (p[0] == '\\' && (p[1] == '/' || p[1] == '?')) {
+ ++p;
+ --len;
+ } else if (strchr("^.[]$*", p[0]))
+ *t++ = '\\';
+ *t++ = *p++;
+ }
+ if (lastdollar)
+ *t++ = '$';
+
+ *ptrnp = bp;
+ *plenp = t - bp;
+ return (0);
+}
+
+/*
+ * re_cscope_conv --
+ * Convert a cscope search path into something that the POSIX
+ * 1003.2 RE functions can handle.
+ */
+static int
+re_cscope_conv(sp, ptrnp, plenp, replacedp)
+ SCR *sp;
+ char **ptrnp;
+ size_t *plenp;
+ int *replacedp;
+{
+ size_t blen, len, nspaces;
+ char *bp, *p, *t;
+
+ /*
+ * Each space in the source line printed by cscope represents an
+ * arbitrary sequence of spaces, tabs, and comments.
+ */
+#define CSCOPE_RE_SPACE "([ \t]|/\\*([^*]|\\*/)*\\*/)*"
+ for (nspaces = 0, p = *ptrnp, len = *plenp; len > 0; ++p, --len)
+ if (*p == ' ')
+ ++nspaces;
+
+ /*
+ * Allocate plenty of space:
+ * the string, plus potential escaping characters;
+ * nspaces + 2 copies of CSCOPE_RE_SPACE;
+ * ^, $, nul terminator characters.
+ */
+ *replacedp = 1;
+ len = (p - *ptrnp) * 2 + (nspaces + 2) * sizeof(CSCOPE_RE_SPACE) + 3;
+ GET_SPACE_RET(sp, bp, blen, len);
+
+ p = *ptrnp;
+ t = bp;
+
+ *t++ = '^';
+ memcpy(t, CSCOPE_RE_SPACE, sizeof(CSCOPE_RE_SPACE) - 1);
+ t += sizeof(CSCOPE_RE_SPACE) - 1;
+
+ for (len = *plenp; len > 0; ++p, --len)
+ if (*p == ' ') {
+ memcpy(t, CSCOPE_RE_SPACE, sizeof(CSCOPE_RE_SPACE) - 1);
+ t += sizeof(CSCOPE_RE_SPACE) - 1;
+ } else {
+ if (strchr("\\^.[]$*+?()|{}", *p))
+ *t++ = '\\';
+ *t++ = *p;
+ }
+
+ memcpy(t, CSCOPE_RE_SPACE, sizeof(CSCOPE_RE_SPACE) - 1);
+ t += sizeof(CSCOPE_RE_SPACE) - 1;
+ *t++ = '$';
+
+ *ptrnp = bp;
+ *plenp = t - bp;
+ return (0);
+}
+
+/*
+ * re_error --
+ * Report a regular expression error.
+ *
+ * PUBLIC: void re_error __P((SCR *, int, regex_t *));
+ */
+void
+re_error(sp, errcode, preg)
+ SCR *sp;
+ int errcode;
+ regex_t *preg;
+{
+ size_t s;
+ char *oe;
+
+ s = regerror(errcode, preg, "", 0);
+ if ((oe = malloc(s)) == NULL)
+ msgq(sp, M_SYSERR, NULL);
+ else {
+ (void)regerror(errcode, preg, oe, s);
+ msgq(sp, M_ERR, "RE error: %s", oe);
+ free(oe);
+ }
+}
+
+/*
+ * re_sub --
* Do the substitution for a regular expression.
*/
-static __inline int
-regsub(sp, ip, lbp, lbclenp, lblenp, match)
+static int
+re_sub(sp, ip, lbp, lbclenp, lblenp, match)
SCR *sp;
char *ip; /* Input line. */
char **lbp;
@@ -902,12 +1360,12 @@ regsub(sp, ip, lbp, lbclenp, lblenp, match)
* \U convert to upper-case, until \E, \e, or end of replacement
*
* Otherwise, since this is the lowest level of replacement, discard
- * all escape characters. This (hopefully) follows historic practice.
+ * all escaping characters. This (hopefully) matches historic practice.
*/
-#define ADDCH(ch) { \
+#define OUTCH(ch, nltrans) { \
CHAR_T __ch = (ch); \
u_int __value = KEY_VAL(sp, __ch); \
- if (__value == K_CR || __value == K_NL) { \
+ if (nltrans && (__value == K_CR || __value == K_NL)) { \
NEEDNEWLINE(sp); \
sp->newl[sp->newl_cnt++] = lbclen; \
} else if (conv != C_NOTSET) { \
@@ -963,7 +1421,7 @@ subzero: if (match[no].rm_so == -1 ||
break;
mlen = match[no].rm_eo - match[no].rm_so;
for (t = ip + match[no].rm_so; mlen--; ++t)
- ADDCH(*t);
+ OUTCH(*t, 0);
continue;
case 'e':
case 'E':
@@ -991,7 +1449,7 @@ subzero: if (match[no].rm_so == -1 ||
break;
}
}
- ADDCH(ch);
+ OUTCH(ch, 1);
}
*lbp = lb; /* Update caller's information. */
diff --git a/contrib/nvi/ex/ex_tag.c b/contrib/nvi/ex/ex_tag.c
new file mode 100644
index 000000000000..461b1526ef00
--- /dev/null
+++ b/contrib/nvi/ex/ex_tag.c
@@ -0,0 +1,1324 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * David Hitz of Auspex Systems, Inc.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_tag.c 10.36 (Berkeley) 9/15/96";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/types.h> /* XXX: param.h may not have included types.h */
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+#include "tag.h"
+
+static char *binary_search __P((char *, char *, char *));
+static int compare __P((char *, char *, char *));
+static void ctag_file __P((SCR *, TAGF *, char *, char **, size_t *));
+static int ctag_search __P((SCR *, char *, size_t, char *));
+static int ctag_sfile __P((SCR *, TAGF *, TAGQ *, char *));
+static TAGQ *ctag_slist __P((SCR *, char *));
+static char *linear_search __P((char *, char *, char *));
+static int tag_copy __P((SCR *, TAG *, TAG **));
+static int tag_pop __P((SCR *, TAGQ *, int));
+static int tagf_copy __P((SCR *, TAGF *, TAGF **));
+static int tagf_free __P((SCR *, TAGF *));
+static int tagq_copy __P((SCR *, TAGQ *, TAGQ **));
+
+/*
+ * ex_tag_first --
+ * The tag code can be entered from main, e.g., "vi -t tag".
+ *
+ * PUBLIC: int ex_tag_first __P((SCR *, char *));
+ */
+int
+ex_tag_first(sp, tagarg)
+ SCR *sp;
+ char *tagarg;
+{
+ ARGS *ap[2], a;
+ EXCMD cmd;
+
+ /* Build an argument for the ex :tag command. */
+ ex_cinit(&cmd, C_TAG, 0, OOBLNO, OOBLNO, 0, ap);
+ ex_cadd(&cmd, &a, tagarg, strlen(tagarg));
+
+ /*
+ * XXX
+ * Historic vi went ahead and created a temporary file when it failed
+ * to find the tag. We match historic practice, but don't distinguish
+ * between real error and failure to find the tag.
+ */
+ if (ex_tag_push(sp, &cmd))
+ return (0);
+
+ /* Display tags in the center of the screen. */
+ F_CLR(sp, SC_SCR_TOP);
+ F_SET(sp, SC_SCR_CENTER);
+
+ return (0);
+}
+
+/*
+ * ex_tag_push -- ^]
+ * :tag[!] [string]
+ *
+ * Enter a new TAGQ context based on a ctag string.
+ *
+ * PUBLIC: int ex_tag_push __P((SCR *, EXCMD *));
+ */
+int
+ex_tag_push(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ EX_PRIVATE *exp;
+ FREF *frp;
+ TAG *rtp;
+ TAGQ *rtqp, *tqp;
+ recno_t lno;
+ size_t cno;
+ long tl;
+ int force, istmp;
+
+ exp = EXP(sp);
+ switch (cmdp->argc) {
+ case 1:
+ if (exp->tag_last != NULL)
+ free(exp->tag_last);
+
+ if ((exp->tag_last = strdup(cmdp->argv[0]->bp)) == NULL) {
+ msgq(sp, M_SYSERR, NULL);
+ return (1);
+ }
+
+ /* Taglength may limit the number of characters. */
+ if ((tl =
+ O_VAL(sp, O_TAGLENGTH)) != 0 && strlen(exp->tag_last) > tl)
+ exp->tag_last[tl] = '\0';
+ break;
+ case 0:
+ if (exp->tag_last == NULL) {
+ msgq(sp, M_ERR, "158|No previous tag entered");
+ return (1);
+ }
+ break;
+ default:
+ abort();
+ }
+
+ /* Get the tag information. */
+ if ((tqp = ctag_slist(sp, exp->tag_last)) == NULL)
+ return (1);
+
+ /*
+ * Allocate all necessary memory before swapping screens. Initialize
+ * flags so we know what to free.
+ */
+ rtp = NULL;
+ rtqp = NULL;
+ if (exp->tq.cqh_first == (void *)&exp->tq) {
+ /* Initialize the `local context' tag queue structure. */
+ CALLOC_GOTO(sp, rtqp, TAGQ *, 1, sizeof(TAGQ));
+ CIRCLEQ_INIT(&rtqp->tagq);
+
+ /* Initialize and link in its tag structure. */
+ CALLOC_GOTO(sp, rtp, TAG *, 1, sizeof(TAG));
+ CIRCLEQ_INSERT_HEAD(&rtqp->tagq, rtp, q);
+ rtqp->current = rtp;
+ }
+
+ /*
+ * Stick the current context information in a convenient place, we're
+ * about to lose it. Note, if we're called on editor startup, there
+ * will be no FREF structure.
+ */
+ frp = sp->frp;
+ lno = sp->lno;
+ cno = sp->cno;
+ istmp = frp == NULL ||
+ F_ISSET(frp, FR_TMPFILE) && !F_ISSET(cmdp, E_NEWSCREEN);
+
+ /* Try to switch to the tag. */
+ force = FL_ISSET(cmdp->iflags, E_C_FORCE);
+ if (F_ISSET(cmdp, E_NEWSCREEN)) {
+ if (ex_tag_Nswitch(sp, tqp->tagq.cqh_first, force))
+ goto err;
+
+ /* Everything else gets done in the new screen. */
+ sp = sp->nextdisp;
+ exp = EXP(sp);
+ } else
+ if (ex_tag_nswitch(sp, tqp->tagq.cqh_first, force))
+ goto err;
+
+ /*
+ * If this is the first tag, put a `current location' queue entry
+ * in place, so we can pop all the way back to the current mark.
+ * Note, it doesn't point to much of anything, it's a placeholder.
+ */
+ if (exp->tq.cqh_first == (void *)&exp->tq) {
+ CIRCLEQ_INSERT_HEAD(&exp->tq, rtqp, q);
+ } else
+ rtqp = exp->tq.cqh_first;
+
+ /* Link the new TAGQ structure into place. */
+ CIRCLEQ_INSERT_HEAD(&exp->tq, tqp, q);
+
+ (void)ctag_search(sp,
+ tqp->current->search, tqp->current->slen, tqp->tag);
+
+ /*
+ * Move the current context from the temporary save area into the
+ * right structure.
+ *
+ * If we were in a temporary file, we don't have a context to which
+ * we can return, so just make it be the same as what we're moving
+ * to. It will be a little odd that ^T doesn't change anything, but
+ * I don't think it's a big deal.
+ */
+ if (istmp) {
+ rtqp->current->frp = sp->frp;
+ rtqp->current->lno = sp->lno;
+ rtqp->current->cno = sp->cno;
+ } else {
+ rtqp->current->frp = frp;
+ rtqp->current->lno = lno;
+ rtqp->current->cno = cno;
+ }
+ return (0);
+
+err:
+alloc_err:
+ if (rtqp != NULL)
+ free(rtqp);
+ if (rtp != NULL)
+ free(rtp);
+ tagq_free(sp, tqp);
+ return (1);
+}
+
+/*
+ * ex_tag_next --
+ * Switch context to the next TAG.
+ *
+ * PUBLIC: int ex_tag_next __P((SCR *, EXCMD *));
+ */
+int
+ex_tag_next(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ EX_PRIVATE *exp;
+ TAG *tp;
+ TAGQ *tqp;
+
+ exp = EXP(sp);
+ if ((tqp = exp->tq.cqh_first) == (void *)&exp->tq) {
+ tag_msg(sp, TAG_EMPTY, NULL);
+ return (1);
+ }
+ if ((tp = tqp->current->q.cqe_next) == (void *)&tqp->tagq) {
+ msgq(sp, M_ERR, "282|Already at the last tag of this group");
+ return (1);
+ }
+ if (ex_tag_nswitch(sp, tp, FL_ISSET(cmdp->iflags, E_C_FORCE)))
+ return (1);
+ tqp->current = tp;
+
+ if (F_ISSET(tqp, TAG_CSCOPE))
+ (void)cscope_search(sp, tqp, tp);
+ else
+ (void)ctag_search(sp, tp->search, tp->slen, tqp->tag);
+ return (0);
+}
+
+/*
+ * ex_tag_prev --
+ * Switch context to the next TAG.
+ *
+ * PUBLIC: int ex_tag_prev __P((SCR *, EXCMD *));
+ */
+int
+ex_tag_prev(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ EX_PRIVATE *exp;
+ TAG *tp;
+ TAGQ *tqp;
+
+ exp = EXP(sp);
+ if ((tqp = exp->tq.cqh_first) == (void *)&exp->tq) {
+ tag_msg(sp, TAG_EMPTY, NULL);
+ return (0);
+ }
+ if ((tp = tqp->current->q.cqe_prev) == (void *)&tqp->tagq) {
+ msgq(sp, M_ERR, "255|Already at the first tag of this group");
+ return (1);
+ }
+ if (ex_tag_nswitch(sp, tp, FL_ISSET(cmdp->iflags, E_C_FORCE)))
+ return (1);
+ tqp->current = tp;
+
+ if (F_ISSET(tqp, TAG_CSCOPE))
+ (void)cscope_search(sp, tqp, tp);
+ else
+ (void)ctag_search(sp, tp->search, tp->slen, tqp->tag);
+ return (0);
+}
+
+/*
+ * ex_tag_nswitch --
+ * Switch context to the specified TAG.
+ *
+ * PUBLIC: int ex_tag_nswitch __P((SCR *, TAG *, int));
+ */
+int
+ex_tag_nswitch(sp, tp, force)
+ SCR *sp;
+ TAG *tp;
+ int force;
+{
+ /* Get a file structure. */
+ if (tp->frp == NULL && (tp->frp = file_add(sp, tp->fname)) == NULL)
+ return (1);
+
+ /* If not changing files, return, we're done. */
+ if (tp->frp == sp->frp)
+ return (0);
+
+ /* Check for permission to leave. */
+ if (file_m1(sp, force, FS_ALL | FS_POSSIBLE))
+ return (1);
+
+ /* Initialize the new file. */
+ if (file_init(sp, tp->frp, NULL, FS_SETALT))
+ return (1);
+
+ /* Display tags in the center of the screen. */
+ F_CLR(sp, SC_SCR_TOP);
+ F_SET(sp, SC_SCR_CENTER);
+
+ /* Switch. */
+ F_SET(sp, SC_FSWITCH);
+ return (0);
+}
+
+/*
+ * ex_tag_Nswitch --
+ * Switch context to the specified TAG in a new screen.
+ *
+ * PUBLIC: int ex_tag_Nswitch __P((SCR *, TAG *, int));
+ */
+int
+ex_tag_Nswitch(sp, tp, force)
+ SCR *sp;
+ TAG *tp;
+ int force;
+{
+ SCR *new;
+
+ /* Get a file structure. */
+ if (tp->frp == NULL && (tp->frp = file_add(sp, tp->fname)) == NULL)
+ return (1);
+
+ /* Get a new screen. */
+ if (screen_init(sp->gp, sp, &new))
+ return (1);
+ if (vs_split(sp, new, 0)) {
+ (void)file_end(new, new->ep, 1);
+ (void)screen_end(new);
+ return (1);
+ }
+
+ /* Get a backing file. */
+ if (tp->frp == sp->frp) {
+ /* Copy file state. */
+ new->ep = sp->ep;
+ ++new->ep->refcnt;
+
+ new->frp = tp->frp;
+ new->frp->flags = sp->frp->flags;
+ } else if (file_init(new, tp->frp, NULL, force)) {
+ (void)vs_discard(new, NULL);
+ (void)screen_end(new);
+ return (1);
+ }
+
+ /* Create the argument list. */
+ new->cargv = new->argv = ex_buildargv(sp, NULL, tp->frp->name);
+
+ /* Display tags in the center of the screen. */
+ F_CLR(new, SC_SCR_TOP);
+ F_SET(new, SC_SCR_CENTER);
+
+ /* Switch. */
+ sp->nextdisp = new;
+ F_SET(sp, SC_SSWITCH);
+
+ return (0);
+}
+
+/*
+ * ex_tag_pop -- ^T
+ * :tagp[op][!] [number | file]
+ *
+ * Pop to a previous TAGQ context.
+ *
+ * PUBLIC: int ex_tag_pop __P((SCR *, EXCMD *));
+ */
+int
+ex_tag_pop(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ EX_PRIVATE *exp;
+ TAGQ *tqp, *dtqp;
+ size_t arglen;
+ long off;
+ char *arg, *p, *t;
+
+ /* Check for an empty stack. */
+ exp = EXP(sp);
+ if (exp->tq.cqh_first == (void *)&exp->tq) {
+ tag_msg(sp, TAG_EMPTY, NULL);
+ return (1);
+ }
+
+ /* Find the last TAG structure that we're going to DISCARD! */
+ switch (cmdp->argc) {
+ case 0: /* Pop one tag. */
+ dtqp = exp->tq.cqh_first;
+ break;
+ case 1: /* Name or number. */
+ arg = cmdp->argv[0]->bp;
+ off = strtol(arg, &p, 10);
+ if (*p != '\0')
+ goto filearg;
+
+ /* Number: pop that many queue entries. */
+ if (off < 1)
+ return (0);
+ for (tqp = exp->tq.cqh_first;
+ tqp != (void *)&exp->tq && --off > 1;
+ tqp = tqp->q.cqe_next);
+ if (tqp == (void *)&exp->tq) {
+ msgq(sp, M_ERR,
+ "159|Less than %s entries on the tags stack; use :display t[ags]",
+ arg);
+ return (1);
+ }
+ dtqp = tqp;
+ break;
+
+ /* File argument: pop to that queue entry. */
+filearg: arglen = strlen(arg);
+ for (tqp = exp->tq.cqh_first;
+ tqp != (void *)&exp->tq;
+ dtqp = tqp, tqp = tqp->q.cqe_next) {
+ /* Don't pop to the current file. */
+ if (tqp == exp->tq.cqh_first)
+ continue;
+ p = tqp->current->frp->name;
+ if ((t = strrchr(p, '/')) == NULL)
+ t = p;
+ else
+ ++t;
+ if (!strncmp(arg, t, arglen))
+ break;
+ }
+ if (tqp == (void *)&exp->tq) {
+ msgq_str(sp, M_ERR, arg,
+ "160|No file %s on the tags stack to return to; use :display t[ags]");
+ return (1);
+ }
+ if (tqp == exp->tq.cqh_first)
+ return (0);
+ break;
+ default:
+ abort();
+ }
+
+ return (tag_pop(sp, dtqp, FL_ISSET(cmdp->iflags, E_C_FORCE)));
+}
+
+/*
+ * ex_tag_top -- :tagt[op][!]
+ * Clear the tag stack.
+ *
+ * PUBLIC: int ex_tag_top __P((SCR *, EXCMD *));
+ */
+int
+ex_tag_top(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ EX_PRIVATE *exp;
+
+ exp = EXP(sp);
+
+ /* Check for an empty stack. */
+ if (exp->tq.cqh_first == (void *)&exp->tq) {
+ tag_msg(sp, TAG_EMPTY, NULL);
+ return (1);
+ }
+
+ /* Return to the oldest information. */
+ return (tag_pop(sp,
+ exp->tq.cqh_last->q.cqe_prev, FL_ISSET(cmdp->iflags, E_C_FORCE)));
+}
+
+/*
+ * tag_pop --
+ * Pop up to and including the specified TAGQ context.
+ */
+static int
+tag_pop(sp, dtqp, force)
+ SCR *sp;
+ TAGQ *dtqp;
+ int force;
+{
+ EX_PRIVATE *exp;
+ TAG *tp;
+ TAGQ *tqp;
+
+ exp = EXP(sp);
+
+ /*
+ * Update the cursor from the saved TAG information of the TAG
+ * structure we're moving to.
+ */
+ tp = dtqp->q.cqe_next->current;
+ if (tp->frp == sp->frp) {
+ sp->lno = tp->lno;
+ sp->cno = tp->cno;
+ } else {
+ if (file_m1(sp, force, FS_ALL | FS_POSSIBLE))
+ return (1);
+
+ tp->frp->lno = tp->lno;
+ tp->frp->cno = tp->cno;
+ F_SET(sp->frp, FR_CURSORSET);
+ if (file_init(sp, tp->frp, NULL, FS_SETALT))
+ return (1);
+
+ F_SET(sp, SC_FSWITCH);
+ }
+
+ /* Pop entries off the queue up to and including dtqp. */
+ do {
+ tqp = exp->tq.cqh_first;
+ if (tagq_free(sp, tqp))
+ return (0);
+ } while (tqp != dtqp);
+
+ /*
+ * If only a single tag left, we've returned to the first tag point,
+ * and the stack is now empty.
+ */
+ if (exp->tq.cqh_first->q.cqe_next == (void *)&exp->tq)
+ tagq_free(sp, exp->tq.cqh_first);
+
+ return (0);
+}
+
+/*
+ * ex_tag_display --
+ * Display the list of tags.
+ *
+ * PUBLIC: int ex_tag_display __P((SCR *));
+ */
+int
+ex_tag_display(sp)
+ SCR *sp;
+{
+ EX_PRIVATE *exp;
+ TAG *tp;
+ TAGQ *tqp;
+ int cnt;
+ size_t len;
+ char *p, *sep;
+
+ exp = EXP(sp);
+ if ((tqp = exp->tq.cqh_first) == (void *)&exp->tq) {
+ tag_msg(sp, TAG_EMPTY, NULL);
+ return (0);
+ }
+
+ /*
+ * We give the file name 20 columns and the search string the rest.
+ * If there's not enough room, we don't do anything special, it's
+ * not worth the effort, it just makes the display more confusing.
+ *
+ * We also assume that characters in file names map 1-1 to printing
+ * characters. This might not be true, but I don't think it's worth
+ * fixing. (The obvious fix is to pass the filenames through the
+ * msg_print function.)
+ */
+#define L_NAME 30 /* Name. */
+#define L_SLOP 4 /* Leading number plus trailing *. */
+#define L_SPACE 5 /* Spaces after name, before tag. */
+#define L_TAG 20 /* Tag. */
+ if (sp->cols <= L_NAME + L_SLOP) {
+ msgq(sp, M_ERR, "292|Display too small.");
+ return (0);
+ }
+
+ /*
+ * Display the list of tags for each queue entry. The first entry
+ * is numbered, and the current tag entry has an asterisk appended.
+ */
+ for (cnt = 1, tqp = exp->tq.cqh_first; !INTERRUPTED(sp) &&
+ tqp != (void *)&exp->tq; ++cnt, tqp = tqp->q.cqe_next)
+ for (tp = tqp->tagq.cqh_first;
+ tp != (void *)&tqp->tagq; tp = tp->q.cqe_next) {
+ if (tp == tqp->tagq.cqh_first)
+ (void)ex_printf(sp, "%2d ", cnt);
+ else
+ (void)ex_printf(sp, " ");
+ p = tp->frp == NULL ? tp->fname : tp->frp->name;
+ if ((len = strlen(p)) > L_NAME) {
+ len = len - (L_NAME - 4);
+ (void)ex_printf(sp, " ... %*.*s",
+ L_NAME - 4, L_NAME - 4, p + len);
+ } else
+ (void)ex_printf(sp,
+ " %*.*s", L_NAME, L_NAME, p);
+ if (tqp->current == tp)
+ (void)ex_printf(sp, "*");
+
+ if (tp == tqp->tagq.cqh_first && tqp->tag != NULL &&
+ (sp->cols - L_NAME) >= L_TAG + L_SPACE) {
+ len = strlen(tqp->tag);
+ if (len > sp->cols - (L_NAME + L_SPACE))
+ len = sp->cols - (L_NAME + L_SPACE);
+ (void)ex_printf(sp, "%s%.*s",
+ tqp->current == tp ? " " : " ",
+ (int)len, tqp->tag);
+ }
+ (void)ex_printf(sp, "\n");
+ }
+ return (0);
+}
+
+/*
+ * ex_tag_copy --
+ * Copy a screen's tag structures.
+ *
+ * PUBLIC: int ex_tag_copy __P((SCR *, SCR *));
+ */
+int
+ex_tag_copy(orig, sp)
+ SCR *orig, *sp;
+{
+ EX_PRIVATE *oexp, *nexp;
+ TAGQ *aqp, *tqp;
+ TAG *ap, *tp;
+ TAGF *atfp, *tfp;
+
+ oexp = EXP(orig);
+ nexp = EXP(sp);
+
+ /* Copy tag queue and tags stack. */
+ for (aqp = oexp->tq.cqh_first;
+ aqp != (void *)&oexp->tq; aqp = aqp->q.cqe_next) {
+ if (tagq_copy(sp, aqp, &tqp))
+ return (1);
+ for (ap = aqp->tagq.cqh_first;
+ ap != (void *)&aqp->tagq; ap = ap->q.cqe_next) {
+ if (tag_copy(sp, ap, &tp))
+ return (1);
+ /* Set the current pointer. */
+ if (aqp->current == ap)
+ tqp->current = tp;
+ CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
+ }
+ CIRCLEQ_INSERT_TAIL(&nexp->tq, tqp, q);
+ }
+
+ /* Copy list of tag files. */
+ for (atfp = oexp->tagfq.tqh_first;
+ atfp != NULL; atfp = atfp->q.tqe_next) {
+ if (tagf_copy(sp, atfp, &tfp))
+ return (1);
+ TAILQ_INSERT_TAIL(&nexp->tagfq, tfp, q);
+ }
+
+ /* Copy the last tag. */
+ if (oexp->tag_last != NULL &&
+ (nexp->tag_last = strdup(oexp->tag_last)) == NULL) {
+ msgq(sp, M_SYSERR, NULL);
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * tagf_copy --
+ * Copy a TAGF structure and return it in new memory.
+ */
+static int
+tagf_copy(sp, otfp, tfpp)
+ SCR *sp;
+ TAGF *otfp, **tfpp;
+{
+ TAGF *tfp;
+
+ MALLOC_RET(sp, tfp, TAGF *, sizeof(TAGF));
+ *tfp = *otfp;
+
+ /* XXX: Allocate as part of the TAGF structure!!! */
+ if ((tfp->name = strdup(otfp->name)) == NULL)
+ return (1);
+
+ *tfpp = tfp;
+ return (0);
+}
+
+/*
+ * tagq_copy --
+ * Copy a TAGQ structure and return it in new memory.
+ */
+static int
+tagq_copy(sp, otqp, tqpp)
+ SCR *sp;
+ TAGQ *otqp, **tqpp;
+{
+ TAGQ *tqp;
+ size_t len;
+
+ len = sizeof(TAGQ);
+ if (otqp->tag != NULL)
+ len += otqp->tlen + 1;
+ MALLOC_RET(sp, tqp, TAGQ *, len);
+ memcpy(tqp, otqp, len);
+
+ CIRCLEQ_INIT(&tqp->tagq);
+ tqp->current = NULL;
+ if (otqp->tag != NULL)
+ tqp->tag = tqp->buf;
+
+ *tqpp = tqp;
+ return (0);
+}
+
+/*
+ * tag_copy --
+ * Copy a TAG structure and return it in new memory.
+ */
+static int
+tag_copy(sp, otp, tpp)
+ SCR *sp;
+ TAG *otp, **tpp;
+{
+ TAG *tp;
+ size_t len;
+
+ len = sizeof(TAG);
+ if (otp->fname != NULL)
+ len += otp->fnlen + 1;
+ if (otp->search != NULL)
+ len += otp->slen + 1;
+ MALLOC_RET(sp, tp, TAG *, len);
+ memcpy(tp, otp, len);
+
+ if (otp->fname != NULL)
+ tp->fname = tp->buf;
+ if (otp->search != NULL)
+ tp->search = tp->fname + otp->fnlen + 1;
+
+ *tpp = tp;
+ return (0);
+}
+
+/*
+ * tagf_free --
+ * Free a TAGF structure.
+ */
+static int
+tagf_free(sp, tfp)
+ SCR *sp;
+ TAGF *tfp;
+{
+ EX_PRIVATE *exp;
+
+ exp = EXP(sp);
+ TAILQ_REMOVE(&exp->tagfq, tfp, q);
+ free(tfp->name);
+ free(tfp);
+ return (0);
+}
+
+/*
+ * tagq_free --
+ * Free a TAGQ structure (and associated TAG structures).
+ *
+ * PUBLIC: int tagq_free __P((SCR *, TAGQ *));
+ */
+int
+tagq_free(sp, tqp)
+ SCR *sp;
+ TAGQ *tqp;
+{
+ EX_PRIVATE *exp;
+ TAG *tp;
+
+ exp = EXP(sp);
+ while ((tp = tqp->tagq.cqh_first) != (void *)&tqp->tagq) {
+ CIRCLEQ_REMOVE(&tqp->tagq, tp, q);
+ free(tp);
+ }
+ /*
+ * !!!
+ * If allocated and then the user failed to switch files, the TAGQ
+ * structure was never attached to any list.
+ */
+ if (tqp->q.cqe_next != NULL)
+ CIRCLEQ_REMOVE(&exp->tq, tqp, q);
+ free(tqp);
+ return (0);
+}
+
+/*
+ * tag_msg
+ * A few common messages.
+ *
+ * PUBLIC: void tag_msg __P((SCR *, tagmsg_t, char *));
+ */
+void
+tag_msg(sp, msg, tag)
+ SCR *sp;
+ tagmsg_t msg;
+ char *tag;
+{
+ switch (msg) {
+ case TAG_BADLNO:
+ msgq_str(sp, M_ERR, tag,
+ "164|%s: the tag's line number is past the end of the file");
+ break;
+ case TAG_EMPTY:
+ msgq(sp, M_INFO, "165|The tags stack is empty");
+ break;
+ case TAG_SEARCH:
+ msgq_str(sp, M_ERR, tag, "166|%s: search pattern not found");
+ break;
+ default:
+ abort();
+ }
+}
+
+/*
+ * ex_tagf_alloc --
+ * Create a new list of ctag files.
+ *
+ * PUBLIC: int ex_tagf_alloc __P((SCR *, char *));
+ */
+int
+ex_tagf_alloc(sp, str)
+ SCR *sp;
+ char *str;
+{
+ EX_PRIVATE *exp;
+ TAGF *tfp;
+ size_t len;
+ char *p, *t;
+
+ /* Free current queue. */
+ exp = EXP(sp);
+ while ((tfp = exp->tagfq.tqh_first) != NULL)
+ tagf_free(sp, tfp);
+
+ /* Create new queue. */
+ for (p = t = str;; ++p) {
+ if (*p == '\0' || isblank(*p)) {
+ if ((len = p - t) > 1) {
+ MALLOC_RET(sp, tfp, TAGF *, sizeof(TAGF));
+ MALLOC(sp, tfp->name, char *, len + 1);
+ if (tfp->name == NULL) {
+ free(tfp);
+ return (1);
+ }
+ memcpy(tfp->name, t, len);
+ tfp->name[len] = '\0';
+ tfp->flags = 0;
+ TAILQ_INSERT_TAIL(&exp->tagfq, tfp, q);
+ }
+ t = p + 1;
+ }
+ if (*p == '\0')
+ break;
+ }
+ return (0);
+}
+ /* Free previous queue. */
+/*
+ * ex_tag_free --
+ * Free the ex tag information.
+ *
+ * PUBLIC: int ex_tag_free __P((SCR *));
+ */
+int
+ex_tag_free(sp)
+ SCR *sp;
+{
+ EX_PRIVATE *exp;
+ TAGF *tfp;
+ TAGQ *tqp;
+
+ /* Free up tag information. */
+ exp = EXP(sp);
+ while ((tqp = exp->tq.cqh_first) != (void *)&exp->tq)
+ tagq_free(sp, tqp);
+ while ((tfp = exp->tagfq.tqh_first) != NULL)
+ tagf_free(sp, tfp);
+ if (exp->tag_last != NULL)
+ free(exp->tag_last);
+ return (0);
+}
+
+/*
+ * ctag_search --
+ * Search a file for a tag.
+ */
+static int
+ctag_search(sp, search, slen, tag)
+ SCR *sp;
+ char *search, *tag;
+ size_t slen;
+{
+ MARK m;
+ char *p;
+
+ /*
+ * !!!
+ * The historic tags file format (from a long, long time ago...)
+ * used a line number, not a search string. I got complaints, so
+ * people are still using the format. POSIX 1003.2 permits it.
+ */
+ if (isdigit(search[0])) {
+ m.lno = atoi(search);
+ if (!db_exist(sp, m.lno)) {
+ tag_msg(sp, TAG_BADLNO, tag);
+ return (1);
+ }
+ } else {
+ /*
+ * Search for the tag; cheap fallback for C functions
+ * if the name is the same but the arguments have changed.
+ */
+ m.lno = 1;
+ m.cno = 0;
+ if (f_search(sp, &m, &m,
+ search, slen, NULL, SEARCH_FILE | SEARCH_TAG))
+ if ((p = strrchr(search, '(')) != NULL) {
+ slen = p - search;
+ if (f_search(sp, &m, &m, search, slen,
+ NULL, SEARCH_FILE | SEARCH_TAG))
+ goto notfound;
+ } else {
+notfound: tag_msg(sp, TAG_SEARCH, tag);
+ return (1);
+ }
+ /*
+ * !!!
+ * Historically, tags set the search direction if it wasn't
+ * already set.
+ */
+ if (sp->searchdir == NOTSET)
+ sp->searchdir = FORWARD;
+ }
+
+ /*
+ * !!!
+ * Tags move to the first non-blank, NOT the search pattern start.
+ */
+ sp->lno = m.lno;
+ sp->cno = 0;
+ (void)nonblank(sp, sp->lno, &sp->cno);
+ return (0);
+}
+
+/*
+ * ctag_slist --
+ * Search the list of tags files for a tag, and return tag queue.
+ */
+static TAGQ *
+ctag_slist(sp, tag)
+ SCR *sp;
+ char *tag;
+{
+ EX_PRIVATE *exp;
+ TAGF *tfp;
+ TAGQ *tqp;
+ size_t len;
+ int echk;
+
+ exp = EXP(sp);
+
+ /* Allocate and initialize the tag queue structure. */
+ len = strlen(tag);
+ CALLOC_GOTO(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + len + 1);
+ CIRCLEQ_INIT(&tqp->tagq);
+ tqp->tag = tqp->buf;
+ memcpy(tqp->tag, tag, (tqp->tlen = len) + 1);
+
+ /*
+ * Find the tag, only display missing file messages once, and
+ * then only if we didn't find the tag.
+ */
+ for (echk = 0,
+ tfp = exp->tagfq.tqh_first; tfp != NULL; tfp = tfp->q.tqe_next)
+ if (ctag_sfile(sp, tfp, tqp, tag)) {
+ echk = 1;
+ F_SET(tfp, TAGF_ERR);
+ } else
+ F_CLR(tfp, TAGF_ERR | TAGF_ERR_WARN);
+
+ /* Check to see if we found anything. */
+ if (tqp->tagq.cqh_first == (void *)&tqp->tagq) {
+ msgq_str(sp, M_ERR, tag, "162|%s: tag not found");
+ if (echk)
+ for (tfp = exp->tagfq.tqh_first;
+ tfp != NULL; tfp = tfp->q.tqe_next)
+ if (F_ISSET(tfp, TAGF_ERR) &&
+ !F_ISSET(tfp, TAGF_ERR_WARN)) {
+ errno = tfp->errnum;
+ msgq_str(sp, M_SYSERR, tfp->name, "%s");
+ F_SET(tfp, TAGF_ERR_WARN);
+ }
+ free(tqp);
+ return (NULL);
+ }
+
+ tqp->current = tqp->tagq.cqh_first;
+ return (tqp);
+
+alloc_err:
+ return (NULL);
+}
+
+/*
+ * ctag_sfile --
+ * Search a tags file for a tag, adding any found to the tag queue.
+ */
+static int
+ctag_sfile(sp, tfp, tqp, tname)
+ SCR *sp;
+ TAGF *tfp;
+ TAGQ *tqp;
+ char *tname;
+{
+ struct stat sb;
+ TAG *tp;
+ size_t dlen, nlen, slen;
+ int fd, i, nf1, nf2;
+ char *back, *cname, *dname, *front, *map, *name, *p, *search, *t;
+
+ if ((fd = open(tfp->name, O_RDONLY, 0)) < 0) {
+ tfp->errnum = errno;
+ return (1);
+ }
+
+ /*
+ * XXX
+ * Some old BSD systems require MAP_FILE as an argument when mapping
+ * regular files.
+ */
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+ /*
+ * XXX
+ * We'd like to test if the file is too big to mmap. Since we don't
+ * know what size or type off_t's or size_t's are, what the largest
+ * unsigned integral type is, or what random insanity the local C
+ * compiler will perpetrate, doing the comparison in a portable way
+ * is flatly impossible. Hope mmap fails if the file is too large.
+ */
+ if (fstat(fd, &sb) != 0 ||
+ (map = mmap(NULL, (size_t)sb.st_size, PROT_READ | PROT_WRITE,
+ MAP_FILE | MAP_PRIVATE, fd, (off_t)0)) == (caddr_t)-1) {
+ tfp->errnum = errno;
+ (void)close(fd);
+ return (1);
+ }
+
+ front = map;
+ back = front + sb.st_size;
+ front = binary_search(tname, front, back);
+ front = linear_search(tname, front, back);
+ if (front == NULL)
+ goto done;
+
+ /*
+ * Initialize and link in the tag structure(s). The historic ctags
+ * file format only permitted a single tag location per tag. The
+ * obvious extension to permit multiple tags locations per tag is to
+ * output multiple records in the standard format. Unfortunately,
+ * this won't work correctly with historic ex/vi implementations,
+ * because their binary search assumes that there's only one record
+ * per tag, and so will use a random tag entry if there si more than
+ * one. This code handles either format.
+ *
+ * The tags file is in the following format:
+ *
+ * <tag> <filename> <line number> | <pattern>
+ *
+ * Figure out how long everything is so we can allocate in one swell
+ * foop, but discard anything that looks wrong.
+ */
+ for (;;) {
+ /* Nul-terminate the end of the line. */
+ for (p = front; p < back && *p != '\n'; ++p);
+ if (p == back || *p != '\n')
+ break;
+ *p = '\0';
+
+ /* Update the pointers for the next time. */
+ t = p + 1;
+ p = front;
+ front = t;
+
+ /* Break the line into tokens. */
+ for (i = 0; i < 2 && (t = strsep(&p, "\t ")) != NULL; ++i)
+ switch (i) {
+ case 0: /* Tag. */
+ cname = t;
+ break;
+ case 1: /* Filename. */
+ name = t;
+ nlen = strlen(name);
+ break;
+ }
+
+ /* Check for corruption. */
+ if (i != 2 || p == NULL || t == NULL)
+ goto corrupt;
+
+ /* The rest of the string is the search pattern. */
+ search = p;
+ if ((slen = strlen(p)) == 0) {
+corrupt: p = msg_print(sp, tname, &nf1);
+ t = msg_print(sp, tfp->name, &nf2);
+ msgq(sp, M_ERR, "163|%s: corrupted tag in %s", p, t);
+ if (nf1)
+ FREE_SPACE(sp, p, 0);
+ if (nf2)
+ FREE_SPACE(sp, t, 0);
+ continue;
+ }
+
+ /* Check for passing the last entry. */
+ if (strcmp(tname, cname))
+ break;
+
+ /* Resolve the file name. */
+ ctag_file(sp, tfp, name, &dname, &dlen);
+
+ CALLOC_GOTO(sp, tp,
+ TAG *, 1, sizeof(TAG) + dlen + 2 + nlen + 1 + slen + 1);
+ tp->fname = tp->buf;
+ if (dlen != 0) {
+ memcpy(tp->fname, dname, dlen);
+ tp->fname[dlen] = '/';
+ ++dlen;
+ }
+ memcpy(tp->fname + dlen, name, nlen + 1);
+ tp->fnlen = dlen + nlen;
+ tp->search = tp->fname + tp->fnlen + 1;
+ memcpy(tp->search, search, (tp->slen = slen) + 1);
+ CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
+ }
+
+alloc_err:
+done: if (munmap(map, (size_t)sb.st_size))
+ msgq(sp, M_SYSERR, "munmap");
+ if (close(fd))
+ msgq(sp, M_SYSERR, "close");
+ return (0);
+}
+
+/*
+ * ctag_file --
+ * Search for the right path to this file.
+ */
+static void
+ctag_file(sp, tfp, name, dirp, dlenp)
+ SCR *sp;
+ TAGF *tfp;
+ char *name, **dirp;
+ size_t *dlenp;
+{
+ struct stat sb;
+ size_t len;
+ char *p, buf[MAXPATHLEN];
+
+ /*
+ * !!!
+ * If the tag file path is a relative path, see if it exists. If it
+ * doesn't, look relative to the tags file path. It's okay for a tag
+ * file to not exist, and historically, vi simply displayed a "new"
+ * file. However, if the path exists relative to the tag file, it's
+ * pretty clear what's happening, so we may as well get it right.
+ */
+ *dlenp = 0;
+ if (name[0] != '/' &&
+ stat(name, &sb) && (p = strrchr(tfp->name, '/')) != NULL) {
+ *p = '\0';
+ len = snprintf(buf, sizeof(buf), "%s/%s", tfp->name, name);
+ *p = '/';
+ if (stat(buf, &sb) == 0) {
+ *dirp = tfp->name;
+ *dlenp = strlen(*dirp);
+ }
+ }
+}
+
+/*
+ * Binary search for "string" in memory between "front" and "back".
+ *
+ * This routine is expected to return a pointer to the start of a line at
+ * *or before* the first word matching "string". Relaxing the constraint
+ * this way simplifies the algorithm.
+ *
+ * Invariants:
+ * front points to the beginning of a line at or before the first
+ * matching string.
+ *
+ * back points to the beginning of a line at or after the first
+ * matching line.
+ *
+ * Base of the Invariants.
+ * front = NULL;
+ * back = EOF;
+ *
+ * Advancing the Invariants:
+ *
+ * p = first newline after halfway point from front to back.
+ *
+ * If the string at "p" is not greater than the string to match,
+ * p is the new front. Otherwise it is the new back.
+ *
+ * Termination:
+ *
+ * The definition of the routine allows it return at any point,
+ * since front is always at or before the line to print.
+ *
+ * In fact, it returns when the chosen "p" equals "back". This
+ * implies that there exists a string is least half as long as
+ * (back - front), which in turn implies that a linear search will
+ * be no more expensive than the cost of simply printing a string or two.
+ *
+ * Trying to continue with binary search at this point would be
+ * more trouble than it's worth.
+ */
+#define EQUAL 0
+#define GREATER 1
+#define LESS (-1)
+
+#define SKIP_PAST_NEWLINE(p, back) while (p < back && *p++ != '\n');
+
+static char *
+binary_search(string, front, back)
+ register char *string, *front, *back;
+{
+ register char *p;
+
+ p = front + (back - front) / 2;
+ SKIP_PAST_NEWLINE(p, back);
+
+ while (p != back) {
+ if (compare(string, p, back) == GREATER)
+ front = p;
+ else
+ back = p;
+ p = front + (back - front) / 2;
+ SKIP_PAST_NEWLINE(p, back);
+ }
+ return (front);
+}
+
+/*
+ * Find the first line that starts with string, linearly searching from front
+ * to back.
+ *
+ * Return NULL for no such line.
+ *
+ * This routine assumes:
+ *
+ * o front points at the first character in a line.
+ * o front is before or at the first line to be printed.
+ */
+static char *
+linear_search(string, front, back)
+ char *string, *front, *back;
+{
+ while (front < back) {
+ switch (compare(string, front, back)) {
+ case EQUAL: /* Found it. */
+ return (front);
+ case LESS: /* No such string. */
+ return (NULL);
+ case GREATER: /* Keep going. */
+ break;
+ }
+ SKIP_PAST_NEWLINE(front, back);
+ }
+ return (NULL);
+}
+
+/*
+ * Return LESS, GREATER, or EQUAL depending on how the string1 compares
+ * with string2 (s1 ??? s2).
+ *
+ * o Matches up to len(s1) are EQUAL.
+ * o Matches up to len(s2) are GREATER.
+ *
+ * The string "s1" is null terminated. The string s2 is '\t', space, (or
+ * "back") terminated.
+ *
+ * !!!
+ * Reasonably modern ctags programs use tabs as separators, not spaces.
+ * However, historic programs did use spaces, and, I got complaints.
+ */
+static int
+compare(s1, s2, back)
+ register char *s1, *s2, *back;
+{
+ for (; *s1 && s2 < back && (*s2 != '\t' && *s2 != ' '); ++s1, ++s2)
+ if (*s1 != *s2)
+ return (*s1 < *s2 ? LESS : GREATER);
+ return (*s1 ? GREATER : s2 < back &&
+ (*s2 != '\t' && *s2 != ' ') ? LESS : EQUAL);
+}
diff --git a/contrib/nvi/ex/ex_tcl.c b/contrib/nvi/ex/ex_tcl.c
new file mode 100644
index 000000000000..06736a781006
--- /dev/null
+++ b/contrib/nvi/ex/ex_tcl.c
@@ -0,0 +1,80 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ * Copyright (c) 1995
+ * George V. Neville-Neil. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_tcl.c 8.10 (Berkeley) 9/15/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+#ifdef HAVE_TCL_INTERP
+#include <tcl.h>
+#endif
+
+/*
+ * ex_tcl -- :[line [,line]] tcl [command]
+ * Run a command through the tcl interpreter.
+ *
+ * PUBLIC: int ex_tcl __P((SCR*, EXCMD *));
+ */
+int
+ex_tcl(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+#ifdef HAVE_TCL_INTERP
+ CHAR_T *p;
+ GS *gp;
+ size_t len;
+ char buf[128];
+
+ /* Initialize the interpreter. */
+ gp = sp->gp;
+ if (gp->tcl_interp == NULL && tcl_init(gp))
+ return (1);
+
+ /* Skip leading white space. */
+ if (cmdp->argc != 0)
+ for (p = cmdp->argv[0]->bp,
+ len = cmdp->argv[0]->len; len > 0; --len, ++p)
+ if (!isblank(*p))
+ break;
+ if (cmdp->argc == 0 || len == 0) {
+ ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+ return (1);
+ }
+
+ (void)snprintf(buf, sizeof(buf),
+ "set viScreenId %d\nset viStartLine %lu\nset viStopLine %lu",
+ sp->id, cmdp->addr1.lno, cmdp->addr2.lno);
+ if (Tcl_Eval(gp->tcl_interp, buf) == TCL_OK &&
+ Tcl_Eval(gp->tcl_interp, cmdp->argv[0]->bp) == TCL_OK)
+ return (0);
+
+ msgq(sp, M_ERR, "Tcl: %s", ((Tcl_Interp *)gp->tcl_interp)->result);
+ return (1);
+#else
+ msgq(sp, M_ERR, "302|Vi was not loaded with a Tcl interpreter");
+ return (1);
+#endif /* HAVE_TCL_INTERP */
+}
diff --git a/contrib/nvi/ex/ex_txt.c b/contrib/nvi/ex/ex_txt.c
new file mode 100644
index 000000000000..2f62ff51a47c
--- /dev/null
+++ b/contrib/nvi/ex/ex_txt.c
@@ -0,0 +1,430 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_txt.c 10.17 (Berkeley) 10/10/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+
+/*
+ * !!!
+ * The backslash characters was special when it preceded a newline as part of
+ * a substitution replacement pattern. For example, the input ":a\<cr>" would
+ * failed immediately with an error, as the <cr> wasn't part of a substitution
+ * replacement pattern. This implies a frightening integration of the editor
+ * and the parser and/or the RE engine. There's no way I'm going to reproduce
+ * those semantics.
+ *
+ * So, if backslashes are special, this code inserts the backslash and the next
+ * character into the string, without regard for the character or the command
+ * being entered. Since "\<cr>" was illegal historically (except for the one
+ * special case), and the command will fail eventually, no historical scripts
+ * should break (presuming they didn't depend on the failure mode itself or the
+ * characters remaining when failure occurred.
+ */
+
+static int txt_dent __P((SCR *, TEXT *));
+static void txt_prompt __P((SCR *, TEXT *, ARG_CHAR_T, u_int32_t));
+
+/*
+ * ex_txt --
+ * Get lines from the terminal for ex.
+ *
+ * PUBLIC: int ex_txt __P((SCR *, TEXTH *, ARG_CHAR_T, u_int32_t));
+ */
+int
+ex_txt(sp, tiqh, prompt, flags)
+ SCR *sp;
+ TEXTH *tiqh;
+ ARG_CHAR_T prompt;
+ u_int32_t flags;
+{
+ EVENT ev;
+ GS *gp;
+ TEXT ait, *ntp, *tp;
+ carat_t carat_st;
+ size_t cnt;
+ int rval;
+
+ rval = 0;
+
+ /*
+ * Get a TEXT structure with some initial buffer space, reusing the
+ * last one if it's big enough. (All TEXT bookkeeping fields default
+ * to 0 -- text_init() handles this.)
+ */
+ if (tiqh->cqh_first != (void *)tiqh) {
+ tp = tiqh->cqh_first;
+ if (tp->q.cqe_next != (void *)tiqh || tp->lb_len < 32) {
+ text_lfree(tiqh);
+ goto newtp;
+ }
+ tp->len = 0;
+ } else {
+newtp: if ((tp = text_init(sp, NULL, 0, 32)) == NULL)
+ goto err;
+ CIRCLEQ_INSERT_HEAD(tiqh, tp, q);
+ }
+
+ /* Set the starting line number. */
+ tp->lno = sp->lno + 1;
+
+ /*
+ * If it's a terminal, set up autoindent, put out the prompt, and
+ * set it up so we know we were suspended. Otherwise, turn off
+ * the autoindent flag, as that requires less special casing below.
+ *
+ * XXX
+ * Historic practice is that ^Z suspended command mode (but, because
+ * it ran in cooked mode, it was unaffected by the autowrite option.)
+ * On restart, any "current" input was discarded, whether in insert
+ * mode or not, and ex was in command mode. This code matches historic
+ * practice, but not 'cause it's easier.
+ */
+ gp = sp->gp;
+ if (F_ISSET(gp, G_SCRIPTED))
+ LF_CLR(TXT_AUTOINDENT);
+ else {
+ if (LF_ISSET(TXT_AUTOINDENT)) {
+ LF_SET(TXT_EOFCHAR);
+ if (v_txt_auto(sp, sp->lno, NULL, 0, tp))
+ goto err;
+ }
+ txt_prompt(sp, tp, prompt, flags);
+ }
+
+ for (carat_st = C_NOTSET;;) {
+ if (v_event_get(sp, &ev, 0, 0))
+ goto err;
+
+ /* Deal with all non-character events. */
+ switch (ev.e_event) {
+ case E_CHARACTER:
+ break;
+ case E_ERR:
+ goto err;
+ case E_REPAINT:
+ case E_WRESIZE:
+ continue;
+ case E_EOF:
+ rval = 1;
+ /* FALLTHROUGH */
+ case E_INTERRUPT:
+ /*
+ * Handle EOF/SIGINT events by discarding partially
+ * entered text and returning. EOF returns failure,
+ * E_INTERRUPT returns success.
+ */
+ goto notlast;
+ default:
+ v_event_err(sp, &ev);
+ goto notlast;
+ }
+
+ /*
+ * Deal with character events.
+ *
+ * Check to see if the character fits into the input buffer.
+ * (Use tp->len, ignore overwrite and non-printable chars.)
+ */
+ BINC_GOTO(sp, tp->lb, tp->lb_len, tp->len + 1);
+
+ switch (ev.e_value) {
+ case K_CR:
+ /*
+ * !!!
+ * Historically, <carriage-return>'s in the command
+ * weren't special, so the ex parser would return an
+ * unknown command error message. However, if they
+ * terminated the command if they were in a map. I'm
+ * pretty sure this still isn't right, but it handles
+ * what I've seen so far.
+ */
+ if (!F_ISSET(&ev.e_ch, CH_MAPPED))
+ goto ins_ch;
+ /* FALLTHROUGH */
+ case K_NL:
+ /*
+ * '\' can escape <carriage-return>/<newline>. We
+ * don't discard the backslash because we need it
+ * to get the <newline> through the ex parser.
+ */
+ if (LF_ISSET(TXT_BACKSLASH) &&
+ tp->len != 0 && tp->lb[tp->len - 1] == '\\')
+ goto ins_ch;
+
+ /*
+ * CR returns from the ex command line.
+ *
+ * XXX
+ * Terminate with a nul, needed by filter.
+ */
+ if (LF_ISSET(TXT_CR)) {
+ tp->lb[tp->len] = '\0';
+ goto done;
+ }
+
+ /*
+ * '.' may terminate text input mode; free the current
+ * TEXT.
+ */
+ if (LF_ISSET(TXT_DOTTERM) && tp->len == tp->ai + 1 &&
+ tp->lb[tp->len - 1] == '.') {
+notlast: CIRCLEQ_REMOVE(tiqh, tp, q);
+ text_free(tp);
+ goto done;
+ }
+
+ /* Set up bookkeeping for the new line. */
+ if ((ntp = text_init(sp, NULL, 0, 32)) == NULL)
+ goto err;
+ ntp->lno = tp->lno + 1;
+
+ /*
+ * Reset the autoindent line value. 0^D keeps the ai
+ * line from changing, ^D changes the level, even if
+ * there were no characters in the old line. Note, if
+ * using the current tp structure, use the cursor as
+ * the length, the autoindent characters may have been
+ * erased.
+ */
+ if (LF_ISSET(TXT_AUTOINDENT)) {
+ if (carat_st == C_NOCHANGE) {
+ if (v_txt_auto(sp,
+ OOBLNO, &ait, ait.ai, ntp))
+ goto err;
+ free(ait.lb);
+ } else
+ if (v_txt_auto(sp,
+ OOBLNO, tp, tp->len, ntp))
+ goto err;
+ carat_st = C_NOTSET;
+ }
+ txt_prompt(sp, ntp, prompt, flags);
+
+ /*
+ * Swap old and new TEXT's, and insert the new TEXT
+ * into the queue.
+ */
+ tp = ntp;
+ CIRCLEQ_INSERT_TAIL(tiqh, tp, q);
+ break;
+ case K_CARAT: /* Delete autoindent chars. */
+ if (tp->len <= tp->ai && LF_ISSET(TXT_AUTOINDENT))
+ carat_st = C_CARATSET;
+ goto ins_ch;
+ case K_ZERO: /* Delete autoindent chars. */
+ if (tp->len <= tp->ai && LF_ISSET(TXT_AUTOINDENT))
+ carat_st = C_ZEROSET;
+ goto ins_ch;
+ case K_CNTRLD: /* Delete autoindent char. */
+ /*
+ * !!!
+ * Historically, the ^D command took (but then ignored)
+ * a count. For simplicity, we don't return it unless
+ * it's the first character entered. The check for len
+ * equal to 0 is okay, TXT_AUTOINDENT won't be set.
+ */
+ if (LF_ISSET(TXT_CNTRLD)) {
+ for (cnt = 0; cnt < tp->len; ++cnt)
+ if (!isblank(tp->lb[cnt]))
+ break;
+ if (cnt == tp->len) {
+ tp->len = 1;
+ tp->lb[0] = ev.e_c;
+ tp->lb[1] = '\0';
+
+ /*
+ * Put out a line separator, in case
+ * the command fails.
+ */
+ (void)putchar('\n');
+ goto done;
+ }
+ }
+
+ /*
+ * POSIX 1003.1b-1993, paragraph 7.1.1.9, states that
+ * the EOF characters are discarded if there are other
+ * characters to process in the line, i.e. if the EOF
+ * is not the first character in the line. For this
+ * reason, historic ex discarded the EOF characters,
+ * even if occurring in the middle of the input line.
+ * We match that historic practice.
+ *
+ * !!!
+ * The test for discarding in the middle of the line is
+ * done in the switch, because the CARAT forms are N+1,
+ * not N.
+ *
+ * !!!
+ * There's considerable magic to make the terminal code
+ * return the EOF character at all. See that code for
+ * details.
+ */
+ if (!LF_ISSET(TXT_AUTOINDENT) || tp->len == 0)
+ continue;
+ switch (carat_st) {
+ case C_CARATSET: /* ^^D */
+ if (tp->len > tp->ai + 1)
+ continue;
+
+ /* Save the ai string for later. */
+ ait.lb = NULL;
+ ait.lb_len = 0;
+ BINC_GOTO(sp, ait.lb, ait.lb_len, tp->ai);
+ memcpy(ait.lb, tp->lb, tp->ai);
+ ait.ai = ait.len = tp->ai;
+
+ carat_st = C_NOCHANGE;
+ goto leftmargin;
+ case C_ZEROSET: /* 0^D */
+ if (tp->len > tp->ai + 1)
+ continue;
+
+ carat_st = C_NOTSET;
+leftmargin: (void)gp->scr_ex_adjust(sp, EX_TERM_CE);
+ tp->ai = tp->len = 0;
+ break;
+ case C_NOTSET: /* ^D */
+ if (tp->len > tp->ai)
+ continue;
+
+ if (txt_dent(sp, tp))
+ goto err;
+ break;
+ default:
+ abort();
+ }
+
+ /* Clear and redisplay the line. */
+ (void)gp->scr_ex_adjust(sp, EX_TERM_CE);
+ txt_prompt(sp, tp, prompt, flags);
+ break;
+ default:
+ /*
+ * See the TXT_BEAUTIFY comment in vi/v_txt_ev.c.
+ *
+ * Silently eliminate any iscntrl() character that was
+ * not already handled specially, except for <tab> and
+ * <ff>.
+ */
+ins_ch: if (LF_ISSET(TXT_BEAUTIFY) && iscntrl(ev.e_c) &&
+ ev.e_value != K_FORMFEED && ev.e_value != K_TAB)
+ break;
+
+ tp->lb[tp->len++] = ev.e_c;
+ break;
+ }
+ }
+ /* NOTREACHED */
+
+done: return (rval);
+
+err:
+alloc_err:
+ return (1);
+}
+
+/*
+ * txt_prompt --
+ * Display the ex prompt, line number, ai characters. Characters had
+ * better be printable by the terminal driver, but that's its problem,
+ * not ours.
+ */
+static void
+txt_prompt(sp, tp, prompt, flags)
+ SCR *sp;
+ TEXT *tp;
+ ARG_CHAR_T prompt;
+ u_int32_t flags;
+{
+ /* Display the prompt. */
+ if (LF_ISSET(TXT_PROMPT))
+ (void)printf("%c", prompt);
+
+ /* Display the line number. */
+ if (LF_ISSET(TXT_NUMBER) && O_ISSET(sp, O_NUMBER))
+ (void)printf("%6lu ", (u_long)tp->lno);
+
+ /* Print out autoindent string. */
+ if (LF_ISSET(TXT_AUTOINDENT))
+ (void)printf("%.*s", (int)tp->ai, tp->lb);
+ (void)fflush(stdout);
+}
+
+/*
+ * txt_dent --
+ * Handle ^D outdents.
+ *
+ * Ex version of vi/v_ntext.c:txt_dent(). See that code for the (usual)
+ * ranting and raving. This is a fair bit simpler as ^T isn't special.
+ */
+static int
+txt_dent(sp, tp)
+ SCR *sp;
+ TEXT *tp;
+{
+ u_long sw, ts;
+ size_t cno, off, scno, spaces, tabs;
+
+ ts = O_VAL(sp, O_TABSTOP);
+ sw = O_VAL(sp, O_SHIFTWIDTH);
+
+ /* Get the current screen column. */
+ for (off = scno = 0; off < tp->len; ++off)
+ if (tp->lb[off] == '\t')
+ scno += COL_OFF(scno, ts);
+ else
+ ++scno;
+
+ /* Get the previous shiftwidth column. */
+ cno = scno;
+ scno -= --scno % sw;
+
+ /*
+ * Since we don't know what comes before the character(s) being
+ * deleted, we have to resolve the autoindent characters . The
+ * example is a <tab>, which doesn't take up a full shiftwidth
+ * number of columns because it's preceded by <space>s. This is
+ * easy to get if the user sets shiftwidth to a value less than
+ * tabstop, and then uses ^T to indent, and ^D to outdent.
+ *
+ * Count up spaces/tabs needed to get to the target.
+ */
+ for (cno = 0, tabs = 0; cno + COL_OFF(cno, ts) <= scno; ++tabs)
+ cno += COL_OFF(cno, ts);
+ spaces = scno - cno;
+
+ /* Make sure there's enough room. */
+ BINC_RET(sp, tp->lb, tp->lb_len, tabs + spaces + 1);
+
+ /* Adjust the final ai character count. */
+ tp->ai = tabs + spaces;
+
+ /* Enter the replacement characters. */
+ for (tp->len = 0; tabs > 0; --tabs)
+ tp->lb[tp->len++] = '\t';
+ for (; spaces > 0; --spaces)
+ tp->lb[tp->len++] = ' ';
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_undo.c b/contrib/nvi/ex/ex_undo.c
new file mode 100644
index 000000000000..0b0b5b26be18
--- /dev/null
+++ b/contrib/nvi/ex/ex_undo.c
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_undo.c 10.6 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_undo -- u
+ * Undo the last change.
+ *
+ * PUBLIC: int ex_undo __P((SCR *, EXCMD *));
+ */
+int
+ex_undo(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ EXF *ep;
+ MARK m;
+
+ /*
+ * !!!
+ * Historic undo always set the previous context mark.
+ */
+ m.lno = sp->lno;
+ m.cno = sp->cno;
+ if (mark_set(sp, ABSMARK1, &m, 1))
+ return (1);
+
+ /*
+ * !!!
+ * Multiple undo isn't available in ex, as there's no '.' command.
+ * Whether 'u' is undo or redo is toggled each time, unless there
+ * was a change since the last undo, in which case it's an undo.
+ */
+ ep = sp->ep;
+ if (!F_ISSET(ep, F_UNDO)) {
+ F_SET(ep, F_UNDO);
+ ep->lundo = FORWARD;
+ }
+ switch (ep->lundo) {
+ case BACKWARD:
+ if (log_forward(sp, &m))
+ return (1);
+ ep->lundo = FORWARD;
+ break;
+ case FORWARD:
+ if (log_backward(sp, &m))
+ return (1);
+ ep->lundo = BACKWARD;
+ break;
+ case NOTSET:
+ abort();
+ }
+ sp->lno = m.lno;
+ sp->cno = m.cno;
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_usage.c b/contrib/nvi/ex/ex_usage.c
new file mode 100644
index 000000000000..cddf7a6643c7
--- /dev/null
+++ b/contrib/nvi/ex/ex_usage.c
@@ -0,0 +1,196 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_usage.c 10.13 (Berkeley) 5/3/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+/*
+ * ex_help -- :help
+ * Display help message.
+ *
+ * PUBLIC: int ex_help __P((SCR *, EXCMD *));
+ */
+int
+ex_help(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ (void)ex_puts(sp,
+ "To see the list of vi commands, enter \":viusage<CR>\"\n");
+ (void)ex_puts(sp,
+ "To see the list of ex commands, enter \":exusage<CR>\"\n");
+ (void)ex_puts(sp,
+ "For an ex command usage statement enter \":exusage [cmd]<CR>\"\n");
+ (void)ex_puts(sp,
+ "For a vi key usage statement enter \":viusage [key]<CR>\"\n");
+ (void)ex_puts(sp, "To exit, enter \":q!\"\n");
+ return (0);
+}
+
+/*
+ * ex_usage -- :exusage [cmd]
+ * Display ex usage strings.
+ *
+ * PUBLIC: int ex_usage __P((SCR *, EXCMD *));
+ */
+int
+ex_usage(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ ARGS *ap;
+ EXCMDLIST const *cp;
+ int newscreen;
+ char *name, *p, nb[MAXCMDNAMELEN + 5];
+
+ switch (cmdp->argc) {
+ case 1:
+ ap = cmdp->argv[0];
+ if (isupper(ap->bp[0])) {
+ newscreen = 1;
+ ap->bp[0] = tolower(ap->bp[0]);
+ } else
+ newscreen = 0;
+ for (cp = cmds; cp->name != NULL &&
+ memcmp(ap->bp, cp->name, ap->len); ++cp);
+ if (cp->name == NULL ||
+ newscreen && !F_ISSET(cp, E_NEWSCREEN)) {
+ if (newscreen)
+ ap->bp[0] = toupper(ap->bp[0]);
+ (void)ex_printf(sp, "The %.*s command is unknown\n",
+ (int)ap->len, ap->bp);
+ } else {
+ (void)ex_printf(sp,
+ "Command: %s\n Usage: %s\n", cp->help, cp->usage);
+ /*
+ * !!!
+ * The "visual" command has two modes, one from ex,
+ * one from the vi colon line. Don't ask.
+ */
+ if (cp != &cmds[C_VISUAL_EX] &&
+ cp != &cmds[C_VISUAL_VI])
+ break;
+ if (cp == &cmds[C_VISUAL_EX])
+ cp = &cmds[C_VISUAL_VI];
+ else
+ cp = &cmds[C_VISUAL_EX];
+ (void)ex_printf(sp,
+ "Command: %s\n Usage: %s\n", cp->help, cp->usage);
+ }
+ break;
+ case 0:
+ for (cp = cmds; cp->name != NULL && !INTERRUPTED(sp); ++cp) {
+ /*
+ * The ^D command has an unprintable name.
+ *
+ * XXX
+ * We display both capital and lower-case versions of
+ * the appropriate commands -- no need to add in extra
+ * room, they're all short names.
+ */
+ if (cp == &cmds[C_SCROLL])
+ name = "^D";
+ else if (F_ISSET(cp, E_NEWSCREEN)) {
+ nb[0] = '[';
+ nb[1] = toupper(cp->name[0]);
+ nb[2] = cp->name[0];
+ nb[3] = ']';
+ for (name = cp->name + 1,
+ p = nb + 4; (*p++ = *name++) != '\0';);
+ name = nb;
+ } else
+ name = cp->name;
+ (void)ex_printf(sp,
+ "%*s: %s\n", MAXCMDNAMELEN, name, cp->help);
+ }
+ break;
+ default:
+ abort();
+ }
+ return (0);
+}
+
+/*
+ * ex_viusage -- :viusage [key]
+ * Display vi usage strings.
+ *
+ * PUBLIC: int ex_viusage __P((SCR *, EXCMD *));
+ */
+int
+ex_viusage(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ GS *gp;
+ VIKEYS const *kp;
+ int key;
+
+ gp = sp->gp;
+ switch (cmdp->argc) {
+ case 1:
+ if (cmdp->argv[0]->len != 1) {
+ ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+ return (1);
+ }
+ key = cmdp->argv[0]->bp[0];
+ if (key > MAXVIKEY)
+ goto nokey;
+
+ /* Special case: '[' and ']' commands. */
+ if ((key == '[' || key == ']') && cmdp->argv[0]->bp[1] != key)
+ goto nokey;
+
+ /* Special case: ~ command. */
+ if (key == '~' && O_ISSET(sp, O_TILDEOP))
+ kp = &tmotion;
+ else
+ kp = &vikeys[key];
+
+ if (kp->usage == NULL)
+nokey: (void)ex_printf(sp,
+ "The %s key has no current meaning\n",
+ KEY_NAME(sp, key));
+ else
+ (void)ex_printf(sp,
+ " Key:%s%s\nUsage: %s\n",
+ isblank(*kp->help) ? "" : " ", kp->help, kp->usage);
+ break;
+ case 0:
+ for (key = 0; key <= MAXVIKEY && !INTERRUPTED(sp); ++key) {
+ /* Special case: ~ command. */
+ if (key == '~' && O_ISSET(sp, O_TILDEOP))
+ kp = &tmotion;
+ else
+ kp = &vikeys[key];
+ if (kp->help != NULL)
+ (void)ex_printf(sp, "%s\n", kp->help);
+ }
+ break;
+ default:
+ abort();
+ }
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_util.c b/contrib/nvi/ex/ex_util.c
new file mode 100644
index 000000000000..6c4772e61540
--- /dev/null
+++ b/contrib/nvi/ex/ex_util.c
@@ -0,0 +1,234 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_util.c 10.23 (Berkeley) 6/19/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_cinit --
+ * Create an EX command structure.
+ *
+ * PUBLIC: void ex_cinit __P((EXCMD *,
+ * PUBLIC: int, int, recno_t, recno_t, int, ARGS **));
+ */
+void
+ex_cinit(cmdp, cmd_id, naddr, lno1, lno2, force, ap)
+ EXCMD *cmdp;
+ int cmd_id, force, naddr;
+ recno_t lno1, lno2;
+ ARGS **ap;
+{
+ memset(cmdp, 0, sizeof(EXCMD));
+ cmdp->cmd = &cmds[cmd_id];
+ cmdp->addrcnt = naddr;
+ cmdp->addr1.lno = lno1;
+ cmdp->addr2.lno = lno2;
+ cmdp->addr1.cno = cmdp->addr2.cno = 1;
+ if (force)
+ cmdp->iflags |= E_C_FORCE;
+ cmdp->argc = 0;
+ if ((cmdp->argv = ap) != NULL)
+ cmdp->argv[0] = NULL;
+}
+
+/*
+ * ex_cadd --
+ * Add an argument to an EX command structure.
+ *
+ * PUBLIC: void ex_cadd __P((EXCMD *, ARGS *, char *, size_t));
+ */
+void
+ex_cadd(cmdp, ap, arg, len)
+ EXCMD *cmdp;
+ ARGS *ap;
+ char *arg;
+ size_t len;
+{
+ cmdp->argv[cmdp->argc] = ap;
+ ap->bp = arg;
+ ap->len = len;
+ cmdp->argv[++cmdp->argc] = NULL;
+}
+
+/*
+ * ex_getline --
+ * Return a line from the file.
+ *
+ * PUBLIC: int ex_getline __P((SCR *, FILE *, size_t *));
+ */
+int
+ex_getline(sp, fp, lenp)
+ SCR *sp;
+ FILE *fp;
+ size_t *lenp;
+{
+ EX_PRIVATE *exp;
+ size_t off;
+ int ch;
+ char *p;
+
+ exp = EXP(sp);
+ for (errno = 0, off = 0, p = exp->ibp;;) {
+ if (off >= exp->ibp_len) {
+ BINC_RET(sp, exp->ibp, exp->ibp_len, off + 1);
+ p = exp->ibp + off;
+ }
+ if ((ch = getc(fp)) == EOF && !feof(fp)) {
+ if (errno == EINTR) {
+ errno = 0;
+ clearerr(fp);
+ continue;
+ }
+ return (1);
+ }
+ if (ch == EOF || ch == '\n') {
+ if (ch == EOF && !off)
+ return (1);
+ *lenp = off;
+ return (0);
+ }
+ *p++ = ch;
+ ++off;
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * ex_ncheck --
+ * Check for more files to edit.
+ *
+ * PUBLIC: int ex_ncheck __P((SCR *, int));
+ */
+int
+ex_ncheck(sp, force)
+ SCR *sp;
+ int force;
+{
+ char **ap;
+
+ /*
+ * !!!
+ * Historic practice: quit! or two quit's done in succession
+ * (where ZZ counts as a quit) didn't check for other files.
+ */
+ if (!force && sp->ccnt != sp->q_ccnt + 1 &&
+ sp->cargv != NULL && sp->cargv[1] != NULL) {
+ sp->q_ccnt = sp->ccnt;
+
+ for (ap = sp->cargv + 1; *ap != NULL; ++ap);
+ msgq(sp, M_ERR,
+ "167|%d more files to edit", (ap - sp->cargv) - 1);
+
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * ex_init --
+ * Init the screen for ex.
+ *
+ * PUBLIC: int ex_init __P((SCR *));
+ */
+int
+ex_init(sp)
+ SCR *sp;
+{
+ GS *gp;
+
+ gp = sp->gp;
+
+ if (gp->scr_screen(sp, SC_EX))
+ return (1);
+ (void)gp->scr_attr(sp, SA_ALTERNATE, 0);
+
+ sp->rows = O_VAL(sp, O_LINES);
+ sp->cols = O_VAL(sp, O_COLUMNS);
+
+ F_CLR(sp, SC_VI);
+ F_SET(sp, SC_EX | SC_SCR_EX);
+ return (0);
+}
+
+/*
+ * ex_emsg --
+ * Display a few common ex and vi error messages.
+ *
+ * PUBLIC: void ex_emsg __P((SCR *, char *, exm_t));
+ */
+void
+ex_emsg(sp, p, which)
+ SCR *sp;
+ char *p;
+ exm_t which;
+{
+ switch (which) {
+ case EXM_EMPTYBUF:
+ msgq(sp, M_ERR, "168|Buffer %s is empty", p);
+ break;
+ case EXM_FILECOUNT:
+ msgq_str(sp, M_ERR, p,
+ "144|%s: expanded into too many file names");
+ break;
+ case EXM_NOCANON:
+ msgq(sp, M_ERR,
+ "283|The %s command requires the ex terminal interface", p);
+ break;
+ case EXM_NOCANON_F:
+ msgq(sp, M_ERR,
+ "272|That form of %s requires the ex terminal interface",
+ p);
+ break;
+ case EXM_NOFILEYET:
+ if (p == NULL)
+ msgq(sp, M_ERR,
+ "274|Command failed, no file read in yet.");
+ else
+ msgq(sp, M_ERR,
+ "173|The %s command requires that a file have already been read in", p);
+ break;
+ case EXM_NOPREVBUF:
+ msgq(sp, M_ERR, "171|No previous buffer to execute");
+ break;
+ case EXM_NOPREVRE:
+ msgq(sp, M_ERR, "172|No previous regular expression");
+ break;
+ case EXM_NOSUSPEND:
+ msgq(sp, M_ERR, "230|This screen may not be suspended");
+ break;
+ case EXM_SECURE:
+ msgq(sp, M_ERR,
+"290|The %s command is not supported when the secure edit option is set", p);
+ break;
+ case EXM_SECURE_F:
+ msgq(sp, M_ERR,
+"284|That form of %s is not supported when the secure edit option is set", p);
+ break;
+ case EXM_USAGE:
+ msgq(sp, M_ERR, "174|Usage: %s", p);
+ break;
+ }
+}
diff --git a/contrib/nvi/ex/ex_version.c b/contrib/nvi/ex/ex_version.c
new file mode 100644
index 000000000000..d7363c8bd1ac
--- /dev/null
+++ b/contrib/nvi/ex/ex_version.c
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1991, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_version.c 10.31 (Berkeley) 8/22/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "version.h"
+
+/*
+ * ex_version -- :version
+ * Display the program version.
+ *
+ * PUBLIC: int ex_version __P((SCR *, EXCMD *));
+ */
+int
+ex_version(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ msgq(sp, M_INFO, VI_VERSION);
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_visual.c b/contrib/nvi/ex/ex_visual.c
new file mode 100644
index 000000000000..82e503d44658
--- /dev/null
+++ b/contrib/nvi/ex/ex_visual.c
@@ -0,0 +1,161 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_visual.c 10.13 (Berkeley) 6/28/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+
+/*
+ * ex_visual -- :[line] vi[sual] [^-.+] [window_size] [flags]
+ * Switch to visual mode.
+ *
+ * PUBLIC: int ex_visual __P((SCR *, EXCMD *));
+ */
+int
+ex_visual(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ SCR *tsp;
+ size_t len;
+ int pos;
+ char buf[256];
+
+ /* If open option off, disallow visual command. */
+ if (!O_ISSET(sp, O_OPEN)) {
+ msgq(sp, M_ERR,
+ "175|The visual command requires that the open option be set");
+ return (1);
+ }
+
+ /* Move to the address. */
+ sp->lno = cmdp->addr1.lno == 0 ? 1 : cmdp->addr1.lno;
+
+ /*
+ * Push a command based on the line position flags. If no
+ * flag specified, the line goes at the top of the screen.
+ */
+ switch (FL_ISSET(cmdp->iflags,
+ E_C_CARAT | E_C_DASH | E_C_DOT | E_C_PLUS)) {
+ case E_C_CARAT:
+ pos = '^';
+ break;
+ case E_C_DASH:
+ pos = '-';
+ break;
+ case E_C_DOT:
+ pos = '.';
+ break;
+ case E_C_PLUS:
+ pos = '+';
+ break;
+ default:
+ sp->frp->lno = sp->lno;
+ sp->frp->cno = 0;
+ (void)nonblank(sp, sp->lno, &sp->cno);
+ F_SET(sp->frp, FR_CURSORSET);
+ goto nopush;
+ }
+
+ if (FL_ISSET(cmdp->iflags, E_C_COUNT))
+ len = snprintf(buf, sizeof(buf),
+ "%luz%c%lu", sp->lno, pos, cmdp->count);
+ else
+ len = snprintf(buf, sizeof(buf), "%luz%c", sp->lno, pos);
+ (void)v_event_push(sp, NULL, buf, len, CH_NOMAP | CH_QUOTED);
+
+ /*
+ * !!!
+ * Historically, if no line address was specified, the [p#l] flags
+ * caused the cursor to be moved to the last line of the file, which
+ * was then positioned as described above. This seems useless, so
+ * I haven't implemented it.
+ */
+ switch (FL_ISSET(cmdp->iflags, E_C_HASH | E_C_LIST | E_C_PRINT)) {
+ case E_C_HASH:
+ O_SET(sp, O_NUMBER);
+ break;
+ case E_C_LIST:
+ O_SET(sp, O_LIST);
+ break;
+ case E_C_PRINT:
+ break;
+ }
+
+nopush: /*
+ * !!!
+ * You can call the visual part of the editor from within an ex
+ * global command.
+ *
+ * XXX
+ * Historically, undoing a visual session was a single undo command,
+ * i.e. you could undo all of the changes you made in visual mode.
+ * We don't get this right; I'm waiting for the new logging code to
+ * be available.
+ *
+ * It's explicit, don't have to wait for the user, unless there's
+ * already a reason to wait.
+ */
+ if (!F_ISSET(sp, SC_SCR_EXWROTE))
+ F_SET(sp, SC_EX_WAIT_NO);
+
+ if (F_ISSET(sp, SC_EX_GLOBAL)) {
+ /*
+ * When the vi screen(s) exit, we don't want to lose our hold
+ * on this screen or this file, otherwise we're going to fail
+ * fairly spectacularly.
+ */
+ ++sp->refcnt;
+ ++sp->ep->refcnt;
+
+ /*
+ * Fake up a screen pointer -- vi doesn't get to change our
+ * underlying file, regardless.
+ */
+ tsp = sp;
+ if (vi(&tsp))
+ return (1);
+
+ /*
+ * !!!
+ * Historically, if the user exited the vi screen(s) using an
+ * ex quit command (e.g. :wq, :q) ex/vi exited, it was only if
+ * they exited vi using the Q command that ex continued. Some
+ * early versions of nvi continued in ex regardless, but users
+ * didn't like the semantic.
+ *
+ * Reset the screen.
+ */
+ if (ex_init(sp))
+ return (1);
+
+ /* Move out of the vi screen. */
+ (void)ex_puts(sp, "\n");
+ } else {
+ F_CLR(sp, SC_EX | SC_SCR_EX);
+ F_SET(sp, SC_VI);
+ }
+ return (0);
+}
diff --git a/contrib/nvi/ex/ex_write.c b/contrib/nvi/ex/ex_write.c
new file mode 100644
index 000000000000..b3122e353563
--- /dev/null
+++ b/contrib/nvi/ex/ex_write.c
@@ -0,0 +1,375 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_write.c 10.30 (Berkeley) 7/12/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+enum which {WN, WQ, WRITE, XIT};
+static int exwr __P((SCR *, EXCMD *, enum which));
+
+/*
+ * ex_wn -- :wn[!] [>>] [file]
+ * Write to a file and switch to the next one.
+ *
+ * PUBLIC: int ex_wn __P((SCR *, EXCMD *));
+ */
+int
+ex_wn(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ if (exwr(sp, cmdp, WN))
+ return (1);
+ if (file_m3(sp, 0))
+ return (1);
+
+ /* The file name isn't a new file to edit. */
+ cmdp->argc = 0;
+
+ return (ex_next(sp, cmdp));
+}
+
+/*
+ * ex_wq -- :wq[!] [>>] [file]
+ * Write to a file and quit.
+ *
+ * PUBLIC: int ex_wq __P((SCR *, EXCMD *));
+ */
+int
+ex_wq(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ int force;
+
+ if (exwr(sp, cmdp, WQ))
+ return (1);
+ if (file_m3(sp, 0))
+ return (1);
+
+ force = FL_ISSET(cmdp->iflags, E_C_FORCE);
+
+ if (ex_ncheck(sp, force))
+ return (1);
+
+ F_SET(sp, force ? SC_EXIT_FORCE : SC_EXIT);
+ return (0);
+}
+
+/*
+ * ex_write -- :write[!] [>>] [file]
+ * :write [!] [cmd]
+ * Write to a file.
+ *
+ * PUBLIC: int ex_write __P((SCR *, EXCMD *));
+ */
+int
+ex_write(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ return (exwr(sp, cmdp, WRITE));
+}
+
+
+/*
+ * ex_xit -- :x[it]! [file]
+ * Write out any modifications and quit.
+ *
+ * PUBLIC: int ex_xit __P((SCR *, EXCMD *));
+ */
+int
+ex_xit(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ int force;
+
+ NEEDFILE(sp, cmdp);
+
+ if (F_ISSET(sp->ep, F_MODIFIED) && exwr(sp, cmdp, XIT))
+ return (1);
+ if (file_m3(sp, 0))
+ return (1);
+
+ force = FL_ISSET(cmdp->iflags, E_C_FORCE);
+
+ if (ex_ncheck(sp, force))
+ return (1);
+
+ F_SET(sp, force ? SC_EXIT_FORCE : SC_EXIT);
+ return (0);
+}
+
+/*
+ * exwr --
+ * The guts of the ex write commands.
+ */
+static int
+exwr(sp, cmdp, cmd)
+ SCR *sp;
+ EXCMD *cmdp;
+ enum which cmd;
+{
+ MARK rm;
+ int flags;
+ char *name, *p;
+
+ NEEDFILE(sp, cmdp);
+
+ /* All write commands can have an associated '!'. */
+ LF_INIT(FS_POSSIBLE);
+ if (FL_ISSET(cmdp->iflags, E_C_FORCE))
+ LF_SET(FS_FORCE);
+
+ /* Skip any leading whitespace. */
+ if (cmdp->argc != 0)
+ for (p = cmdp->argv[0]->bp; *p != '\0' && isblank(*p); ++p);
+
+ /* If "write !" it's a pipe to a utility. */
+ if (cmdp->argc != 0 && cmd == WRITE && *p == '!') {
+ /* Secure means no shell access. */
+ if (O_ISSET(sp, O_SECURE)) {
+ ex_emsg(sp, cmdp->cmd->name, EXM_SECURE_F);
+ return (1);
+ }
+
+ /* Expand the argument. */
+ for (++p; *p && isblank(*p); ++p);
+ if (*p == '\0') {
+ ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
+ return (1);
+ }
+ if (argv_exp1(sp, cmdp, p, strlen(p), 1))
+ return (1);
+
+ /*
+ * Historically, vi waited after a write filter even if there
+ * wasn't any output from the command. People complained when
+ * nvi waited only if there was output, wanting the visual cue
+ * that the program hadn't written anything.
+ */
+ F_SET(sp, SC_EX_WAIT_YES);
+
+ /*
+ * !!!
+ * Ignore the return cursor position, the cursor doesn't
+ * move.
+ */
+ if (ex_filter(sp, cmdp, &cmdp->addr1,
+ &cmdp->addr2, &rm, cmdp->argv[1]->bp, FILTER_WRITE))
+ return (1);
+
+ /* Ex terminates with a bang, even if the command fails. */
+ if (!F_ISSET(sp, SC_VI) && !F_ISSET(sp, SC_EX_SILENT))
+ (void)ex_puts(sp, "!\n");
+
+ return (0);
+ }
+
+ /* Set the FS_ALL flag if we're writing the entire file. */
+ if (cmdp->addr1.lno <= 1 && !db_exist(sp, cmdp->addr2.lno + 1))
+ LF_SET(FS_ALL);
+
+ /* If "write >>" it's an append to a file. */
+ if (cmdp->argc != 0 && cmd != XIT && p[0] == '>' && p[1] == '>') {
+ LF_SET(FS_APPEND);
+
+ /* Skip ">>" and whitespace. */
+ for (p += 2; *p && isblank(*p); ++p);
+ }
+
+ /* If no other arguments, just write the file back. */
+ if (cmdp->argc == 0 || *p == '\0')
+ return (file_write(sp,
+ &cmdp->addr1, &cmdp->addr2, NULL, flags));
+
+ /* Build an argv so we get an argument count and file expansion. */
+ if (argv_exp2(sp, cmdp, p, strlen(p)))
+ return (1);
+
+ /*
+ * 0 args: impossible.
+ * 1 args: impossible (I hope).
+ * 2 args: read it.
+ * >2 args: object, too many args.
+ *
+ * The 1 args case depends on the argv_sexp() function refusing
+ * to return success without at least one non-blank character.
+ */
+ switch (cmdp->argc) {
+ case 0:
+ case 1:
+ abort();
+ /* NOTREACHED */
+ case 2:
+ name = cmdp->argv[1]->bp;
+
+ /*
+ * !!!
+ * Historically, the read and write commands renamed
+ * "unnamed" files, or, if the file had a name, set
+ * the alternate file name.
+ */
+ if (F_ISSET(sp->frp, FR_TMPFILE) &&
+ !F_ISSET(sp->frp, FR_EXNAMED)) {
+ if ((p = v_strdup(sp,
+ cmdp->argv[1]->bp, cmdp->argv[1]->len)) != NULL) {
+ free(sp->frp->name);
+ sp->frp->name = p;
+ }
+ /*
+ * The file has a real name, it's no longer a
+ * temporary, clear the temporary file flags.
+ *
+ * !!!
+ * If we're writing the whole file, FR_NAMECHANGE
+ * will be cleared by the write routine -- this is
+ * historic practice.
+ */
+ F_CLR(sp->frp, FR_TMPEXIT | FR_TMPFILE);
+ F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED);
+
+ /* Notify the screen. */
+ (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+ } else
+ set_alt_name(sp, name);
+ break;
+ default:
+ ex_emsg(sp, p, EXM_FILECOUNT);
+ return (1);
+ }
+
+ return (file_write(sp, &cmdp->addr1, &cmdp->addr2, name, flags));
+}
+
+/*
+ * ex_writefp --
+ * Write a range of lines to a FILE *.
+ *
+ * PUBLIC: int ex_writefp __P((SCR *,
+ * PUBLIC: char *, FILE *, MARK *, MARK *, u_long *, u_long *, int));
+ */
+int
+ex_writefp(sp, name, fp, fm, tm, nlno, nch, silent)
+ SCR *sp;
+ char *name;
+ FILE *fp;
+ MARK *fm, *tm;
+ u_long *nlno, *nch;
+ int silent;
+{
+ struct stat sb;
+ GS *gp;
+ u_long ccnt; /* XXX: can't print off_t portably. */
+ recno_t fline, tline, lcnt;
+ size_t len;
+ int rval;
+ char *msg, *p;
+
+ gp = sp->gp;
+ fline = fm->lno;
+ tline = tm->lno;
+
+ if (nlno != NULL) {
+ *nch = 0;
+ *nlno = 0;
+ }
+
+ /*
+ * The vi filter code has multiple processes running simultaneously,
+ * and one of them calls ex_writefp(). The "unsafe" function calls
+ * in this code are to db_get() and msgq(). Db_get() is safe, see
+ * the comment in ex_filter.c:ex_filter() for details. We don't call
+ * msgq if the multiple process bit in the EXF is set.
+ *
+ * !!!
+ * Historic vi permitted files of 0 length to be written. However,
+ * since the way vi got around dealing with "empty" files was to
+ * always have a line in the file no matter what, it wrote them as
+ * files of a single, empty line. We write empty files.
+ *
+ * "Alex, I'll take vi trivia for $1000."
+ */
+ ccnt = 0;
+ lcnt = 0;
+ msg = "253|Writing...";
+ if (tline != 0)
+ for (; fline <= tline; ++fline, ++lcnt) {
+ /* Caller has to provide any interrupt message. */
+ if ((lcnt + 1) % INTERRUPT_CHECK == 0) {
+ if (INTERRUPTED(sp))
+ break;
+ if (!silent) {
+ gp->scr_busy(sp, msg, msg == NULL ?
+ BUSY_UPDATE : BUSY_ON);
+ msg = NULL;
+ }
+ }
+ if (db_get(sp, fline, DBG_FATAL, &p, &len))
+ goto err;
+ if (fwrite(p, 1, len, fp) != len)
+ goto err;
+ ccnt += len;
+ if (putc('\n', fp) != '\n')
+ break;
+ ++ccnt;
+ }
+
+ if (fflush(fp))
+ goto err;
+ /*
+ * XXX
+ * I don't trust NFS -- check to make sure that we're talking to
+ * a regular file and sync so that NFS is forced to flush.
+ */
+ if (!fstat(fileno(fp), &sb) &&
+ S_ISREG(sb.st_mode) && fsync(fileno(fp)))
+ goto err;
+
+ if (fclose(fp))
+ goto err;
+
+ rval = 0;
+ if (0) {
+err: if (!F_ISSET(sp->ep, F_MULTILOCK))
+ msgq_str(sp, M_SYSERR, name, "%s");
+ (void)fclose(fp);
+ rval = 1;
+ }
+
+ if (!silent)
+ gp->scr_busy(sp, NULL, BUSY_OFF);
+
+ /* Report the possibly partial transfer. */
+ if (nlno != NULL) {
+ *nch = ccnt;
+ *nlno = lcnt;
+ }
+ return (rval);
+}
diff --git a/contrib/nvi/ex/ex_yank.c b/contrib/nvi/ex/ex_yank.c
new file mode 100644
index 000000000000..778dc7dee62c
--- /dev/null
+++ b/contrib/nvi/ex/ex_yank.c
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_yank.c 10.7 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+
+/*
+ * ex_yank -- :[line [,line]] ya[nk] [buffer] [count]
+ * Yank the lines into a buffer.
+ *
+ * PUBLIC: int ex_yank __P((SCR *, EXCMD *));
+ */
+int
+ex_yank(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ NEEDFILE(sp, cmdp);
+
+ /*
+ * !!!
+ * Historically, yanking lines in ex didn't count toward the
+ * number-of-lines-yanked report.
+ */
+ return (cut(sp,
+ FL_ISSET(cmdp->iflags, E_C_BUFFER) ? &cmdp->buffer : NULL,
+ &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE));
+}
diff --git a/usr.bin/vi/ex/ex_z.c b/contrib/nvi/ex/ex_z.c
index a5917b315974..41b72ad1fd42 100644
--- a/usr.bin/vi/ex/ex_z.c
+++ b/contrib/nvi/ex/ex_z.c
@@ -1,74 +1,46 @@
/*-
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)ex_z.c 8.6 (Berkeley) 7/23/94";
+static const char sccsid[] = "@(#)ex_z.c 10.10 (Berkeley) 3/6/96";
#endif /* not lint */
#include <sys/types.h>
#include <sys/queue.h>
-#include <sys/time.h>
#include <bitstring.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-#include "vi.h"
-#include "excmd.h"
+#include "../common/common.h"
/*
* ex_z -- :[line] z [^-.+=] [count] [flags]
- *
* Adjust window.
+ *
+ * PUBLIC: int ex_z __P((SCR *, EXCMD *));
*/
int
-ex_z(sp, ep, cmdp)
+ex_z(sp, cmdp)
SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
+ EXCMD *cmdp;
{
MARK abs;
recno_t cnt, equals, lno;
int eofcheck;
+ NEEDFILE(sp, cmdp);
+
/*
* !!!
* If no count specified, use either two times the size of the
@@ -80,7 +52,7 @@ ex_z(sp, ep, cmdp)
* a line from the cnt if using the window size to leave room for
* the next ex prompt.
*/
- if (F_ISSET(cmdp, E_COUNT))
+ if (FL_ISSET(cmdp->iflags, E_C_COUNT))
cnt = cmdp->count;
else
#ifdef HISTORIC_PRACTICE
@@ -93,9 +65,9 @@ ex_z(sp, ep, cmdp)
eofcheck = 0;
lno = cmdp->addr1.lno;
- switch (F_ISSET(cmdp,
- E_F_CARAT | E_F_DASH | E_F_DOT | E_F_EQUAL | E_F_PLUS)) {
- case E_F_CARAT: /* Display cnt * 2 before the line. */
+ switch (FL_ISSET(cmdp->iflags,
+ E_C_CARAT | E_C_DASH | E_C_DOT | E_C_EQUAL | E_C_PLUS)) {
+ case E_C_CARAT: /* Display cnt * 2 before the line. */
eofcheck = 1;
if (lno > cnt * 2)
cmdp->addr1.lno = (lno - cnt * 2) + 1;
@@ -103,11 +75,11 @@ ex_z(sp, ep, cmdp)
cmdp->addr1.lno = 1;
cmdp->addr2.lno = (cmdp->addr1.lno + cnt) - 1;
break;
- case E_F_DASH: /* Line goes at the bottom of the screen. */
+ case E_C_DASH: /* Line goes at the bottom of the screen. */
cmdp->addr1.lno = lno > cnt ? (lno - cnt) + 1 : 1;
cmdp->addr2.lno = lno;
break;
- case E_F_DOT: /* Line goes in the middle of the screen. */
+ case E_C_DOT: /* Line goes in the middle of the screen. */
/*
* !!!
* Historically, the "middleness" of the line overrode the
@@ -126,9 +98,9 @@ ex_z(sp, ep, cmdp)
*/
abs.lno = sp->lno;
abs.cno = sp->cno;
- (void)mark_set(sp, ep, ABSMARK1, &abs, 1);
+ (void)mark_set(sp, ABSMARK1, &abs, 1);
break;
- case E_F_EQUAL: /* Center with hyphens. */
+ case E_C_EQUAL: /* Center with hyphens. */
/*
* !!!
* Strangeness. The '=' flag is like the '.' flag (see the
@@ -141,24 +113,22 @@ ex_z(sp, ep, cmdp)
cnt = (cnt - 1) / 2;
cmdp->addr1.lno = lno > cnt ? lno - cnt : 1;
cmdp->addr2.lno = lno - 1;
- if (ex_pr(sp, ep, cmdp))
+ if (ex_pr(sp, cmdp))
return (1);
- (void)ex_printf(EXCOOKIE,
- "%s", "----------------------------------------\n");
+ (void)ex_puts(sp, "----------------------------------------\n");
cmdp->addr2.lno = cmdp->addr1.lno = equals = lno;
- if (ex_pr(sp, ep, cmdp))
+ if (ex_pr(sp, cmdp))
return (1);
- (void)ex_printf(EXCOOKIE,
- "%s", "----------------------------------------\n");
+ (void)ex_puts(sp, "----------------------------------------\n");
cmdp->addr1.lno = lno + 1;
cmdp->addr2.lno = (lno + cnt) - 1;
break;
default:
/* If no line specified, move to the next one. */
- if (F_ISSET(cmdp, E_ADDRDEF))
+ if (F_ISSET(cmdp, E_ADDR_DEF))
++lno;
/* FALLTHROUGH */
- case E_F_PLUS: /* Line goes at the top of the screen. */
+ case E_C_PLUS: /* Line goes at the top of the screen. */
eofcheck = 1;
cmdp->addr1.lno = lno;
cmdp->addr2.lno = (lno + cnt) - 1;
@@ -166,13 +136,13 @@ ex_z(sp, ep, cmdp)
}
if (eofcheck) {
- if (file_lline(sp, ep, &lno))
+ if (db_last(sp, &lno))
return (1);
if (cmdp->addr2.lno > lno)
cmdp->addr2.lno = lno;
}
- if (ex_pr(sp, ep, cmdp))
+ if (ex_pr(sp, cmdp))
return (1);
if (equals)
sp->lno = equals;
diff --git a/contrib/nvi/ex/script.h b/contrib/nvi/ex/script.h
new file mode 100644
index 000000000000..e29f63347961
--- /dev/null
+++ b/contrib/nvi/ex/script.h
@@ -0,0 +1,23 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)script.h 10.2 (Berkeley) 3/6/96
+ */
+
+struct _script {
+ pid_t sh_pid; /* Shell pid. */
+ int sh_master; /* Master pty fd. */
+ int sh_slave; /* Slave pty fd. */
+ char *sh_prompt; /* Prompt. */
+ size_t sh_prompt_len; /* Prompt length. */
+ char sh_name[64]; /* Pty name */
+#ifdef TIOCGWINSZ
+ struct winsize sh_win; /* Window size. */
+#endif
+ struct termios sh_term; /* Terminal information. */
+};
diff --git a/contrib/nvi/ex/tag.h b/contrib/nvi/ex/tag.h
new file mode 100644
index 000000000000..aee3dd27471d
--- /dev/null
+++ b/contrib/nvi/ex/tag.h
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ * Copyright (c) 1994, 1996
+ * Rob Mayoff. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)tag.h 10.5 (Berkeley) 5/15/96
+ */
+
+/*
+ * Cscope connection information. One of these is maintained per cscope
+ * connection, linked from the EX_PRIVATE structure.
+ */
+struct _csc {
+ LIST_ENTRY(_csc) q; /* Linked list of cscope connections. */
+
+ char *dname; /* Base directory of this cscope connection. */
+ size_t dlen; /* Length of base directory. */
+ pid_t pid; /* PID of the connected cscope process. */
+ time_t mtime; /* Last modification time of cscope database. */
+
+ FILE *from_fp; /* from cscope: FILE. */
+ int from_fd; /* from cscope: file descriptor. */
+ FILE *to_fp; /* to cscope: FILE. */
+ int to_fd; /* to cscope: file descriptor. */
+
+ char **paths; /* Array of search paths for this cscope. */
+ char *pbuf; /* Search path buffer. */
+ size_t pblen; /* Search path buffer length. */
+
+ char buf[1]; /* Variable length buffer. */
+};
+
+/*
+ * Tag file information. One of these is maintained per tag file, linked
+ * from the EXPRIVATE structure.
+ */
+struct _tagf { /* Tag files. */
+ TAILQ_ENTRY(_tagf) q; /* Linked list of tag files. */
+ char *name; /* Tag file name. */
+ int errnum; /* Errno. */
+
+#define TAGF_ERR 0x01 /* Error occurred. */
+#define TAGF_ERR_WARN 0x02 /* Error reported. */
+ u_int8_t flags;
+};
+
+/*
+ * Tags are structured internally as follows:
+ *
+ * +----+ +----+ +----+ +----+
+ * | EP | -> | Q1 | <-- | T1 | <-- | T2 |
+ * +----+ +----+ --> +----+ --> +----+
+ * |
+ * +----+ +----+
+ * | Q2 | <-- | T1 |
+ * +----+ --> +----+
+ * |
+ * +----+ +----+
+ * | Q3 | <-- | T1 |
+ * +----+ --> +----+
+ *
+ * Each Q is a TAGQ, or tag "query", which is the result of one tag or cscope
+ * command. Each Q references one or more TAG's, or tagged file locations.
+ *
+ * tag: put a new Q at the head (^])
+ * tagnext: T1 -> T2 inside Q (^N)
+ * tagprev: T2 -> T1 inside Q (^P)
+ * tagpop: discard Q (^T)
+ * tagtop: discard all Q
+ */
+struct _tag { /* Tag list. */
+ CIRCLEQ_ENTRY(_tag) q; /* Linked list of tags. */
+
+ /* Tag pop/return information. */
+ FREF *frp; /* Saved file. */
+ recno_t lno; /* Saved line number. */
+ size_t cno; /* Saved column number. */
+
+ char *fname; /* Filename. */
+ size_t fnlen; /* Filename length. */
+ recno_t slno; /* Search line number. */
+ char *search; /* Search string. */
+ size_t slen; /* Search string length. */
+
+ char buf[1]; /* Variable length buffer. */
+};
+
+struct _tagq { /* Tag queue. */
+ CIRCLEQ_ENTRY(_tagq) q; /* Linked list of tag queues. */
+ /* This queue's tag list. */
+ CIRCLEQ_HEAD(_tagqh, _tag) tagq;
+
+ TAG *current; /* Current TAG within the queue. */
+
+ char *tag; /* Tag string. */
+ size_t tlen; /* Tag string length. */
+
+#define TAG_CSCOPE 0x01 /* Cscope tag. */
+ u_int8_t flags;
+
+ char buf[1]; /* Variable length buffer. */
+};
diff --git a/contrib/nvi/ex/version.h b/contrib/nvi/ex/version.h
new file mode 100644
index 000000000000..7d657b635fc2
--- /dev/null
+++ b/contrib/nvi/ex/version.h
@@ -0,0 +1,2 @@
+#define VI_VERSION \
+ "Version 1.79 (10/23/96) The CSRG, University of California, Berkeley."
diff --git a/contrib/nvi/include/bitstring.h b/contrib/nvi/include/bitstring.h
new file mode 100644
index 000000000000..88437e7fb9f7
--- /dev/null
+++ b/contrib/nvi/include/bitstring.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Vixie.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)bitstring.h 8.1 (Berkeley) 7/19/93
+ */
+
+#ifndef _BITSTRING_H_
+#define _BITSTRING_H_
+
+typedef unsigned char bitstr_t;
+
+/* internal macros */
+ /* byte of the bitstring bit is in */
+#define _bit_byte(bit) \
+ ((bit) >> 3)
+
+ /* mask for the bit within its byte */
+#define _bit_mask(bit) \
+ (1 << ((bit)&0x7))
+
+/* external macros */
+ /* bytes in a bitstring of nbits bits */
+#define bitstr_size(nbits) \
+ ((((nbits) - 1) >> 3) + 1)
+
+ /* allocate a bitstring */
+#define bit_alloc(nbits) \
+ (bitstr_t *)calloc(1, \
+ (unsigned int)bitstr_size(nbits) * sizeof(bitstr_t))
+
+ /* allocate a bitstring on the stack */
+#define bit_decl(name, nbits) \
+ (name)[bitstr_size(nbits)]
+
+ /* is bit N of bitstring name set? */
+#define bit_test(name, bit) \
+ ((name)[_bit_byte(bit)] & _bit_mask(bit))
+
+ /* set bit N of bitstring name */
+#define bit_set(name, bit) \
+ (name)[_bit_byte(bit)] |= _bit_mask(bit)
+
+ /* clear bit N of bitstring name */
+#define bit_clear(name, bit) \
+ (name)[_bit_byte(bit)] &= ~_bit_mask(bit)
+
+ /* clear bits start ... stop in bitstring */
+#define bit_nclear(name, start, stop) { \
+ register bitstr_t *_name = name; \
+ register int _start = start, _stop = stop; \
+ register int _startbyte = _bit_byte(_start); \
+ register int _stopbyte = _bit_byte(_stop); \
+ if (_startbyte == _stopbyte) { \
+ _name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \
+ (0xff << ((_stop&0x7) + 1))); \
+ } else { \
+ _name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \
+ while (++_startbyte < _stopbyte) \
+ _name[_startbyte] = 0; \
+ _name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \
+ } \
+}
+
+ /* set bits start ... stop in bitstring */
+#define bit_nset(name, start, stop) { \
+ register bitstr_t *_name = name; \
+ register int _start = start, _stop = stop; \
+ register int _startbyte = _bit_byte(_start); \
+ register int _stopbyte = _bit_byte(_stop); \
+ if (_startbyte == _stopbyte) { \
+ _name[_startbyte] |= ((0xff << (_start&0x7)) & \
+ (0xff >> (7 - (_stop&0x7)))); \
+ } else { \
+ _name[_startbyte] |= 0xff << ((_start)&0x7); \
+ while (++_startbyte < _stopbyte) \
+ _name[_startbyte] = 0xff; \
+ _name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \
+ } \
+}
+
+ /* find first bit clear in name */
+#define bit_ffc(name, nbits, value) { \
+ register bitstr_t *_name = name; \
+ register int _byte, _nbits = nbits; \
+ register int _stopbyte = _bit_byte(_nbits), _value = -1; \
+ for (_byte = 0; _byte <= _stopbyte; ++_byte) \
+ if (_name[_byte] != 0xff) { \
+ _value = _byte << 3; \
+ for (_stopbyte = _name[_byte]; (_stopbyte&0x1); \
+ ++_value, _stopbyte >>= 1); \
+ break; \
+ } \
+ *(value) = _value; \
+}
+
+ /* find first bit set in name */
+#define bit_ffs(name, nbits, value) { \
+ register bitstr_t *_name = name; \
+ register int _byte, _nbits = nbits; \
+ register int _stopbyte = _bit_byte(_nbits), _value = -1; \
+ for (_byte = 0; _byte <= _stopbyte; ++_byte) \
+ if (_name[_byte]) { \
+ _value = _byte << 3; \
+ for (_stopbyte = _name[_byte]; !(_stopbyte&0x1); \
+ ++_value, _stopbyte >>= 1); \
+ break; \
+ } \
+ *(value) = _value; \
+}
+
+#endif /* !_BITSTRING_H_ */
diff --git a/contrib/nvi/include/cl_extern.h b/contrib/nvi/include/cl_extern.h
new file mode 100644
index 000000000000..bafeb944e969
--- /dev/null
+++ b/contrib/nvi/include/cl_extern.h
@@ -0,0 +1,56 @@
+#ifndef HAVE_CURSES_ADDNSTR
+int addnstr __P((char *, int));
+#endif
+#ifndef HAVE_CURSES_BEEP
+void beep __P((void));
+#endif
+#ifndef HAVE_CURSES_FLASH
+void flash __P((void));
+#endif
+#ifndef HAVE_CURSES_IDLOK
+void idlok __P((WINDOW *, int));
+#endif
+#ifndef HAVE_CURSES_KEYPAD
+int keypad __P((void *, int));
+#endif
+#ifndef HAVE_CURSES_NEWTERM
+void *newterm __P((const char *, FILE *, FILE *));
+#endif
+#ifndef HAVE_CURSES_SETUPTERM
+void setupterm __P((char *, int, int *));
+#endif
+#ifdef HAVE_CURSES_TIGETSTR
+char *tigetstr();
+#else
+char *tigetstr __P((char *));
+#endif
+#ifndef HAVE_CURSES_TIGETSTR
+int tigetnum __P((char *));
+#endif
+int cl_addstr __P((SCR *, const char *, size_t));
+int cl_attr __P((SCR *, scr_attr_t, int));
+int cl_baud __P((SCR *, u_long *));
+int cl_bell __P((SCR *));
+int cl_clrtoeol __P((SCR *));
+int cl_cursor __P((SCR *, size_t *, size_t *));
+int cl_deleteln __P((SCR *));
+int cl_ex_adjust __P((SCR *, exadj_t));
+int cl_insertln __P((SCR *));
+int cl_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
+int cl_move __P((SCR *, size_t, size_t));
+int cl_refresh __P((SCR *, int));
+int cl_rename __P((SCR *, char *, int));
+int cl_suspend __P((SCR *, int *));
+void cl_usage __P((void));
+int sig_init __P((GS *, SCR *));
+int cl_event __P((SCR *, EVENT *, u_int32_t, int));
+int cl_screen __P((SCR *, u_int32_t));
+int cl_quit __P((GS *));
+int cl_getcap __P((SCR *, char *, char **));
+int cl_term_init __P((SCR *));
+int cl_term_end __P((GS *));
+int cl_fmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
+int cl_optchange __P((SCR *, int, char *, u_long *));
+int cl_omesg __P((SCR *, CL_PRIVATE *, int));
+int cl_ssize __P((SCR *, int, size_t *, size_t *, int *));
+int cl_putchar __P((int));
diff --git a/contrib/nvi/include/com_extern.h b/contrib/nvi/include/com_extern.h
new file mode 100644
index 000000000000..f140f9e34232
--- /dev/null
+++ b/contrib/nvi/include/com_extern.h
@@ -0,0 +1,199 @@
+#ifndef HAVE_BSEARCH
+void *bsearch __P((const void *, const void *, size_t,
+ size_t, int (*)(const void *, const void *)));
+#endif
+#ifndef HAVE_SETENV
+int setenv __P((const char *, const char *, int));
+#endif
+#ifndef HAVE_UNSETENV
+void unsetenv __P((const char *));
+#endif
+#ifndef HAVE_GETHOSTNAME
+int gethostname __P((char *, int));
+#endif
+#ifndef HAVE_GETOPT
+int getopt __P((int, char * const *, const char *));
+#endif
+#ifndef HAVE_MEMCHR
+void *memchr __P((const void *, int, size_t));
+#endif
+#ifndef HAVE_MEMCPY
+void *memcpy __P((void *, const void *, size_t));
+#endif
+#ifndef HAVE_MEMMOVE
+void *memmove __P((void *, const void *, size_t));
+#endif
+#ifndef HAVE_MEMSET
+void *memset __P((void *, int, size_t));
+#endif
+#ifndef HAVE_MKSTEMP
+int mkstemp __P((char *));
+#endif
+#ifndef HAVE_MMAP
+char *mmap __P((char *, size_t, int, int, int, off_t));
+#endif
+#ifndef HAVE_MMAP
+int munmap __P((char *, size_t));
+#endif
+#ifndef HAVE_SNPRINTF
+int snprintf __P((char *, size_t, const char *, ...));
+#endif
+#ifndef HAVE_STRDUP
+char *strdup __P((const char *));
+#endif
+#ifndef HAVE_STRERROR
+char *strerror __P((int));
+#endif
+#ifndef HAVE_STRPBRK
+char *strpbrk __P((const char *, const char *));
+#endif
+#ifndef HAVE_STRSEP
+char *strsep __P((char **, const char *));
+#endif
+#ifndef HAVE_STRTOL
+long strtol __P((const char *, char **, int));
+#endif
+#ifndef HAVE_STRTOUL
+unsigned long strtoul __P((const char *, char **, int));
+#endif
+#ifndef HAVE_VSNPRINTF
+int vsnprintf __P((char *, size_t, const char *, ...));
+#endif
+SCR *api_fscreen __P((int, char *));
+int api_aline __P((SCR *, recno_t, char *, size_t));
+int api_dline __P((SCR *, recno_t));
+int api_gline __P((SCR *, recno_t, char **, size_t *));
+int api_iline __P((SCR *, recno_t, char *, size_t));
+int api_lline __P((SCR *, recno_t *));
+int api_sline __P((SCR *, recno_t, char *, size_t));
+int api_getmark __P((SCR *, int, MARK *));
+int api_setmark __P((SCR *, int, MARK *));
+int api_nextmark __P((SCR *, int, char *));
+int api_getcursor __P((SCR *, MARK *));
+int api_setcursor __P((SCR *, MARK *));
+void api_emessage __P((SCR *, char *));
+void api_imessage __P((SCR *, char *));
+int api_edit __P((SCR *, char *, SCR **, int));
+int api_escreen __P((SCR *));
+int api_swscreen __P((SCR *, SCR *));
+int api_map __P((SCR *, char *, char *, size_t));
+int api_unmap __P((SCR *, char *));
+int api_opts_get __P((SCR *, char *, char **, int *));
+int api_opts_set __P((SCR *, char *, char *, u_long, int));
+int api_run_str __P((SCR *, char *));
+int cut __P((SCR *, CHAR_T *, MARK *, MARK *, int));
+int cut_line __P((SCR *, recno_t, size_t, size_t, CB *));
+void cut_close __P((GS *));
+TEXT *text_init __P((SCR *, const char *, size_t, size_t));
+void text_lfree __P((TEXTH *));
+void text_free __P((TEXT *));
+int del __P((SCR *, MARK *, MARK *, int));
+FREF *file_add __P((SCR *, CHAR_T *));
+int file_init __P((SCR *, FREF *, char *, int));
+int file_end __P((SCR *, EXF *, int));
+int file_write __P((SCR *, MARK *, MARK *, char *, int));
+int file_m1 __P((SCR *, int, int));
+int file_m2 __P((SCR *, int));
+int file_m3 __P((SCR *, int));
+int file_aw __P((SCR *, int));
+void set_alt_name __P((SCR *, char *));
+lockr_t file_lock __P((SCR *, char *, int *, int, int));
+int v_key_init __P((SCR *));
+void v_key_ilookup __P((SCR *));
+size_t v_key_len __P((SCR *, ARG_CHAR_T));
+CHAR_T *v_key_name __P((SCR *, ARG_CHAR_T));
+int v_key_val __P((SCR *, ARG_CHAR_T));
+int v_event_push __P((SCR *, EVENT *, CHAR_T *, size_t, u_int));
+int v_event_get __P((SCR *, EVENT *, int, u_int32_t));
+void v_event_err __P((SCR *, EVENT *));
+int v_event_flush __P((SCR *, u_int));
+int db_eget __P((SCR *, recno_t, char **, size_t *, int *));
+int db_get __P((SCR *, recno_t, u_int32_t, char **, size_t *));
+int db_delete __P((SCR *, recno_t));
+int db_append __P((SCR *, int, recno_t, char *, size_t));
+int db_insert __P((SCR *, recno_t, char *, size_t));
+int db_set __P((SCR *, recno_t, char *, size_t));
+int db_exist __P((SCR *, recno_t));
+int db_last __P((SCR *, recno_t *));
+void db_err __P((SCR *, recno_t));
+int log_init __P((SCR *, EXF *));
+int log_end __P((SCR *, EXF *));
+int log_cursor __P((SCR *));
+int log_line __P((SCR *, recno_t, u_int));
+int log_mark __P((SCR *, LMARK *));
+int log_backward __P((SCR *, MARK *));
+int log_setline __P((SCR *));
+int log_forward __P((SCR *, MARK *));
+int editor __P((GS *, int, char *[]));
+void v_end __P((GS *));
+int mark_init __P((SCR *, EXF *));
+int mark_end __P((SCR *, EXF *));
+int mark_get __P((SCR *, ARG_CHAR_T, MARK *, mtype_t));
+int mark_set __P((SCR *, ARG_CHAR_T, MARK *, int));
+int mark_insdel __P((SCR *, lnop_t, recno_t));
+void msgq __P((SCR *, mtype_t, const char *, ...));
+void msgq_str __P((SCR *, mtype_t, char *, char *));
+void mod_rpt __P((SCR *));
+void msgq_status __P((SCR *, recno_t, u_int));
+int msg_open __P((SCR *, char *));
+void msg_close __P((GS *));
+const char *msg_cmsg __P((SCR *, cmsg_t, size_t *));
+const char *msg_cat __P((SCR *, const char *, size_t *));
+char *msg_print __P((SCR *, const char *, int *));
+int opts_init __P((SCR *, int *));
+int opts_set __P((SCR *, ARGS *[], char *));
+int o_set __P((SCR *, int, u_int, char *, u_long));
+int opts_empty __P((SCR *, int, int));
+void opts_dump __P((SCR *, enum optdisp));
+int opts_save __P((SCR *, FILE *));
+OPTLIST const *opts_search __P((char *));
+void opts_nomatch __P((SCR *, char *));
+int opts_copy __P((SCR *, SCR *));
+void opts_free __P((SCR *));
+int f_altwerase __P((SCR *, OPTION *, char *, u_long *));
+int f_columns __P((SCR *, OPTION *, char *, u_long *));
+int f_lines __P((SCR *, OPTION *, char *, u_long *));
+int f_lisp __P((SCR *, OPTION *, char *, u_long *));
+int f_msgcat __P((SCR *, OPTION *, char *, u_long *));
+int f_paragraph __P((SCR *, OPTION *, char *, u_long *));
+int f_print __P((SCR *, OPTION *, char *, u_long *));
+int f_readonly __P((SCR *, OPTION *, char *, u_long *));
+int f_recompile __P((SCR *, OPTION *, char *, u_long *));
+int f_reformat __P((SCR *, OPTION *, char *, u_long *));
+int f_section __P((SCR *, OPTION *, char *, u_long *));
+int f_ttywerase __P((SCR *, OPTION *, char *, u_long *));
+int f_w300 __P((SCR *, OPTION *, char *, u_long *));
+int f_w1200 __P((SCR *, OPTION *, char *, u_long *));
+int f_w9600 __P((SCR *, OPTION *, char *, u_long *));
+int f_window __P((SCR *, OPTION *, char *, u_long *));
+int put __P((SCR *, CB *, CHAR_T *, MARK *, MARK *, int));
+int rcv_tmp __P((SCR *, EXF *, char *));
+int rcv_init __P((SCR *));
+int rcv_sync __P((SCR *, u_int));
+int rcv_list __P((SCR *));
+int rcv_read __P((SCR *, FREF *));
+int screen_init __P((GS *, SCR *, SCR **));
+int screen_end __P((SCR *));
+SCR *screen_next __P((SCR *));
+int f_search __P((SCR *,
+ MARK *, MARK *, char *, size_t, char **, u_int));
+int b_search __P((SCR *,
+ MARK *, MARK *, char *, size_t, char **, u_int));
+void search_busy __P((SCR *, busy_t));
+int seq_set __P((SCR *, CHAR_T *,
+ size_t, CHAR_T *, size_t, CHAR_T *, size_t, seq_t, int));
+int seq_delete __P((SCR *, CHAR_T *, size_t, seq_t));
+int seq_mdel __P((SEQ *));
+SEQ *seq_find
+ __P((SCR *, SEQ **, EVENT *, CHAR_T *, size_t, seq_t, int *));
+void seq_close __P((GS *));
+int seq_dump __P((SCR *, seq_t, int));
+int seq_save __P((SCR *, FILE *, char *, seq_t));
+int e_memcmp __P((CHAR_T *, EVENT *, size_t));
+void *binc __P((SCR *, void *, size_t *, size_t));
+int nonblank __P((SCR *, recno_t, size_t *));
+char *tail __P((char *));
+CHAR_T *v_strdup __P((SCR *, const CHAR_T *, size_t));
+enum nresult nget_uslong __P((u_long *, const char *, char **, int));
+enum nresult nget_slong __P((long *, const char *, char **, int));
+void TRACE __P((SCR *, const char *, ...));
diff --git a/contrib/nvi/include/ex_def.h b/contrib/nvi/include/ex_def.h
new file mode 100644
index 000000000000..2e69b4872f59
--- /dev/null
+++ b/contrib/nvi/include/ex_def.h
@@ -0,0 +1,78 @@
+#define C_SCROLL 0
+#define C_BANG 1
+#define C_HASH 2
+#define C_SUBAGAIN 3
+#define C_STAR 4
+#define C_SHIFTL 5
+#define C_EQUAL 6
+#define C_SHIFTR 7
+#define C_AT 8
+#define C_APPEND 9
+#define C_ABBR 10
+#define C_ARGS 11
+#define C_BG 12
+#define C_CHANGE 13
+#define C_CD 14
+#define C_CHDIR 15
+#define C_COPY 16
+#define C_CSCOPE 17
+#define C_DELETE 18
+#define C_DISPLAY 19
+#define C_EDIT 20
+#define C_EX 21
+#define C_EXUSAGE 22
+#define C_FILE 23
+#define C_FG 24
+#define C_GLOBAL 25
+#define C_HELP 26
+#define C_INSERT 27
+#define C_JOIN 28
+#define C_K 29
+#define C_LIST 30
+#define C_MOVE 31
+#define C_MARK 32
+#define C_MAP 33
+#define C_MKEXRC 34
+#define C_NEXT 35
+#define C_NUMBER 36
+#define C_OPEN 37
+#define C_PRINT 38
+#define C_PERLCMD 39
+#define C_PERLDOCMD 40
+#define C_PRESERVE 41
+#define C_PREVIOUS 42
+#define C_PUT 43
+#define C_QUIT 44
+#define C_READ 45
+#define C_RECOVER 46
+#define C_RESIZE 47
+#define C_REWIND 48
+#define C_SUBSTITUTE 49
+#define C_SCRIPT 50
+#define C_SET 51
+#define C_SHELL 52
+#define C_SOURCE 53
+#define C_STOP 54
+#define C_SUSPEND 55
+#define C_T 56
+#define C_TAG 57
+#define C_TAGNEXT 58
+#define C_TAGPOP 59
+#define C_TAGPREV 60
+#define C_TAGTOP 61
+#define C_TCLCMD 62
+#define C_UNDO 63
+#define C_UNABBREVIATE 64
+#define C_UNMAP 65
+#define C_V 66
+#define C_VERSION 67
+#define C_VISUAL_EX 68
+#define C_VISUAL_VI 69
+#define C_VIUSAGE 70
+#define C_WRITE 71
+#define C_WN 72
+#define C_WQ 73
+#define C_XIT 74
+#define C_YANK 75
+#define C_Z 76
+#define C_SUBTILDE 77
diff --git a/contrib/nvi/include/ex_extern.h b/contrib/nvi/include/ex_extern.h
new file mode 100644
index 000000000000..ed01701f1185
--- /dev/null
+++ b/contrib/nvi/include/ex_extern.h
@@ -0,0 +1,127 @@
+int ex __P((SCR **));
+int ex_cmd __P((SCR *));
+int ex_range __P((SCR *, EXCMD *, int *));
+int ex_is_abbrev __P((char *, size_t));
+int ex_is_unmap __P((char *, size_t));
+void ex_badaddr
+ __P((SCR *, EXCMDLIST const *, enum badaddr, enum nresult));
+int ex_abbr __P((SCR *, EXCMD *));
+int ex_unabbr __P((SCR *, EXCMD *));
+int ex_append __P((SCR *, EXCMD *));
+int ex_change __P((SCR *, EXCMD *));
+int ex_insert __P((SCR *, EXCMD *));
+int ex_next __P((SCR *, EXCMD *));
+int ex_prev __P((SCR *, EXCMD *));
+int ex_rew __P((SCR *, EXCMD *));
+int ex_args __P((SCR *, EXCMD *));
+char **ex_buildargv __P((SCR *, EXCMD *, char *));
+int argv_init __P((SCR *, EXCMD *));
+int argv_exp0 __P((SCR *, EXCMD *, char *, size_t));
+int argv_exp1 __P((SCR *, EXCMD *, char *, size_t, int));
+int argv_exp2 __P((SCR *, EXCMD *, char *, size_t));
+int argv_exp3 __P((SCR *, EXCMD *, char *, size_t));
+int argv_free __P((SCR *));
+int ex_at __P((SCR *, EXCMD *));
+int ex_bang __P((SCR *, EXCMD *));
+int ex_cd __P((SCR *, EXCMD *));
+int ex_cscope __P((SCR *, EXCMD *));
+int cscope_display __P((SCR *));
+int cscope_search __P((SCR *, TAGQ *, TAG *));
+int ex_delete __P((SCR *, EXCMD *));
+int ex_display __P((SCR *, EXCMD *));
+int ex_edit __P((SCR *, EXCMD *));
+int ex_equal __P((SCR *, EXCMD *));
+int ex_file __P((SCR *, EXCMD *));
+int ex_filter __P((SCR *,
+ EXCMD *, MARK *, MARK *, MARK *, char *, enum filtertype));
+int ex_global __P((SCR *, EXCMD *));
+int ex_v __P((SCR *, EXCMD *));
+int ex_g_insdel __P((SCR *, lnop_t, recno_t));
+int ex_screen_copy __P((SCR *, SCR *));
+int ex_screen_end __P((SCR *));
+int ex_optchange __P((SCR *, int, char *, u_long *));
+int ex_exrc __P((SCR *));
+int ex_run_str __P((SCR *, char *, char *, size_t, int, int));
+int ex_join __P((SCR *, EXCMD *));
+int ex_map __P((SCR *, EXCMD *));
+int ex_unmap __P((SCR *, EXCMD *));
+int ex_mark __P((SCR *, EXCMD *));
+int ex_mkexrc __P((SCR *, EXCMD *));
+int ex_copy __P((SCR *, EXCMD *));
+int ex_move __P((SCR *, EXCMD *));
+int ex_open __P((SCR *, EXCMD *));
+int ex_perl __P((SCR*, EXCMD *));
+int ex_preserve __P((SCR *, EXCMD *));
+int ex_recover __P((SCR *, EXCMD *));
+int ex_list __P((SCR *, EXCMD *));
+int ex_number __P((SCR *, EXCMD *));
+int ex_pr __P((SCR *, EXCMD *));
+int ex_print __P((SCR *, EXCMD *, MARK *, MARK *, u_int32_t));
+int ex_ldisplay __P((SCR *, const char *, size_t, size_t, u_int));
+int ex_scprint __P((SCR *, MARK *, MARK *));
+int ex_printf __P((SCR *, const char *, ...));
+int ex_puts __P((SCR *, const char *));
+int ex_fflush __P((SCR *sp));
+int ex_put __P((SCR *, EXCMD *));
+int ex_quit __P((SCR *, EXCMD *));
+int ex_read __P((SCR *, EXCMD *));
+int ex_readfp __P((SCR *, char *, FILE *, MARK *, recno_t *, int));
+int ex_bg __P((SCR *, EXCMD *));
+int ex_fg __P((SCR *, EXCMD *));
+int ex_resize __P((SCR *, EXCMD *));
+int ex_sdisplay __P((SCR *));
+int ex_script __P((SCR *, EXCMD *));
+int sscr_exec __P((SCR *, recno_t));
+int sscr_input __P((SCR *));
+int sscr_end __P((SCR *));
+int ex_set __P((SCR *, EXCMD *));
+int ex_shell __P((SCR *, EXCMD *));
+int ex_exec_proc __P((SCR *, EXCMD *, char *, const char *, int));
+int proc_wait __P((SCR *, long, const char *, int, int));
+int ex_shiftl __P((SCR *, EXCMD *));
+int ex_shiftr __P((SCR *, EXCMD *));
+int ex_source __P((SCR *, EXCMD *));
+int ex_stop __P((SCR *, EXCMD *));
+int ex_s __P((SCR *, EXCMD *));
+int ex_subagain __P((SCR *, EXCMD *));
+int ex_subtilde __P((SCR *, EXCMD *));
+int re_compile __P((SCR *,
+ char *, size_t, char **, size_t *, regex_t *, u_int));
+void re_error __P((SCR *, int, regex_t *));
+int ex_tag_first __P((SCR *, char *));
+int ex_tag_push __P((SCR *, EXCMD *));
+int ex_tag_next __P((SCR *, EXCMD *));
+int ex_tag_prev __P((SCR *, EXCMD *));
+int ex_tag_nswitch __P((SCR *, TAG *, int));
+int ex_tag_Nswitch __P((SCR *, TAG *, int));
+int ex_tag_pop __P((SCR *, EXCMD *));
+int ex_tag_top __P((SCR *, EXCMD *));
+int ex_tag_display __P((SCR *));
+int ex_tag_copy __P((SCR *, SCR *));
+int tagq_free __P((SCR *, TAGQ *));
+void tag_msg __P((SCR *, tagmsg_t, char *));
+int ex_tagf_alloc __P((SCR *, char *));
+int ex_tag_free __P((SCR *));
+int ex_tcl __P((SCR*, EXCMD *));
+int ex_txt __P((SCR *, TEXTH *, ARG_CHAR_T, u_int32_t));
+int ex_undo __P((SCR *, EXCMD *));
+int ex_help __P((SCR *, EXCMD *));
+int ex_usage __P((SCR *, EXCMD *));
+int ex_viusage __P((SCR *, EXCMD *));
+void ex_cinit __P((EXCMD *,
+ int, int, recno_t, recno_t, int, ARGS **));
+void ex_cadd __P((EXCMD *, ARGS *, char *, size_t));
+int ex_getline __P((SCR *, FILE *, size_t *));
+int ex_ncheck __P((SCR *, int));
+int ex_init __P((SCR *));
+void ex_emsg __P((SCR *, char *, exm_t));
+int ex_version __P((SCR *, EXCMD *));
+int ex_visual __P((SCR *, EXCMD *));
+int ex_wn __P((SCR *, EXCMD *));
+int ex_wq __P((SCR *, EXCMD *));
+int ex_write __P((SCR *, EXCMD *));
+int ex_xit __P((SCR *, EXCMD *));
+int ex_writefp __P((SCR *,
+ char *, FILE *, MARK *, MARK *, u_long *, u_long *, int));
+int ex_yank __P((SCR *, EXCMD *));
+int ex_z __P((SCR *, EXCMD *));
diff --git a/contrib/nvi/include/ip_extern.h b/contrib/nvi/include/ip_extern.h
new file mode 100644
index 000000000000..b805343a8e81
--- /dev/null
+++ b/contrib/nvi/include/ip_extern.h
@@ -0,0 +1,23 @@
+int ip_addstr __P((SCR *, const char *, size_t));
+int ip_attr __P((SCR *, scr_attr_t, int));
+int ip_baud __P((SCR *, u_long *));
+int ip_bell __P((SCR *));
+void ip_busy __P((SCR *, const char *, busy_t));
+int ip_clrtoeol __P((SCR *));
+int ip_cursor __P((SCR *, size_t *, size_t *));
+int ip_deleteln __P((SCR *));
+int ip_ex_adjust __P((SCR *, exadj_t));
+int ip_insertln __P((SCR *));
+int ip_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
+int ip_move __P((SCR *, size_t, size_t));
+int ip_refresh __P((SCR *, int));
+int ip_rename __P((SCR *));
+int ip_suspend __P((SCR *, int *));
+void ip_usage __P((void));
+int ip_event __P((SCR *, EVENT *, u_int32_t, int));
+int ip_screen __P((SCR *, u_int32_t));
+int ip_quit __P((GS *));
+int ip_term_init __P((SCR *));
+int ip_term_end __P((GS *));
+int ip_fmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
+int ip_optchange __P((SCR *, int, char *, u_long *));
diff --git a/contrib/nvi/include/options_def.h b/contrib/nvi/include/options_def.h
new file mode 100644
index 000000000000..089fa7f4ea4c
--- /dev/null
+++ b/contrib/nvi/include/options_def.h
@@ -0,0 +1,79 @@
+#define O_ALTWERASE 0
+#define O_AUTOINDENT 1
+#define O_AUTOPRINT 2
+#define O_AUTOWRITE 3
+#define O_BACKUP 4
+#define O_BEAUTIFY 5
+#define O_CDPATH 6
+#define O_CEDIT 7
+#define O_COLUMNS 8
+#define O_COMMENT 9
+#define O_DIRECTORY 10
+#define O_EDCOMPATIBLE 11
+#define O_ESCAPETIME 12
+#define O_ERRORBELLS 13
+#define O_EXRC 14
+#define O_EXTENDED 15
+#define O_FILEC 16
+#define O_FLASH 17
+#define O_HARDTABS 18
+#define O_ICLOWER 19
+#define O_IGNORECASE 20
+#define O_KEYTIME 21
+#define O_LEFTRIGHT 22
+#define O_LINES 23
+#define O_LISP 24
+#define O_LIST 25
+#define O_LOCKFILES 26
+#define O_MAGIC 27
+#define O_MATCHTIME 28
+#define O_MESG 29
+#define O_MODELINE 30
+#define O_MSGCAT 31
+#define O_NOPRINT 32
+#define O_NUMBER 33
+#define O_OCTAL 34
+#define O_OPEN 35
+#define O_OPTIMIZE 36
+#define O_PARAGRAPHS 37
+#define O_PATH 38
+#define O_PRINT 39
+#define O_PROMPT 40
+#define O_READONLY 41
+#define O_RECDIR 42
+#define O_REDRAW 43
+#define O_REMAP 44
+#define O_REPORT 45
+#define O_RULER 46
+#define O_SCROLL 47
+#define O_SEARCHINCR 48
+#define O_SECTIONS 49
+#define O_SECURE 50
+#define O_SHELL 51
+#define O_SHELLMETA 52
+#define O_SHIFTWIDTH 53
+#define O_SHOWMATCH 54
+#define O_SHOWMODE 55
+#define O_SIDESCROLL 56
+#define O_SLOWOPEN 57
+#define O_SOURCEANY 58
+#define O_TABSTOP 59
+#define O_TAGLENGTH 60
+#define O_TAGS 61
+#define O_TERM 62
+#define O_TERSE 63
+#define O_TILDEOP 64
+#define O_TIMEOUT 65
+#define O_TTYWERASE 66
+#define O_VERBOSE 67
+#define O_W1200 68
+#define O_W300 69
+#define O_W9600 70
+#define O_WARN 71
+#define O_WINDOW 72
+#define O_WINDOWNAME 73
+#define O_WRAPLEN 74
+#define O_WRAPMARGIN 75
+#define O_WRAPSCAN 76
+#define O_WRITEANY 77
+#define O_OPTIONCOUNT 78
diff --git a/contrib/nvi/include/perl_extern.h b/contrib/nvi/include/perl_extern.h
new file mode 100644
index 000000000000..5d6dd0d33bb6
--- /dev/null
+++ b/contrib/nvi/include/perl_extern.h
@@ -0,0 +1,8 @@
+int perl_end __P((GS *));
+int perl_init __P((SCR *));
+int perl_screen_end __P((SCR*));
+int perl_ex_perl __P((SCR*, CHAR_T *, size_t, recno_t, recno_t));
+int perl_ex_perldo __P((SCR*, CHAR_T *, size_t, recno_t, recno_t));
+#ifdef USE_SFIO
+Sfdisc_t* sfdcnewnvi __P((SCR*));
+#endif
diff --git a/contrib/nvi/include/sys/queue.h b/contrib/nvi/include/sys/queue.h
new file mode 100644
index 000000000000..cbd75864ecda
--- /dev/null
+++ b/contrib/nvi/include/sys/queue.h
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+/*
+ * This file defines three types of data structures: lists, tail queues,
+ * and circular queues.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may only be traversed in the forward direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List functions.
+ */
+#define LIST_INIT(head) { \
+ (head)->lh_first = NULL; \
+}
+
+#define LIST_INSERT_AFTER(listelm, elm, field) { \
+ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
+ (listelm)->field.le_next->field.le_prev = \
+ &(elm)->field.le_next; \
+ (listelm)->field.le_next = (elm); \
+ (elm)->field.le_prev = &(listelm)->field.le_next; \
+}
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+}
+
+#define LIST_INSERT_HEAD(head, elm, field) { \
+ if (((elm)->field.le_next = (head)->lh_first) != NULL) \
+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+ (head)->lh_first = (elm); \
+ (elm)->field.le_prev = &(head)->lh_first; \
+}
+
+#define LIST_REMOVE(elm, field) { \
+ if ((elm)->field.le_next != NULL) \
+ (elm)->field.le_next->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = (elm)->field.le_next; \
+}
+
+/*
+ * Tail queue definitions.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+}
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+}
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_INIT(head) { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_last = &(head)->tqh_first; \
+}
+
+#define TAILQ_INSERT_HEAD(head, elm, field) { \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+}
+
+#define TAILQ_INSERT_TAIL(head, elm, field) { \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+}
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) { \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+}
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+}
+
+#define TAILQ_REMOVE(head, elm, field) { \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+}
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type) \
+struct name { \
+ struct type *cqh_first; /* first element */ \
+ struct type *cqh_last; /* last element */ \
+}
+
+#define CIRCLEQ_ENTRY(type) \
+struct { \
+ struct type *cqe_next; /* next element */ \
+ struct type *cqe_prev; /* previous element */ \
+}
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_INIT(head) { \
+ (head)->cqh_first = (void *)(head); \
+ (head)->cqh_last = (void *)(head); \
+}
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) { \
+ (elm)->field.cqe_next = (listelm)->field.cqe_next; \
+ (elm)->field.cqe_prev = (listelm); \
+ if ((listelm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (listelm)->field.cqe_next->field.cqe_prev = (elm); \
+ (listelm)->field.cqe_next = (elm); \
+}
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) { \
+ (elm)->field.cqe_next = (listelm); \
+ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
+ if ((listelm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (listelm)->field.cqe_prev->field.cqe_next = (elm); \
+ (listelm)->field.cqe_prev = (elm); \
+}
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) { \
+ (elm)->field.cqe_next = (head)->cqh_first; \
+ (elm)->field.cqe_prev = (void *)(head); \
+ if ((head)->cqh_last == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (head)->cqh_first->field.cqe_prev = (elm); \
+ (head)->cqh_first = (elm); \
+}
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) { \
+ (elm)->field.cqe_next = (void *)(head); \
+ (elm)->field.cqe_prev = (head)->cqh_last; \
+ if ((head)->cqh_first == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (head)->cqh_last->field.cqe_next = (elm); \
+ (head)->cqh_last = (elm); \
+}
+
+#define CIRCLEQ_REMOVE(head, elm, field) { \
+ if ((elm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm)->field.cqe_prev; \
+ else \
+ (elm)->field.cqe_next->field.cqe_prev = \
+ (elm)->field.cqe_prev; \
+ if ((elm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm)->field.cqe_next; \
+ else \
+ (elm)->field.cqe_prev->field.cqe_next = \
+ (elm)->field.cqe_next; \
+}
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/contrib/nvi/include/tcl_extern.h b/contrib/nvi/include/tcl_extern.h
new file mode 100644
index 000000000000..ac68ae4119fd
--- /dev/null
+++ b/contrib/nvi/include/tcl_extern.h
@@ -0,0 +1 @@
+int tcl_init __P((GS *));
diff --git a/contrib/nvi/include/tk_extern.h b/contrib/nvi/include/tk_extern.h
new file mode 100644
index 000000000000..20a4de459f5e
--- /dev/null
+++ b/contrib/nvi/include/tk_extern.h
@@ -0,0 +1,29 @@
+int tk_addstr __P((SCR *, const char *, size_t));
+int tk_attr __P((SCR *, scr_attr_t, int));
+int tk_baud __P((SCR *, u_long *));
+int tk_bell __P((SCR *));
+int tk_clrtoeol __P((SCR *));
+int tk_cursor __P((SCR *, size_t *, size_t *));
+int tk_deleteln __P((SCR *));
+int tk_ex_adjust __P((SCR *, exadj_t));
+int tk_insertln __P((SCR *));
+int tk_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
+int tk_move __P((SCR *, size_t, size_t));
+int tk_refresh __P((SCR *, int));
+int tk_rename __P((SCR *));
+int tk_suspend __P((SCR *, int *));
+void tk_usage __P((void));
+int tk_event __P((SCR *, EVENT *, u_int32_t, int));
+int tk_key __P((ClientData, Tcl_Interp *, int, char *[]));
+int tk_screen __P((SCR *, u_int32_t));
+int tk_quit __P((GS *));
+int tk_term_init __P((SCR *));
+int tk_term_end __P((GS *));
+int tk_fmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
+int tk_optchange __P((SCR *, int, char *, u_long *));
+int tk_ssize __P((SCR *, int, size_t *, size_t *, int *));
+int tk_op __P((ClientData, Tcl_Interp *, int, char *[]));
+int tk_opt_init __P((ClientData, Tcl_Interp *, int, char *[]));
+int tk_opt_set __P((ClientData, Tcl_Interp *, int, char *[]));
+int tk_version __P((ClientData, Tcl_Interp *, int, char *[]));
+void tk_msg __P((SCR *, mtype_t, char *, size_t));
diff --git a/contrib/nvi/include/vi_extern.h b/contrib/nvi/include/vi_extern.h
new file mode 100644
index 000000000000..b3c335e6c580
--- /dev/null
+++ b/contrib/nvi/include/vi_extern.h
@@ -0,0 +1,142 @@
+int cs_init __P((SCR *, VCS *));
+int cs_next __P((SCR *, VCS *));
+int cs_fspace __P((SCR *, VCS *));
+int cs_fblank __P((SCR *, VCS *));
+int cs_prev __P((SCR *, VCS *));
+int cs_bblank __P((SCR *, VCS *));
+int v_at __P((SCR *, VICMD *));
+int v_chrepeat __P((SCR *, VICMD *));
+int v_chrrepeat __P((SCR *, VICMD *));
+int v_cht __P((SCR *, VICMD *));
+int v_chf __P((SCR *, VICMD *));
+int v_chT __P((SCR *, VICMD *));
+int v_chF __P((SCR *, VICMD *));
+int v_delete __P((SCR *, VICMD *));
+int v_again __P((SCR *, VICMD *));
+int v_exmode __P((SCR *, VICMD *));
+int v_join __P((SCR *, VICMD *));
+int v_shiftl __P((SCR *, VICMD *));
+int v_shiftr __P((SCR *, VICMD *));
+int v_suspend __P((SCR *, VICMD *));
+int v_switch __P((SCR *, VICMD *));
+int v_tagpush __P((SCR *, VICMD *));
+int v_tagpop __P((SCR *, VICMD *));
+int v_filter __P((SCR *, VICMD *));
+int v_event_exec __P((SCR *, VICMD *));
+int v_ex __P((SCR *, VICMD *));
+int v_ecl_exec __P((SCR *));
+int v_increment __P((SCR *, VICMD *));
+int v_screen_copy __P((SCR *, SCR *));
+int v_screen_end __P((SCR *));
+int v_optchange __P((SCR *, int, char *, u_long *));
+int v_iA __P((SCR *, VICMD *));
+int v_ia __P((SCR *, VICMD *));
+int v_iI __P((SCR *, VICMD *));
+int v_ii __P((SCR *, VICMD *));
+int v_iO __P((SCR *, VICMD *));
+int v_io __P((SCR *, VICMD *));
+int v_change __P((SCR *, VICMD *));
+int v_Replace __P((SCR *, VICMD *));
+int v_subst __P((SCR *, VICMD *));
+int v_left __P((SCR *, VICMD *));
+int v_cfirst __P((SCR *, VICMD *));
+int v_first __P((SCR *, VICMD *));
+int v_ncol __P((SCR *, VICMD *));
+int v_zero __P((SCR *, VICMD *));
+int v_mark __P((SCR *, VICMD *));
+int v_bmark __P((SCR *, VICMD *));
+int v_fmark __P((SCR *, VICMD *));
+int v_match __P((SCR *, VICMD *));
+int v_paragraphf __P((SCR *, VICMD *));
+int v_paragraphb __P((SCR *, VICMD *));
+int v_buildps __P((SCR *, char *, char *));
+int v_Put __P((SCR *, VICMD *));
+int v_put __P((SCR *, VICMD *));
+int v_redraw __P((SCR *, VICMD *));
+int v_replace __P((SCR *, VICMD *));
+int v_right __P((SCR *, VICMD *));
+int v_dollar __P((SCR *, VICMD *));
+int v_screen __P((SCR *, VICMD *));
+int v_lgoto __P((SCR *, VICMD *));
+int v_home __P((SCR *, VICMD *));
+int v_middle __P((SCR *, VICMD *));
+int v_bottom __P((SCR *, VICMD *));
+int v_up __P((SCR *, VICMD *));
+int v_cr __P((SCR *, VICMD *));
+int v_down __P((SCR *, VICMD *));
+int v_hpageup __P((SCR *, VICMD *));
+int v_hpagedown __P((SCR *, VICMD *));
+int v_pagedown __P((SCR *, VICMD *));
+int v_pageup __P((SCR *, VICMD *));
+int v_lineup __P((SCR *, VICMD *));
+int v_linedown __P((SCR *, VICMD *));
+int v_searchb __P((SCR *, VICMD *));
+int v_searchf __P((SCR *, VICMD *));
+int v_searchN __P((SCR *, VICMD *));
+int v_searchn __P((SCR *, VICMD *));
+int v_searchw __P((SCR *, VICMD *));
+int v_correct __P((SCR *, VICMD *, int));
+int v_sectionf __P((SCR *, VICMD *));
+int v_sectionb __P((SCR *, VICMD *));
+int v_sentencef __P((SCR *, VICMD *));
+int v_sentenceb __P((SCR *, VICMD *));
+int v_status __P((SCR *, VICMD *));
+int v_tcmd __P((SCR *, VICMD *, ARG_CHAR_T, u_int));
+int v_txt __P((SCR *, VICMD *, MARK *,
+ const char *, size_t, ARG_CHAR_T, recno_t, u_long, u_int32_t));
+int v_txt_auto __P((SCR *, recno_t, TEXT *, size_t, TEXT *));
+int v_ulcase __P((SCR *, VICMD *));
+int v_mulcase __P((SCR *, VICMD *));
+int v_Undo __P((SCR *, VICMD *));
+int v_undo __P((SCR *, VICMD *));
+void v_eof __P((SCR *, MARK *));
+void v_eol __P((SCR *, MARK *));
+void v_nomove __P((SCR *));
+void v_sof __P((SCR *, MARK *));
+void v_sol __P((SCR *));
+int v_isempty __P((char *, size_t));
+void v_emsg __P((SCR *, char *, vim_t));
+int v_wordW __P((SCR *, VICMD *));
+int v_wordw __P((SCR *, VICMD *));
+int v_wordE __P((SCR *, VICMD *));
+int v_worde __P((SCR *, VICMD *));
+int v_wordB __P((SCR *, VICMD *));
+int v_wordb __P((SCR *, VICMD *));
+int v_xchar __P((SCR *, VICMD *));
+int v_Xchar __P((SCR *, VICMD *));
+int v_yank __P((SCR *, VICMD *));
+int v_z __P((SCR *, VICMD *));
+int vs_crel __P((SCR *, long));
+int v_zexit __P((SCR *, VICMD *));
+int vi __P((SCR **));
+int vs_line __P((SCR *, SMAP *, size_t *, size_t *));
+int vs_number __P((SCR *));
+void vs_busy __P((SCR *, const char *, busy_t));
+void vs_home __P((SCR *));
+void vs_update __P((SCR *, const char *, const char *));
+void vs_msg __P((SCR *, mtype_t, char *, size_t));
+int vs_ex_resolve __P((SCR *, int *));
+int vs_resolve __P((SCR *, SCR *, int));
+int vs_repaint __P((SCR *, EVENT *));
+int vs_refresh __P((SCR *, int));
+int vs_column __P((SCR *, size_t *));
+size_t vs_screens __P((SCR *, recno_t, size_t *));
+size_t vs_columns __P((SCR *, char *, recno_t, size_t *, size_t *));
+size_t vs_rcm __P((SCR *, recno_t, int));
+size_t vs_colpos __P((SCR *, recno_t, size_t));
+int vs_change __P((SCR *, recno_t, lnop_t));
+int vs_sm_fill __P((SCR *, recno_t, pos_t));
+int vs_sm_scroll __P((SCR *, MARK *, recno_t, scroll_t));
+int vs_sm_1up __P((SCR *));
+int vs_sm_1down __P((SCR *));
+int vs_sm_next __P((SCR *, SMAP *, SMAP *));
+int vs_sm_prev __P((SCR *, SMAP *, SMAP *));
+int vs_sm_cursor __P((SCR *, SMAP **));
+int vs_sm_position __P((SCR *, MARK *, u_long, pos_t));
+recno_t vs_sm_nlines __P((SCR *, SMAP *, recno_t, size_t));
+int vs_split __P((SCR *, SCR *, int));
+int vs_discard __P((SCR *, SCR **));
+int vs_fg __P((SCR *, SCR **, CHAR_T *, int));
+int vs_bg __P((SCR *));
+int vs_swap __P((SCR *, SCR **, char *));
+int vs_resize __P((SCR *, long, adj_t));
diff --git a/contrib/nvi/ip/IP_INSTRUCTIONS b/contrib/nvi/ip/IP_INSTRUCTIONS
new file mode 100644
index 000000000000..7745c8858d6f
--- /dev/null
+++ b/contrib/nvi/ip/IP_INSTRUCTIONS
@@ -0,0 +1,41 @@
+1: Add:
+ -DRUNNING_IP
+
+ to the Makefile CFLAGS line and rebuild cl_main.o if it's already
+ been compiled.
+
+2: Add:
+
+ IPOBJS= ip_funcs.o ip_main.o ip_read.o ip_screen.o ip_term.o
+
+ after the other object lists in the Makefile.
+
+3: Add
+ $(IPOBJS)
+
+ to the end of the NVIALL= line in the Makefile.
+
+4: Add:
+
+ # Vi IP sources.
+ ip_funcs.o: $(srcdir)/ip/ip_funcs.c
+ $(CC) $(CFLAGS) $?
+ ip_main.o: $(srcdir)/ip/ip_main.c
+ $(CC) $(CFLAGS) $?
+ ip_read.o: $(srcdir)/ip/ip_read.c
+ $(CC) $(CFLAGS) $?
+ ip_screen.o: $(srcdir)/ip/ip_screen.c
+ $(CC) $(CFLAGS) $?
+ ip_term.o: $(srcdir)/ip/ip_term.c
+ $(CC) $(CFLAGS) $?
+
+ at the end of the Makefile.
+
+5: Remove cl_main.o if it exists, and make nvi.
+
+6: Go to ip_cl and change the entries in the Makefile to reflect
+ where the nvi binary was just built.
+
+7: Build ip_cl.
+
+8: Enter ip_cl and you should be running vi over a pipe.
diff --git a/contrib/nvi/ip/ip.h b/contrib/nvi/ip/ip.h
new file mode 100644
index 000000000000..f7798c3121b4
--- /dev/null
+++ b/contrib/nvi/ip/ip.h
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)ip.h 8.3 (Berkeley) 10/13/96
+ */
+
+typedef struct _ip_private {
+ int i_fd; /* Input file descriptor. */
+ int o_fd; /* Output file descriptor. */
+
+ size_t row; /* Current row. */
+ size_t col; /* Current column. */
+
+ size_t iblen; /* Input buffer length. */
+ size_t iskip; /* Returned input buffer. */
+ char ibuf[256]; /* Input buffer. */
+
+#define IP_SCR_VI_INIT 0x0001 /* Vi screen initialized. */
+ u_int32_t flags;
+} IP_PRIVATE;
+
+#define IPP(sp) ((IP_PRIVATE *)((sp)->gp->ip_private))
+#define GIPP(gp) ((IP_PRIVATE *)((gp)->ip_private))
+
+/* The screen line relative to a specific window. */
+#define RLNO(sp, lno) (sp)->woff + (lno)
+
+/*
+ * The IP protocol consists of frames, each containing:
+ *
+ * <IPO_><object>
+ *
+ * XXX
+ * We should have a marking byte, 0xaa to delimit frames.
+ *
+ */
+#define IPO_CODE 1 /* An event specification. */
+#define IPO_INT 2 /* 4-byte, network order integer. */
+#define IPO_STR 3 /* IPO_INT: followed by N bytes. */
+
+#define IPO_CODE_LEN 1
+#define IPO_INT_LEN 4
+
+/* A structure that can hold the information for any frame. */
+typedef struct _ip_buf {
+ int code; /* Event code. */
+ const char *str; /* String. */
+ size_t len; /* String length. */
+ u_int32_t val1; /* First value. */
+ u_int32_t val2; /* Second value. */
+} IP_BUF;
+
+/*
+ * Screen/editor IP_CODE's.
+ *
+ * The program structure depends on the event loop being able to return
+ * IPO_EOF/IPOE_ERR multiple times -- eventually enough things will end
+ * due to the events that vi will reach the command level for the screen,
+ * at which point the exit flags will be set and vi will exit.
+ *
+ * IP events sent from the screen to vi.
+ */
+#define IPO_EOF 1 /* End of input (NOT ^D). */
+#define IPO_ERR 2 /* Input error. */
+#define IPO_INTERRUPT 3 /* Interrupt. */
+#define IPO_QUIT 4 /* Quit. */
+#define IPO_RESIZE 5 /* Screen resize: IPO_INT, IPO_INT. */
+#define IPO_SIGHUP 6 /* SIGHUP. */
+#define IPO_SIGTERM 7 /* SIGTERM. */
+#define IPO_STRING 8 /* Input string: IPO_STR. */
+#define IPO_WRITE 9 /* Write. */
+
+/*
+ * IP events sent from vi to the screen.
+ */
+#define IPO_ADDSTR 1 /* Add a string: IPO_STR. */
+#define IPO_ATTRIBUTE 2 /* Set screen attribute: IPO_INT, IPO_INT. */
+#define IPO_BELL 3 /* Beep/bell/flash the terminal. */
+#define IPO_BUSY 4 /* Display a busy message: IPO_STR. */
+#define IPO_CLRTOEOL 5 /* Clear to the end of the line. */
+#define IPO_DELETELN 6 /* Delete a line. */
+#define IPO_INSERTLN 7 /* Insert a line. */
+#define IPO_MOVE 8 /* Move the cursor: IPO_INT, IPO_INT. */
+#define IPO_REDRAW 9 /* Redraw the screen. */
+#define IPO_REFRESH 10 /* Refresh the screen. */
+#define IPO_RENAME 11 /* Rename the screen: IPO_STR. */
+#define IPO_REWRITE 12 /* Rewrite a line: IPO_INT. */
+
+#include "ip_extern.h"
diff --git a/contrib/nvi/ip/ip_funcs.c b/contrib/nvi/ip/ip_funcs.c
new file mode 100644
index 000000000000..c92f1eda2439
--- /dev/null
+++ b/contrib/nvi/ip/ip_funcs.c
@@ -0,0 +1,443 @@
+/*-
+ * Copyright (c) 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ip_funcs.c 8.4 (Berkeley) 10/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+#include "ip.h"
+
+static int ip_send __P((SCR *, char *, IP_BUF *));
+
+/*
+ * ip_addstr --
+ * Add len bytes from the string at the cursor, advancing the cursor.
+ *
+ * PUBLIC: int ip_addstr __P((SCR *, const char *, size_t));
+ */
+int
+ip_addstr(sp, str, len)
+ SCR *sp;
+ const char *str;
+ size_t len;
+{
+ IP_BUF ipb;
+ IP_PRIVATE *ipp;
+ int iv, rval;
+
+ ipp = IPP(sp);
+
+ /*
+ * If ex isn't in control, it's the last line of the screen and
+ * it's a split screen, use inverse video.
+ */
+ iv = 0;
+ if (!F_ISSET(sp, SC_SCR_EXWROTE) &&
+ ipp->row == LASTLINE(sp) && IS_SPLIT(sp)) {
+ iv = 1;
+ ip_attr(sp, SA_INVERSE, 1);
+ }
+ ipb.code = IPO_ADDSTR;
+ ipb.len = len;
+ ipb.str = str;
+ rval = ip_send(sp, "s", &ipb);
+
+ if (iv)
+ ip_attr(sp, SA_INVERSE, 0);
+ return (rval);
+}
+
+/*
+ * ip_attr --
+ * Toggle a screen attribute on/off.
+ *
+ * PUBLIC: int ip_attr __P((SCR *, scr_attr_t, int));
+ */
+int
+ip_attr(sp, attribute, on)
+ SCR *sp;
+ scr_attr_t attribute;
+ int on;
+{
+ IP_BUF ipb;
+
+ ipb.code = IPO_ATTRIBUTE;
+ ipb.val1 = attribute;
+ ipb.val2 = on;
+
+ return (ip_send(sp, "12", &ipb));
+}
+
+/*
+ * ip_baud --
+ * Return the baud rate.
+ *
+ * PUBLIC: int ip_baud __P((SCR *, u_long *));
+ */
+int
+ip_baud(sp, ratep)
+ SCR *sp;
+ u_long *ratep;
+{
+ *ratep = 9600; /* XXX: Translation: fast. */
+ return (0);
+}
+
+/*
+ * ip_bell --
+ * Ring the bell/flash the screen.
+ *
+ * PUBLIC: int ip_bell __P((SCR *));
+ */
+int
+ip_bell(sp)
+ SCR *sp;
+{
+ IP_BUF ipb;
+
+ ipb.code = IPO_BELL;
+
+ return (ip_send(sp, NULL, &ipb));
+}
+
+/*
+ * ip_busy --
+ * Display a busy message.
+ *
+ * PUBLIC: void ip_busy __P((SCR *, const char *, busy_t));
+ */
+void
+ip_busy(sp, str, bval)
+ SCR *sp;
+ const char *str;
+ busy_t bval;
+{
+ IP_BUF ipb;
+
+ ipb.code = IPO_BUSY;
+ if (str == NULL) {
+ ipb.len = 0;
+ ipb.str = "";
+ } else {
+ ipb.len = strlen(str);
+ ipb.str = str;
+ }
+ ipb.val1 = bval;
+
+ (void)ip_send(sp, "s1", &ipb);
+}
+
+/*
+ * ip_clrtoeol --
+ * Clear from the current cursor to the end of the line.
+ *
+ * PUBLIC: int ip_clrtoeol __P((SCR *));
+ */
+int
+ip_clrtoeol(sp)
+ SCR *sp;
+{
+ IP_BUF ipb;
+
+ ipb.code = IPO_CLRTOEOL;
+
+ return (ip_send(sp, NULL, &ipb));
+}
+
+/*
+ * ip_cursor --
+ * Return the current cursor position.
+ *
+ * PUBLIC: int ip_cursor __P((SCR *, size_t *, size_t *));
+ */
+int
+ip_cursor(sp, yp, xp)
+ SCR *sp;
+ size_t *yp, *xp;
+{
+ IP_PRIVATE *ipp;
+
+ ipp = IPP(sp);
+ *yp = ipp->row;
+ *xp = ipp->col;
+ return (0);
+}
+
+/*
+ * ip_deleteln --
+ * Delete the current line, scrolling all lines below it.
+ *
+ * PUBLIC: int ip_deleteln __P((SCR *));
+ */
+int
+ip_deleteln(sp)
+ SCR *sp;
+{
+ IP_BUF ipb;
+
+ /*
+ * This clause is required because the curses screen uses reverse
+ * video to delimit split screens. If the screen does not do this,
+ * this code won't be necessary.
+ *
+ * If the bottom line was in reverse video, rewrite it in normal
+ * video before it's scrolled.
+ */
+ if (!F_ISSET(sp, SC_SCR_EXWROTE) && IS_SPLIT(sp)) {
+ ipb.code = IPO_REWRITE;
+ ipb.val1 = RLNO(sp, LASTLINE(sp));
+ if (ip_send(sp, "1", &ipb))
+ return (1);
+ }
+
+ /*
+ * The bottom line is expected to be blank after this operation,
+ * and other screens must support that semantic.
+ */
+ ipb.code = IPO_DELETELN;
+ return (ip_send(sp, NULL, &ipb));
+}
+
+/*
+ * ip_ex_adjust --
+ * Adjust the screen for ex.
+ *
+ * PUBLIC: int ip_ex_adjust __P((SCR *, exadj_t));
+ */
+int
+ip_ex_adjust(sp, action)
+ SCR *sp;
+ exadj_t action;
+{
+ abort();
+ /* NOTREACHED */
+}
+
+/*
+ * ip_insertln --
+ * Push down the current line, discarding the bottom line.
+ *
+ * PUBLIC: int ip_insertln __P((SCR *));
+ */
+int
+ip_insertln(sp)
+ SCR *sp;
+{
+ IP_BUF ipb;
+
+ ipb.code = IPO_INSERTLN;
+
+ return (ip_send(sp, NULL, &ipb));
+}
+
+/*
+ * ip_keyval --
+ * Return the value for a special key.
+ *
+ * PUBLIC: int ip_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
+ */
+int
+ip_keyval(sp, val, chp, dnep)
+ SCR *sp;
+ scr_keyval_t val;
+ CHAR_T *chp;
+ int *dnep;
+{
+ /*
+ * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990,
+ * VWERASE is a 4BSD extension.
+ */
+ switch (val) {
+ case KEY_VEOF:
+ *dnep = '\004'; /* ^D */
+ break;
+ case KEY_VERASE:
+ *dnep = '\b'; /* ^H */
+ break;
+ case KEY_VKILL:
+ *dnep = '\025'; /* ^U */
+ break;
+#ifdef VWERASE
+ case KEY_VWERASE:
+ *dnep = '\027'; /* ^W */
+ break;
+#endif
+ default:
+ *dnep = 1;
+ break;
+ }
+ return (0);
+}
+
+/*
+ * ip_move --
+ * Move the cursor.
+ *
+ * PUBLIC: int ip_move __P((SCR *, size_t, size_t));
+ */
+int
+ip_move(sp, lno, cno)
+ SCR *sp;
+ size_t lno, cno;
+{
+ IP_PRIVATE *ipp;
+ IP_BUF ipb;
+
+ ipp = IPP(sp);
+ ipp->row = lno;
+ ipp->col = cno;
+
+ ipb.code = IPO_MOVE;
+ ipb.val1 = RLNO(sp, lno);
+ ipb.val2 = cno;
+ return (ip_send(sp, "12", &ipb));
+}
+
+/*
+ * ip_refresh --
+ * Refresh the screen.
+ *
+ * PUBLIC: int ip_refresh __P((SCR *, int));
+ */
+int
+ip_refresh(sp, repaint)
+ SCR *sp;
+ int repaint;
+{
+ IP_BUF ipb;
+
+ ipb.code = repaint ? IPO_REDRAW : IPO_REFRESH;
+
+ return (ip_send(sp, NULL, &ipb));
+}
+
+/*
+ * ip_rename --
+ * Rename the file.
+ *
+ * PUBLIC: int ip_rename __P((SCR *));
+ */
+int
+ip_rename(sp)
+ SCR *sp;
+{
+ IP_BUF ipb;
+
+ ipb.code = IPO_RENAME;
+ ipb.len = strlen(sp->frp->name);
+ ipb.str = sp->frp->name;
+
+ return (ip_send(sp, "s", &ipb));
+}
+
+/*
+ * ip_suspend --
+ * Suspend a screen.
+ *
+ * PUBLIC: int ip_suspend __P((SCR *, int *));
+ */
+int
+ip_suspend(sp, allowedp)
+ SCR *sp;
+ int *allowedp;
+{
+ *allowedp = 0;
+ return (0);
+}
+
+/*
+ * ip_usage --
+ * Print out the ip usage messages.
+ *
+ * PUBLIC: void ip_usage __P((void));
+ */
+void
+ip_usage()
+{
+#define USAGE "\
+usage: vi [-eFlRrSv] [-c command] [-I ifd.ofd] [-t tag] [-w size] [file ...]\n"
+ (void)fprintf(stderr, "%s", USAGE);
+#undef USAGE
+}
+
+/*
+ * ip_send --
+ * Construct and send an IP buffer.
+ */
+static int
+ip_send(sp, fmt, ipbp)
+ SCR *sp;
+ char *fmt;
+ IP_BUF *ipbp;
+{
+ IP_PRIVATE *ipp;
+ size_t blen, off;
+ u_int32_t ilen;
+ int nlen, n, nw, rval;
+ char *bp, *p;
+
+ ipp = IPP(sp);
+
+ GET_SPACE_RET(sp, bp, blen, 128);
+
+ p = bp;
+ nlen = 0;
+ *p++ = ipbp->code;
+ nlen += IPO_CODE_LEN;
+
+ if (fmt != NULL)
+ for (; *fmt != '\0'; ++fmt)
+ switch (*fmt) {
+ case '1': /* Value 1. */
+ ilen = htonl(ipbp->val1);
+ goto value;
+ case '2': /* Value 2. */
+ ilen = htonl(ipbp->val2);
+value: nlen += IPO_INT_LEN;
+ off = p - bp;
+ ADD_SPACE_RET(sp, bp, blen, nlen);
+ p = bp + off;
+ memmove(p, &ilen, IPO_INT_LEN);
+ p += IPO_INT_LEN;
+ break;
+ case 's': /* String. */
+ ilen = ipbp->len; /* XXX: conversion. */
+ ilen = htonl(ilen);
+ nlen += IPO_INT_LEN + ipbp->len;
+ off = p - bp;
+ ADD_SPACE_RET(sp, bp, blen, nlen);
+ p = bp + off;
+ memmove(p, &ilen, IPO_INT_LEN);
+ p += IPO_INT_LEN;
+ memmove(p, ipbp->str, ipbp->len);
+ p += ipbp->len;
+ break;
+ }
+
+
+ rval = 0;
+ for (n = p - bp, p = bp; n > 0; n -= nw, p += nw)
+ if ((nw = write(ipp->o_fd, p, n)) < 0) {
+ rval = 1;
+ break;
+ }
+
+ FREE_SPACE(sp, bp, blen);
+
+ return (rval);
+}
diff --git a/contrib/nvi/ip/ip_main.c b/contrib/nvi/ip/ip_main.c
new file mode 100644
index 000000000000..7ca9f55024fd
--- /dev/null
+++ b/contrib/nvi/ip/ip_main.c
@@ -0,0 +1,165 @@
+/*-
+ * Copyright (c) 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ip_main.c 8.3 (Berkeley) 10/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "ip.h"
+
+static void ip_func_std __P((GS *));
+static IP_PRIVATE *ip_init __P((GS *, char *));
+static void perr __P((char *, char *));
+
+/*
+ * main --
+ * This is the main loop for the vi-as-library editor.
+ */
+int
+ip_main(argc, argv, gp, ip_arg)
+ int argc;
+ char *argv[], *ip_arg;
+ GS *gp;
+{
+ EVENT ev;
+ IP_PRIVATE *ipp;
+ IP_BUF ipb;
+ int rval;
+
+ /* Create and partially initialize the IP structure. */
+ if ((ipp = ip_init(gp, ip_arg)) == NULL)
+ return (1);
+
+ /* Add the terminal type to the global structure. */
+ if ((OG_D_STR(gp, GO_TERM) =
+ OG_STR(gp, GO_TERM) = strdup("ip_curses")) == NULL)
+ perr(gp->progname, NULL);
+
+ /*
+ * Figure out how big the screen is -- read events until we get
+ * the rows and columns.
+ */
+ do {
+ if (ip_event(NULL, &ev, 0, 0))
+ return (1);
+ } while (ev.e_event != E_EOF && ev.e_event != E_ERR &&
+ ev.e_event != E_QUIT && ev.e_event != E_WRESIZE &&
+ ev.e_event != E_SIGHUP && ev.e_event != E_SIGTERM);
+ if (ev.e_event != E_WRESIZE)
+ return (1);
+
+ /* Run ex/vi. */
+ rval = editor(gp, argc, argv);
+
+ /* Clean up the screen. */
+ (void)ip_quit(gp);
+
+ /* Free the global and IP private areas. */
+#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
+ free(ipp);
+ free(gp);
+#endif
+
+ return (rval);
+}
+
+/*
+ * ip_init --
+ * Create and partially initialize the GS structure.
+ */
+static IP_PRIVATE *
+ip_init(gp, ip_arg)
+ GS *gp;
+ char *ip_arg;
+{
+ IP_PRIVATE *ipp;
+ char *ep;
+
+ /* Allocate the IP private structure. */
+ CALLOC_NOMSG(NULL, ipp, IP_PRIVATE *, 1, sizeof(IP_PRIVATE));
+ if (ipp == NULL)
+ perr(gp->progname, NULL);
+ gp->ip_private = ipp;
+
+ /*
+ * Crack ip_arg -- it's of the form #.#, where the first number is the
+ * file descriptor from the screen, the second is the file descriptor
+ * to the screen.
+ */
+ if (!isdigit(ip_arg[0]))
+ goto usage;
+ ipp->i_fd = strtol(ip_arg, &ep, 10);
+ if (ep[0] != '.' || !isdigit(ep[1]))
+ goto usage;
+ ipp->o_fd = strtol(++ep, &ep, 10);
+ if (ep[0] != '\0') {
+usage: ip_usage();
+ return (NULL);
+ }
+
+ /* Initialize the list of ip functions. */
+ ip_func_std(gp);
+
+ return (ipp);
+}
+
+/*
+ * ip_func_std --
+ * Initialize the standard ip functions.
+ */
+static void
+ip_func_std(gp)
+ GS *gp;
+{
+ gp->scr_addstr = ip_addstr;
+ gp->scr_attr = ip_attr;
+ gp->scr_baud = ip_baud;
+ gp->scr_bell = ip_bell;
+ gp->scr_busy = ip_busy;
+ gp->scr_clrtoeol = ip_clrtoeol;
+ gp->scr_cursor = ip_cursor;
+ gp->scr_deleteln = ip_deleteln;
+ gp->scr_event = ip_event;
+ gp->scr_ex_adjust = ip_ex_adjust;
+ gp->scr_fmap = ip_fmap;
+ gp->scr_insertln = ip_insertln;
+ gp->scr_keyval = ip_keyval;
+ gp->scr_move = ip_move;
+ gp->scr_msg = NULL;
+ gp->scr_optchange = ip_optchange;
+ gp->scr_refresh = ip_refresh;
+ gp->scr_rename = ip_rename;
+ gp->scr_screen = ip_screen;
+ gp->scr_suspend = ip_suspend;
+ gp->scr_usage = ip_usage;
+}
+
+/*
+ * perr --
+ * Print system error.
+ */
+static void
+perr(name, msg)
+ char *name, *msg;
+{
+ (void)fprintf(stderr, "%s:", name);
+ if (msg != NULL)
+ (void)fprintf(stderr, "%s:", msg);
+ (void)fprintf(stderr, "%s\n", strerror(errno));
+ exit(1);
+}
diff --git a/contrib/nvi/ip/ip_read.c b/contrib/nvi/ip/ip_read.c
new file mode 100644
index 000000000000..9fd977774173
--- /dev/null
+++ b/contrib/nvi/ip/ip_read.c
@@ -0,0 +1,307 @@
+/*-
+ * Copyright (c) 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ip_read.c 8.3 (Berkeley) 9/24/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+#include <termios.h>
+#include <time.h>
+
+#include "../common/common.h"
+#include "../ex/script.h"
+#include "ip.h"
+
+extern GS *__global_list;
+
+typedef enum { INP_OK=0, INP_EOF, INP_ERR, INP_TIMEOUT } input_t;
+
+static input_t ip_read __P((SCR *, IP_PRIVATE *, struct timeval *));
+static int ip_resize __P((SCR *, size_t, size_t));
+static int ip_trans __P((SCR *, IP_PRIVATE *, EVENT *));
+
+/*
+ * ip_event --
+ * Return a single event.
+ *
+ * PUBLIC: int ip_event __P((SCR *, EVENT *, u_int32_t, int));
+ */
+int
+ip_event(sp, evp, flags, ms)
+ SCR *sp;
+ EVENT *evp;
+ u_int32_t flags;
+ int ms;
+{
+ IP_PRIVATE *ipp;
+ struct timeval t, *tp;
+
+ if (LF_ISSET(EC_INTERRUPT)) { /* XXX */
+ evp->e_event = E_TIMEOUT;
+ return (0);
+ }
+
+ ipp = sp == NULL ? GIPP(__global_list) : IPP(sp);
+
+ /* Discard the last command. */
+ if (ipp->iskip != 0) {
+ ipp->iblen -= ipp->iskip;
+ memmove(ipp->ibuf, ipp->ibuf + ipp->iskip, ipp->iblen);
+ ipp->iskip = 0;
+ }
+
+ /* Set timer. */
+ if (ms == 0)
+ tp = NULL;
+ else {
+ t.tv_sec = ms / 1000;
+ t.tv_usec = (ms % 1000) * 1000;
+ tp = &t;
+ }
+
+ /* Read input events. */
+ for (;;) {
+ switch (ip_read(sp, ipp, tp)) {
+ case INP_OK:
+ if (!ip_trans(sp, ipp, evp))
+ continue;
+ break;
+ case INP_EOF:
+ evp->e_event = E_EOF;
+ break;
+ case INP_ERR:
+ evp->e_event = E_ERR;
+ break;
+ case INP_TIMEOUT:
+ evp->e_event = E_TIMEOUT;
+ break;
+ default:
+ abort();
+ }
+ break;
+ }
+ return (0);
+}
+
+/*
+ * ip_read --
+ * Read characters from the input.
+ */
+static input_t
+ip_read(sp, ipp, tp)
+ SCR *sp;
+ IP_PRIVATE *ipp;
+ struct timeval *tp;
+{
+ struct timeval poll;
+ GS *gp;
+ SCR *tsp;
+ fd_set rdfd;
+ input_t rval;
+ size_t blen;
+ int maxfd, nr;
+ char *bp;
+
+ gp = sp == NULL ? __global_list : sp->gp;
+ bp = ipp->ibuf + ipp->iblen;
+ blen = sizeof(ipp->ibuf) - ipp->iblen;
+
+ /*
+ * 1: A read with an associated timeout, e.g., trying to complete
+ * a map sequence. If input exists, we fall into #2.
+ */
+ FD_ZERO(&rdfd);
+ poll.tv_sec = 0;
+ poll.tv_usec = 0;
+ if (tp != NULL) {
+ FD_SET(ipp->i_fd, &rdfd);
+ switch (select(ipp->i_fd + 1,
+ &rdfd, NULL, NULL, tp == NULL ? &poll : tp)) {
+ case 0:
+ return (INP_TIMEOUT);
+ case -1:
+ goto err;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * 2: Wait for input.
+ *
+ * Select on the command input and scripting window file descriptors.
+ * It's ugly that we wait on scripting file descriptors here, but it's
+ * the only way to keep from locking out scripting windows.
+ */
+ if (sp != NULL && F_ISSET(gp, G_SCRWIN)) {
+loop: FD_ZERO(&rdfd);
+ FD_SET(ipp->i_fd, &rdfd);
+ maxfd = ipp->i_fd;
+ for (tsp = gp->dq.cqh_first;
+ tsp != (void *)&gp->dq; tsp = tsp->q.cqe_next)
+ if (F_ISSET(sp, SC_SCRIPT)) {
+ FD_SET(sp->script->sh_master, &rdfd);
+ if (sp->script->sh_master > maxfd)
+ maxfd = sp->script->sh_master;
+ }
+ switch (select(maxfd + 1, &rdfd, NULL, NULL, NULL)) {
+ case 0:
+ abort();
+ case -1:
+ goto err;
+ default:
+ break;
+ }
+ if (!FD_ISSET(ipp->i_fd, &rdfd)) {
+ if (sscr_input(sp))
+ return (INP_ERR);
+ goto loop;
+ }
+ }
+
+ /*
+ * 3: Read the input.
+ */
+ switch (nr = read(ipp->i_fd, bp, blen)) {
+ case 0: /* EOF. */
+ rval = INP_EOF;
+ break;
+ case -1: /* Error or interrupt. */
+err: rval = INP_ERR;
+ msgq(sp, M_SYSERR, "input");
+ break;
+ default: /* Input characters. */
+ ipp->iblen += nr;
+ rval = INP_OK;
+ break;
+ }
+ return (rval);
+}
+
+/*
+ * ip_trans --
+ * Translate messages into events.
+ */
+static int
+ip_trans(sp, ipp, evp)
+ SCR *sp;
+ IP_PRIVATE *ipp;
+ EVENT *evp;
+{
+ u_int32_t val1, val2;
+
+ switch (ipp->ibuf[0]) {
+ case IPO_EOF:
+ evp->e_event = E_EOF;
+ ipp->iskip = IPO_CODE_LEN;
+ return (1);
+ case IPO_ERR:
+ evp->e_event = E_ERR;
+ ipp->iskip = IPO_CODE_LEN;
+ return (1);
+ case IPO_INTERRUPT:
+ evp->e_event = E_INTERRUPT;
+ ipp->iskip = IPO_CODE_LEN;
+ return (1);
+ case IPO_QUIT:
+ evp->e_event = E_QUIT;
+ ipp->iskip = IPO_CODE_LEN;
+ return (1);
+ case IPO_RESIZE:
+ if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN * 2)
+ return (0);
+ evp->e_event = E_WRESIZE;
+ memcpy(&val1, ipp->ibuf + IPO_CODE_LEN, IPO_INT_LEN);
+ val1 = ntohl(val1);
+ memcpy(&val2,
+ ipp->ibuf + IPO_CODE_LEN + IPO_INT_LEN, IPO_INT_LEN);
+ val2 = ntohl(val2);
+ ip_resize(sp, val1, val2);
+ ipp->iskip = IPO_CODE_LEN + IPO_INT_LEN * 2;
+ return (1);
+ case IPO_SIGHUP:
+ evp->e_event = E_SIGHUP;
+ ipp->iskip = IPO_CODE_LEN;
+ return (1);
+ case IPO_SIGTERM:
+ evp->e_event = E_SIGTERM;
+ ipp->iskip = IPO_CODE_LEN;
+ return (1);
+ case IPO_STRING:
+ evp->e_event = E_STRING;
+string: if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN)
+ return (0);
+ memcpy(&val1, ipp->ibuf + IPO_CODE_LEN, IPO_INT_LEN);
+ val1 = ntohl(val1);
+ if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN + val1)
+ return (0);
+ ipp->iskip = IPO_CODE_LEN + IPO_INT_LEN + val1;
+ evp->e_csp = ipp->ibuf + IPO_CODE_LEN + IPO_INT_LEN;
+ evp->e_len = val1;
+ return (1);
+ case IPO_WRITE:
+ evp->e_event = E_WRITE;
+ ipp->iskip = IPO_CODE_LEN;
+ return (1);
+ default:
+ /*
+ * XXX: Protocol is out of sync?
+ */
+ abort();
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * ip_resize --
+ * Reset the options for a resize event.
+ */
+static int
+ip_resize(sp, lines, columns)
+ SCR *sp;
+ size_t lines, columns;
+{
+ GS *gp;
+ ARGS *argv[2], a, b;
+ char b1[1024];
+
+ /*
+ * XXX
+ * The IP screen has to know the lines and columns before anything
+ * else happens. So, we may not have a valid SCR pointer, and we
+ * have to deal with that.
+ */
+ if (sp == NULL) {
+ gp = __global_list;
+ OG_VAL(gp, GO_LINES) = OG_D_VAL(gp, GO_LINES) = lines;
+ OG_VAL(gp, GO_COLUMNS) = OG_D_VAL(gp, GO_COLUMNS) = columns;
+ return (0);
+ }
+
+ a.bp = b1;
+ b.bp = NULL;
+ a.len = b.len = 0;
+ argv[0] = &a;
+ argv[1] = &b;
+
+ (void)snprintf(b1, sizeof(b1), "lines=%lu", (u_long)lines);
+ a.len = strlen(b1);
+ if (opts_set(sp, argv, NULL))
+ return (1);
+ (void)snprintf(b1, sizeof(b1), "columns=%lu", (u_long)columns);
+ a.len = strlen(b1);
+ if (opts_set(sp, argv, NULL))
+ return (1);
+ return (0);
+}
diff --git a/contrib/nvi/ip/ip_screen.c b/contrib/nvi/ip/ip_screen.c
new file mode 100644
index 000000000000..71578e0d1b39
--- /dev/null
+++ b/contrib/nvi/ip/ip_screen.c
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ip_screen.c 8.2 (Berkeley) 10/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "ip.h"
+
+/*
+ * ip_screen --
+ * Initialize/shutdown the IP screen.
+ *
+ * PUBLIC: int ip_screen __P((SCR *, u_int32_t));
+ */
+int
+ip_screen(sp, flags)
+ SCR *sp;
+ u_int32_t flags;
+{
+ GS *gp;
+ IP_PRIVATE *ipp;
+
+ gp = sp->gp;
+ ipp = IPP(sp);
+
+ /* See if the current information is incorrect. */
+ if (F_ISSET(gp, G_SRESTART)) {
+ if (ip_quit(gp))
+ return (1);
+ F_CLR(gp, G_SRESTART);
+ }
+
+ /* See if we're already in the right mode. */
+ if (LF_ISSET(SC_VI) && F_ISSET(ipp, IP_SCR_VI_INIT))
+ return (0);
+
+ /* Ex isn't possible. */
+ if (LF_ISSET(SC_EX))
+ return (1);
+
+ /* Initialize terminal based information. */
+ if (ip_term_init(sp))
+ return (1);
+
+ /* Put up the first file name. */
+ if (ip_rename(sp))
+ return (1);
+
+ F_SET(ipp, IP_SCR_VI_INIT);
+ return (0);
+}
+
+/*
+ * ip_quit --
+ * Shutdown the screens.
+ *
+ * PUBLIC: int ip_quit __P((GS *));
+ */
+int
+ip_quit(gp)
+ GS *gp;
+{
+ IP_PRIVATE *ipp;
+ int rval;
+
+ /* Clean up the terminal mappings. */
+ rval = ip_term_end(gp);
+
+ ipp = GIPP(gp);
+ F_CLR(ipp, IP_SCR_VI_INIT);
+
+ return (rval);
+}
diff --git a/contrib/nvi/ip/ip_term.c b/contrib/nvi/ip/ip_term.c
new file mode 100644
index 000000000000..28e686dddd28
--- /dev/null
+++ b/contrib/nvi/ip/ip_term.c
@@ -0,0 +1,108 @@
+/*-
+ * Copyright (c) 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ip_term.c 8.2 (Berkeley) 10/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "ip.h"
+
+/*
+ * ip_term_init --
+ * Initialize the terminal special keys.
+ *
+ * PUBLIC: int ip_term_init __P((SCR *));
+ */
+int
+ip_term_init(sp)
+ SCR *sp;
+{
+ SEQ *qp;
+
+ /*
+ * Rework any function key mappings that were set before the
+ * screen was initialized.
+ */
+ for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next)
+ if (F_ISSET(qp, SEQ_FUNCMAP))
+ (void)ip_fmap(sp, qp->stype,
+ qp->input, qp->ilen, qp->output, qp->olen);
+ return (0);
+}
+
+/*
+ * ip_term_end --
+ * End the special keys defined by the termcap/terminfo entry.
+ *
+ * PUBLIC: int ip_term_end __P((GS *));
+ */
+int
+ip_term_end(gp)
+ GS *gp;
+{
+ SEQ *qp, *nqp;
+
+ /* Delete screen specific mappings. */
+ for (qp = gp->seqq.lh_first; qp != NULL; qp = nqp) {
+ nqp = qp->q.le_next;
+ if (F_ISSET(qp, SEQ_SCREEN))
+ (void)seq_mdel(qp);
+ }
+ return (0);
+}
+
+/*
+ * ip_fmap --
+ * Map a function key.
+ *
+ * PUBLIC: int ip_fmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
+ */
+int
+ip_fmap(sp, stype, from, flen, to, tlen)
+ SCR *sp;
+ seq_t stype;
+ CHAR_T *from, *to;
+ size_t flen, tlen;
+{
+ /* Bind a function key to a string sequence. */
+ return (1);
+}
+
+/*
+ * ip_optchange --
+ * IP screen specific "option changed" routine.
+ *
+ * PUBLIC: int ip_optchange __P((SCR *, int, char *, u_long *));
+ */
+int
+ip_optchange(sp, opt, str, valp)
+ SCR *sp;
+ int opt;
+ char *str;
+ u_long *valp;
+{
+ switch (opt) {
+ case O_COLUMNS:
+ case O_LINES:
+ F_SET(sp->gp, G_SRESTART);
+ F_CLR(sp, SC_SCR_EX | SC_SCR_VI);
+ break;
+ case O_TERM:
+ msgq(sp, M_ERR, "The screen type may not be changed");
+ return (1);
+ }
+ return (0);
+}
diff --git a/contrib/nvi/ip_cl/Makefile b/contrib/nvi/ip_cl/Makefile
new file mode 100644
index 000000000000..9503c4dac501
--- /dev/null
+++ b/contrib/nvi/ip_cl/Makefile
@@ -0,0 +1,20 @@
+# TR turns on tracing, to the specified file.
+TR= -DTR=\"/dev/ttypa\"
+#TR= -DTR=\"__log\"
+
+# VI is the binary that ip_cl runs.
+VI= -DVI=\"../build.local/nvi\"
+
+DEBUG= -DDEBUG -g
+INC= -I. -I../build.local -I../include
+CFLAGS= $(DEBUG) $(TR) $(VI) $(INC)
+
+OBJS= ip_cl.o
+
+LIBS= -lcurses -ltermcap
+
+ip_cl: ${OBJS}
+ ${CC} ${OBJS} -o $@ ${LIBS}
+
+clean:
+ rm -f ip_cl ${OBJS}
diff --git a/contrib/nvi/ip_cl/ip_cl.c b/contrib/nvi/ip_cl/ip_cl.c
new file mode 100644
index 000000000000..5137b3f56abc
--- /dev/null
+++ b/contrib/nvi/ip_cl/ip_cl.c
@@ -0,0 +1,742 @@
+/*-
+ * Copyright (c) 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ip_cl.c 8.4 (Berkeley) 10/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/queue.h>
+#include <sys/select.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <curses.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../ip/ip.h"
+#include "pathnames.h"
+
+size_t cols, rows; /* Screen columns, rows. */
+int die; /* Child died. */
+int i_fd, o_fd; /* Input/output fd's. */
+int resize; /* Window resized. */
+
+void arg_format __P((int *, char **[], int, int));
+void attach __P((void));
+void ip_cur_end __P((void));
+void ip_cur_init __P((void));
+void ip_read __P((void));
+void ip_resize __P((void));
+int ip_send __P((char *, IP_BUF *));
+void ip_siginit __P((void));
+int ip_trans __P((char *, size_t, size_t *));
+void nomem __P((void));
+void onchld __P((int));
+void onintr __P((int));
+void onwinch __P((int));
+void trace __P((const char *, ...));
+void usage __P((void));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ fd_set fdset;
+ pid_t pid;
+ size_t blen, len, skip;
+ int ch, nr, rpipe[2], wpipe[2];
+ char *bp;
+
+ while ((ch = getopt(argc, argv, "D")) != EOF)
+ switch (ch) {
+ case 'D':
+ attach();
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ /*
+ * Open the communications pipes. The pipes are named from our
+ * viewpoint, so we read from rpipe[0] and write to wpipe[1].
+ * Vi reads from wpipe[0], and writes to rpipe[1].
+ */
+ if (pipe(rpipe) == -1 || pipe(wpipe) == -1) {
+ perror("ip_cl: pipe");
+ exit (1);
+ }
+ i_fd = rpipe[0];
+ o_fd = wpipe[1];
+
+ /*
+ * Format our arguments, adding a -I to the list. The first file
+ * descriptor to the -I argument is vi's input, and the second is
+ * vi's output.
+ */
+ arg_format(&argc, &argv, wpipe[0], rpipe[1]);
+
+ /* Run vi. */
+ switch (pid = fork()) {
+ case -1: /* Error. */
+ perror("ip_cl: fork");
+ exit (1);
+ case 0: /* Vi. */
+ execv(VI, argv);
+ perror("ip_cl: execv ../build/nvi");
+ exit (1);
+ default: /* Ip_cl. */
+ break;
+ }
+
+ /*
+ * Allocate initial input buffer.
+ * XXX
+ * We don't dynamically resize, so there better not be any individual
+ * messages larger than this buffer.
+ */
+ blen = 4 * 1024;
+ if ((bp = malloc(blen)) == NULL)
+ nomem();
+
+ /* Clear the file descriptor mask. */
+ FD_ZERO(&fdset);
+
+ /* Initialize signals. */
+ ip_siginit();
+
+ /* Initialize the curses screen. */
+ ip_cur_init();
+
+ /* The first thing vi wants is the screen size. */
+ ip_resize();
+
+ /* Main loop. */
+ for (len = 0;;) {
+ if (die)
+ break;
+ /*
+ * XXX
+ * Race #1: if there's an event coming from vi that requires
+ * that we know what size the screen is, and we take a resize
+ * signal, we'll differ from vi in the size of the screen for
+ * that event. Fixing this will requires information attached
+ * to message as to what set of state was in place when the
+ * message was sent. Not hard, but not worth doing now.
+ *
+ * Race #2: we cycle, handling resize events until there aren't
+ * any waiting. We then do a select. If the resize signal
+ * arrives after we exit the loop but before we enter select,
+ * we'll wait on the user to enter a keystroke, handle it and
+ * then handle the resize.
+ */
+ while (resize) {
+ resize = 0;
+ ip_resize();
+ ip_cur_end();
+ ip_cur_init();
+ }
+
+ /* Wait until vi or the screen wants to talk. */
+ FD_SET(i_fd, &fdset);
+ FD_SET(STDIN_FILENO, &fdset);
+ errno = 0;
+ switch (select(i_fd + 1, &fdset, NULL, NULL, NULL)) {
+ case 0:
+ abort(); /* Timeout. */
+ /* NOTREACHED */
+ case -1:
+ if (errno == EINTR)
+ continue;
+ perror("ip_cl: select");
+ exit (1);
+ default:
+ break;
+ }
+
+ /* Read waiting tty characters and send them to vi. */
+ if (FD_ISSET(STDIN_FILENO, &fdset)) {
+ ip_read();
+ continue;
+ }
+
+ /* Read waiting vi messages and translate to curses calls. */
+ switch (nr = read(i_fd, bp + len, blen - len)) {
+ case 0:
+ continue;
+ case -1:
+ perror("ip_cl: read");
+ exit (1);
+ default:
+ break;
+ }
+
+ /* Parse to data end or partial message. */
+ for (len += nr, skip = 0; len > skip &&
+ ip_trans(bp + skip, len - skip, &skip) == 1;);
+
+ /* Copy any partial messages down in the buffer. */
+ len -= skip;
+ if (len > 0)
+ memmove(bp, bp + skip, len);
+ }
+
+ /* End the screen. */
+ ip_cur_end();
+
+ exit (0);
+}
+
+/*
+ * ip_read --
+ * Read characters from the screen and send them to vi.
+ */
+void
+ip_read()
+{
+ IP_BUF ipb;
+ int nr;
+ char bp[1024];
+
+ /* Read waiting tty characters. */
+ switch (nr = read(STDIN_FILENO, bp, sizeof(bp))) {
+ case 0:
+ return;
+ case -1:
+ perror("ip_cl: read");
+ exit (1);
+ default:
+ break;
+ }
+
+ ipb.code = IPO_STRING;
+ ipb.len = nr;
+ ipb.str = bp;
+ ip_send("s", &ipb);
+}
+
+/*
+ * ip_trans --
+ * Translate vi messages into curses calls.
+ */
+int
+ip_trans(bp, len, skipp)
+ char *bp;
+ size_t len, *skipp;
+{
+ IP_BUF ipb;
+ size_t cno, lno, nlen, oldy, oldx, spcnt;
+ int ch;
+ char *fmt, *p;
+
+ switch (bp[0]) {
+ case IPO_ADDSTR:
+ case IPO_RENAME:
+ fmt = "s";
+ break;
+ case IPO_BUSY:
+ fmt = "s1";
+ break;
+ case IPO_ATTRIBUTE:
+ case IPO_MOVE:
+ fmt = "12";
+ break;
+ case IPO_REWRITE:
+ fmt = "1";
+ break;
+ default:
+ fmt = "";
+ }
+
+ nlen = IPO_CODE_LEN;
+ p = bp + IPO_CODE_LEN;
+ for (; *fmt != '\0'; ++fmt)
+ switch (*fmt) {
+ case '1':
+ nlen += IPO_INT_LEN;
+ if (len < nlen)
+ return (0);
+ memcpy(&ipb.val1, p, IPO_INT_LEN);
+ ipb.val1 = ntohl(ipb.val1);
+ p += IPO_INT_LEN;
+ break;
+ case '2':
+ nlen += IPO_INT_LEN;
+ if (len < nlen)
+ return (0);
+ memcpy(&ipb.val2, p, IPO_INT_LEN);
+ ipb.val2 = ntohl(ipb.val2);
+ p += IPO_INT_LEN;
+ break;
+ case 's':
+ nlen += IPO_INT_LEN;
+ if (len < nlen)
+ return (0);
+ memcpy(&ipb.len, p, IPO_INT_LEN);
+ ipb.len = ntohl(ipb.len);
+ p += IPO_INT_LEN;
+ nlen += ipb.len;
+ if (len < nlen)
+ return (0);
+ ipb.str = p;
+ p += ipb.len;
+ break;
+ }
+ *skipp += nlen;
+
+ switch (bp[0]) {
+ case IPO_ADDSTR:
+#ifdef TR
+ trace("addnstr {%.*s}\n", (int)ipb.len, ipb.str);
+#endif
+ (void)addnstr(ipb.str, ipb.len);
+ break;
+ case IPO_ATTRIBUTE:
+ switch (ipb.val1) {
+ case SA_ALTERNATE:
+#ifdef TR
+ trace("attr: alternate\n");
+#endif
+ /*
+ * XXX
+ * Nothing.
+ */
+ break;
+ case SA_INVERSE:
+#ifdef TR
+ trace("attr: inverse\n");
+#endif
+ if (ipb.val2)
+ (void)standout();
+ else
+ (void)standend();
+ break;
+ default:
+ abort();
+ /* NOTREACHED */
+ }
+ break;
+ case IPO_BELL:
+#ifdef TR
+ trace("bell\n");
+#endif
+ (void)write(1, "\007", 1); /* '\a' */
+ break;
+ case IPO_BUSY:
+#ifdef TR
+ trace("busy {%.*s}\n", (int)ipb.len, ipb.str);
+#endif
+ /*
+ * XXX
+ * Nothing...
+ * ip_busy(ipb.str, ipb.len);
+ */
+ break;
+ case IPO_CLRTOEOL:
+#ifdef TR
+ trace("clrtoeol\n");
+#endif
+ clrtoeol();
+ break;
+ case IPO_DELETELN:
+#ifdef TR
+ trace("deleteln\n");
+#endif
+ deleteln();
+ break;
+ case IPO_INSERTLN:
+#ifdef TR
+ trace("insertln\n");
+#endif
+ insertln();
+ break;
+ case IPO_MOVE:
+#ifdef TR
+ trace("move: %lu %lu\n", (u_long)ipb.val1, (u_long)ipb.val2);
+#endif
+ (void)move(ipb.val1, ipb.val2);
+ break;
+ case IPO_REDRAW:
+#ifdef TR
+ trace("redraw\n");
+#endif
+ clearok(curscr, 1);
+ refresh();
+ break;
+ case IPO_REFRESH:
+#ifdef TR
+ trace("refresh\n");
+#endif
+ refresh();
+ break;
+ case IPO_RENAME:
+#ifdef TR
+ trace("rename {%.*s}\n", (int)ipb.len, ipb.str);
+#endif
+ /*
+ * XXX
+ * Nothing...
+ * ip_rename(ipb.str, ipb.len);
+ */
+ break;
+ case IPO_REWRITE:
+#ifdef TR
+ trace("rewrite {%lu}\n", (u_long)ipb.val1);
+#endif
+ getyx(stdscr, oldy, oldx);
+ for (lno = ipb.val1, cno = spcnt = 0;;) {
+ (void)move(lno, cno);
+ ch = winch(stdscr);
+ if (isblank(ch))
+ ++spcnt;
+ else {
+ (void)move(lno, cno - spcnt);
+ for (; spcnt > 0; --spcnt)
+ (void)addch(' ');
+ (void)addch(ch);
+ }
+ if (++cno >= cols)
+ break;
+ }
+ (void)move(oldy, oldx);
+ break;
+ default:
+ /*
+ * XXX: Protocol is out of sync?
+ */
+ abort();
+ }
+
+ return (1);
+}
+
+/*
+ * arg_format
+ */
+void
+arg_format(argcp, argvp, i_fd, o_fd)
+ int *argcp, i_fd, o_fd;
+ char **argvp[];
+{
+ char **largv, *iarg, *p;
+
+ /* Get space for the argument array and the -I argument. */
+ if ((iarg = malloc(64)) == NULL ||
+ (largv = malloc((*argcp + 3) * sizeof(char *))) == NULL) {
+ perror("ip_cl");
+ exit (1);
+ }
+ memcpy(largv + 2, *argvp, *argcp * sizeof(char *) + 1);
+
+ /* Reset argv[0] to be the exec'd program. */
+ if ((p = strrchr(VI, '/')) == NULL)
+ largv[0] = VI;
+ else
+ largv[0] = p + 1;
+
+ /* Create the -I argument. */
+ (void)sprintf(iarg, "-I%d%s%d", i_fd, ".", o_fd);
+ largv[1] = iarg;
+
+ /* Reset the argument array. */
+ *argvp = largv;
+}
+
+/*
+ * ip_cur_init --
+ * Initialize the curses screen.
+ */
+void
+ip_cur_init()
+{
+ /*
+ * XXX
+ * This is 4BSD curses' specific -- if this is to be a real program
+ * we'll have to do all the stuff that we do in the cl directory to
+ * run with different curses variants.
+ */
+ if (initscr() == ERR) {
+ perror("ip_cl: initscr");
+ exit (1);
+ }
+ noecho();
+ nonl();
+ raw();
+ idlok(stdscr, 1);
+}
+
+/*
+ * ip_cur_end --
+ * End the curses screen.
+ */
+void
+ip_cur_end()
+{
+ (void)move(0, 0);
+ (void)deleteln();
+ (void)move(rows - 1, 0);
+ (void)refresh();
+ (void)endwin();
+}
+
+/*
+ * ip_siginit --
+ * Initialize the signals.
+ */
+void
+ip_siginit()
+{
+ /* We need to know if vi dies horribly. */
+ (void)signal(SIGCHLD, onchld);
+
+ /* We want to allow interruption at least for now. */
+ (void)signal(SIGINT, onintr);
+
+#ifdef SIGWINCH
+ /* We need to know if the screen is resized. */
+ (void)signal(SIGWINCH, onwinch);
+#endif
+}
+
+/*
+ * ip_resize --
+ * Send the window size.
+ */
+void
+ip_resize()
+{
+ struct winsize win;
+ IP_BUF ipb;
+
+ if (ioctl(STDERR_FILENO, TIOCGWINSZ, &win) == -1) {
+ perror("ip_cl: TIOCGWINSZ");
+ exit(1);
+ }
+
+ if (rows == win.ws_row && cols == win.ws_col)
+ return;
+
+ ipb.val1 = rows = win.ws_row;
+ ipb.val2 = cols = win.ws_col;
+ ipb.code = IPO_RESIZE;
+ ip_send("12", &ipb);
+}
+
+/*
+ * ip_send --
+ * Construct and send an IP buffer.
+ */
+int
+ip_send(fmt, ipbp)
+ char *fmt;
+ IP_BUF *ipbp;
+{
+ static char *bp;
+ static size_t blen;
+ size_t off;
+ u_int32_t ilen;
+ int nlen, n, nw;
+ char *p;
+
+ if (blen == 0 && (bp = malloc(blen = 512)) == NULL)
+ nomem();
+
+ p = bp;
+ nlen = 0;
+ *p++ = ipbp->code;
+ nlen += IPO_CODE_LEN;
+
+ if (fmt != NULL)
+ for (; *fmt != '\0'; ++fmt)
+ switch (*fmt) {
+ case '1': /* Value 1. */
+ ilen = htonl(ipbp->val1);
+ goto value;
+ case '2': /* Value 2. */
+ ilen = htonl(ipbp->val2);
+value: nlen += IPO_INT_LEN;
+ if (nlen >= blen) {
+ blen = blen * 2 + nlen;
+ off = p - bp;
+ if ((bp = realloc(bp, blen)) == NULL)
+ nomem();
+ p = bp + off;
+ }
+ memmove(p, &ilen, IPO_INT_LEN);
+ p += IPO_INT_LEN;
+ break;
+ case 's': /* String. */
+ ilen = ipbp->len; /* XXX: conversion. */
+ ilen = htonl(ilen);
+ nlen += IPO_INT_LEN + ipbp->len;
+ if (nlen >= blen) {
+ blen = blen * 2 + nlen;
+ off = p - bp;
+ if ((bp = realloc(bp, blen)) == NULL)
+ nomem();
+ p = bp + off;
+ }
+ memmove(p, &ilen, IPO_INT_LEN);
+ p += IPO_INT_LEN;
+ memmove(p, ipbp->str, ipbp->len);
+ p += ipbp->len;
+ break;
+ }
+#ifdef TR
+ trace("WROTE: ");
+ for (n = p - bp, p = bp; n > 0; --n, ++p)
+ if (isprint(*p))
+ (void)trace("%c", *p);
+ else
+ trace("<%x>", (u_char)*p);
+ trace("\n");
+#endif
+
+ for (n = p - bp, p = bp; n > 0; n -= nw, p += nw)
+ if ((nw = write(o_fd, p, n)) < 0) {
+ perror("ip_cl: write");
+ exit(1);
+ }
+
+ return (0);
+}
+
+void
+nomem()
+{
+ perror("ip_cl");
+ exit (1);
+}
+
+/*
+ * onchld --
+ * Handle SIGCHLD.
+ */
+void
+onchld(signo)
+ int signo;
+{
+ die = 1;
+
+#ifdef TR
+ trace("SIGCHLD\n");
+#endif
+
+ /* Interrupt select if it's running. */
+ (void)kill(getpid(), SIGINT);
+}
+
+/*
+ * onintr --
+ * Handle SIGINT.
+ */
+void
+onintr(signo)
+ int signo;
+{
+ /*
+ * If we receive an interrupt, we may have sent it ourselves.
+ * If not, die from the signal.
+ */
+ if (die)
+ return;
+ (void)signal(SIGINT, SIG_DFL);
+ kill(getpid(), SIGINT);
+}
+
+/*
+ * onwinch --
+ * Handle SIGWINCH.
+ */
+void
+onwinch(signo)
+ int signo;
+{
+ resize = 1;
+}
+
+void
+attach()
+{
+ int fd;
+ char ch;
+
+ (void)printf("process %lu waiting, enter <CR> to continue: ",
+ (u_long)getpid());
+ (void)fflush(stdout);
+
+ if ((fd = open(_PATH_TTY, O_RDONLY, 0)) < 0) {
+ perror(_PATH_TTY);
+ exit (1);;
+ }
+ do {
+ if (read(fd, &ch, 1) != 1) {
+ (void)close(fd);
+ return;
+ }
+ } while (ch != '\n' && ch != '\r');
+ (void)close(fd);
+}
+
+#ifdef TR
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+/*
+ * TR --
+ * debugging trace routine.
+ */
+void
+#ifdef __STDC__
+trace(const char *fmt, ...)
+#else
+trace(fmt, va_alist)
+ char *fmt;
+ va_dcl
+#endif
+{
+ static FILE *tfp;
+ va_list ap;
+
+ if (tfp == NULL && (tfp = fopen(TR, "w")) == NULL)
+ tfp = stderr;
+
+#ifdef __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ (void)vfprintf(tfp, fmt, ap);
+ va_end(ap);
+
+ (void)fflush(tfp);
+}
+#endif
+
+void
+usage()
+{
+ (void)fprintf(stderr, "usage: ip_cl [-D]\n");
+ exit(1);
+}
diff --git a/contrib/nvi/perl_api/VI.pod b/contrib/nvi/perl_api/VI.pod
new file mode 100644
index 000000000000..a87e24d911d8
--- /dev/null
+++ b/contrib/nvi/perl_api/VI.pod
@@ -0,0 +1,218 @@
+=head1 NAME
+
+VI - VI module within perl embedded nvi
+
+=head1 SYNOPSIS
+
+ sub wc {
+ my $words;
+ $i = $VI::StartLine;
+ while ($i <= $VI::StopLine) {
+ $_ = VI::GetLine($VI::ScreenId, $i++);
+ $words+=split;
+ }
+ VI::Msg($VI::ScreenId,"$words words");
+ }
+
+=head1 DESCRIPTION
+
+This pseudo module is available to perl programs run from within nvi and
+provides access to the files being edited and some internal data.
+
+Beware that you should not use this module from within a C<perldo> or
+from within an C<END> block or a C<DESTROY> method.
+
+=head2 Variables
+
+These are set by nvi before starting each perl command.
+
+=over 8
+
+=item * $ScreenId
+
+Screen id of the current screen.
+
+=item * $StartLine
+
+Line number of the first line of the selected range or of the file if no
+range was specified.
+
+=item * $StopLine
+
+Line number of the last line of the selected range or of the file if no
+range was specified.
+
+=back
+
+=head2 Functions
+
+=over 8
+
+=item * AppendLine
+
+ VI::AppendLine(screenId,lineNumber,text);
+
+Append the string text after the line in lineNumber.
+
+=item * DelLine
+
+ VI::DelLine(screenId,lineNum);
+
+Delete lineNum.
+
+=item * EndScreen
+
+VI::EndScreen(screenId);
+
+End a screen.
+
+=item * FindScreen
+
+ VI::FindScreen(file);
+
+Return the screen id associated with file name.
+
+=item * GetCursor
+
+ ($line, $column) = VI::GetCursor(screenId);
+
+Return the current cursor position as a list with two elements.
+
+=item * GetLine
+
+ VI::GetLine(screenId,lineNumber);
+
+Return lineNumber.
+
+=item * GetMark
+
+ ($line, $column) = VI::GetMark(screenId,mark);
+
+Return the mark's cursor position as a list with two elements.
+
+=item * GetOpt
+
+ VI::GetOpt(screenId,option);
+
+Return the value of an option.
+
+=item * InsertLine
+
+ VI::InsertLine(screenId,lineNumber,text);
+
+Insert the string text before the line in lineNumber.
+
+=item * LastLine
+
+ VI::LastLine(screenId);
+
+Return the last line in the screen.
+
+=item * MapKey
+
+ VI::MapKey(screenId,key,perlproc);
+
+Associate a key with a perl procedure.
+
+=item * Msg
+
+ VI::Msg(screenId,text);
+
+Set the message line to text.
+
+=item * NewScreen
+
+ VI::NewScreen(screenId);
+ VI::NewScreen(screenId,file);
+
+Create a new screen. If a filename is specified then the screen is
+opened with that file.
+
+=item * Run
+
+ VI::Run(screenId,cmd);
+
+Run the ex command cmd.
+
+=item * SetCursor
+
+ VI::SetCursor(screenId,line,column);
+
+Set the cursor to the line and column numbers supplied.
+
+=item * SetLine
+
+ VI::SetLine(screenId,lineNumber,text);
+
+Set lineNumber to the text supplied.
+
+=item * SetMark
+
+ VI::SetMark(screenId,mark,line,column);
+
+Set the mark to the line and column numbers supplied.
+
+=item * SetOpt
+
+ VI::SetOpt(screenId,command);
+
+Set an option.
+
+=item * SwitchScreen
+
+ VI::SwitchScreen(screenId,screenId);
+
+Change the current focus to screen.
+
+=item * UnmapKey
+
+ VI::UnmmapKey(screenId,key);
+
+Unmap a key.
+
+=item * Warn
+
+This is the default warning handler.
+It adds any warnings to the error string.
+
+=back
+
+=head1 EXAMPLES
+
+ sub showmarks {
+ my ($mark, $all);
+ for $mark ('a' .. 'z') {
+ eval {VI::GetMark($VI::ScreenId, $mark)};
+ $all .= $mark unless ($@);
+ }
+ VI::Msg($VI::ScreenId,"Set marks: $all");
+ }
+
+ sub forall {
+ my ($code) = shift;
+ my ($i) = $VI::StartLine-1;
+ while (++$i <= $VI::StopLine) {
+ $_ = VI::GetLine($VI::ScreenId, $i);
+ VI::SetLine($VI::ScreenId, $i, $_) if(&$code);
+ }
+ }
+
+Now you can do
+
+ :perl forall sub{s/perlre/substitution/}
+
+Although you'll probably use
+
+ :perldo s/perlre/substitution/
+
+instead.
+
+See L<perlre> for perl regular expressions.
+
+=head1 SEE ALSO
+
+L<nviperl>
+
+=head1 AUTHOR
+
+Sven Verdoolaege <skimo@dns.ufsia.ac.be>
diff --git a/contrib/nvi/perl_api/nviperl.pod b/contrib/nvi/perl_api/nviperl.pod
new file mode 100644
index 000000000000..43850d8b6363
--- /dev/null
+++ b/contrib/nvi/perl_api/nviperl.pod
@@ -0,0 +1,43 @@
+=head1 NAME
+
+nviperl - nvi with embedded perl
+
+=head1 SYNOPSIS
+
+ :perl require 'wc.pl'
+ :perl wc
+ :,$perldo $_=reverse($_)
+
+=head1 DESCRIPTION
+
+nvi with embedded perl allows you to run perl commands from within nvi.
+Two additional commands are made available when you enable the perl
+interpreter:
+
+=over 8
+
+=item * perl cmd
+
+The perl command passes the specified commands to the perl interpreter.
+The C<$VI::ScreenId>, C<$VI::StartLine> and C<$VI::StopLine> are set.
+To find out how to maniplulate the nvi screens, see L<VI>.
+
+=item * perldo cmd
+
+The perldo command runs the specified commands on each line of the range
+(every line of the file if no range specified). Before running the
+command the line is copied into $_. If the command returns a true value
+the line is replaced by the new value of $_.
+
+The perldo commando does B<not> set the C<VI> variables. (If you think
+this is a bad idea, tell me.)
+
+=back
+
+=head1 SEE ALSO
+
+L<VI>
+
+=head1 AUTHOR
+
+Sven Verdoolaege <skimo@dns.ufsia.ac.be>
diff --git a/contrib/nvi/perl_api/perl.xs b/contrib/nvi/perl_api/perl.xs
new file mode 100644
index 000000000000..0b48cded5bfc
--- /dev/null
+++ b/contrib/nvi/perl_api/perl.xs
@@ -0,0 +1,1115 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ * Copyright (c) 1995
+ * George V. Neville-Neil. All rights reserved.
+ * Copyright (c) 1996
+ * Sven Verdoolaege. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)perl.xs 8.27 (Berkeley) 10/16/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+
+#include "perl_extern.h"
+
+static void msghandler __P((SCR *, mtype_t, char *, size_t));
+
+extern GS *__global_list; /* XXX */
+
+static char *errmsg = 0;
+
+/*
+ * INITMESSAGE --
+ * Macros to point messages at the Perl message handler.
+ */
+#define INITMESSAGE \
+ scr_msg = __global_list->scr_msg; \
+ __global_list->scr_msg = msghandler;
+#define ENDMESSAGE \
+ __global_list->scr_msg = scr_msg; \
+ if (rval) croak(errmsg);
+
+static void xs_init __P((void));
+
+/*
+ * perl_end --
+ * Clean up perl interpreter
+ *
+ * PUBLIC: int perl_end __P((GS *));
+ */
+int
+perl_end(gp)
+ GS *gp;
+{
+ /*
+ * Call perl_run and perl_destuct to call END blocks and DESTROY
+ * methods.
+ */
+ if (gp->perl_interp) {
+ /*Irestartop = 0; / * XXX */
+ perl_run(gp->perl_interp);
+ perl_destruct(gp->perl_interp);
+#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
+ perl_free(gp->perl_interp);
+#endif
+ }
+}
+
+/*
+ * perl_eval
+ * Evaluate a string
+ * We don't use mortal SVs because no one will clean up after us
+ */
+static void
+perl_eval(string)
+ char *string;
+{
+#ifdef HAVE_PERL_5_003_01
+ SV* sv = newSVpv(string, 0);
+
+ perl_eval_sv(sv, G_DISCARD | G_NOARGS);
+ SvREFCNT_dec(sv);
+#else
+ char *argv[2];
+
+ argv[0] = string;
+ argv[1] = NULL;
+ perl_call_argv("_eval_", G_EVAL | G_DISCARD | G_KEEPERR, argv);
+#endif
+}
+
+/*
+ * perl_init --
+ * Create the perl commands used by nvi.
+ *
+ * PUBLIC: int perl_init __P((SCR *));
+ */
+int
+perl_init(scrp)
+ SCR *scrp;
+{
+ AV * av;
+ GS *gp;
+ char *bootargs[] = { "VI", NULL };
+#ifndef USE_SFIO
+ SV *svcurscr;
+#endif
+
+#ifndef HAVE_PERL_5_003_01
+ static char *args[] = { "", "-e", "sub _eval_ { eval $_[0] }" };
+#else
+ static char *args[] = { "", "-e", "" };
+#endif
+ STRLEN length;
+ char *file = __FILE__;
+
+ gp = scrp->gp;
+ gp->perl_interp = perl_alloc();
+ perl_construct(gp->perl_interp);
+ if (perl_parse(gp->perl_interp, xs_init, 3, args, 0)) {
+ perl_destruct(gp->perl_interp);
+ perl_free(gp->perl_interp);
+ gp->perl_interp = NULL;
+ return 1;
+ }
+ perl_call_argv("VI::bootstrap", G_DISCARD, bootargs);
+ perl_eval("$SIG{__WARN__}='VI::Warn'");
+
+ av_unshift(av = GvAVn(incgv), 1);
+ av_store(av, 0, newSVpv(_PATH_PERLSCRIPTS,
+ sizeof(_PATH_PERLSCRIPTS)-1));
+
+#ifdef USE_SFIO
+ sfdisc(PerlIO_stdout(), sfdcnewnvi(scrp));
+ sfdisc(PerlIO_stderr(), sfdcnewnvi(scrp));
+#else
+ svcurscr = perl_get_sv("curscr", TRUE);
+ sv_magic((SV *)gv_fetchpv("STDOUT",TRUE, SVt_PVIO), svcurscr,
+ 'q', Nullch, 0);
+ sv_magic((SV *)gv_fetchpv("STDERR",TRUE, SVt_PVIO), svcurscr,
+ 'q', Nullch, 0);
+#endif /* USE_SFIO */
+ return (0);
+}
+
+/*
+ * perl_screen_end
+ * Remove all refences to the screen to be destroyed
+ *
+ * PUBLIC: int perl_screen_end __P((SCR*));
+ */
+int
+perl_screen_end(scrp)
+ SCR *scrp;
+{
+ if (scrp->perl_private) {
+ sv_setiv((SV*) scrp->perl_private, 0);
+ }
+ return 0;
+}
+
+static void
+my_sighandler(i)
+ int i;
+{
+ croak("Perl command interrupted by SIGINT");
+}
+
+/* Create a new reference to an SV pointing to the SCR structure
+ * The perl_private part of the SCR structure points to the SV,
+ * so there can only be one such SV for a particular SCR structure.
+ * When the last reference has gone (DESTROY is called),
+ * perl_private is reset; When the screen goes away before
+ * all references are gone, the value of the SV is reset;
+ * any subsequent use of any of those reference will produce
+ * a warning. (see typemap)
+ */
+static SV *
+newVIrv(rv, screen)
+ SV *rv;
+ SCR *screen;
+{
+ sv_upgrade(rv, SVt_RV);
+ if (!screen->perl_private) {
+ screen->perl_private = newSV(0);
+ sv_setiv(screen->perl_private, (IV) screen);
+ }
+ else SvREFCNT_inc(screen->perl_private);
+ SvRV(rv) = screen->perl_private;
+ SvROK_on(rv);
+ return sv_bless(rv, gv_stashpv("VI", TRUE));
+}
+
+
+/*
+ * perl_ex_perl -- :[line [,line]] perl [command]
+ * Run a command through the perl interpreter.
+ *
+ * PUBLIC: int perl_ex_perl __P((SCR*, CHAR_T *, size_t, recno_t, recno_t));
+ */
+int
+perl_ex_perl(scrp, cmdp, cmdlen, f_lno, t_lno)
+ SCR *scrp;
+ CHAR_T *cmdp;
+ size_t cmdlen;
+ recno_t f_lno, t_lno;
+{
+ static SV *svcurscr = 0, *svstart, *svstop, *svid;
+ GS *gp;
+ STRLEN length;
+ size_t len;
+ char *err;
+ Signal_t (*istat)();
+
+ /* Initialize the interpreter. */
+ gp = scrp->gp;
+ if (!svcurscr) {
+ if (gp->perl_interp == NULL && perl_init(scrp))
+ return (1);
+ SvREADONLY_on(svcurscr = perl_get_sv("curscr", TRUE));
+ SvREADONLY_on(svstart = perl_get_sv("VI::StartLine", TRUE));
+ SvREADONLY_on(svstop = perl_get_sv("VI::StopLine", TRUE));
+ SvREADONLY_on(svid = perl_get_sv("VI::ScreenId", TRUE));
+ }
+
+ sv_setiv(svstart, f_lno);
+ sv_setiv(svstop, t_lno);
+ newVIrv(svcurscr, scrp);
+ /* Backwards compatibility. */
+ newVIrv(svid, scrp);
+
+ istat = signal(SIGINT, my_sighandler);
+ perl_eval(cmdp);
+ signal(SIGINT, istat);
+
+ SvREFCNT_dec(SvRV(svcurscr));
+ SvROK_off(svcurscr);
+ SvREFCNT_dec(SvRV(svid));
+ SvROK_off(svid);
+
+ err = SvPV(GvSV(errgv), length);
+ if (!length)
+ return (0);
+
+ err[length - 1] = '\0';
+ msgq(scrp, M_ERR, "perl: %s", err);
+ return (1);
+}
+
+/*
+ * replace_line
+ * replace a line with the contents of the perl variable $_
+ * lines are split at '\n's
+ * if $_ is undef, the line is deleted
+ * returns possibly adjusted linenumber
+ */
+static int
+replace_line(scrp, line, t_lno)
+ SCR *scrp;
+ recno_t line, *t_lno;
+{
+ char *str, *next;
+ size_t len;
+
+ if (SvOK(GvSV(defgv))) {
+ str = SvPV(GvSV(defgv),len);
+ next = memchr(str, '\n', len);
+ api_sline(scrp, line, str, next ? (next - str) : len);
+ while (next++) {
+ len -= next - str;
+ next = memchr(str = next, '\n', len);
+ api_iline(scrp, ++line, str, next ? (next - str) : len);
+ (*t_lno)++;
+ }
+ } else {
+ api_dline(scrp, line--);
+ (*t_lno)--;
+ }
+ return line;
+}
+
+/*
+ * perl_ex_perldo -- :[line [,line]] perl [command]
+ * Run a set of lines through the perl interpreter.
+ *
+ * PUBLIC: int perl_ex_perldo __P((SCR*, CHAR_T *, size_t, recno_t, recno_t));
+ */
+int
+perl_ex_perldo(scrp, cmdp, cmdlen, f_lno, t_lno)
+ SCR *scrp;
+ CHAR_T *cmdp;
+ size_t cmdlen;
+ recno_t f_lno, t_lno;
+{
+ static SV *svcurscr = 0, *svstart, *svstop, *svid;
+ CHAR_T *p;
+ GS *gp;
+ STRLEN length;
+ size_t len;
+ recno_t i;
+ char *str;
+#ifndef HAVE_PERL_5_003_01
+ char *argv[2];
+#else
+ SV* sv;
+#endif
+ dSP;
+
+ /* Initialize the interpreter. */
+ gp = scrp->gp;
+ if (!svcurscr) {
+ if (gp->perl_interp == NULL && perl_init(scrp))
+ return (1);
+ SPAGAIN;
+ SvREADONLY_on(svcurscr = perl_get_sv("curscr", TRUE));
+ SvREADONLY_on(svstart = perl_get_sv("VI::StartLine", TRUE));
+ SvREADONLY_on(svstop = perl_get_sv("VI::StopLine", TRUE));
+ SvREADONLY_on(svid = perl_get_sv("VI::ScreenId", TRUE));
+ }
+
+#ifndef HAVE_PERL_5_003_01
+ argv[0] = cmdp;
+ argv[1] = NULL;
+#else
+ length = strlen(cmdp);
+ sv = newSV(length + sizeof("sub VI::perldo {")-1 + 1 /* } */);
+ sv_setpvn(sv, "sub VI::perldo {", sizeof("sub VI::perldo {")-1);
+ sv_catpvn(sv, cmdp, length);
+ sv_catpvn(sv, "}", 1);
+ perl_eval_sv(sv, G_DISCARD | G_NOARGS);
+ SvREFCNT_dec(sv);
+ str = SvPV(GvSV(errgv),length);
+ if (length)
+ goto err;
+#endif
+
+ newVIrv(svcurscr, scrp);
+ /* Backwards compatibility. */
+ newVIrv(svid, scrp);
+
+ ENTER;
+ SAVETMPS;
+ for (i = f_lno; i <= t_lno && !api_gline(scrp, i, &str, &len); i++) {
+ sv_setpvn(GvSV(defgv),str,len);
+ sv_setiv(svstart, i);
+ sv_setiv(svstop, i);
+#ifndef HAVE_PERL_5_003_01
+ perl_call_argv("_eval_", G_SCALAR | G_EVAL | G_KEEPERR, argv);
+#else
+ PUSHMARK(sp);
+ perl_call_pv("VI::perldo", G_SCALAR | G_EVAL);
+#endif
+ str = SvPV(GvSV(errgv), length);
+ if (length) break;
+ SPAGAIN;
+ if(SvTRUEx(POPs))
+ i = replace_line(scrp, i, &t_lno);
+ PUTBACK;
+ }
+ FREETMPS;
+ LEAVE;
+
+ SvREFCNT_dec(SvRV(svcurscr));
+ SvROK_off(svcurscr);
+ SvREFCNT_dec(SvRV(svid));
+ SvROK_off(svid);
+
+ if (!length)
+ return (0);
+
+err: str[length - 1] = '\0';
+ msgq(scrp, M_ERR, "perl: %s", str);
+ return (1);
+}
+
+/*
+ * msghandler --
+ * Perl message routine so that error messages are processed in
+ * Perl, not in nvi.
+ */
+static void
+msghandler(sp, mtype, msg, len)
+ SCR *sp;
+ mtype_t mtype;
+ char *msg;
+ size_t len;
+{
+ /* Replace the trailing <newline> with an EOS. */
+ /* Let's do that later instead */
+ if (errmsg) free (errmsg);
+ errmsg = malloc(len + 1);
+ memcpy(errmsg, msg, len);
+ errmsg[len] = '\0';
+}
+
+/* Register any extra external extensions */
+
+extern void boot_DynaLoader _((CV* cv));
+extern void boot_VI _((CV* cv));
+
+static void
+xs_init()
+{
+#ifdef HAVE_PERL_5_003_01
+ dXSUB_SYS;
+#endif
+ char *file = __FILE__;
+
+ newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
+ newXS("VI::bootstrap", boot_VI, file);
+}
+
+typedef SCR * VI;
+typedef SCR * VI__OPT;
+typedef SCR * VI__MAP;
+typedef SCR * VI__MARK;
+typedef AV * AVREF;
+
+MODULE = VI PACKAGE = VI
+
+# msg --
+# Set the message line to text.
+#
+# Perl Command: VI::Msg
+# Usage: VI::Msg screenId text
+
+void
+Msg(screen, text)
+ VI screen
+ char * text
+
+ ALIAS:
+ PRINT = 1
+
+ CODE:
+ api_imessage(screen, text);
+
+# XS_VI_escreen --
+# End a screen.
+#
+# Perl Command: VI::EndScreen
+# Usage: VI::EndScreen screenId
+
+void
+EndScreen(screen)
+ VI screen
+
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ CODE:
+ INITMESSAGE;
+ rval = api_escreen(screen);
+ ENDMESSAGE;
+
+# XS_VI_iscreen --
+# Create a new screen. If a filename is specified then the screen
+# is opened with that file.
+#
+# Perl Command: VI::NewScreen
+# Usage: VI::NewScreen screenId [file]
+
+VI
+Edit(screen, ...)
+ VI screen
+
+ ALIAS:
+ NewScreen = 1
+
+ PROTOTYPE: $;$
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+ char *file;
+ SCR *nsp;
+
+ CODE:
+ file = (items == 1) ? NULL : (char *)SvPV(ST(1),na);
+ INITMESSAGE;
+ rval = api_edit(screen, file, &nsp, ix);
+ ENDMESSAGE;
+
+ RETVAL = ix ? nsp : screen;
+
+ OUTPUT:
+ RETVAL
+
+# XS_VI_fscreen --
+# Return the screen id associated with file name.
+#
+# Perl Command: VI::FindScreen
+# Usage: VI::FindScreen file
+
+VI
+FindScreen(file)
+ char *file
+
+ PREINIT:
+ SCR *fsp;
+ CODE:
+ RETVAL = api_fscreen(0, file);
+
+# XS_VI_aline --
+# -- Append the string text after the line in lineNumber.
+#
+# Perl Command: VI::AppendLine
+# Usage: VI::AppendLine screenId lineNumber text
+
+void
+AppendLine(screen, linenumber, text)
+ VI screen
+ int linenumber
+ char *text
+
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+ STRLEN length;
+
+ CODE:
+ SvPV(ST(2), length);
+ INITMESSAGE;
+ rval = api_aline(screen, linenumber, text, length);
+ ENDMESSAGE;
+
+# XS_VI_dline --
+# Delete lineNum.
+#
+# Perl Command: VI::DelLine
+# Usage: VI::DelLine screenId lineNum
+
+void
+DelLine(screen, linenumber)
+ VI screen
+ int linenumber
+
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ CODE:
+ INITMESSAGE;
+ rval = api_dline(screen, (recno_t)linenumber);
+ ENDMESSAGE;
+
+# XS_VI_gline --
+# Return lineNumber.
+#
+# Perl Command: VI::GetLine
+# Usage: VI::GetLine screenId lineNumber
+
+char *
+GetLine(screen, linenumber)
+ VI screen
+ int linenumber
+
+ PREINIT:
+ size_t len;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+ char *line, *p;
+
+ PPCODE:
+ INITMESSAGE;
+ rval = api_gline(screen, (recno_t)linenumber, &p, &len);
+ ENDMESSAGE;
+
+ EXTEND(sp,1);
+ PUSHs(sv_2mortal(newSVpv(p, len)));
+
+# XS_VI_sline --
+# Set lineNumber to the text supplied.
+#
+# Perl Command: VI::SetLine
+# Usage: VI::SetLine screenId lineNumber text
+
+void
+SetLine(screen, linenumber, text)
+ VI screen
+ int linenumber
+ char *text
+
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+ STRLEN length;
+
+ CODE:
+ SvPV(ST(2), length);
+ INITMESSAGE;
+ rval = api_sline(screen, linenumber, text, length);
+ ENDMESSAGE;
+
+# XS_VI_iline --
+# Insert the string text before the line in lineNumber.
+#
+# Perl Command: VI::InsertLine
+# Usage: VI::InsertLine screenId lineNumber text
+
+void
+InsertLine(screen, linenumber, text)
+ VI screen
+ int linenumber
+ char *text
+
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+ STRLEN length;
+
+ CODE:
+ SvPV(ST(2), length);
+ INITMESSAGE;
+ rval = api_iline(screen, linenumber, text, length);
+ ENDMESSAGE;
+
+# XS_VI_lline --
+# Return the last line in the screen.
+#
+# Perl Command: VI::LastLine
+# Usage: VI::LastLine screenId
+
+int
+LastLine(screen)
+ VI screen
+
+ PREINIT:
+ recno_t last;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ CODE:
+ INITMESSAGE;
+ rval = api_lline(screen, &last);
+ ENDMESSAGE;
+ RETVAL=last;
+
+ OUTPUT:
+ RETVAL
+
+# XS_VI_getmark --
+# Return the mark's cursor position as a list with two elements.
+# {line, column}.
+#
+# Perl Command: VI::GetMark
+# Usage: VI::GetMark screenId mark
+
+void
+GetMark(screen, mark)
+ VI screen
+ char mark
+
+ PREINIT:
+ struct _mark cursor;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ PPCODE:
+ INITMESSAGE;
+ rval = api_getmark(screen, (int)mark, &cursor);
+ ENDMESSAGE;
+
+ EXTEND(sp,2);
+ PUSHs(sv_2mortal(newSViv(cursor.lno)));
+ PUSHs(sv_2mortal(newSViv(cursor.cno)));
+
+# XS_VI_setmark --
+# Set the mark to the line and column numbers supplied.
+#
+# Perl Command: VI::SetMark
+# Usage: VI::SetMark screenId mark line column
+
+void
+SetMark(screen, mark, line, column)
+ VI screen
+ char mark
+ int line
+ int column
+
+ PREINIT:
+ struct _mark cursor;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ CODE:
+ INITMESSAGE;
+ cursor.lno = line;
+ cursor.cno = column;
+ rval = api_setmark(screen, (int)mark, &cursor);
+ ENDMESSAGE;
+
+# XS_VI_getcursor --
+# Return the current cursor position as a list with two elements.
+# {line, column}.
+#
+# Perl Command: VI::GetCursor
+# Usage: VI::GetCursor screenId
+
+void
+GetCursor(screen)
+ VI screen
+
+ PREINIT:
+ struct _mark cursor;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ PPCODE:
+ INITMESSAGE;
+ rval = api_getcursor(screen, &cursor);
+ ENDMESSAGE;
+
+ EXTEND(sp,2);
+ PUSHs(sv_2mortal(newSViv(cursor.lno)));
+ PUSHs(sv_2mortal(newSViv(cursor.cno)));
+
+# XS_VI_setcursor --
+# Set the cursor to the line and column numbers supplied.
+#
+# Perl Command: VI::SetCursor
+# Usage: VI::SetCursor screenId line column
+
+void
+SetCursor(screen, line, column)
+ VI screen
+ int line
+ int column
+
+ PREINIT:
+ struct _mark cursor;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ CODE:
+ INITMESSAGE;
+ cursor.lno = line;
+ cursor.cno = column;
+ rval = api_setcursor(screen, &cursor);
+ ENDMESSAGE;
+
+# XS_VI_swscreen --
+# Change the current focus to screen.
+#
+# Perl Command: VI::SwitchScreen
+# Usage: VI::SwitchScreen screenId screenId
+
+void
+SwitchScreen(screenFrom, screenTo)
+ VI screenFrom
+ VI screenTo
+
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ CODE:
+ INITMESSAGE;
+ rval = api_swscreen(screenFrom, screenTo);
+ ENDMESSAGE;
+
+# XS_VI_map --
+# Associate a key with a perl procedure.
+#
+# Perl Command: VI::MapKey
+# Usage: VI::MapKey screenId key perlproc
+
+void
+MapKey(screen, key, perlproc)
+ VI screen
+ char *key
+ SV *perlproc
+
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+ int length;
+ char *command;
+ SV *svc;
+
+ CODE:
+ INITMESSAGE;
+ svc = sv_2mortal(newSVpv(":perl ", 6));
+ sv_catsv(svc, perlproc);
+ command = SvPV(svc, length);
+ rval = api_map(screen, key, command, length);
+ ENDMESSAGE;
+
+# XS_VI_unmap --
+# Unmap a key.
+#
+# Perl Command: VI::UnmapKey
+# Usage: VI::UnmmapKey screenId key
+
+void
+UnmapKey(screen, key)
+ VI screen
+ char *key
+
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ CODE:
+ INITMESSAGE;
+ rval = api_unmap(screen, key);
+ ENDMESSAGE;
+
+# XS_VI_opts_set --
+# Set an option.
+#
+# Perl Command: VI::SetOpt
+# Usage: VI::SetOpt screenId setting
+
+void
+SetOpt(screen, setting)
+ VI screen
+ char *setting
+
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+ SV *svc;
+
+ CODE:
+ INITMESSAGE;
+ svc = sv_2mortal(newSVpv(":set ", 5));
+ sv_catpv(svc, setting);
+ rval = api_run_str(screen, SvPV(svc, na));
+ ENDMESSAGE;
+
+# XS_VI_opts_get --
+# Return the value of an option.
+#
+# Perl Command: VI::GetOpt
+# Usage: VI::GetOpt screenId option
+
+void
+GetOpt(screen, option)
+ VI screen
+ char *option
+
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+ char *value;
+
+ PPCODE:
+ INITMESSAGE;
+ rval = api_opts_get(screen, option, &value, NULL);
+ ENDMESSAGE;
+
+ EXTEND(SP,1);
+ PUSHs(sv_2mortal(newSVpv(value, 0)));
+ free(value);
+
+# XS_VI_run --
+# Run the ex command cmd.
+#
+# Perl Command: VI::Run
+# Usage: VI::Run screenId cmd
+
+void
+Run(screen, command)
+ VI screen
+ char *command;
+
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ CODE:
+ INITMESSAGE;
+ rval = api_run_str(screen, command);
+ ENDMESSAGE;
+
+void
+DESTROY(screen)
+ VI screen
+
+ CODE:
+ screen->perl_private = 0;
+
+void
+Warn(warning)
+ char *warning;
+
+ PREINIT:
+ int i;
+ CODE:
+ sv_catpv(GvSV(errgv),warning);
+
+#define TIED(package) \
+ sv_magic((SV *) (hv = \
+ (HV *)sv_2mortal((SV *)newHV())), \
+ sv_setref_pv(sv_newmortal(), package, \
+ newVIrv(newSV(0), screen)),\
+ 'P', Nullch, 0);\
+ RETVAL = newRV((SV *)hv)
+
+SV *
+Opt(screen)
+ VI screen;
+ PREINIT:
+ HV *hv;
+ CODE:
+ TIED("VI::OPT");
+ OUTPUT:
+ RETVAL
+
+SV *
+Map(screen)
+ VI screen;
+ PREINIT:
+ HV *hv;
+ CODE:
+ TIED("VI::MAP");
+ OUTPUT:
+ RETVAL
+
+SV *
+Mark(screen)
+ VI screen
+ PREINIT:
+ HV *hv;
+ CODE:
+ TIED("VI::MARK");
+ OUTPUT:
+ RETVAL
+
+MODULE = VI PACKAGE = VI::OPT
+
+void
+DESTROY(screen)
+ VI::OPT screen
+
+ CODE:
+ # typemap did all the checking
+ SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
+
+void
+FETCH(screen, key)
+ VI::OPT screen
+ char *key
+
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+ char *value;
+ int boolvalue;
+
+ PPCODE:
+ INITMESSAGE;
+ rval = api_opts_get(screen, key, &value, &boolvalue);
+ if (!rval) {
+ EXTEND(SP,1);
+ PUSHs(sv_2mortal((boolvalue == -1) ? newSVpv(value, 0)
+ : newSViv(boolvalue)));
+ free(value);
+ } else ST(0) = &sv_undef;
+ rval = 0;
+ ENDMESSAGE;
+
+void
+STORE(screen, key, value)
+ VI::OPT screen
+ char *key
+ SV *value
+
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ CODE:
+ INITMESSAGE;
+ rval = api_opts_set(screen, key, SvPV(value, na), SvIV(value),
+ SvTRUEx(value));
+ ENDMESSAGE;
+
+MODULE = VI PACKAGE = VI::MAP
+
+void
+DESTROY(screen)
+ VI::MAP screen
+
+ CODE:
+ # typemap did all the checking
+ SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
+
+void
+STORE(screen, key, perlproc)
+ VI::MAP screen
+ char *key
+ SV *perlproc
+
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+ int length;
+ char *command;
+ SV *svc;
+
+ CODE:
+ INITMESSAGE;
+ svc = sv_2mortal(newSVpv(":perl ", 6));
+ sv_catsv(svc, perlproc);
+ command = SvPV(svc, length);
+ rval = api_map(screen, key, command, length);
+ ENDMESSAGE;
+
+void
+DELETE(screen, key)
+ VI::MAP screen
+ char *key
+
+ PREINIT:
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ CODE:
+ INITMESSAGE;
+ rval = api_unmap(screen, key);
+ ENDMESSAGE;
+
+MODULE = VI PACKAGE = VI::MARK
+
+void
+DESTROY(screen)
+ VI::MARK screen
+
+ CODE:
+ # typemap did all the checking
+ SvREFCNT_dec((SV*)SvIV((SV*)SvRV(ST(0))));
+
+AV *
+FETCH(screen, mark)
+ VI::MARK screen
+ char mark
+
+ PREINIT:
+ struct _mark cursor;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ CODE:
+ INITMESSAGE;
+ rval = api_getmark(screen, (int)mark, &cursor);
+ ENDMESSAGE;
+ RETVAL = newAV();
+ av_push(RETVAL, newSViv(cursor.lno));
+ av_push(RETVAL, newSViv(cursor.cno));
+
+ OUTPUT:
+ RETVAL
+
+void
+STORE(screen, mark, pos)
+ VI::MARK screen
+ char mark
+ AVREF pos
+
+ PREINIT:
+ struct _mark cursor;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ CODE:
+ if (av_len(pos) < 1)
+ croak("cursor position needs 2 elements");
+ INITMESSAGE;
+ cursor.lno = SvIV(*av_fetch(pos, 0, 0));
+ cursor.cno = SvIV(*av_fetch(pos, 1, 0));
+ rval = api_setmark(screen, (int)mark, &cursor);
+ ENDMESSAGE;
+
+void
+FIRSTKEY(screen, ...)
+ VI::MARK screen
+
+ ALIAS:
+ NEXTKEY = 1
+
+ PROTOTYPE: $;$
+
+ PREINIT:
+ struct _mark cursor;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int next;
+ char key[] = {0, 0};
+
+ PPCODE:
+ if (items == 2) {
+ next = 1;
+ *key = *(char *)SvPV(ST(1),na);
+ } else next = 0;
+ if (api_nextmark(screen, next, key) != 1) {
+ EXTEND(sp, 1);
+ PUSHs(sv_2mortal(newSVpv(key, 1)));
+ } else ST(0) = &sv_undef;
diff --git a/contrib/nvi/perl_api/perlsfio.c b/contrib/nvi/perl_api/perlsfio.c
new file mode 100644
index 000000000000..20ff4773495a
--- /dev/null
+++ b/contrib/nvi/perl_api/perlsfio.c
@@ -0,0 +1,85 @@
+/*-
+ * Copyright (c) 1996
+ * Keith Bostic. All rights reserved.
+ * Copyright (c) 1996
+ * Sven Verdoolaege. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)perlsfio.c 8.1 (Berkeley) 9/24/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+
+#include "perl_extern.h"
+
+/*
+ * PUBLIC: #ifdef USE_SFIO
+ */
+#ifdef USE_SFIO
+
+#define NIL(type) ((type)0)
+
+static int
+sfnviwrite(f, buf, n, disc)
+Sfio_t* f; /* stream involved */
+char* buf; /* buffer to read into */
+int n; /* number of bytes to read */
+Sfdisc_t* disc; /* discipline */
+{
+ SCR *scrp;
+
+ scrp = (SCR *)SvIV((SV*)SvRV(perl_get_sv("curscr", FALSE)));
+ msgq(scrp, M_INFO, "%.*s", n, buf);
+ return n;
+}
+
+/*
+ * sfdcnewnvi --
+ * Create nvi discipline
+ *
+ * PUBLIC: Sfdisc_t* sfdcnewnvi __P((SCR*));
+ */
+
+Sfdisc_t *
+sfdcnewnvi(scrp)
+ SCR *scrp;
+{
+ Sfdisc_t* disc;
+
+ MALLOC(scrp, disc, Sfdisc_t*, sizeof(Sfdisc_t));
+ if (!disc) return disc;
+
+ disc->readf = (Sfread_f)NULL;
+ disc->writef = sfnviwrite;
+ disc->seekf = (Sfseek_f)NULL;
+ disc->exceptf = (Sfexcept_f)NULL;
+ return disc;
+}
+
+/*
+ * PUBLIC: #endif
+ */
+#endif /* USE_SFIO */
diff --git a/contrib/nvi/perl_api/typemap b/contrib/nvi/perl_api/typemap
new file mode 100644
index 000000000000..0e38a9c07bc7
--- /dev/null
+++ b/contrib/nvi/perl_api/typemap
@@ -0,0 +1,42 @@
+TYPEMAP
+# Grr can't let it end in OBJ 'cause xsubpp would
+# s/OBJ$/REF/ that for the DESTROY function
+VI T_VIOBJNOMUNGE
+VI::OPT T_VIOBJREF
+VI::MAP T_VIOBJREF
+VI::MARK T_VIOBJREF
+AVREF T_AVREFREF
+
+INPUT
+T_AVREFREF
+ if (SvROK($arg) && SvTYPE(SvRV($arg)) == SVt_PVAV)
+ $var = (AV *)SvRV($arg);
+ else
+ croak(\"$var is not a reference to an array\")
+T_VIOBJNOMUNGE
+ if (sv_isa($arg, \"VI\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = ($type) tmp;
+ if (!tmp)
+ croak(\"screen no longer exists\");
+ }
+ else
+ croak(\"$var is not of type ${ntype}\")
+T_VIOBJREF
+ if (sv_isa($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ if (sv_isa((SV *)tmp, \"VI\")) {
+ IV tmp2 = SvIV((SV*)SvRV((SV *)tmp));
+ $var = ($type) tmp2;
+ if (!tmp2)
+ croak(\"screen no longer exists\");
+ }
+ else
+ croak(\"$var is not of type ${ntype}\");
+ }
+ else
+ croak(\"$var is not of type ${ntype}\")
+
+OUTPUT
+T_VIOBJNOMUNGE
+ newVIrv($arg, $var);
diff --git a/contrib/nvi/perl_scripts/forall.pl b/contrib/nvi/perl_scripts/forall.pl
new file mode 100644
index 000000000000..b9f85013b17d
--- /dev/null
+++ b/contrib/nvi/perl_scripts/forall.pl
@@ -0,0 +1,10 @@
+sub forall {
+ my ($code) = shift;
+ my ($i) = $VI::StartLine-1;
+ while (++$i <= $VI::StopLine) {
+ $_ = $curscr->GetLine($i);
+ VI::SetLine($VI::ScreenId, $i, $_) if(&$code);
+ }
+}
+
+1;
diff --git a/contrib/nvi/perl_scripts/make.pl b/contrib/nvi/perl_scripts/make.pl
new file mode 100644
index 000000000000..118dd99a424c
--- /dev/null
+++ b/contrib/nvi/perl_scripts/make.pl
@@ -0,0 +1,27 @@
+sub make {
+ open MAKE, "make 2>&1 1>/dev/null |";
+ while(<MAKE>) {
+ if (($file, $line, $msg) = /([^: ]*):(\d*):(.+)/) {
+ if ($file == $prevfile && $line == $prevline) {
+ $error[-1]->[2] .= "\n$msg";
+ } else {
+ push @error, [$file, $line, $msg];
+ ($prevline, $prevfile) = ($line, $file);
+ }
+ }
+ }
+ close MAKE;
+}
+
+sub nexterror {
+ if ($index <= $#error) {
+ my $error = $error[$index++];
+ $curscr->Edit($error->[0]);
+ $curscr->SetCursor($error->[1],0);
+ $curscr->Msg($error->[2]);
+ }
+}
+
+# preverror is left as an exercise
+
+1;
diff --git a/contrib/nvi/perl_scripts/tk.pl b/contrib/nvi/perl_scripts/tk.pl
new file mode 100644
index 000000000000..f8d1bc068df3
--- /dev/null
+++ b/contrib/nvi/perl_scripts/tk.pl
@@ -0,0 +1,20 @@
+# make sure every subprocess has it's exit and that the main one
+# hasn't
+sub fun {
+ unless ($pid = fork) {
+ unless (fork) {
+ use Tk;
+ $MW = MainWindow->new;
+ $hello = $MW->Button(
+ -text => 'Hello, world',
+ -command => sub {exit;},
+ );
+ $hello->pack;
+ MainLoop;
+ }
+ exit 0;
+ }
+ waitpid($pid, 0);
+}
+
+1;
diff --git a/contrib/nvi/perl_scripts/wc.pl b/contrib/nvi/perl_scripts/wc.pl
new file mode 100644
index 000000000000..0a5015987d10
--- /dev/null
+++ b/contrib/nvi/perl_scripts/wc.pl
@@ -0,0 +1,11 @@
+sub wc {
+ my $words;
+ $i = $VI::StartLine;
+ while ($i <= $VI::StopLine) {
+ $_ = $curscr->GetLine($i++);
+ $words+=split;
+ }
+ $curscr->Msg("$words words");
+}
+
+1;
diff --git a/contrib/nvi/tcl_api/tcl.c b/contrib/nvi/tcl_api/tcl.c
new file mode 100644
index 000000000000..8f4a430bac4c
--- /dev/null
+++ b/contrib/nvi/tcl_api/tcl.c
@@ -0,0 +1,852 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995
+ * Keith Bostic. All rights reserved.
+ * Copyright (c) 1995
+ * George V. Neville-Neil. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)tcl.c 8.16 (Berkeley) 10/16/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tcl.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "tcl_extern.h"
+
+static int getint __P((Tcl_Interp *, char *, char *, int *));
+static int getscreenid __P((Tcl_Interp *, SCR **, char *, char *));
+static void msghandler __P((SCR *, mtype_t, char *, size_t));
+
+extern GS *__global_list; /* XXX */
+
+/*
+ * INITMESSAGE --
+ * Macros to point messages at the Tcl message handler.
+ */
+#define INITMESSAGE \
+ scr_msg = __global_list->scr_msg; \
+ __global_list->scr_msg = msghandler;
+#define ENDMESSAGE \
+ __global_list->scr_msg = scr_msg;
+
+/*
+ * tcl_fscreen --
+ * Return the screen id associated with file name.
+ *
+ * Tcl Command: viFindScreen
+ * Usage: viFindScreen file
+ */
+static int
+tcl_fscreen(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ SCR *sp;
+
+ if (argc != 2) {
+ Tcl_SetResult(interp, "Usage: viFindScreen file", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, NULL, argv[1]))
+ return (TCL_ERROR);
+
+ (void)sprintf(interp->result, "%d", sp->id);
+ return (TCL_OK);
+}
+
+/*
+ * tcl_aline --
+ * -- Append the string text after the line in lineNumber.
+ *
+ * Tcl Command: viAppendLine
+ * Usage: viAppendLine screenId lineNumber text
+ */
+static int
+tcl_aline(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ SCR *sp;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int lno, rval;
+
+ if (argc != 4) {
+ Tcl_SetResult(interp,
+ "Usage: viAppendLine screenId lineNumber text", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL) ||
+ getint(interp, "line number", argv[2], &lno))
+ return (TCL_ERROR);
+ INITMESSAGE;
+ rval = api_aline(sp, (recno_t)lno, argv[3], strlen(argv[3]));
+ ENDMESSAGE;
+
+ return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_dline --
+ * Delete lineNum.
+ *
+ * Tcl Command: viDelLine
+ * Usage: viDelLine screenId lineNum
+ */
+static int
+tcl_dline(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ SCR *sp;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int lno, rval;
+
+ if (argc != 3) {
+ Tcl_SetResult(interp,
+ "Usage: viDelLine screenId lineNumber", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL) ||
+ getint(interp, "line number", argv[2], &lno))
+ return (TCL_ERROR);
+ INITMESSAGE;
+ rval = api_dline(sp, (recno_t)lno);
+ ENDMESSAGE;
+
+ return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_gline --
+ * Return lineNumber.
+ *
+ * Tcl Command: viGetLine
+ * Usage: viGetLine screenId lineNumber
+ */
+static int
+tcl_gline(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ SCR *sp;
+ size_t len;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int lno, rval;
+ char *line, *p;
+
+ if (argc != 3) {
+ Tcl_SetResult(interp,
+ "Usage: viGetLine screenId lineNumber", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+ if (getscreenid(interp, &sp, argv[1], NULL) ||
+ getint(interp, "line number", argv[2], &lno))
+ return (TCL_ERROR);
+ INITMESSAGE;
+ rval = api_gline(sp, (recno_t)lno, &p, &len);
+ ENDMESSAGE;
+
+ if (rval)
+ return (TCL_ERROR);
+
+ if ((line = malloc(len + 1)) == NULL)
+ exit(1); /* XXX */
+ memmove(line, p, len);
+ line[len] = '\0';
+ Tcl_SetResult(interp, line, TCL_DYNAMIC);
+ return (TCL_OK);
+}
+
+/*
+ * tcl_iline --
+ * Insert the string text after the line in lineNumber.
+ *
+ * Tcl Command: viInsertLine
+ * Usage: viInsertLine screenId lineNumber text
+ */
+static int
+tcl_iline(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ SCR *sp;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int lno, rval;
+
+ if (argc != 4) {
+ Tcl_SetResult(interp,
+ "Usage: viInsertLine screenId lineNumber text", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL) ||
+ getint(interp, "line number", argv[2], &lno))
+ return (TCL_ERROR);
+ INITMESSAGE;
+ rval = api_iline(sp, (recno_t)lno, argv[3], strlen(argv[3]));
+ ENDMESSAGE;
+
+ return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_lline --
+ * Return the last line in the screen.
+ *
+ * Tcl Command: viLastLine
+ * Usage: viLastLine screenId
+ */
+static int
+tcl_lline(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ SCR *sp;
+ recno_t last;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ if (argc != 2) {
+ Tcl_SetResult(interp, "Usage: viLastLine screenId", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL))
+ return (TCL_ERROR);
+ INITMESSAGE;
+ rval = api_lline(sp, &last);
+ ENDMESSAGE;
+ if (rval)
+ return (TCL_ERROR);
+
+ (void)sprintf(interp->result, "%lu", (unsigned long)last);
+ return (TCL_OK);
+}
+
+/*
+ * tcl_sline --
+ * Set lineNumber to the text supplied.
+ *
+ * Tcl Command: viSetLine
+ * Usage: viSetLine screenId lineNumber text
+ */
+static int
+tcl_sline(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ SCR *sp;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int lno, rval;
+
+ if (argc != 4) {
+ Tcl_SetResult(interp,
+ "Usage: viSetLine screenId lineNumber text", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL) ||
+ getint(interp, "line number", argv[2], &lno))
+ return (TCL_ERROR);
+ INITMESSAGE;
+ rval = api_sline(sp, (recno_t)lno, argv[3], strlen(argv[3]));
+ ENDMESSAGE;
+
+ return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_getmark --
+ * Return the mark's cursor position as a list with two elements.
+ * {line, column}.
+ *
+ * Tcl Command: viGetMark
+ * Usage: viGetMark screenId mark
+ */
+static int
+tcl_getmark(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ MARK cursor;
+ SCR *sp;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+ char buf[20];
+
+ if (argc != 3) {
+ Tcl_SetResult(interp,
+ "Usage: viGetMark screenId mark", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL))
+ return (TCL_ERROR);
+ INITMESSAGE;
+ rval = api_getmark(sp, (int)argv[2][0], &cursor);
+ ENDMESSAGE;
+
+ if (rval)
+ return (TCL_ERROR);
+
+ (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.lno);
+ Tcl_AppendElement(interp, buf);
+ (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.cno);
+ Tcl_AppendElement(interp, buf);
+ return (TCL_OK);
+}
+
+/*
+ * tcl_setmark --
+ * Set the mark to the line and column numbers supplied.
+ *
+ * Tcl Command: viSetMark
+ * Usage: viSetMark screenId mark line column
+ */
+static int
+tcl_setmark(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ MARK cursor;
+ SCR *sp;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int i, rval;
+
+ if (argc != 5) {
+ Tcl_SetResult(interp,
+ "Usage: viSetMark screenId mark line column", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL))
+ return (TCL_ERROR);
+ if (getint(interp, "line number", argv[3], &i))
+ return (TCL_ERROR);
+ cursor.lno = i;
+ if (getint(interp, "column number", argv[4], &i))
+ return (TCL_ERROR);
+ cursor.cno = i;
+ INITMESSAGE;
+ rval = api_setmark(sp, (int)argv[2][0], &cursor);
+ ENDMESSAGE;
+
+ return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_getcursor --
+ * Return the current cursor position as a list with two elements.
+ * {line, column}.
+ *
+ * Tcl Command: viGetCursor
+ * Usage: viGetCursor screenId
+ */
+static int
+tcl_getcursor(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ MARK cursor;
+ SCR *sp;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+ char buf[20];
+
+ if (argc != 2) {
+ Tcl_SetResult(interp,
+ "Usage: viGetCursor screenId", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL))
+ return (TCL_ERROR);
+ INITMESSAGE;
+ rval = api_getcursor(sp, &cursor);
+ ENDMESSAGE;
+
+ if (rval)
+ return (TCL_ERROR);
+
+ (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.lno);
+ Tcl_AppendElement(interp, buf);
+ (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.cno);
+ Tcl_AppendElement(interp, buf);
+ return (TCL_OK);
+}
+
+/*
+ * tcl_setcursor --
+ * Set the cursor to the line and column numbers supplied.
+ *
+ * Tcl Command: viSetCursor
+ * Usage: viSetCursor screenId line column
+ */
+static int
+tcl_setcursor(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ MARK cursor;
+ SCR *sp;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int i, rval;
+
+ if (argc != 4) {
+ Tcl_SetResult(interp,
+ "Usage: viSetCursor screenId line column", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL))
+ return (TCL_ERROR);
+ if (getint(interp, "screen id", argv[2], &i))
+ return (TCL_ERROR);
+ cursor.lno = i;
+ if (getint(interp, "screen id", argv[3], &i))
+ return (TCL_ERROR);
+ cursor.cno = i;
+ INITMESSAGE;
+ rval = api_setcursor(sp, &cursor);
+ ENDMESSAGE;
+
+ return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_msg --
+ * Set the message line to text.
+ *
+ * Tcl Command: viMsg
+ * Usage: viMsg screenId text
+ */
+static int
+tcl_msg(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ SCR *sp;
+
+ if (argc != 3) {
+ Tcl_SetResult(interp, "Usage: viMsg screenId text", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL))
+ return (TCL_ERROR);
+ api_imessage(sp, argv[2]);
+
+ return (TCL_OK);
+}
+
+/*
+ * tcl_iscreen --
+ * Create a new screen. If a filename is specified then the screen
+ * is opened with that file.
+ *
+ * Tcl Command: viNewScreen
+ * Usage: viNewScreen screenId [file]
+ */
+static int
+tcl_iscreen(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ SCR *sp, *nsp;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ if (argc != 2 && argc != 3) {
+ Tcl_SetResult(interp,
+ "Usage: viNewScreen screenId [file]", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL))
+ return (TCL_ERROR);
+ INITMESSAGE;
+ rval = api_edit(sp, argv[2], &nsp, 1);
+ ENDMESSAGE;
+
+ if (rval)
+ return (TCL_ERROR);
+
+ (void)sprintf(interp->result, "%d", nsp->id);
+ return (TCL_OK);
+}
+
+/*
+ * tcl_escreen --
+ * End a screen.
+ *
+ * Tcl Command: viEndScreen
+ * Usage: viEndScreen screenId
+ */
+static int
+tcl_escreen(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ SCR *sp;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ if (argc != 2) {
+ Tcl_SetResult(interp,
+ "Usage: viEndScreen screenId", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL))
+ return (TCL_ERROR);
+ INITMESSAGE;
+ rval = api_escreen(sp);
+ ENDMESSAGE;
+
+ return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_swscreen --
+ * Change the current focus to screen.
+ *
+ * Tcl Command: viSwitchScreen
+ * Usage: viSwitchScreen screenId screenId
+ */
+static int
+tcl_swscreen(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ SCR *sp, *new;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ if (argc != 3) {
+ Tcl_SetResult(interp,
+ "Usage: viSwitchScreen cur_screenId new_screenId",
+ TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL))
+ return (TCL_ERROR);
+ if (getscreenid(interp, &new, argv[2], NULL))
+ return (TCL_ERROR);
+ INITMESSAGE;
+ rval = api_swscreen(sp, new);
+ ENDMESSAGE;
+
+ return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_map --
+ * Associate a key with a tcl procedure.
+ *
+ * Tcl Command: viMapKey
+ * Usage: viMapKey screenId key tclproc
+ */
+static int
+tcl_map(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ SCR *sp;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+ char command[256];
+
+ if (argc != 4) {
+ Tcl_SetResult(interp,
+ "Usage: viMapKey screenId key tclproc", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL))
+ return (TCL_ERROR);
+ INITMESSAGE;
+ (void)snprintf(command, sizeof(command), ":tcl %s\n", argv[3]);
+ rval = api_map(sp, argv[2], command, strlen(command));
+ ENDMESSAGE;
+
+ return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_unmap --
+ * Unmap a key.
+ *
+ * Tcl Command: viUnmapKey
+ * Usage: viUnmMapKey screenId key
+ */
+static int
+tcl_unmap(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ SCR *sp;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+
+ if (argc != 3) {
+ Tcl_SetResult(interp,
+ "Usage: viUnmapKey screenId key", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL))
+ return (TCL_ERROR);
+ INITMESSAGE;
+ rval = api_unmap(sp, argv[2]);
+ ENDMESSAGE;
+
+ return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_opts_set --
+ * Set an option.
+ *
+ * Tcl Command: viSetOpt
+ * Usage: viSetOpt screenId command
+ */
+static int
+tcl_opts_set(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ SCR *sp;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+ char *setting;
+
+ if (argc != 3) {
+ Tcl_SetResult(interp,
+ "Usage: viSetOpt screenId command", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL))
+ return (TCL_ERROR);
+ INITMESSAGE;
+ /*rval = api_opts_set(sp, argv[2]);*/
+ MALLOC(sp, setting, char *, strlen(argv[2])+6);
+ strcpy(setting, ":set ");
+ strcpy(setting+5, argv[2]);
+ rval=api_run_str(sp, setting);
+ free(setting);
+ ENDMESSAGE;
+
+ return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tcl_opts_get --
+ Return the value of an option.
+ *
+ * Tcl Command: viGetOpt
+ * Usage: viGetOpt screenId option
+ */
+static int
+tcl_opts_get(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char **argv;
+{
+ SCR *sp;
+ void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
+ int rval;
+ char *value;
+
+ if (argc != 3) {
+ Tcl_SetResult(interp,
+ "Usage: viGetOpt screenId option", TCL_STATIC);
+ return (TCL_ERROR);
+ }
+
+ if (getscreenid(interp, &sp, argv[1], NULL))
+ return (TCL_ERROR);
+ INITMESSAGE;
+ rval = api_opts_get(sp, argv[2], &value, NULL);
+ ENDMESSAGE;
+ if (rval)
+ return (TCL_ERROR);
+
+ Tcl_SetResult(interp, value, TCL_DYNAMIC);
+ return (TCL_OK);
+}
+
+/*
+ * tcl_init --
+ * Create the TCL commands used by nvi.
+ *
+ * PUBLIC: int tcl_init __P((GS *));
+ */
+int
+tcl_init(gp)
+ GS *gp;
+{
+ gp->tcl_interp = Tcl_CreateInterp();
+ if (Tcl_Init(gp->tcl_interp) == TCL_ERROR)
+ return (1);
+
+#define TCC(name, function) { \
+ Tcl_CreateCommand(gp->tcl_interp, name, function, \
+ (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); \
+}
+ TCC("viAppendLine", tcl_aline);
+ TCC("viDelLine", tcl_dline);
+ TCC("viEndScreen", tcl_escreen);
+ TCC("viFindScreen", tcl_fscreen);
+ TCC("viGetCursor", tcl_getcursor);
+ TCC("viGetLine", tcl_gline);
+ TCC("viGetMark", tcl_getmark);
+ TCC("viGetOpt", tcl_opts_get);
+ TCC("viInsertLine", tcl_iline);
+ TCC("viLastLine", tcl_lline);
+ TCC("viMapKey", tcl_map);
+ TCC("viMsg", tcl_msg);
+ TCC("viNewScreen", tcl_iscreen);
+ TCC("viSetCursor", tcl_setcursor);
+ TCC("viSetLine", tcl_sline);
+ TCC("viSetMark", tcl_setmark);
+ TCC("viSetOpt", tcl_opts_set);
+ TCC("viSwitchScreen", tcl_swscreen);
+ TCC("viUnmapKey", tcl_unmap);
+
+ return (0);
+}
+
+/*
+ * getscreenid --
+ * Get the specified screen pointer.
+ *
+ * XXX
+ * This is fatal. We can't post a message into vi that we're unable to find
+ * the screen without first finding the screen... So, this must be the first
+ * thing a Tcl routine does, and, if it fails, the last as well.
+ */
+static int
+getscreenid(interp, spp, id, name)
+ Tcl_Interp *interp;
+ SCR **spp;
+ char *id, *name;
+{
+ int scr_no;
+ char buf[64];
+
+ if (id != NULL && getint(interp, "screen id", id, &scr_no))
+ return (1);
+ if ((*spp = api_fscreen(scr_no, name)) == NULL) {
+ (void)snprintf(buf, sizeof(buf),
+ "unknown screen id: %s", name == NULL ? id : name);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * getint --
+ * Get a Tcl integer.
+ *
+ * XXX
+ * This code assumes that both recno_t and size_t are larger than ints.
+ */
+static int
+getint(interp, msg, s, intp)
+ Tcl_Interp *interp;
+ char *msg, *s;
+ int *intp;
+{
+ char buf[64];
+
+ if (Tcl_GetInt(interp, s, intp) == TCL_ERROR)
+ return (1);
+ if (*intp < 0) {
+ (void)snprintf(buf, sizeof(buf),
+ "illegal %s %s: may not be negative", msg, s);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * msghandler --
+ * Tcl message routine so that error messages are processed in
+ * Tcl, not in nvi.
+ */
+static void
+msghandler(sp, mtype, msg, len)
+ SCR *sp;
+ mtype_t mtype;
+ char *msg;
+ size_t len;
+{
+ /* Replace the trailing <newline> with an EOS. */
+ msg[len - 1] = '\0';
+
+ Tcl_SetResult(sp->gp->tcl_interp, msg, TCL_VOLATILE);
+}
diff --git a/contrib/nvi/tcl_scripts/errors.tcl b/contrib/nvi/tcl_scripts/errors.tcl
new file mode 100644
index 000000000000..94a1e6a8c3c9
--- /dev/null
+++ b/contrib/nvi/tcl_scripts/errors.tcl
@@ -0,0 +1,44 @@
+# @(#)errors.tcl 8.2 (Berkeley) 11/18/95
+#
+# File: errors.tcl
+#
+# Author: George V. Neville-Neil
+#
+# Purpose: This file contains vi/tcl code that allows a vi user to parse
+# compiler errors and warnings from a make.out file.
+
+proc findErr {} {
+ global errScreen
+ global currFile
+ global fileScreen
+ set errLine [lindex [viGetCursor $errScreen] 0]
+ set currLine [split [viGetLine $errScreen $errLine] :]
+ set currFile [lindex $currLine 0]
+ set fileScreen [viNewScreen $errScreen $currFile]
+ viSetCursor $fileScreen [lindex $currLine 1] 1
+ viMapKey $viScreenId  nextErr
+}
+
+proc nextErr {} {
+ global errScreen
+ global fileScreen
+ global currFile
+ set errLine [lindex [viGetCursor $errScreen] 0]
+ set currLine [split [viGetLine $errScreen $errLine] :]
+ if {[string match $currFile [lindex $currLine 0]]} {
+ viSetCursor $fileScreen [lindex $currLine 1] 0
+ viSwitchScreen $fileScreen
+ } else {
+ viEndScreen $fileScreen
+ set currFile [lindex $currLine 0]
+ set fileScreen[viNewScreen $errScreen $currFile]
+ viSetCursor $fileScreen [lindex $currLine 1] 0
+ }
+}
+
+proc initErr {} {
+ global viScreenId
+ global errScreen
+ set errScreen [viNewScreen $viScreenId make.out]
+ viMapKey $viScreenId  findErr
+}
diff --git a/contrib/nvi/tcl_scripts/gnats.tcl b/contrib/nvi/tcl_scripts/gnats.tcl
new file mode 100644
index 000000000000..61ecb6e2cda0
--- /dev/null
+++ b/contrib/nvi/tcl_scripts/gnats.tcl
@@ -0,0 +1,95 @@
+# @(#)gnats.tcl 8.2 (Berkeley) 11/18/95
+#
+proc init {catFile} {
+ global viScreenId
+ global categories
+ set categories {}
+ set categoriesFile [open $catFile r]
+ while {[gets $categoriesFile line] >= 0} {
+ lappend categories $line
+ }
+ close $categoriesFile
+ viMsg $viScreenId $categories
+ viMapKey $viScreenId  next
+}
+
+proc next {} {
+ global viScreenId
+ set cursor [viGetCursor $viScreenId]
+ set lineNum [lindex $cursor 0]
+ set line [viGetLine $viScreenId $lineNum]
+ viMsg $viScreenId [lindex $line 0]
+ if {[lindex $line 0] == ">Confidential:"} {
+ confNext $lineNum $line
+ } elseif {[lindex $line 0] == ">Severity:"} {
+ sevNext $lineNum $line
+ } elseif {[lindex $line 0] == ">Priority:"} {
+ priNext $lineNum $line
+ } elseif {[lindex $line 0] == ">Class:"} {
+ classNext $lineNum $line
+ } elseif {[lindex $line 0] == ">Category:"} {
+ catNext $lineNum $line
+ }
+}
+
+proc confNext {lineNum line} {
+ global viScreenId
+ viMsg $viScreenId [lindex $line 1]
+ if {[lindex $line 1] == "yes"} {
+ viSetLine $viScreenId $lineNum ">Confidential: no"
+ } else {
+ viSetLine $viScreenId $lineNum ">Confidential: yes"
+ }
+}
+
+proc sevNext {lineNum line} {
+ global viScreenId
+ viMsg $viScreenId [lindex $line 1]
+ if {[lindex $line 1] == "non-critical"} {
+ viSetLine $viScreenId $lineNum ">Severity: serious"
+ } elseif {[lindex $line 1] == "serious"} {
+ viSetLine $viScreenId $lineNum ">Severity: critical"
+ } elseif {[lindex $line 1] == "critical"} {
+ viSetLine $viScreenId $lineNum ">Severity: non-critical"
+ }
+}
+
+proc priNext {lineNum line} {
+ global viScreenId
+ viMsg $viScreenId [lindex $line 1]
+ if {[lindex $line 1] == "low"} {
+ viSetLine $viScreenId $lineNum ">Priority: medium"
+ } elseif {[lindex $line 1] == "medium"} {
+ viSetLine $viScreenId $lineNum ">Priority: high"
+ } elseif {[lindex $line 1] == "high"} {
+ viSetLine $viScreenId $lineNum ">Priority: low"
+ }
+}
+
+proc classNext {lineNum line} {
+ global viScreenId
+ viMsg $viScreenId [lindex $line 1]
+ if {[lindex $line 1] == "sw-bug"} {
+ viSetLine $viScreenId $lineNum ">Class: doc-bug"
+ } elseif {[lindex $line 1] == "doc-bug"} {
+ viSetLine $viScreenId $lineNum ">Class: change-request"
+ } elseif {[lindex $line 1] == "change-request"} {
+ viSetLine $viScreenId $lineNum ">Class: support"
+ } elseif {[lindex $line 1] == "support"} {
+ viSetLine $viScreenId $lineNum ">Class: sw-bug"
+ }
+}
+
+proc catNext {lineNum line} {
+ global viScreenId
+ global categories
+ viMsg $viScreenId [lindex $line 1]
+ set curr [lsearch -exact $categories [lindex $line 1]]
+ if {$curr == -1} {
+ set curr 0
+ }
+ viMsg $viScreenId $curr
+ viSetLine $viScreenId $lineNum ">Class: [lindex $categories $curr]"
+}
+
+init abekas
diff --git a/contrib/nvi/tcl_scripts/mailprocs.tcl b/contrib/nvi/tcl_scripts/mailprocs.tcl
new file mode 100644
index 000000000000..eccb9cdfcf74
--- /dev/null
+++ b/contrib/nvi/tcl_scripts/mailprocs.tcl
@@ -0,0 +1,115 @@
+# @(#)mailprocs.tcl 8.3 (Berkeley) 4/29/96
+#
+proc validLine {} {
+ global viScreenId
+ set line [viGetLine $viScreenId [lindex [viGetCursor $viScreenId] 0]]
+ if {[string compare [lindex [split $line :] 0] "To"] == 0} {
+ set addrs [lindex [split $line :] 1]
+ foreach name [split $addrs ,] {
+ isValid [string trim $name]
+ }
+ }
+}
+
+proc valid {target} {
+ set found 0
+ set aliasFile [open "~/Mail/aliases" r]
+ while {[gets $aliasFile line] >= 0} {
+ set name [lindex [split $line :] 0]
+ set address [lindex [split $line :] 1]
+ if {[string compare $target $name] == 0} {
+ set found 1
+ break
+ }
+ }
+ close $aliasFile
+ if {$found == 1} {
+ return $address
+ } else {
+ return $found
+ }
+}
+
+proc isValid {target} {
+ global viScreenId
+ set address [valid $target]
+ if {$address != 0} {
+ viMsg $viScreenId "$target is [string trim $address]"
+ } else {
+ viMsg $viScreenId "$target not found"
+ }
+}
+
+proc isAliasedLine {} {
+ global viScreenId
+ set line [viGetLine $viScreenId [lindex [viGetCursor $viScreenId] 0]]
+ if {[string match [lindex [split $line :] 0] "*To"] == 0} {
+ set addrs [lindex [split $line :] 1]
+ foreach name [split $addrs ,] {
+ isAliased [string trim $name]
+ }
+ }
+}
+
+proc aliased {target} {
+ set found 0
+ set aliasFile [open "~/Mail/aliases" r]
+ while {[gets $aliasFile line] >= 0} {
+ set name [lindex [split $line :] 0]
+ set address [lindex [split $line :] 1]
+ if {[string compare $target [string trim $address]] == 0} {
+ set found 1
+ break
+ }
+ }
+ close $aliasFile
+
+ return $found
+}
+
+proc isAliased {target} {
+ global viScreenId
+ set found [aliased $target]
+
+ if {$found} {
+ viMsg $viScreenId "$target is aliased to [string trim $name]"
+ } else {
+ viMsg $viScreenId "$target not aliased"
+ }
+}
+
+proc appendAlias {target address} {
+ if {![aliased $target]} {
+ set aliasFile [open "~/Mail/aliases" a]
+ puts $aliasFile "$target: $address"
+ }
+ close $aliasFile
+}
+
+proc expand {} {
+ global viScreenId
+ set row [lindex [viGetCursor $viScreenId] 0]]
+ set column [lindex [viGetCursor $viScreenId] 1]]
+ set line [viGetLine $viScreenId $row]
+ while {$column < [string length $line] && \
+ [string index $line $column] != ' '} {
+ append $target [string index $line $column]
+ incr $column
+ }
+ set found [isValid $target]
+}
+
+proc cite {} {
+ global viScreenId
+ global viStartLine
+ global viStopLine
+ for {set i $viStartLine} {$i <= $viStopLine} {incr i} {
+ set newLine "> "
+ append newLine [viGetLine $viScreenId $i]
+ viSetLine $viScreenId $i $newLine
+ }
+}
+
+global viScreenId
+viMapKey $viScreenId  isAliasedLine
+viMapKey $viScreenId  validLine
diff --git a/contrib/nvi/tcl_scripts/wc.tcl b/contrib/nvi/tcl_scripts/wc.tcl
new file mode 100644
index 000000000000..25d0f6254391
--- /dev/null
+++ b/contrib/nvi/tcl_scripts/wc.tcl
@@ -0,0 +1,16 @@
+# @(#)wc.tcl 8.2 (Berkeley) 11/18/95
+#
+proc wc {} {
+ global viScreenId
+ global viStartLine
+ global viStopLine
+
+ set lines [viLastLine $viScreenId]
+ set output ""
+ set words 0
+ for {set i $viStartLine} {$i <= $viStopLine} {incr i} {
+ set outLine [split [string trim [viGetLine $viScreenId $i]]]
+ set words [expr $words + [llength $outLine]]
+ }
+ viMsg $viScreenId "$words words"
+}
diff --git a/contrib/nvi/tk/init.tcl b/contrib/nvi/tk/init.tcl
new file mode 100644
index 000000000000..78c5a115c0a7
--- /dev/null
+++ b/contrib/nvi/tk/init.tcl
@@ -0,0 +1,1096 @@
+# @(#)init.tcl 8.10 (Berkeley) 7/19/96
+proc screen {} {
+ global tk_ssize_row
+ global tk_ssize_col
+
+ # Build menubar with File, Options and Help entries.
+ frame .menu -relief raised -borderwidth 1
+ pack append . .menu {top fillx}
+
+ # File pull-down menu
+ menubutton .menu.file -text "File" \
+ -menu .menu.file.fileops -underline 0
+ menu .menu.file.fileops
+ .menu.file.fileops add command -label "Edit ..." \
+ -command "tk_edit" -underline 0
+ .menu.file.fileops add command -label "Save File" \
+ -command "tk_write" -underline 0
+ .menu.file.fileops add command -label "Save File as ..." \
+ -command "tk_writeas" -underline 1
+ .menu.file.fileops add command -label "Save and Quit" \
+ -command "tk_writequit" -underline 7
+ .menu.file.fileops add command -label "Quit" \
+ -command "tk_quit" -underline 0
+
+ # Options pull-down menu
+ menubutton .menu.option -text "Options" \
+ -menu .menu.option.optionops -underline 0
+ menu .menu.option.optionops
+ .menu.option.optionops add command -label "Set all" \
+ -command tk_options -underline 0
+
+ # Help pull-down menu
+ menubutton .menu.help -text "Help" \
+ -menu .menu.help.helpops -underline 0
+ menu .menu.help.helpops
+ .menu.help.helpops add command -label "On Help" -underline 3 \
+ -command tk_help
+ .menu.help.helpops add command -label "On Version" -underline 3 \
+ -command tk_version
+
+ pack append .menu \
+ .menu.file {left} .menu.option {left} .menu.help {right}
+
+ # Set up for keyboard-based menu traversal
+ tk_bindForTraversal .
+ bind . <Any-Enter> {focus .}
+ focus .
+ tk_menuBar .menu .menu.file .menu.help
+
+ # Create text window
+ text .t -relief raised -bd 1 -setgrid true -yscrollcommand ".s set"
+ scrollbar .s -relief flat -command ".t yview"
+ pack append . .s {right filly} .t {expand fill}
+
+ # Use tags to build a cursor for the text window.
+ set bg [lindex [.t config -background] 4]
+ set fg [lindex [.t config -foreground] 4]
+ .t tag configure tk_cursor -background $fg -foreground $bg
+ .t mark set tk_cursor_indx insert
+ .t tag add tk_cursor tk_cursor_indx
+
+ # Bind the keys.
+ bind .t <Any-KeyPress> {tk_flash; break}
+ bind .t 0 {tk_key_enter "0"; break}
+ bind .t 1 {tk_key_enter "1"; break}
+ bind .t 2 {tk_key_enter "2"; break}
+ bind .t 3 {tk_key_enter "3"; break}
+ bind .t 4 {tk_key_enter "4"; break}
+ bind .t 5 {tk_key_enter "5"; break}
+ bind .t 6 {tk_key_enter "6"; break}
+ bind .t 7 {tk_key_enter "7"; break}
+ bind .t 8 {tk_key_enter "8"; break}
+ bind .t 9 {tk_key_enter "9"; break}
+ bind .t <BackSpace> {tk_key_enter "\010"; break}
+ bind .t <Control-a> {tk_key_enter "\001"; break}
+ bind .t <Control-b> {tk_key_enter "\002"; break}
+ bind .t <Control-c> {tk_key_enter "\003"; break}
+ bind .t <Control-d> {tk_key_enter "\004"; break}
+ bind .t <Control-e> {tk_key_enter "\005"; break}
+ bind .t <Control-f> {tk_key_enter "\006"; break}
+ bind .t <Control-g> {tk_key_enter "\007"; break}
+ bind .t <Control-h> {tk_key_enter "\010"; break}
+ bind .t <Control-i> {tk_key_enter "\011"; break}
+ bind .t <Control-j> {tk_key_enter "\012"; break}
+ bind .t <Control-k> {tk_key_enter "\013"; break}
+ bind .t <Control-l> {tk_key_enter "\014"; break}
+ bind .t <Control-m> {tk_key_enter "\015"; break}
+ bind .t <Control-n> {tk_key_enter "\016"; break}
+ bind .t <Control-o> {tk_key_enter "\017"; break}
+ bind .t <Control-p> {tk_key_enter "\020"; break}
+ bind .t <Control-q> {tk_key_enter "\021"; break}
+ bind .t <Control-r> {tk_key_enter "\022"; break}
+ bind .t <Control-s> {tk_key_enter "\023"; break}
+ bind .t <Control-t> {tk_key_enter "\024"; break}
+ bind .t <Control-u> {tk_key_enter "\025"; break}
+ bind .t <Control-v> {tk_key_enter "\026"; break}
+ bind .t <Control-w> {tk_key_enter "\027"; break}
+ bind .t <Control-x> {tk_key_enter "\030"; break}
+ bind .t <Control-y> {tk_key_enter "\031"; break}
+ bind .t <Control-z> {tk_key_enter "\032"; break}
+ bind .t <Control_L> {tk_noop; break}
+ bind .t <Control_R> {tk_noop; break}
+ bind .t <Delete> {tk_key_enter "x"; break}
+ bind .t <Down> {tk_key_enter "j"; break}
+ bind .t <End> {tk_key_enter "G"; break}
+ bind .t <Escape> {tk_key_enter "\033"; break}
+ bind .t <Home> {tk_key_enter "1G"; break}
+ bind .t <Insert> {tk_key_enter "i"; break}
+ bind .t <Left> {tk_key_enter "h"; break}
+ bind .t <Next> {tk_key_enter "\006"; break}
+ bind .t <Prior> {tk_key_enter "\002"; break}
+ bind .t <Return> {tk_key_enter "\015"; break}
+ bind .t <Right> {tk_key_enter "l"; break}
+ bind .t <Shift_L> {tk_noop; break}
+ bind .t <Shift_Lock> {tk_noop; break}
+ bind .t <Shift_R> {tk_noop; break}
+ bind .t <Tab> {tk_key_enter "\011"; break}
+ bind .t <Up> {tk_key_enter "k"; break}
+ bind .t <ampersand> {tk_key_enter "&"; break}
+ bind .t <asciicircum> {tk_key_enter "^"; break}
+ bind .t <asciitilde> {tk_key_enter "~"; break}
+ bind .t <asterisk> {tk_key_enter "*"; break}
+ bind .t <at> {tk_key_enter "@"; break}
+ bind .t <backslash> {tk_key_enter "\\"; break}
+ bind .t <bar> {tk_key_enter "|"; break}
+ bind .t <braceleft> {tk_key_enter "{"; break}
+ bind .t <braceright> {tk_key_enter "; break}"}
+ bind .t <bracketleft> {tk_key_enter "\["; break}
+ bind .t <bracketright> {tk_key_enter "]"; break}
+ bind .t <colon> {tk_key_enter ":"; break}
+ bind .t <comma> {tk_key_enter ","; break}
+ bind .t <dollar> {tk_key_enter "$"; break}
+ bind .t <equal> {tk_key_enter "="; break}
+ bind .t <exclam> {tk_key_enter "!"; break}
+ bind .t <greater> {tk_key_enter ">"; break}
+ bind .t <less> {tk_key_enter "<"; break}
+ bind .t <minus> {tk_key_enter "-"; break}
+ bind .t <numbersign> {tk_key_enter "#"; break}
+ bind .t <parenleft> {tk_key_enter "("; break}
+ bind .t <parenright> {tk_key_enter ")"; break}
+ bind .t <percent> {tk_key_enter "%"; break}
+ bind .t <period> {tk_key_enter "."; break}
+ bind .t <plus> {tk_key_enter "+"; break}
+ bind .t <question> {tk_key_enter "?"; break}
+ bind .t <quotedbl> {tk_key_enter "\""; break}
+ bind .t <quoteright> {tk_key_enter "'"; break}
+ bind .t <semicolon> {tk_key_enter ";"; break}
+ bind .t <slash> {tk_key_enter "/"; break}
+ bind .t <space> {tk_key_enter " "; break}
+ bind .t <underscore> {tk_key_enter "_"; break}
+ bind .t A {tk_key_enter "A"; break}
+ bind .t B {tk_key_enter "B"; break}
+ bind .t C {tk_key_enter "C"; break}
+ bind .t D {tk_key_enter "D"; break}
+ bind .t E {tk_key_enter "E"; break}
+ bind .t F {tk_key_enter "F"; break}
+ bind .t G {tk_key_enter "G"; break}
+ bind .t H {tk_key_enter "H"; break}
+ bind .t I {tk_key_enter "I"; break}
+ bind .t J {tk_key_enter "J"; break}
+ bind .t K {tk_key_enter "K"; break}
+ bind .t L {tk_key_enter "L"; break}
+ bind .t M {tk_key_enter "M"; break}
+ bind .t N {tk_key_enter "N"; break}
+ bind .t O {tk_key_enter "O"; break}
+ bind .t P {tk_key_enter "P"; break}
+ bind .t Q {tk_key_enter "Q"; break}
+ bind .t R {tk_key_enter "R"; break}
+ bind .t S {tk_key_enter "S"; break}
+ bind .t T {tk_key_enter "T"; break}
+ bind .t U {tk_key_enter "U"; break}
+ bind .t V {tk_key_enter "V"; break}
+ bind .t W {tk_key_enter "W"; break}
+ bind .t X {tk_key_enter "X"; break}
+ bind .t Y {tk_key_enter "Y"; break}
+ bind .t Z {tk_key_enter "Z"; break}
+ bind .t a {tk_key_enter "a"; break}
+ bind .t b {tk_key_enter "b"; break}
+ bind .t c {tk_key_enter "c"; break}
+ bind .t d {tk_key_enter "d"; break}
+ bind .t e {tk_key_enter "e"; break}
+ bind .t f {tk_key_enter "f"; break}
+ bind .t g {tk_key_enter "g"; break}
+ bind .t h {tk_key_enter "h"; break}
+ bind .t i {tk_key_enter "i"; break}
+ bind .t j {tk_key_enter "j"; break}
+ bind .t k {tk_key_enter "k"; break}
+ bind .t l {tk_key_enter "l"; break}
+ bind .t m {tk_key_enter "m"; break}
+ bind .t n {tk_key_enter "n"; break}
+ bind .t o {tk_key_enter "o"; break}
+ bind .t p {tk_key_enter "p"; break}
+ bind .t q {tk_key_enter "q"; break}
+ bind .t r {tk_key_enter "r"; break}
+ bind .t s {tk_key_enter "s"; break}
+ bind .t t {tk_key_enter "t"; break}
+ bind .t u {tk_key_enter "u"; break}
+ bind .t v {tk_key_enter "v"; break}
+ bind .t w {tk_key_enter "w"; break}
+ bind .t x {tk_key_enter "x"; break}
+ bind .t y {tk_key_enter "y"; break}
+ bind .t z {tk_key_enter "z"; break}
+
+ # XXX
+ # I haven't been able to make Tcl/Tk write uninitialized portions
+ # of the text window. Fill in the screen.
+ tk_ssize
+ .t mark set insert 1.0
+ for {set i 1} {$i <= $tk_ssize_row} {incr i} {
+ for {set j 1} {$j <= $tk_ssize_col} {incr j} {
+ .t insert insert " "
+ }
+ .t insert insert "\n"
+ }
+}
+
+# tk_noop --
+# Do nothing.
+#
+# XXX
+# I can't figure out how to get a binding that does nothing without
+# calling a function, so this stub does it for me.
+proc tk_noop {} {
+}
+
+# tk_key_enter --
+# Enter a key.
+proc tk_key_enter {val} {
+ global newkey
+ global waiting
+
+ set waiting 0
+ tk_key $val
+ set newkey 1
+}
+
+# tk_key_wait --
+# Wait for a key.
+proc tk_key_wait {timeout} {
+ global newkey
+ global waiting
+
+ if { $timeout != 0 } {
+ after $timeout "set newkey 1"
+ }
+ set waiting 1
+ tkwait variable newkey
+}
+
+# Callback functions for the File menu.
+# tk_edit
+# Edit another file.
+proc tk_edit {} {
+}
+
+# tk_quit
+# Quit.
+proc tk_quit {} {
+ global newkey
+ global waiting
+
+ tk_op quit
+ if { $waiting != 0 } {
+ set newkey 1
+ }
+}
+
+# tk_write
+# Write the edit buffer.
+proc tk_write {} {
+ global newkey
+ global waiting
+
+ tk_op write
+ if { $waiting != 0 } {
+ set newkey 1
+ }
+}
+
+# tk_writeas
+# Write the edit buffer to a named file.
+proc tk_writeas {} {
+}
+
+# tk_writequit
+# Write and quit.
+proc tk_writequit {} {
+ global newkey
+ global waiting
+
+ tk_op writequit
+ if { $waiting != 0 } {
+ set newkey 1
+ }
+}
+
+# Callback functions for the Help menu.
+#
+# tk_help --
+# Present a help screen.
+proc tk_help {} {
+ tk_dialog .d {} "No help screen currently available." {} 0 Continue
+}
+
+# tk_options
+# Contains the option selector box. It is divided into three parts, the
+# checkbuttons for the boolean options, the entry fields for the string
+# numeric options, and a control area containing buttons. There is only
+# one function.
+proc tk_options {} {
+
+ # Build option selector box with three subframes for boolean,
+ # numeric, and string options. Make it a toplevel window.
+ toplevel .os
+ wm title .os options
+
+ # Option variables.
+ global tko_altwerase
+ global tko_autoindent
+ global tko_autoprint
+ global tko_autowrite
+ global tko_backup
+ global tko_beautify
+ global tko_cdpath
+ global tko_cedit
+ global tko_columns
+ global tko_comment
+ global tko_directory
+ global tko_edcompatible
+ global tko_escapetime
+ global tko_errorbells
+ global tko_exrc
+ global tko_extended
+ global tko_filec
+ global tko_flash
+ global tko_hardtabs
+ global tko_iclower
+ global tko_ignorecase
+ global tko_keytime
+ global tko_leftright
+ global tko_lines
+ global tko_lisp
+ global tko_list
+ global tko_lock
+ global tko_magic
+ global tko_matchtime
+ global tko_mesg
+ global tko_modeline
+ global tko_msgcat
+ global tko_noprint
+ global tko_number
+ global tko_octal
+ global tko_open
+ global tko_optimize
+ global tko_paragraphs
+ global tko_print
+ global tko_prompt
+ global tko_readonly
+ global tko_recdir
+ global tko_redraw
+ global tko_remap
+ global tko_report
+ global tko_ruler
+ global tko_scroll
+ global tko_searchincr
+ global tko_sections
+ global tko_secure
+ global tko_shell
+ global tko_shellmeta
+ global tko_shiftwidth
+ global tko_showmatch
+ global tko_showmode
+ global tko_sidescroll
+ global tko_slowopen
+ global tko_sourceany
+ global tko_tabstop
+ global tko_taglength
+ global tko_tags
+ global tko_term
+ global tko_terse
+ global tko_tildeop
+ global tko_timeout
+ global tko_ttywerase
+ global tko_verbose
+ global tko_warn
+ global tko_window
+ global tko_windowname
+ global tko_wraplen
+ global tko_wrapmargin
+ global tko_wrapscan
+ global tko_writeany
+
+ # Initialize option values.
+ tk_opt_init
+
+ # Build subframe for boolean options.
+ frame .os.bopts
+
+ # This is the width of the edcompatible button.
+ set buttonwidth 13
+
+ # Pack the boolean os, 5 to a frame.
+ frame .os.bopts.f1
+ pack append .os.bopts .os.bopts.f1 {top}
+ checkbutton .os.bopts.f1.b1 \
+ -variable tko_altwerase -text "altwerase" \
+ -command "tk_opt_set altwerase $tko_altwerase" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f1.b2 \
+ -variable tko_autoindent -text "autoindent" \
+ -command "tk_opt_set autoindent $tko_autoindent" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f1.b3 \
+ -variable tko_autoprint -text "autoprint" \
+ -command "tk_opt_set autoprint $tko_autoprint" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f1.b4 \
+ -variable tko_autowrite -text "autowrite" \
+ -command "tk_opt_set autowrite $tko_autowrite" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f1.b5 \
+ -variable tko_beautify -text "beautify" \
+ -command "tk_opt_set beautify $tko_beautify" \
+ -width $buttonwidth -anchor w
+ pack append .os.bopts.f1 \
+ .os.bopts.f1.b1 {left frame w} \
+ .os.bopts.f1.b2 {left frame w} \
+ .os.bopts.f1.b3 {left frame w} \
+ .os.bopts.f1.b4 {left frame w} \
+ .os.bopts.f1.b5 {left frame w}
+
+ frame .os.bopts.f2
+ pack append .os.bopts .os.bopts.f2 {top}
+ checkbutton .os.bopts.f2.b1 \
+ -variable tko_comment -text "comment" \
+ -command "tk_opt_set comment $tko_comment" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f2.b2 \
+ -variable tko_edcompatible -text "edcompatible" \
+ -command "tk_opt_set edcompatible $tko_edcompatible" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f2.b3 \
+ -variable tko_errorbells -text "errorbells" \
+ -command "tk_opt_set errorbells $tko_errorbells" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f2.b4 \
+ -variable tko_exrc -text "exrc" \
+ -command "tk_opt_set exrc $tko_exrc" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f2.b5 \
+ -variable tko_extended -text "extended" \
+ -command "tk_opt_set extended $tko_extended" \
+ -width $buttonwidth -anchor w
+ pack append .os.bopts.f2 \
+ .os.bopts.f2.b1 {left frame w} \
+ .os.bopts.f2.b2 {left frame w} \
+ .os.bopts.f2.b3 {left frame w} \
+ .os.bopts.f2.b4 {left frame w} \
+ .os.bopts.f2.b5 {left frame w}
+
+ frame .os.bopts.f3
+ pack append .os.bopts .os.bopts.f3 {top}
+ checkbutton .os.bopts.f3.b1 \
+ -variable tko_flash -text "flash" \
+ -command "tk_opt_set flash $tko_flash" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f3.b2 \
+ -variable tko_iclower -text "iclower" \
+ -command "tk_opt_set iclower $tko_iclower" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f3.b3 \
+ -variable tko_ignorecase -text "ignorecase" \
+ -command "tk_opt_set ignorecase $tko_ignorecase" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f3.b4 \
+ -variable tko_leftright -text "leftright" \
+ -command "tk_opt_set leftright $tko_leftright" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f3.b5 \
+ -variable tko_lisp -text "lisp" \
+ -command "tk_opt_set lisp $tko_lisp" \
+ -width $buttonwidth -anchor w
+ pack append .os.bopts.f3 \
+ .os.bopts.f3.b1 {left frame w} \
+ .os.bopts.f3.b2 {left frame w} \
+ .os.bopts.f3.b3 {left frame w} \
+ .os.bopts.f3.b4 {left frame w} \
+ .os.bopts.f3.b5 {left frame w}
+
+ frame .os.bopts.f4
+ pack append .os.bopts .os.bopts.f4 {top}
+ checkbutton .os.bopts.f4.b1 \
+ -variable tko_list -text "list" \
+ -command "tk_opt_set list $tko_list" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f4.b2 \
+ -variable tko_lock -text "lock" \
+ -command "tk_opt_set lock $tko_lock" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f4.b3 \
+ -variable tko_magic -text "magic" \
+ -command "tk_opt_set magic $tko_magic" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f4.b4 \
+ -variable tko_mesg -text "mesg" \
+ -command "tk_opt_set mesg $tko_mesg" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f4.b5\
+ -variable tko_number -text "number" \
+ -command "tk_opt_set number $tko_number" \
+ -width $buttonwidth -anchor w
+ pack append .os.bopts.f4 \
+ .os.bopts.f4.b1 {left frame w} \
+ .os.bopts.f4.b2 {left frame w} \
+ .os.bopts.f4.b3 {left frame w} \
+ .os.bopts.f4.b4 {left frame w} \
+ .os.bopts.f4.b5 {left frame w}
+
+ frame .os.bopts.f5
+ pack append .os.bopts .os.bopts.f5 {top}
+ checkbutton .os.bopts.f5.b1 \
+ -variable tko_octal -text "octal" \
+ -command "tk_opt_set octal $tko_octal" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f5.b2 \
+ -variable tko_open -text "open" \
+ -command "tk_opt_set open $tko_open" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f5.b3 \
+ -variable tko_optimize -text "optimize" \
+ -command "tk_opt_set optimize $tko_optimize" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f5.b4 \
+ -variable tko_prompt -text "prompt" \
+ -command "tk_opt_set prompt $tko_prompt" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f5.b5 \
+ -variable tko_readonly -text "readonly" \
+ -command "tk_opt_set readonly $tko_readonly" \
+ -width $buttonwidth -anchor w
+ pack append .os.bopts.f5 \
+ .os.bopts.f5.b1 {left frame w} \
+ .os.bopts.f5.b2 {left frame w} \
+ .os.bopts.f5.b3 {left frame w} \
+ .os.bopts.f5.b4 {left frame w} \
+ .os.bopts.f5.b5 {left frame w}
+
+ frame .os.bopts.f6
+ pack append .os.bopts .os.bopts.f6 {top}
+ checkbutton .os.bopts.f6.b1 \
+ -variable tko_remap -text "remap" \
+ -command "tk_opt_set remap $tko_remap" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f6.b2 \
+ -variable tko_ruler -text "ruler" \
+ -command "tk_opt_set ruler $tko_ruler" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f6.b3 \
+ -variable tko_searchincr -text "searchincr" \
+ -command "tk_opt_set searchincr $tko_searchincr" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f6.b4 \
+ -variable tko_secure -text "secure" \
+ -command "tk_opt_set secure $tko_secure" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f6.b5 \
+ -variable tko_showmatch -text "showmatch" \
+ -command "tk_opt_set showmatch $tko_showmatch" \
+ -width $buttonwidth -anchor w
+ pack append .os.bopts.f6 \
+ .os.bopts.f6.b1 {left frame w} \
+ .os.bopts.f6.b2 {left frame w} \
+ .os.bopts.f6.b3 {left frame w} \
+ .os.bopts.f6.b4 {left frame w} \
+ .os.bopts.f6.b5 {left frame w}
+
+ frame .os.bopts.f7
+ pack append .os.bopts .os.bopts.f7 {top}
+ checkbutton .os.bopts.f7.b1 \
+ -variable tko_showmode -text "showmode" \
+ -command "tk_opt_set showmode $tko_showmode" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f7.b2 \
+ -variable tko_slowopen -text "slowopen" \
+ -command "tk_opt_set slowopen $tko_slowopen" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f7.b3 \
+ -variable tko_sourceany -text "sourceany" \
+ -command "tk_opt_set sourceany $tko_sourceany" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f7.b4 \
+ -variable tko_terse -text "terse" \
+ -command "tk_opt_set terse $tko_terse" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f7.b5 \
+ -variable tko_tildeop -text "tildeop" \
+ -command "tk_opt_set tildeope $tko_tildeop" \
+ -width $buttonwidth -anchor w
+ pack append .os.bopts.f7 \
+ .os.bopts.f7.b1 {left frame w} \
+ .os.bopts.f7.b2 {left frame w} \
+ .os.bopts.f7.b3 {left frame w} \
+ .os.bopts.f7.b4 {left frame w} \
+ .os.bopts.f7.b5 {left frame w}
+
+ frame .os.bopts.f8
+ pack append .os.bopts .os.bopts.f8 {top fillx}
+ checkbutton .os.bopts.f8.b1 \
+ -variable tko_timeout -text "timeout" \
+ -command "tk_opt_set timeout $tko_timeout" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f8.b2 \
+ -variable tko_ttywerase -text "ttywerase" \
+ -command "tk_opt_set ttywerase $tko_ttywerase" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f8.b3 \
+ -variable tko_verbose -text "verbose" \
+ -command "tk_opt_set verbose $tko_verbose" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f8.b4 \
+ -variable tko_warn -text "warn" \
+ -command "tk_opt_set warn $tko_warn" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f8.b5 \
+ -variable tko_windowname -text "windowname" \
+ -command "tk_opt_set windowname $tko_windowname" \
+ -width $buttonwidth -anchor w
+ pack append .os.bopts.f8 \
+ .os.bopts.f8.b1 {left frame w} \
+ .os.bopts.f8.b2 {left frame w} \
+ .os.bopts.f8.b3 {left frame w} \
+ .os.bopts.f8.b4 {left frame w} \
+ .os.bopts.f8.b5 {left frame w}
+
+ frame .os.bopts.f9
+ pack append .os.bopts .os.bopts.f9 {top fillx}
+ checkbutton .os.bopts.f9.b1 \
+ -variable tko_wrapscan -text "wrapscan" \
+ -command "tk_opt_set wrapscan $tko_wrapscan" \
+ -width $buttonwidth -anchor w
+ checkbutton .os.bopts.f9.b2 \
+ -variable tko_writeany -text "writeany" \
+ -command "tk_opt_set writeany $tko_writeany" \
+ -width $buttonwidth -anchor w
+ pack append .os.bopts.f9 \
+ .os.bopts.f9.b1 {left frame w} \
+ .os.bopts.f9.b2 {left frame w}
+
+ # Build frame for number options:
+ frame .os.nopts
+
+ # Label and entry widths.
+ set lwidth 12
+ set ewidth 3
+
+ frame .os.nopts.n1
+ label .os.nopts.n1.l -text "column:" -width $lwidth -anchor w
+ entry .os.nopts.n1.e -width $ewidth -relief raised \
+ -textvariable tko_columns
+ trace variable tko_columns w tk_opt_ew
+ pack append .os.nopts.n1 \
+ .os.nopts.n1.l {left} .os.nopts.n1.e {left frame w}
+
+ frame .os.nopts.n2
+ label .os.nopts.n2.l -text "escapetime:" -width $lwidth -anchor w
+ entry .os.nopts.n2.e -width $ewidth -textvariable tko_escapetime \
+ -relief raised
+ trace variable tko_escapetime w tk_opt_ew
+ pack append .os.nopts.n2 \
+ .os.nopts.n2.l {left} .os.nopts.n2.e {left frame w}
+
+ frame .os.nopts.n3
+ label .os.nopts.n3.l -text "hardtabs:" -width $lwidth -anchor w
+ entry .os.nopts.n3.e -width $ewidth -textvariable tko_hardtabs \
+ -relief raised
+ trace variable tko_hardtabs w tk_opt_ew
+ pack append .os.nopts.n3 \
+ .os.nopts.n3.l {left} .os.nopts.n3.e {left frame w}
+
+ frame .os.nopts.n4
+ label .os.nopts.n4.l -text "keytime:" -width $lwidth -anchor w
+ entry .os.nopts.n4.e -width $ewidth -textvariable tko_keytime \
+ -relief raised
+ trace variable tko_keytime w tk_opt_ew
+ pack append .os.nopts.n4 \
+ .os.nopts.n4.l {left} .os.nopts.n4.e {left frame w}
+
+ frame .os.nopts.n5
+ label .os.nopts.n5.l -text "lines:" -width $lwidth -anchor w
+ entry .os.nopts.n5.e -width $ewidth -textvariable tko_lines \
+ -relief raised
+ trace variable tko_lines w tk_opt_ew
+ pack append .os.nopts.n5 \
+ .os.nopts.n5.l {left} .os.nopts.n5.e {left frame w}
+
+ frame .os.nopts.n6
+ label .os.nopts.n6.l -text "matchtime:" -width $lwidth -anchor w
+ entry .os.nopts.n6.e -width $ewidth -textvariable tko_matchtime \
+ -relief raised
+ trace variable tko_matchtime w tk_opt_ew
+ pack append .os.nopts.n6 \
+ .os.nopts.n6.l {left} .os.nopts.n6.e {left frame w}
+
+ frame .os.nopts.n7
+ label .os.nopts.n7.l -text "report:" -width $lwidth -anchor w
+ entry .os.nopts.n7.e -width $ewidth -textvariable tko_report \
+ -relief raised
+ trace variable tko_report w tk_opt_ew
+ pack append .os.nopts.n7 \
+ .os.nopts.n7.l {left} .os.nopts.n7.e {left frame w}
+
+ frame .os.nopts.n8
+ label .os.nopts.n8.l -text "scroll:" -width $lwidth -anchor w
+ entry .os.nopts.n8.e -width $ewidth -textvariable tko_scroll \
+ -relief raised
+ trace variable tko_scroll w tk_opt_ew
+ pack append .os.nopts.n8 \
+ .os.nopts.n8.l {left} .os.nopts.n8.e {left frame w}
+
+ frame .os.nopts.n9
+ label .os.nopts.n9.l -text "shiftwidth:" -width $lwidth -anchor w
+ entry .os.nopts.n9.e -width $ewidth -textvariable tko_shiftwidth \
+ -relief raised
+ trace variable tko_shiftwidth w tk_opt_ew
+ pack append .os.nopts.n9 \
+ .os.nopts.n9.l {left} .os.nopts.n9.e {left frame w}
+
+ frame .os.nopts.n10
+ label .os.nopts.n10.l -text "sidescroll:" -width $lwidth -anchor w
+ entry .os.nopts.n10.e -width $ewidth -textvariable tko_sidescroll \
+ -relief raised
+ trace variable tko_sidescroll w tk_opt_ew
+ pack append .os.nopts.n10 \
+ .os.nopts.n10.l {left} .os.nopts.n10.e {left frame w}
+
+ frame .os.nopts.n11
+ label .os.nopts.n11.l -text "tabstop:" -width $lwidth -anchor w
+ entry .os.nopts.n11.e -width $ewidth -textvariable tko_tabstop \
+ -relief raised
+ trace variable tko_tabstop w tk_opt_ew
+ pack append .os.nopts.n11 \
+ .os.nopts.n11.l {left} .os.nopts.n11.e {left frame w}
+
+ frame .os.nopts.n12
+ label .os.nopts.n12.l -text "taglength:" -width $lwidth -anchor w
+ entry .os.nopts.n12.e -width $ewidth -textvariable tko_taglength \
+ -relief raised
+ trace variable tko_taglength w tk_opt_ew
+ pack append .os.nopts.n12 \
+ .os.nopts.n12.l {left} .os.nopts.n12.e {left frame w}
+
+ frame .os.nopts.n13
+ label .os.nopts.n13.l -text "window:" -width $lwidth -anchor w
+ entry .os.nopts.n13.e -width $ewidth -textvariable tko_window \
+ -relief raised
+ trace variable tko_window w tk_opt_ew
+ pack append .os.nopts.n13 \
+ .os.nopts.n13.l {left} .os.nopts.n13.e {left frame w}
+
+ frame .os.nopts.n14
+ label .os.nopts.n14.l -text "wraplen:" -width $lwidth -anchor w
+ entry .os.nopts.n14.e -width $ewidth -textvariable tko_wraplen \
+ -relief raised
+ trace variable tko_wraplen w tk_opt_ew
+ pack append .os.nopts.n14 \
+ .os.nopts.n14.l {left} .os.nopts.n14.e {left frame w}
+
+ frame .os.nopts.n15
+ label .os.nopts.n15.l -text "wrapmargin:" -width $lwidth -anchor w
+ entry .os.nopts.n15.e -width $ewidth -textvariable tko_wrapmargin \
+ -relief raised
+ trace variable tko_wrapmargin w tk_opt_ew
+ pack append .os.nopts.n15 \
+ .os.nopts.n15.l {left} .os.nopts.n15.e {left frame w}
+
+ pack append .os.nopts \
+ .os.nopts.n1 {top fillx} \
+ .os.nopts.n3 {top expand fillx} \
+ .os.nopts.n4 {top expand fillx} \
+ .os.nopts.n5 {top expand fillx} \
+ .os.nopts.n6 {top expand fillx} \
+ .os.nopts.n7 {top expand fillx} \
+ .os.nopts.n8 {top expand fillx} \
+ .os.nopts.n9 {top expand fillx} \
+ .os.nopts.n10 {top expand fillx} \
+ .os.nopts.n11 {top expand fillx} \
+ .os.nopts.n12 {top expand fillx} \
+ .os.nopts.n13 {top expand fillx} \
+ .os.nopts.n14 {top expand fillx} \
+ .os.nopts.n15 {top expand fillx}
+
+ # Build frame for string options
+ frame .os.sopts
+
+ # Entry width.
+ set ewidth 40
+
+ frame .os.sopts.s1
+ label .os.sopts.s1.l -text "backup:" -width $lwidth -anchor w
+ entry .os.sopts.s1.e -width $ewidth -textvariable tko_backup \
+ -relief raised
+ pack append .os.sopts.s1 \
+ .os.sopts.s1.l {left} .os.sopts.s1.e {left frame w}
+
+ frame .os.sopts.s2
+ label .os.sopts.s2.l -text "cdpath:" -width $lwidth -anchor w
+ entry .os.sopts.s2.e -width $ewidth -textvariable tko_cdpath \
+ -relief raised
+ pack append .os.sopts.s2 \
+ .os.sopts.s2.l {left} .os.sopts.s2.e {left frame w}
+
+ frame .os.sopts.s3
+ label .os.sopts.s3.l -text "directory:" -width $lwidth -anchor w
+ entry .os.sopts.s3.e -width $ewidth -textvariable tko_directory \
+ -relief raised
+ pack append .os.sopts.s3 \
+ .os.sopts.s3.l {left} .os.sopts.s3.e {left frame w}
+
+ frame .os.sopts.s4
+ label .os.sopts.s4.l -text "cedit:" -width $lwidth -anchor w
+ entry .os.sopts.s4.e -width $ewidth -textvariable tko_cedit \
+ -relief raised
+ pack append .os.sopts.s4 \
+ .os.sopts.s4.l {left} .os.sopts.s4.e {left frame w}
+
+ frame .os.sopts.s5
+ label .os.sopts.s5.l -text "filec:" -width $lwidth -anchor w
+ entry .os.sopts.s5.e -width $ewidth -textvariable tko_filec \
+ -relief raised
+ pack append .os.sopts.s5 \
+ .os.sopts.s5.l {left} .os.sopts.s5.e {left frame w}
+
+ frame .os.sopts.s6
+ label .os.sopts.s6.l -text "msgcat:" -width $lwidth -anchor w
+ entry .os.sopts.s6.e -width $ewidth -textvariable tko_msgcat \
+ -relief raised
+ pack append .os.sopts.s6 \
+ .os.sopts.s6.l {left} .os.sopts.s6.e {left frame w}
+
+ frame .os.sopts.s7
+ label .os.sopts.s7.l -text "noprint:" -width $lwidth -anchor w
+ entry .os.sopts.s7.e -width $ewidth -textvariable tko_noprint \
+ -relief raised
+ pack append .os.sopts.s7 \
+ .os.sopts.s7.l {left} .os.sopts.s7.e {left frame w}
+
+ frame .os.sopts.s8
+ label .os.sopts.s8.l -text "paragraphs:" -width $lwidth -anchor w
+ entry .os.sopts.s8.e -width $ewidth -textvariable tko_paragraphs \
+ -relief raised
+ pack append .os.sopts.s8 \
+ .os.sopts.s8.l {left} .os.sopts.s8.e {left frame w}
+
+ frame .os.sopts.s9
+ label .os.sopts.s9.l -text "print:" -width $lwidth -anchor w
+ entry .os.sopts.s9.e -width $ewidth -textvariable tko_print \
+ -relief raised
+ pack append .os.sopts.s9 \
+ .os.sopts.s9.l {left} .os.sopts.s9.e {left frame w}
+
+ frame .os.sopts.s10
+ label .os.sopts.s10.l -text "recdir:" -width $lwidth -anchor w
+ entry .os.sopts.s10.e -width $ewidth -textvariable tko_recdir \
+ -relief raised
+ pack append .os.sopts.s10 \
+ .os.sopts.s10.l {left} .os.sopts.s10.e {left frame w}
+
+ frame .os.sopts.s11
+ label .os.sopts.s11.l -text "sections:" -width $lwidth -anchor w
+ entry .os.sopts.s11.e -width $ewidth -textvariable tko_sections \
+ -relief raised
+ pack append .os.sopts.s11 \
+ .os.sopts.s11.l {left} .os.sopts.s11.e {left frame w}
+
+ frame .os.sopts.s12
+ label .os.sopts.s12.l -text "shell:" -width $lwidth -anchor w
+ entry .os.sopts.s12.e -width $ewidth -textvariable tko_shell \
+ -relief raised
+ pack append .os.sopts.s12 \
+ .os.sopts.s12.l {left} .os.sopts.s12.e {left frame w}
+
+ frame .os.sopts.s13
+ label .os.sopts.s13.l -text "shellmeta:" -width $lwidth -anchor w
+ entry .os.sopts.s13.e -width $ewidth -textvariable tko_shellmeta \
+ -relief raised
+ pack append .os.sopts.s13 \
+ .os.sopts.s13.l {left} .os.sopts.s13.e {left frame w}
+
+ frame .os.sopts.s14
+ label .os.sopts.s14.l -text "tags:" -width $lwidth -anchor w
+ entry .os.sopts.s14.e -width $ewidth -textvariable tko_tags \
+ -relief raised
+ pack append .os.sopts.s14 \
+ .os.sopts.s14.l {left} .os.sopts.s14.e {left frame w}
+
+ frame .os.sopts.s15
+ label .os.sopts.s15.l -text "term:" -width $lwidth -anchor w
+ entry .os.sopts.s15.e -width $ewidth -textvariable tko_term \
+ -relief raised
+ pack append .os.sopts.s15 \
+ .os.sopts.s15.l {left} .os.sopts.s15.e {left frame w}
+
+ pack append .os.sopts \
+ .os.sopts.s1 {top expand fillx} \
+ .os.sopts.s2 {top expand fillx} \
+ .os.sopts.s3 {top expand fillx} \
+ .os.sopts.s4 {top expand fillx} \
+ .os.sopts.s5 {top expand fillx} \
+ .os.sopts.s6 {top expand fillx} \
+ .os.sopts.s7 {top expand fillx} \
+ .os.sopts.s8 {top expand fillx} \
+ .os.sopts.s9 {top expand fillx} \
+ .os.sopts.s10 {top expand fillx} \
+ .os.sopts.s11 {top expand fillx} \
+ .os.sopts.s12 {top expand fillx} \
+ .os.sopts.s13 {top expand fillx} \
+ .os.sopts.s14 {top expand fillx} \
+ .os.sopts.s15 {top expand fillx}
+
+ # Build frame for continue button.
+ frame .os.control -bd 4
+ button .os.control.quit -text "Continue" -command "destroy .os"
+ bind .os <Return> ".os.control.quit flash; destroy .os"
+ pack append .os.control .os.control.quit {left}
+
+ # Pack everything together.
+ pack append .os \
+ .os.bopts {top} \
+ .os.control {bottom fillx} \
+ .os.nopts {left fillx padx 4m pady 4m} \
+ .os.sopts {left fillx pady 4m}
+
+ grab .os
+ focus .os
+}
+
+# tk_opt_ew --
+# Handle a change to an option entry widget.
+proc tk_opt_ew {name element op} {
+ upvar $name x
+ tk_opt_set "$name=$x"
+}
+
+# tk_err --
+# Display a Tcl/Tk error message.
+proc tk_err {msg} {
+ tk_dialog .d {} "$msg" {} 0 Continue
+
+ #puts "msg: $msg"
+}
+
+# tk_addstr --
+# Add a string to the screen.
+proc tk_addstr {len str} {
+ global tk_cursor_row
+ global tk_cursor_col
+
+ # Delete the current characters, then insert the new ones.
+ .t mark set insert $tk_cursor_row.$tk_cursor_col
+ .t delete insert "insert + $len chars"
+ .t insert insert "$str"
+ incr tk_cursor_col $len
+
+ #puts "tk_addstr: row $tk_cursor_row col $tk_cursor_col: insert $str"
+}
+
+# tk_clrtoeol --
+# Clear to the end of the line.
+proc tk_clrtoeol {} {
+ global tk_cursor_row
+ global tk_cursor_col
+ global tk_ssize_col
+
+ # Overwrite to the end of the line with spaces.
+ .t mark set insert $tk_cursor_row.$tk_cursor_col
+ .t delete insert "insert lineend"
+ for {set j $tk_cursor_col} {$j < $tk_ssize_col} {incr j} {
+ .t insert insert " "
+ }
+
+ #puts "tk_clrtoel: row $tk_cursor_row col $tk_cursor_col"
+}
+
+# tk_deleteln --
+# Delete the line.
+proc tk_deleteln {} {
+ global tk_cursor_row
+ global tk_cursor_col
+ global tk_ssize_col
+
+ # Delete the line.
+ .t mark set insert $tk_cursor_row.$tk_cursor_col
+ .t delete insert "insert lineend + 1 chars"
+
+ # Append a new, blank line at the end of the screen.
+ .t mark set insert end
+ for {set j 1} {$j <= $tk_ssize_col} {incr j} {
+ .t insert insert " "
+ }
+ .t insert insert "\n"
+
+ #puts "tk_deleteln: row $tk_cursor_row"
+}
+
+# tk_flash --
+# Flash the screen.
+proc tk_flash {} {
+ set bg [lindex [.t config -background] 4]
+ set fg [lindex [.t config -foreground] 4]
+ .t configure -background $fg -foreground $bg
+ update idletasks
+ .t configure -background $bg -foreground $fg
+ update idletasks
+}
+
+# tk_insertln --
+# Insert the line.
+proc tk_insertln {} {
+ global tk_cursor_row
+ global tk_cursor_col
+ global tk_ssize_row
+ global tk_ssize_col
+
+ # Delete the last line on the screen.
+ .t mark set insert $tk_ssize_row.0
+ .t delete insert "insert lineend + 1 chars"
+
+ # Insert a new, blank line.
+ .t mark set insert $tk_cursor_row.$tk_cursor_col
+ for {set j 1} {$j <= $tk_ssize_col} {incr j} {
+ .t insert insert " "
+ }
+ .t insert insert "\n"
+
+ #puts "tk_insertln: row $tk_cursor_row"
+}
+
+# tk_move --
+# Move the cursor.
+proc tk_move {row col} {
+ global tk_cursor_row
+ global tk_cursor_col
+
+ # Convert to Tcl/Tk coordinates, update the insert cursor.
+ set tk_cursor_row [ expr $row + 1 ]
+ set tk_cursor_col $col
+ .t mark set insert $tk_cursor_row.$tk_cursor_col
+
+ # Update the screen cursor.
+ .t tag remove tk_cursor tk_cursor_indx
+ .t mark set tk_cursor_indx insert
+ .t tag add tk_cursor tk_cursor_indx
+
+ #puts "tk_move: row $tk_cursor_row col $tk_cursor_col"
+}
+
+# tk_rename --
+# Rename the screen.
+proc tk_rename {name} {
+ wm title . "$name"
+}
+
+# tk_ssize --
+# Return the window size.
+proc tk_ssize {} {
+ global tk_ssize_col
+ global tk_ssize_row
+
+ set s [ .t configure -width ]
+ set tk_ssize_col [ lindex $s [ expr [ llength $s ] -1 ] ]
+ set s [ .t configure -height ]
+ set tk_ssize_row [ lindex $s [ expr [ llength $s ] -1 ] ]
+
+ #puts "tk_ssize: rows $tk_ssize_row, cols $tk_ssize_col"
+}
+
+# tk_standout --
+# Change into standout mode.
+proc tk_standout {} {
+}
+
+# tk_standend --
+# Change out of standout mode.
+proc tk_standend {} {
+}
+
+# Cursor
+set tk_cursor_row 1
+set tk_cursor_col 0
+
+# Screen size
+set tk_ssize_row 0
+set tk_ssize_col 0
+
+screen
+#tkwait window .
diff --git a/contrib/nvi/tk/tk_funcs.c b/contrib/nvi/tk/tk_funcs.c
new file mode 100644
index 000000000000..be2b0d96ea09
--- /dev/null
+++ b/contrib/nvi/tk/tk_funcs.c
@@ -0,0 +1,346 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)tk_funcs.c 8.11 (Berkeley) 9/23/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../vi/vi.h"
+#include "tki.h"
+
+/*
+ * tk_addstr --
+ * Add len bytes from the string at the cursor, advancing the cursor.
+ *
+ * PUBLIC: int tk_addstr __P((SCR *, const char *, size_t));
+ */
+int
+tk_addstr(sp, str, len)
+ SCR *sp;
+ const char *str;
+ size_t len;
+{
+ TK_PRIVATE *tkp;
+ int iv;
+ char buf[20];
+
+ iv = 0;
+
+ tkp = TKP(sp);
+ if (iv)
+ (void)Tcl_Eval(tkp->interp, "tk_standout");
+
+ (void)snprintf(buf, sizeof(buf), "%d ", (int)len);
+ if ((Tcl_VarEval(tkp->interp,
+ "tk_addstr ", buf, "{", str, "}", NULL) != TCL_OK))
+ return (1);
+
+ if (iv)
+ (void)Tcl_Eval(tkp->interp, "tk_standend");
+ return (0);
+}
+
+/*
+ * tk_attr --
+ * Toggle a screen attribute on/off.
+ *
+ * PUBLIC: int tk_attr __P((SCR *, scr_attr_t, int));
+ */
+int
+tk_attr(sp, attribute, on)
+ SCR *sp;
+ scr_attr_t attribute;
+ int on;
+{
+ TK_PRIVATE *tkp;
+
+ tkp = TKP(sp);
+ switch (attribute) {
+ case SA_ALTERNATE: /* No alternate screen. */
+ break;
+ case SA_INVERSE:
+ if (on)
+ (void)Tcl_Eval(tkp->interp, "tk_standout");
+ else
+ (void)Tcl_Eval(tkp->interp, "tk_standend");
+ break;
+ default:
+ abort();
+ }
+ return (0);
+}
+
+/*
+ * tk_baud --
+ * Return the baud rate.
+ *
+ * PUBLIC: int tk_baud __P((SCR *, u_long *));
+ */
+int
+tk_baud(sp, ratep)
+ SCR *sp;
+ u_long *ratep;
+{
+ *ratep = 9600;
+ return (0);
+}
+
+/*
+ * tk_bell --
+ * Ring the bell/flash the screen.
+ *
+ * PUBLIC: int tk_bell __P((SCR *));
+ */
+int
+tk_bell(sp)
+ SCR *sp;
+{
+ TK_PRIVATE *tkp;
+
+ tkp = TKP(sp);
+ return (Tcl_Eval(tkp->interp, "tk_flash") != TCL_OK);
+}
+
+/*
+ * tk_clrtoeol --
+ * Clear from the current cursor to the end of the line.
+ *
+ * PUBLIC: int tk_clrtoeol __P((SCR *));
+ */
+int
+tk_clrtoeol(sp)
+ SCR *sp;
+{
+ TK_PRIVATE *tkp;
+
+ tkp = TKP(sp);
+ return (Tcl_Eval(tkp->interp, "tk_clrtoeol") != TCL_OK);
+}
+
+/*
+ * tk_cursor --
+ * Return the current cursor position.
+ *
+ * PUBLIC: int tk_cursor __P((SCR *, size_t *, size_t *));
+ */
+int
+tk_cursor(sp, yp, xp)
+ SCR *sp;
+ size_t *yp, *xp;
+{
+ TK_PRIVATE *tkp;
+
+ tkp = TKP(sp);
+ *yp = (tkp->tk_cursor_row - 1) - sp->woff;
+ *xp = tkp->tk_cursor_col;
+ return (0);
+}
+
+/*
+ * tk_deleteln --
+ * Delete the current line, scrolling all lines below it.
+ *
+ * PUBLIC: int tk_deleteln __P((SCR *));
+ */
+int
+tk_deleteln(sp)
+ SCR *sp;
+{
+ TK_PRIVATE *tkp;
+
+ tkp = TKP(sp);
+ return (Tcl_Eval(tkp->interp, "tk_deleteln") != TCL_OK);
+}
+
+/*
+ * tk_ex_adjust --
+ * Adjust the screen for ex.
+ *
+ * PUBLIC: int tk_ex_adjust __P((SCR *, exadj_t));
+ */
+int
+tk_ex_adjust(sp, action)
+ SCR *sp;
+ exadj_t action;
+{
+ abort();
+ /* NOTREACHED */
+}
+
+/*
+ * tk_insertln --
+ * Push down the current line, discarding the bottom line.
+ *
+ * PUBLIC: int tk_insertln __P((SCR *));
+ */
+int
+tk_insertln(sp)
+ SCR *sp;
+{
+ TK_PRIVATE *tkp;
+
+ tkp = TKP(sp);
+ return (Tcl_Eval(tkp->interp, "tk_insertln") != TCL_OK);
+}
+
+/*
+ * tk_keyval --
+ * Return the value for a special key.
+ *
+ * PUBLIC: int tk_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *));
+ */
+int
+tk_keyval(sp, val, chp, dnep)
+ SCR *sp;
+ scr_keyval_t val;
+ CHAR_T *chp;
+ int *dnep;
+{
+ TK_PRIVATE *tkp;
+
+ /*
+ * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990,
+ * VWERASE is a 4BSD extension.
+ */
+ tkp = TKP(sp);
+ switch (val) {
+ case KEY_VEOF:
+ *dnep = (*chp = tkp->orig.c_cc[VEOF]) == _POSIX_VDISABLE;
+ break;
+ case KEY_VERASE:
+ *dnep = (*chp = tkp->orig.c_cc[VERASE]) == _POSIX_VDISABLE;
+ break;
+ case KEY_VKILL:
+ *dnep = (*chp = tkp->orig.c_cc[VKILL]) == _POSIX_VDISABLE;
+ break;
+#ifdef VWERASE
+ case KEY_VWERASE:
+ *dnep = (*chp = tkp->orig.c_cc[VWERASE]) == _POSIX_VDISABLE;
+ break;
+#endif
+ default:
+ *dnep = 1;
+ break;
+ }
+ return (0);
+}
+
+/*
+ * tk_move --
+ * Move the cursor.
+ *
+ * PUBLIC: int tk_move __P((SCR *, size_t, size_t));
+ */
+int
+tk_move(sp, lno, cno)
+ SCR *sp;
+ size_t lno, cno;
+{
+ TK_PRIVATE *tkp;
+ char buf[40];
+
+ (void)snprintf(buf, sizeof(buf), "%d %d", RLNO(sp, lno), cno);
+
+ tkp = TKP(sp);
+ return (Tcl_VarEval(tkp->interp, "tk_move ", buf, NULL) != TCL_OK);
+}
+
+/*
+ * tk_refresh --
+ * Refresh the screen.
+ *
+ * PUBLIC: int tk_refresh __P((SCR *, int));
+ */
+int
+tk_refresh(sp, repaint)
+ SCR *sp;
+ int repaint;
+{
+ TK_PRIVATE *tkp;
+
+ /*
+ * If repaint is set, the editor is telling us that we don't know
+ * what's on the screen, so we have to repaint from scratch.
+ *
+ * XXX
+ * I have no idea how to do this in Tk. My guess is that we have
+ * to delete all of the text and call the editor with an E_REPAINT
+ * event.
+ */
+ if (repaint) {
+ }
+
+ tkp = TKP(sp);
+ return (Tcl_Eval(tkp->interp, "update idletasks") != TCL_OK);
+}
+
+/*
+ * tk_rename --
+ * Rename the file.
+ *
+ * PUBLIC: int tk_rename __P((SCR *));
+ */
+int
+tk_rename(sp)
+ SCR *sp;
+{
+ TK_PRIVATE *tkp;
+
+ tkp = TKP(sp);
+ return (Tcl_VarEval(tkp->interp,
+ "tk_rename ", sp->frp->name, NULL) != TCL_OK);
+}
+
+/*
+ * tk_suspend --
+ * Suspend a screen.
+ *
+ * PUBLIC: int tk_suspend __P((SCR *, int *));
+ */
+int
+tk_suspend(sp, allowedp)
+ SCR *sp;
+ int *allowedp;
+{
+ *allowedp = 0;
+ return (0);
+}
+
+/*
+ * tk_usage --
+ * Print out the Tk/Tcl usage messages.
+ *
+ * PUBLIC: void tk_usage __P((void));
+ */
+void
+tk_usage()
+{
+#define USAGE "\
+usage: tkvi [-eFlRrSv] [-c command] [-bg color] [-fg color]\n\
+ [-geometry widthxheight+x+y] [-i script] [-t tag] [-w size]\n\
+ [file ...]\n"
+ (void)fprintf(stderr, "%s", USAGE);
+#undef USAGE
+}
diff --git a/contrib/nvi/tk/tk_main.c b/contrib/nvi/tk/tk_main.c
new file mode 100644
index 000000000000..c2f34e7b2d9f
--- /dev/null
+++ b/contrib/nvi/tk/tk_main.c
@@ -0,0 +1,423 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)tk_main.c 8.18 (Berkeley) 9/24/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "tki.h"
+#include "pathnames.h"
+
+GS *__global_list; /* GLOBAL: List of screens. */
+sigset_t __sigblockset; /* GLOBAL: Blocked signals. */
+
+static GS *gs_init __P((char *));
+static void killsig __P((SCR *));
+static void perr __P((char *, char *));
+static void sig_end __P((GS *));
+static int sig_init __P((GS *));
+static int tcl_init __P((GS *));
+static void tcl_err __P((TK_PRIVATE *));
+
+/*
+ * main --
+ * This is the main loop for the standalone Tcl/Tk editor.
+ */
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ static int reenter;
+ GS *gp;
+ TK_PRIVATE *tkp;
+ size_t rows, cols;
+ int rval;
+ char **p_av, **t_av, *script;
+
+ /* If loaded at 0 and jumping through a NULL pointer, stop. */
+ if (reenter++)
+ abort();
+
+ /* Create and initialize the global structure. */
+ __global_list = gp = gs_init(argv[0]);
+
+ /* Initialize Tk/Tcl. */
+ if (tcl_init(gp))
+ exit (1);
+
+ /*
+ * Strip out any arguments that the common editor doesn't understand
+ * (i.e. the Tk/Tcl arguments). Search for -i first, it's the Tk/Tcl
+ * startup script and needs to be run first.
+ *
+ * XXX
+ * There's no way to portably call getopt twice.
+ */
+ script = "init.tcl";
+ for (p_av = t_av = argv;;) {
+ if (*t_av == NULL) {
+ *p_av = NULL;
+ break;
+ }
+ if (!strcmp(*t_av, "--")) {
+ while ((*p_av++ = *t_av++) != NULL);
+ break;
+ }
+ if (!memcmp(*t_av, "-i", sizeof("-i") - 1)) {
+ if (t_av[0][2] != '\0') {
+ script = t_av[0] + 2;
+ ++t_av;
+ --argc;
+ continue;
+ }
+ if (t_av[1] != NULL) {
+ script = t_av[1];
+ t_av += 2;
+ argc -= 2;
+ continue;
+ }
+ }
+ *p_av++ = *t_av++;
+ }
+ for (p_av = t_av = argv;;) {
+ if (*t_av == NULL) {
+ *p_av = NULL;
+ break;
+ }
+ if (!strcmp(*t_av, "--")) {
+ while ((*p_av++ = *t_av++) != NULL);
+ break;
+ }
+ if (t_av[1] != NULL &&
+ (!memcmp(*t_av, "-background", sizeof("-background") - 1) ||
+ !memcmp(*t_av, "-bg", sizeof("-bg") - 1) ||
+ !memcmp(*t_av, "-borderwidth", sizeof("-borderwidth") - 1)||
+ !memcmp(*t_av, "-bd", sizeof("-bd") - 1) ||
+ !memcmp(*t_av, "-foreground", sizeof("-foreground") - 1) ||
+ !memcmp(*t_av, "-fg", sizeof("-fg") - 1) ||
+ !memcmp(*t_av, "-font", sizeof("-font") - 1))) {
+ if (Tcl_VarEval(tkp->interp, ".t configure ",
+ t_av[0], " ", t_av[1], NULL) == TCL_ERROR)
+ tcl_err(tkp);
+ t_av += 2;
+ argc -= 2;
+ continue;
+ }
+ if (!memcmp(*t_av, "-geometry", sizeof("-geometry") - 1)) {
+ if (Tcl_VarEval(tkp->interp, "wm geometry . ",
+ *t_av + sizeof("-geometry") - 1, NULL) == TCL_ERROR)
+ tcl_err(tkp);
+ ++t_av;
+ --argc;
+ continue;
+ }
+ *p_av++ = *t_av++;
+ }
+
+ /* Load the initial Tcl/Tk script. */
+ tkp = GTKP(gp);
+ if (Tcl_EvalFile(tkp->interp, script) == TCL_ERROR)
+ tcl_err(tkp);
+
+ /* Add the terminal type to the global structure. */
+ if ((OG_D_STR(gp, GO_TERM) =
+ OG_STR(gp, GO_TERM) = strdup("tkterm")) == NULL)
+ perr(gp->progname, NULL);
+
+ /* Figure out how big the screen is. */
+ if (tk_ssize(NULL, 0, &rows, &cols, NULL))
+ exit (1);
+
+ /* Add the rows and columns to the global structure. */
+ OG_VAL(gp, GO_LINES) = OG_D_VAL(gp, GO_LINES) = rows;
+ OG_VAL(gp, GO_COLUMNS) = OG_D_VAL(gp, GO_COLUMNS) = cols;
+
+ /* Start catching signals. */
+ if (sig_init(gp))
+ exit (1);
+
+ /* Run ex/vi. */
+ rval = editor(gp, argc, argv);
+
+ /* Clean up signals. */
+ sig_end(gp);
+
+ /* Clean up the terminal. */
+ (void)tk_quit(gp);
+
+ /* If a killer signal arrived, pretend we just got it. */
+ if (tkp->killersig) {
+ (void)signal(tkp->killersig, SIG_DFL);
+ (void)kill(getpid(), tkp->killersig);
+ /* NOTREACHED */
+ }
+
+ /* Free the global and TK private areas. */
+#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY)
+ free(tkp);
+ free(gp);
+#endif
+
+ exit (rval);
+}
+
+/*
+ * gs_init --
+ * Create and partially initialize the GS structure.
+ */
+static GS *
+gs_init(name)
+ char *name;
+{
+ TK_PRIVATE *tkp;
+ GS *gp;
+ int fd;
+ char *p;
+
+ /* Figure out what our name is. */
+ if ((p = strrchr(name, '/')) != NULL)
+ name = p + 1;
+
+ /* Allocate the global structure. */
+ CALLOC_NOMSG(NULL, gp, GS *, 1, sizeof(GS));
+
+ /* Allocate the CL private structure. */
+ if (gp != NULL)
+ CALLOC_NOMSG(NULL, tkp, TK_PRIVATE *, 1, sizeof(TK_PRIVATE));
+ if (gp == NULL || tkp == NULL)
+ perr(name, NULL);
+ gp->tk_private = tkp;
+ TAILQ_INIT(&tkp->evq);
+
+ /* Initialize the list of curses functions. */
+ gp->scr_addstr = tk_addstr;
+ gp->scr_attr = tk_attr;
+ gp->scr_baud = tk_baud;
+ gp->scr_bell = tk_bell;
+ gp->scr_busy = NULL;
+ gp->scr_clrtoeol = tk_clrtoeol;
+ gp->scr_cursor = tk_cursor;
+ gp->scr_deleteln = tk_deleteln;
+ gp->scr_event = tk_event;
+ gp->scr_ex_adjust = tk_ex_adjust;
+ gp->scr_fmap = tk_fmap;
+ gp->scr_insertln = tk_insertln;
+ gp->scr_keyval = tk_keyval;
+ gp->scr_move = tk_move;
+ gp->scr_msg = NULL;
+ gp->scr_optchange = tk_optchange;
+ gp->scr_refresh = tk_refresh;
+ gp->scr_rename = tk_rename;
+ gp->scr_screen = tk_screen;
+ gp->scr_suspend = tk_suspend;
+ gp->scr_usage = tk_usage;
+
+ /*
+ * We expect that if we've lost our controlling terminal that the
+ * open() (but not the tcgetattr()) will fail.
+ */
+ if (isatty(STDIN_FILENO)) {
+ if (tcgetattr(STDIN_FILENO, &tkp->orig) == -1)
+ goto tcfail;
+ } else if ((fd = open(_PATH_TTY, O_RDONLY, 0)) != -1) {
+ if (tcgetattr(fd, &tkp->orig) == -1)
+tcfail: perr(name, "tcgetattr");
+ (void)close(fd);
+ }
+
+ gp->progname = name;
+ return (gp);
+}
+
+/*
+ * tcl_init --
+ * Get Tcl/Tk up and running.
+ */
+static int
+tcl_init(gp)
+ GS *gp;
+{
+ TK_PRIVATE *tkp;
+
+ tkp = GTKP(gp);
+ if ((tkp->interp = Tcl_CreateInterp()) == NULL)
+ tcl_err(tkp);
+ /* XXX: Tk 4.1 has an incompatible change. */
+#if (TK_MAJOR_VERSION == 4) && (TK_MINOR_VERSION == 0)
+ if (Tk_CreateMainWindow(tkp->interp, NULL, "vi", "Vi") == NULL)
+ tcl_err(tkp);
+#endif
+ if (Tcl_Init(tkp->interp) == TCL_ERROR)
+ tcl_err(tkp);
+ if (Tk_Init(tkp->interp) == TCL_ERROR)
+ tcl_err(tkp);
+
+ /* Shared variables. */
+ (void)Tcl_LinkVar(tkp->interp,
+ "tk_cursor_row", (char *)&tkp->tk_cursor_row, TCL_LINK_INT);
+ (void)Tcl_LinkVar(tkp->interp,
+ "tk_cursor_col", (char *)&tkp->tk_cursor_col, TCL_LINK_INT);
+ (void)Tcl_LinkVar(tkp->interp,
+ "tk_ssize_row", (char *)&tkp->tk_ssize_row, TCL_LINK_INT);
+ (void)Tcl_LinkVar(tkp->interp,
+ "tk_ssize_col", (char *)&tkp->tk_ssize_col, TCL_LINK_INT);
+
+ /* Functions called by Tcl script. */
+ Tcl_CreateCommand(tkp->interp, "tk_key", tk_key, tkp, NULL);
+ Tcl_CreateCommand(tkp->interp, "tk_op", tk_op, tkp, NULL);
+ Tcl_CreateCommand(tkp->interp, "tk_opt_init", tk_opt_init, tkp, NULL);
+ Tcl_CreateCommand(tkp->interp, "tk_opt_set", tk_opt_set, tkp, NULL);
+ Tcl_CreateCommand(tkp->interp, "tk_version", tk_version, tkp, NULL);
+
+ /* Other initialization. */
+ if (Tcl_Eval(tkp->interp, "wm geometry . =80x28+0+0") == TCL_ERROR)
+ tcl_err(tkp);
+ return (0);
+}
+
+/*
+ * tcl_err --
+ * Tcl/Tk error message during initialization.
+ */
+static void
+tcl_err(tkp)
+ TK_PRIVATE *tkp;
+{
+ (void)fprintf(stderr, "%s\n", tkp->interp->result != NULL ?
+ tkp->interp->result : "Tcl/Tk: initialization error");
+ (void)tk_usage();
+ exit (1);
+}
+
+#define GLOBAL_TKP \
+ TK_PRIVATE *tkp = GTKP(__global_list);
+static void
+h_hup(signo)
+ int signo;
+{
+ GLOBAL_TKP;
+
+ F_SET(tkp, TK_SIGHUP);
+ tkp->killersig = SIGHUP;
+}
+
+static void
+h_int(signo)
+ int signo;
+{
+ GLOBAL_TKP;
+
+ F_SET(tkp, TK_SIGINT);
+}
+
+static void
+h_term(signo)
+ int signo;
+{
+ GLOBAL_TKP;
+
+ F_SET(tkp, TK_SIGTERM);
+ tkp->killersig = SIGTERM;
+}
+
+static void
+h_winch(signo)
+ int signo;
+{
+ GLOBAL_TKP;
+
+ F_SET(tkp, TK_SIGWINCH);
+}
+#undef GLOBAL_TKP
+
+/*
+ * sig_init --
+ * Initialize signals.
+ */
+static int
+sig_init(gp)
+ GS *gp;
+{
+ TK_PRIVATE *tkp;
+ struct sigaction act;
+
+ tkp = GTKP(gp);
+
+ (void)sigemptyset(&__sigblockset);
+
+ /*
+ * Use sigaction(2), not signal(3), since we don't always want to
+ * restart system calls. The example is when waiting for a command
+ * mode keystroke and SIGWINCH arrives. Besides, you can't portably
+ * restart system calls (thanks, POSIX!).
+ */
+#define SETSIG(signal, handler, off) { \
+ if (sigaddset(&__sigblockset, signal)) \
+ goto err; \
+ act.sa_handler = handler; \
+ sigemptyset(&act.sa_mask); \
+ act.sa_flags = 0; \
+ if (sigaction(signal, &act, &tkp->oact[off])) \
+ goto err; \
+}
+#undef SETSIG
+ return (0);
+
+err: perr(gp->progname, NULL);
+ return (1);
+}
+
+/*
+ * sig_end --
+ * End signal setup.
+ */
+static void
+sig_end(gp)
+ GS *gp;
+{
+ TK_PRIVATE *tkp;
+
+ tkp = GTKP(gp);
+ (void)sigaction(SIGHUP, NULL, &tkp->oact[INDX_HUP]);
+ (void)sigaction(SIGINT, NULL, &tkp->oact[INDX_INT]);
+ (void)sigaction(SIGTERM, NULL, &tkp->oact[INDX_TERM]);
+ (void)sigaction(SIGWINCH, NULL, &tkp->oact[INDX_WINCH]);
+}
+
+/*
+ * perr --
+ * Print system error.
+ */
+static void
+perr(name, msg)
+ char *name, *msg;
+{
+ (void)fprintf(stderr, "%s:", name);
+ if (msg != NULL)
+ (void)fprintf(stderr, "%s:", msg);
+ (void)fprintf(stderr, "%s\n", strerror(errno));
+ exit(1);
+}
diff --git a/contrib/nvi/tk/tk_read.c b/contrib/nvi/tk/tk_read.c
new file mode 100644
index 000000000000..b5cfab71c7e2
--- /dev/null
+++ b/contrib/nvi/tk/tk_read.c
@@ -0,0 +1,207 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)tk_read.c 8.12 (Berkeley) 9/24/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "../ex/script.h"
+#include "tki.h"
+
+static input_t tk_read __P((SCR *, int));
+static int tk_resize __P((SCR *, size_t, size_t));
+
+
+/*
+ * tk_event --
+ * Return a single event.
+ *
+ * PUBLIC: int tk_event __P((SCR *, EVENT *, u_int32_t, int));
+ */
+int
+tk_event(sp, evp, flags, timeout)
+ SCR *sp;
+ EVENT *evp;
+ u_int32_t flags;
+ int timeout;
+{
+ EVENT *tevp;
+ TK_PRIVATE *tkp;
+ size_t lines, columns;
+ int changed;
+
+ /*
+ * Queue signal based events. We never clear SIGHUP or SIGTERM events,
+ * so that we just keep returning them until the editor dies.
+ */
+ tkp = TKP(sp);
+sig: if (LF_ISSET(EC_INTERRUPT) || F_ISSET(tkp, TK_SIGINT)) {
+ if (F_ISSET(tkp, TK_SIGINT)) {
+ F_CLR(tkp, TK_SIGINT);
+ evp->e_event = E_INTERRUPT;
+ } else
+ evp->e_event = E_TIMEOUT;
+ return (0);
+ }
+ if (F_ISSET(tkp, TK_SIGHUP | TK_SIGTERM | TK_SIGWINCH)) {
+ if (F_ISSET(tkp, TK_SIGHUP)) {
+ evp->e_event = E_SIGHUP;
+ return (0);
+ }
+ if (F_ISSET(tkp, TK_SIGTERM)) {
+ evp->e_event = E_SIGTERM;
+ return (0);
+ }
+ if (F_ISSET(tkp, TK_SIGWINCH)) {
+ F_CLR(tkp, TK_SIGWINCH);
+ (void)tk_ssize(sp, 1, &lines, &columns, &changed);
+ if (changed) {
+ (void)tk_resize(sp, lines, columns);
+ evp->e_event = E_WRESIZE;
+ return (0);
+ }
+ /* No change, so ignore the signal. */
+ }
+ }
+
+ /* Queue special ops. */
+ops: if ((tevp = tkp->evq.tqh_first) != NULL) {
+ *evp = *tevp;
+ TAILQ_REMOVE(&tkp->evq, tevp, q);
+ free(tevp);
+ return (0);
+ }
+
+ /* Read input characters. */
+ switch (tk_read(sp, timeout)) {
+ case INP_OK:
+ evp->e_csp = tkp->ibuf;
+ evp->e_len = tkp->ibuf_cnt;
+ evp->e_event = E_STRING;
+ tkp->ibuf_cnt = 0;
+ break;
+ case INP_EOF:
+ evp->e_event = E_EOF;
+ break;
+ case INP_ERR:
+ evp->e_event = E_ERR;
+ break;
+ case INP_INTR:
+ goto sig;
+ break;
+ case INP_TIMEOUT:
+ /* May have returned because queued a special op. */
+ if (tkp->evq.tqh_first != NULL)
+ goto ops;
+
+ /* Otherwise, we timed out. */
+ evp->e_event = E_TIMEOUT;
+ break;
+ default:
+ abort();
+ }
+ return (0);
+}
+
+/*
+ * tk_read --
+ * Read characters from the input.
+ */
+static input_t
+tk_read(sp, timeout)
+ SCR *sp;
+ int timeout;
+{
+ TK_PRIVATE *tkp;
+ char buf[20];
+
+ /*
+ * Check scripting window file descriptors. It's ugly that we wait
+ * on scripting file descriptors here, but it's the only way to keep
+ * from locking out scripting windows.
+ */
+ if (F_ISSET(sp->gp, G_SCRWIN) && sscr_input(sp))
+ return (INP_ERR);
+
+ /* Read characters. */
+ tkp = TKP(sp);
+ (void)snprintf(buf, sizeof(buf), "%d", timeout);
+ (void)Tcl_VarEval(tkp->interp, "tk_key_wait ", buf, NULL);
+
+ return (tkp->ibuf_cnt == 0 ? INP_TIMEOUT : INP_OK);
+}
+
+/*
+ * tk_key --
+ * Receive an input key.
+ *
+ * PUBLIC: int tk_key __P((ClientData, Tcl_Interp *, int, char *[]));
+ */
+int
+tk_key(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char *argv[];
+{
+ TK_PRIVATE *tkp;
+ u_int8_t *p, *t;
+
+ tkp = (TK_PRIVATE *)clientData;
+ for (p =
+ tkp->ibuf + tkp->ibuf_cnt, t = argv[1]; (*p++ = *t++) != '\0';
+ ++tkp->ibuf_cnt);
+ return (TCL_OK);
+}
+
+/*
+ * tk_resize --
+ * Reset the options for a resize event.
+ */
+static int
+tk_resize(sp, lines, columns)
+ SCR *sp;
+ size_t lines, columns;
+{
+ ARGS *argv[2], a, b;
+ int rval;
+ char b1[1024];
+
+ a.bp = b1;
+ b.bp = NULL;
+ a.len = b.len = 0;
+ argv[0] = &a;
+ argv[1] = &b;
+
+ (void)snprintf(b1, sizeof(b1), "lines=%lu", (u_long)lines);
+ a.len = strlen(b1);
+ if (opts_set(sp, argv, NULL))
+ return (1);
+ (void)snprintf(b1, sizeof(b1), "columns=%lu", (u_long)columns);
+ a.len = strlen(b1);
+ if (opts_set(sp, argv, NULL))
+ return (1);
+ return (0);
+}
diff --git a/contrib/nvi/tk/tk_screen.c b/contrib/nvi/tk/tk_screen.c
new file mode 100644
index 000000000000..e1090930ba23
--- /dev/null
+++ b/contrib/nvi/tk/tk_screen.c
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)tk_screen.c 8.9 (Berkeley) 5/24/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "tki.h"
+
+/*
+ * tk_screen --
+ * Initialize/shutdown the Tcl/Tk screen.
+ *
+ * PUBLIC: int tk_screen __P((SCR *, u_int32_t));
+ */
+int
+tk_screen(sp, flags)
+ SCR *sp;
+ u_int32_t flags;
+{
+ TK_PRIVATE *tkp;
+
+ tkp = TKP(sp);
+
+ /* See if we're already in the right mode. */
+ if (LF_ISSET(SC_VI) && F_ISSET(sp, SC_SCR_VI))
+ return (0);
+
+ /* Ex isn't possible. */
+ if (LF_ISSET(SC_EX))
+ return (1);
+
+ /* Initialize terminal based information. */
+ if (tk_term_init(sp))
+ return (1);
+
+ /* Put up the first file name. */
+ if (tk_rename(sp))
+ return (1);
+
+ F_SET(tkp, TK_SCR_VI_INIT);
+ return (0);
+}
+
+/*
+ * tk_quit --
+ * Shutdown the screens.
+ *
+ * PUBLIC: int tk_quit __P((GS *));
+ */
+int
+tk_quit(gp)
+ GS *gp;
+{
+ TK_PRIVATE *tkp;
+ int rval;
+
+ /* Clean up the terminal mappings. */
+ rval = tk_term_end(gp);
+
+ tkp = GTKP(gp);
+ F_CLR(tkp, TK_SCR_VI_INIT);
+
+ return (rval);
+}
diff --git a/contrib/nvi/tk/tk_term.c b/contrib/nvi/tk/tk_term.c
new file mode 100644
index 000000000000..18299a28ae77
--- /dev/null
+++ b/contrib/nvi/tk/tk_term.c
@@ -0,0 +1,169 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)tk_term.c 8.12 (Berkeley) 10/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "tki.h"
+
+/*
+ * tk_term_init --
+ * Initialize the terminal special keys.
+ *
+ * PUBLIC: int tk_term_init __P((SCR *));
+ */
+int
+tk_term_init(sp)
+ SCR *sp;
+{
+ SEQ *qp;
+
+ /*
+ * Rework any function key mappings that were set before the
+ * screen was initialized.
+ */
+ for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next)
+ if (F_ISSET(qp, SEQ_FUNCMAP))
+ (void)tk_fmap(sp, qp->stype,
+ qp->input, qp->ilen, qp->output, qp->olen);
+ return (0);
+}
+
+/*
+ * tk_term_end --
+ * End the special keys defined by the termcap/terminfo entry.
+ *
+ * PUBLIC: int tk_term_end __P((GS *));
+ */
+int
+tk_term_end(gp)
+ GS *gp;
+{
+ SEQ *qp, *nqp;
+
+ /* Delete screen specific mappings. */
+ for (qp = gp->seqq.lh_first; qp != NULL; qp = nqp) {
+ nqp = qp->q.le_next;
+ if (F_ISSET(qp, SEQ_SCREEN))
+ (void)seq_mdel(qp);
+ }
+ return (0);
+}
+
+/*
+ * tk_fmap --
+ * Map a function key.
+ *
+ * PUBLIC: int tk_fmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
+ */
+int
+tk_fmap(sp, stype, from, flen, to, tlen)
+ SCR *sp;
+ seq_t stype;
+ CHAR_T *from, *to;
+ size_t flen, tlen;
+{
+ VI_INIT_IGNORE(sp);
+
+ /* Bind a Tk/Tcl function key to a string sequence. */
+ return (0);
+}
+
+/*
+ * tk_optchange --
+ * Curses screen specific "option changed" routine.
+ *
+ * PUBLIC: int tk_optchange __P((SCR *, int, char *, u_long *));
+ */
+int
+tk_optchange(sp, opt, str, valp)
+ SCR *sp;
+ int opt;
+ char *str;
+ u_long *valp;
+{
+ switch (opt) {
+ case O_COLUMNS:
+ case O_LINES:
+ /*
+ * Changing the columns or lines require that we restart
+ * the screen.
+ */
+ F_SET(sp->gp, G_SRESTART);
+ F_CLR(sp, SC_SCR_EX | SC_SCR_VI);
+ break;
+ case O_TERM:
+ msgq(sp, M_ERR, "The screen type may not be changed");
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * tk_ssize --
+ * Return the window size.
+ *
+ * PUBLIC: int tk_ssize __P((SCR *, int, size_t *, size_t *, int *));
+ */
+int
+tk_ssize(sp, sigwinch, rowp, colp, changedp)
+ SCR *sp;
+ int sigwinch;
+ size_t *rowp, *colp;
+ int *changedp;
+{
+ TK_PRIVATE *tkp;
+
+ tkp = GTKP(__global_list);
+ (void)Tcl_Eval(tkp->interp, "tk_ssize");
+
+ /*
+ * SunOS systems deliver SIGWINCH when windows are uncovered
+ * as well as when they change size. In addition, we call
+ * here when continuing after being suspended since the window
+ * may have changed size. Since we don't want to background
+ * all of the screens just because the window was uncovered,
+ * ignore the signal if there's no change.
+ *
+ * !!!
+ * sp may be NULL.
+ */
+ if (sigwinch && sp != NULL &&
+ tkp->tk_ssize_row == O_VAL(sp, O_LINES) &&
+ tkp->tk_ssize_col == O_VAL(sp, O_COLUMNS)) {
+ if (changedp != NULL)
+ *changedp = 0;
+ return (0);
+ }
+
+ if (rowp != NULL)
+ *rowp = tkp->tk_ssize_row;
+ if (colp != NULL)
+ *colp = tkp->tk_ssize_col;
+ if (changedp != NULL)
+ *changedp = 1;
+ return (0);
+}
diff --git a/contrib/nvi/tk/tk_util.c b/contrib/nvi/tk/tk_util.c
new file mode 100644
index 000000000000..096fa7bb3eba
--- /dev/null
+++ b/contrib/nvi/tk/tk_util.c
@@ -0,0 +1,250 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)tk_util.c 8.14 (Berkeley) 7/19/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "tki.h"
+
+static int tk_op_push __P((SCR *, TK_PRIVATE *, e_event_t));
+
+/*
+ * tk_op --
+ * Events provided directly from Tcl/Tk.
+ *
+ * PUBLIC: int tk_op __P((ClientData, Tcl_Interp *, int, char *[]));
+ */
+int
+tk_op(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char *argv[];
+{
+ SCR *sp;
+ TK_PRIVATE *tkp;
+
+ sp = __global_list->dq.cqh_first; /* XXX */
+ tkp = (TK_PRIVATE *)clientData;
+
+ switch (argv[1][0]) {
+ case 'q':
+ if (!strcmp(argv[1], "quit"))
+ return (tk_op_push(sp, tkp, E_QUIT));
+ break;
+ case 'w':
+ if (!strcmp(argv[1], "write"))
+ return (tk_op_push(sp, tkp, E_WRITE));
+ if (!strcmp(argv[1], "writequit")) {
+ if (tk_op_push(sp, tkp, E_WRITE) != TCL_OK)
+ return (TCL_ERROR);
+ if (tk_op_push(sp, tkp, E_QUIT) != TCL_OK)
+ return (TCL_ERROR);
+ return (TCL_OK);
+ }
+ break;
+ }
+ (void)Tcl_VarEval(tkp->interp,
+ "tk_err {", argv[1], ": unknown event", "}", NULL);
+ return (TCL_OK);
+}
+
+/*
+ * tk_op_push --
+ * Push an event.
+ */
+static int
+tk_op_push(sp, tkp, et)
+ SCR *sp;
+ TK_PRIVATE *tkp;
+ e_event_t et;
+{
+ EVENT *evp;
+
+ CALLOC(sp, evp, EVENT *, 1, sizeof(EVENT));
+ if (evp == NULL)
+ return (TCL_ERROR);
+
+ evp->e_event = et;
+ TAILQ_INSERT_TAIL(&tkp->evq, evp, q);
+ return (TCL_OK);
+}
+
+/*
+ * tk_opt_init --
+ * Initialize the values of the current options.
+ *
+ * PUBLIC: int tk_opt_init __P((ClientData, Tcl_Interp *, int, char *[]));
+ */
+int
+tk_opt_init(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char *argv[];
+{
+ OPTLIST const *op;
+ SCR *sp;
+ TK_PRIVATE *tkp;
+ int off;
+ char buf[20];
+
+ sp = __global_list->dq.cqh_first; /* XXX */
+
+ tkp = (TK_PRIVATE *)clientData;
+ for (op = optlist, off = 0; op->name != NULL; ++op, ++off) {
+ if (F_ISSET(op, OPT_NDISP))
+ continue;
+ switch (op->type) {
+ case OPT_0BOOL:
+ case OPT_1BOOL:
+ (void)Tcl_VarEval(tkp->interp, "set tko_",
+ op->name, O_ISSET(sp, off) ? " 1" : " 0", NULL);
+ break;
+ case OPT_NUM:
+ (void)snprintf(buf,
+ sizeof(buf), " %lu", O_VAL(sp, off));
+ (void)Tcl_VarEval(tkp->interp,
+ "set tko_", op->name, buf, NULL);
+ break;
+ case OPT_STR:
+ (void)Tcl_VarEval(tkp->interp,
+ "set tko_", op->name, " {",
+ O_STR(sp, off) == NULL ? "" : O_STR(sp, off),
+ "}", NULL);
+ break;
+ }
+ }
+ return (TCL_OK);
+}
+
+/*
+ * tk_opt_set --
+ * Set an options button.
+ *
+ * PUBLIC: int tk_opt_set __P((ClientData, Tcl_Interp *, int, char *[]));
+ */
+int
+tk_opt_set(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char *argv[];
+{
+ ARGS *ap[2], a, b;
+ GS *gp;
+ SCR *sp;
+ int rval;
+ void (*msg) __P((SCR *, mtype_t, char *, size_t));
+ char buf[64];
+
+ gp = __global_list;
+ sp = gp->dq.cqh_first; /* XXX */
+
+ switch (argc) {
+ case 2:
+ a.bp = argv[1] + (sizeof("tko_") - 1);
+ a.len = strlen(a.bp);
+ break;
+ case 3:
+ a.bp = buf;
+ a.len = snprintf(buf, sizeof(buf),
+ "%s%s", atoi(argv[2]) ? "no" : "", argv[1]);
+ break;
+ default:
+ abort();
+ }
+ b.bp = NULL;
+ b.len = 0;
+ ap[0] = &a;
+ ap[1] = &b;
+
+ /* Use Tcl/Tk for error messages. */
+ msg = gp->scr_msg;
+ gp->scr_msg = tk_msg;
+
+ rval = opts_set(sp, ap, NULL);
+
+ gp->scr_msg = msg;
+ return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tk_version --
+ * Display the version in Tcl/Tk.
+ *
+ * PUBLIC: int tk_version __P((ClientData, Tcl_Interp *, int, char *[]));
+ */
+int
+tk_version(clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char *argv[];
+{
+ EXCMD cmd;
+ GS *gp;
+ SCR *sp;
+ int rval;
+ void (*msg) __P((SCR *, mtype_t, char *, size_t));
+
+ gp = __global_list;
+ sp = gp->dq.cqh_first; /* XXX */
+
+ msg = gp->scr_msg;
+ gp->scr_msg = tk_msg;
+
+ ex_cinit(&cmd, C_VERSION, 0, OOBLNO, OOBLNO, 0, NULL);
+ rval = cmd.cmd->fn(sp, &cmd);
+ (void)ex_fflush(sp);
+
+ gp->scr_msg = msg;
+ return (rval ? TCL_ERROR : TCL_OK);
+}
+
+/*
+ * tk_msg --
+ * Display an error message in Tcl/Tk.
+ *
+ * PUBLIC: void tk_msg __P((SCR *, mtype_t, char *, size_t));
+ */
+void
+tk_msg(sp, mtype, line, rlen)
+ SCR *sp;
+ mtype_t mtype;
+ char *line;
+ size_t rlen;
+{
+ TK_PRIVATE *tkp;
+ char buf[2048];
+
+ if (line == NULL)
+ return;
+
+ tkp = TKP(sp);
+ (void)snprintf(buf, sizeof(buf), "%.*s", (int)rlen, line);
+ (void)Tcl_VarEval(tkp->interp, "tk_err {", buf, "}", NULL);
+}
diff --git a/contrib/nvi/tk/tki.h b/contrib/nvi/tk/tki.h
new file mode 100644
index 000000000000..206dacf5d73b
--- /dev/null
+++ b/contrib/nvi/tk/tki.h
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)tki.h 8.6 (Berkeley) 4/27/96
+ */
+
+#include <tcl.h>
+#include <tk.h>
+
+typedef struct _tk_private {
+ Tcl_Interp *interp;/* Tcl interpreter cookie. */
+
+ /* Shared variables. */
+ int tk_cursor_row; /* Current cursor row. */
+ int tk_cursor_col; /* Current cursor col. */
+ int tk_ssize_row; /* Screen rows. */
+ int tk_ssize_col; /* Screen columns. */
+
+ struct termios orig; /* Original terminal values. */
+
+ CHAR_T ibuf[64]; /* Input keys. */
+ int ibuf_cnt; /* Number of input keys. */
+
+ /* Event queue. */
+ TAILQ_HEAD(_eventh, _event) evq;
+
+ int killersig; /* Killer signal. */
+#define INDX_HUP 0
+#define INDX_INT 1
+#define INDX_TERM 2
+#define INDX_WINCH 3
+#define INDX_MAX 4 /* Original signal information. */
+ struct sigaction oact[INDX_MAX];
+
+#define TK_LLINE_IV 0x0001 /* Last line is in inverse video. */
+#define TK_SCR_VI_INIT 0x0002 /* Vi screen initialized. */
+#define TK_SIGHUP 0x0004 /* SIGHUP arrived. */
+#define TK_SIGINT 0x0008 /* SIGINT arrived. */
+#define TK_SIGTERM 0x0010 /* SIGTERM arrived. */
+#define TK_SIGWINCH 0x0020 /* SIGWINCH arrived. */
+ u_int16_t flags;
+} TK_PRIVATE;
+
+extern GS *__global_list;
+#define TKP(sp) ((TK_PRIVATE *)((sp)->gp->tk_private))
+#define GTKP(gp) ((TK_PRIVATE *)gp->tk_private)
+
+/* Return possibilities from the keyboard read routine. */
+typedef enum { INP_OK=0, INP_EOF, INP_ERR, INP_INTR, INP_TIMEOUT } input_t;
+
+/* The screen line relative to a specific window. */
+#define RLNO(sp, lno) (sp)->woff + (lno)
+
+/* Some functions can be safely ignored until the screen is running. */
+#define VI_INIT_IGNORE(sp) \
+ if (F_ISSET(sp, SC_VI) && !F_ISSET(TKP(sp), TK_SCR_VI_INIT)) \
+ return (0);
+
+#include "tk_extern.h"
diff --git a/usr.bin/vi/vi/getc.c b/contrib/nvi/vi/getc.c
index 14c8423120c0..5e60adee96d7 100644
--- a/usr.bin/vi/vi/getc.c
+++ b/contrib/nvi/vi/getc.c
@@ -1,38 +1,16 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)getc.c 8.9 (Berkeley) 5/21/94";
+static const char sccsid[] = "@(#)getc.c 10.10 (Berkeley) 3/6/96";
#endif /* not lint */
#include <sys/types.h>
@@ -42,16 +20,11 @@ static char sccsid[] = "@(#)getc.c 8.9 (Berkeley) 5/21/94";
#include <bitstring.h>
#include <ctype.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
+#include <stdlib.h>
+#include "../common/common.h"
#include "vi.h"
-#include "vcmd.h"
/*
* Character stream routines --
@@ -66,23 +39,19 @@ static char sccsid[] = "@(#)getc.c 8.9 (Berkeley) 5/21/94";
/*
* cs_init --
* Initialize character stream routines.
+ *
+ * PUBLIC: int cs_init __P((SCR *, VCS *));
*/
int
-cs_init(sp, ep, csp)
+cs_init(sp, csp)
SCR *sp;
- EXF *ep;
VCS *csp;
{
- recno_t lno;
+ int isempty;
- if ((csp->cs_bp =
- file_gline(sp, ep, csp->cs_lno, &csp->cs_len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno == 0)
- msgq(sp, M_BERR, "Empty file");
- else
- GETLINE_ERR(sp, csp->cs_lno);
+ if (db_eget(sp, csp->cs_lno, &csp->cs_bp, &csp->cs_len, &isempty)) {
+ if (isempty)
+ msgq(sp, M_BERR, "177|Empty file");
return (1);
}
if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) {
@@ -98,36 +67,32 @@ cs_init(sp, ep, csp)
/*
* cs_next --
* Retrieve the next character.
+ *
+ * PUBLIC: int cs_next __P((SCR *, VCS *));
*/
int
-cs_next(sp, ep, csp)
+cs_next(sp, csp)
SCR *sp;
- EXF *ep;
VCS *csp;
{
- recno_t slno;
+ char *p;
switch (csp->cs_flags) {
case CS_EMP: /* EMP; get next line. */
case CS_EOL: /* EOL; get next line. */
- slno = csp->cs_lno; /* Save current line. */
- if ((csp->cs_bp =
- file_gline(sp, ep, ++csp->cs_lno, &csp->cs_len)) == NULL) {
- csp->cs_lno = slno;
- if (file_lline(sp, ep, &slno))
- return (1);
- if (slno > csp->cs_lno) {
- GETLINE_ERR(sp, csp->cs_lno);
- return (1);
- }
+ if (db_get(sp, ++csp->cs_lno, 0, &p, &csp->cs_len)) {
+ --csp->cs_lno;
csp->cs_flags = CS_EOF;
- } else if (csp->cs_len == 0 ||
- v_isempty(csp->cs_bp, csp->cs_len)) {
- csp->cs_cno = 0;
- csp->cs_flags = CS_EMP;
} else {
- csp->cs_flags = 0;
- csp->cs_ch = csp->cs_bp[csp->cs_cno = 0];
+ csp->cs_bp = p;
+ if (csp->cs_len == 0 ||
+ v_isempty(csp->cs_bp, csp->cs_len)) {
+ csp->cs_cno = 0;
+ csp->cs_flags = CS_EMP;
+ } else {
+ csp->cs_flags = 0;
+ csp->cs_ch = csp->cs_bp[csp->cs_cno = 0];
+ }
}
break;
case 0:
@@ -154,17 +119,18 @@ cs_next(sp, ep, csp)
* Semantics of checking the current character were coded for the fword()
* function -- once the other word routines are converted, they may have
* to change.
+ *
+ * PUBLIC: int cs_fspace __P((SCR *, VCS *));
*/
int
-cs_fspace(sp, ep, csp)
+cs_fspace(sp, csp)
SCR *sp;
- EXF *ep;
VCS *csp;
{
if (csp->cs_flags != 0 || !isblank(csp->cs_ch))
return (0);
for (;;) {
- if (cs_next(sp, ep, csp))
+ if (cs_next(sp, csp))
return (1);
if (csp->cs_flags != 0 || !isblank(csp->cs_ch))
break;
@@ -175,15 +141,16 @@ cs_fspace(sp, ep, csp)
/*
* cs_fblank --
* Eat forward to the next non-whitespace character.
+ *
+ * PUBLIC: int cs_fblank __P((SCR *, VCS *));
*/
int
-cs_fblank(sp, ep, csp)
+cs_fblank(sp, csp)
SCR *sp;
- EXF *ep;
VCS *csp;
{
for (;;) {
- if (cs_next(sp, ep, csp))
+ if (cs_next(sp, csp))
return (1);
if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP ||
csp->cs_flags == 0 && isblank(csp->cs_ch))
@@ -196,15 +163,14 @@ cs_fblank(sp, ep, csp)
/*
* cs_prev --
* Retrieve the previous character.
+ *
+ * PUBLIC: int cs_prev __P((SCR *, VCS *));
*/
int
-cs_prev(sp, ep, csp)
+cs_prev(sp, csp)
SCR *sp;
- EXF *ep;
VCS *csp;
{
- recno_t slno;
-
switch (csp->cs_flags) {
case CS_EMP: /* EMP; get previous line. */
case CS_EOL: /* EOL; get previous line. */
@@ -212,11 +178,9 @@ cs_prev(sp, ep, csp)
csp->cs_flags = CS_SOF;
break;
}
- slno = csp->cs_lno; /* Save current line. */
- if ((csp->cs_bp = /* Line should exist. */
- file_gline(sp, ep, --csp->cs_lno, &csp->cs_len)) == NULL) {
- GETLINE_ERR(sp, csp->cs_lno);
- csp->cs_lno = slno;
+ if (db_get(sp, /* The line should exist. */
+ --csp->cs_lno, DBG_FATAL, &csp->cs_bp, &csp->cs_len)) {
+ ++csp->cs_lno;
return (1);
}
if (csp->cs_len == 0 || v_isempty(csp->cs_bp, csp->cs_len)) {
@@ -228,6 +192,7 @@ cs_prev(sp, ep, csp)
csp->cs_ch = csp->cs_bp[csp->cs_cno];
}
break;
+ case CS_EOF: /* EOF: get previous char. */
case 0:
if (csp->cs_cno == 0)
if (csp->cs_lno == 1)
@@ -249,15 +214,16 @@ cs_prev(sp, ep, csp)
/*
* cs_bblank --
* Eat backward to the next non-whitespace character.
+ *
+ * PUBLIC: int cs_bblank __P((SCR *, VCS *));
*/
int
-cs_bblank(sp, ep, csp)
+cs_bblank(sp, csp)
SCR *sp;
- EXF *ep;
VCS *csp;
{
for (;;) {
- if (cs_prev(sp, ep, csp))
+ if (cs_prev(sp, csp))
return (1);
if (csp->cs_flags == CS_EOL || csp->cs_flags == CS_EMP ||
csp->cs_flags == 0 && isblank(csp->cs_ch))
diff --git a/contrib/nvi/vi/v_at.c b/contrib/nvi/vi/v_at.c
new file mode 100644
index 000000000000..d266f275d983
--- /dev/null
+++ b/contrib/nvi/vi/v_at.c
@@ -0,0 +1,109 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_at.c 10.8 (Berkeley) 4/27/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_at -- @
+ * Execute a buffer.
+ *
+ * PUBLIC: int v_at __P((SCR *, VICMD *));
+ */
+int
+v_at(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ CB *cbp;
+ CHAR_T name;
+ TEXT *tp;
+ size_t len;
+ char nbuf[20];
+
+ /*
+ * !!!
+ * Historically, [@*]<carriage-return> and [@*][@*] executed the most
+ * recently executed buffer in ex mode. In vi mode, only @@ repeated
+ * the last buffer. We change historic practice and make @* work from
+ * vi mode as well, it's simpler and more consistent.
+ *
+ * My intent is that *[buffer] will, in the future, pass the buffer to
+ * whatever interpreter is loaded.
+ */
+ name = F_ISSET(vp, VC_BUFFER) ? vp->buffer : '@';
+ if (name == '@' || name == '*') {
+ if (!F_ISSET(sp, SC_AT_SET)) {
+ ex_emsg(sp, NULL, EXM_NOPREVBUF);
+ return (1);
+ }
+ name = sp->at_lbuf;
+ }
+ F_SET(sp, SC_AT_SET);
+
+ CBNAME(sp, cbp, name);
+ if (cbp == NULL) {
+ ex_emsg(sp, KEY_NAME(sp, name), EXM_EMPTYBUF);
+ return (1);
+ }
+
+ /* Save for reuse. */
+ sp->at_lbuf = name;
+
+ /*
+ * The buffer is executed in vi mode, while in vi mode, so simply
+ * push it onto the terminal queue and continue.
+ *
+ * !!!
+ * Historic practice is that if the buffer was cut in line mode,
+ * <newlines> were appended to each line as it was pushed onto
+ * the stack. If the buffer was cut in character mode, <newlines>
+ * were appended to all lines but the last one.
+ *
+ * XXX
+ * Historic practice is that execution of an @ buffer could be
+ * undone by a single 'u' command, i.e. the changes were grouped
+ * together. We don't get this right; I'm waiting for the new DB
+ * logging code to be available.
+ */
+ for (tp = cbp->textq.cqh_last;
+ tp != (void *)&cbp->textq; tp = tp->q.cqe_prev)
+ if ((F_ISSET(cbp, CB_LMODE) ||
+ tp->q.cqe_next != (void *)&cbp->textq) &&
+ v_event_push(sp, NULL, "\n", 1, 0) ||
+ v_event_push(sp, NULL, tp->lb, tp->len, 0))
+ return (1);
+
+ /*
+ * !!!
+ * If any count was supplied, it applies to the first command in the
+ * at buffer.
+ */
+ if (F_ISSET(vp, VC_C1SET)) {
+ len = snprintf(nbuf, sizeof(nbuf), "%lu", vp->count);
+ if (v_event_push(sp, NULL, nbuf, len, 0))
+ return (1);
+ }
+ return (0);
+}
diff --git a/usr.bin/vi/vi/v_ch.c b/contrib/nvi/vi/v_ch.c
index 1e59460ff7d9..6a1b61182680 100644
--- a/usr.bin/vi/vi/v_ch.c
+++ b/contrib/nvi/vi/v_ch.c
@@ -1,38 +1,16 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)v_ch.c 8.13 (Berkeley) 7/27/94";
+static const char sccsid[] = "@(#)v_ch.c 10.8 (Berkeley) 3/6/96";
#endif /* not lint */
#include <sys/types.h>
@@ -41,17 +19,11 @@ static char sccsid[] = "@(#)v_ch.c 8.13 (Berkeley) 7/27/94";
#include <bitstring.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
+#include "../common/common.h"
#include "vi.h"
-#include "vcmd.h"
static void notfound __P((SCR *, ARG_CHAR_T));
static void noprev __P((SCR *));
@@ -59,12 +31,13 @@ static void noprev __P((SCR *));
/*
* v_chrepeat -- [count];
* Repeat the last F, f, T or t search.
+ *
+ * PUBLIC: int v_chrepeat __P((SCR *, VICMD *));
*/
int
-v_chrepeat(sp, ep, vp)
+v_chrepeat(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
vp->character = VIP(sp)->lastckey;
@@ -73,13 +46,13 @@ v_chrepeat(sp, ep, vp)
noprev(sp);
return (1);
case FSEARCH:
- return (v_chF(sp, ep, vp));
+ return (v_chF(sp, vp));
case fSEARCH:
- return (v_chf(sp, ep, vp));
+ return (v_chf(sp, vp));
case TSEARCH:
- return (v_chT(sp, ep, vp));
+ return (v_chT(sp, vp));
case tSEARCH:
- return (v_cht(sp, ep, vp));
+ return (v_cht(sp, vp));
default:
abort();
}
@@ -89,14 +62,15 @@ v_chrepeat(sp, ep, vp)
/*
* v_chrrepeat -- [count],
* Repeat the last F, f, T or t search in the reverse direction.
+ *
+ * PUBLIC: int v_chrrepeat __P((SCR *, VICMD *));
*/
int
-v_chrrepeat(sp, ep, vp)
+v_chrrepeat(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
- enum cdirection savedir;
+ cdir_t savedir;
int rval;
vp->character = VIP(sp)->lastckey;
@@ -107,16 +81,16 @@ v_chrrepeat(sp, ep, vp)
noprev(sp);
return (1);
case FSEARCH:
- rval = v_chf(sp, ep, vp);
+ rval = v_chf(sp, vp);
break;
case fSEARCH:
- rval = v_chF(sp, ep, vp);
+ rval = v_chF(sp, vp);
break;
case TSEARCH:
- rval = v_cht(sp, ep, vp);
+ rval = v_cht(sp, vp);
break;
case tSEARCH:
- rval = v_chT(sp, ep, vp);
+ rval = v_chT(sp, vp);
break;
default:
abort();
@@ -129,14 +103,15 @@ v_chrrepeat(sp, ep, vp)
* v_cht -- [count]tc
* Search forward in the line for the character before the next
* occurrence of the specified character.
+ *
+ * PUBLIC: int v_cht __P((SCR *, VICMD *));
*/
int
-v_cht(sp, ep, vp)
+v_cht(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
- if (v_chf(sp, ep, vp))
+ if (v_chf(sp, vp))
return (1);
/*
@@ -161,17 +136,17 @@ v_cht(sp, ep, vp)
* v_chf -- [count]fc
* Search forward in the line for the next occurrence of the
* specified character.
+ *
+ * PUBLIC: int v_chf __P((SCR *, VICMD *));
*/
int
-v_chf(sp, ep, vp)
+v_chf(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
size_t len;
- recno_t lno;
u_long cnt;
- int key;
+ int isempty, key;
char *endp, *p, *startp;
/*
@@ -184,19 +159,14 @@ v_chf(sp, ep, vp)
VIP(sp)->lastckey = key;
VIP(sp)->csearchdir = fSEARCH;
- if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno == 0) {
- notfound(sp, key);
- return (1);
- }
- GETLINE_ERR(sp, vp->m_start.lno);
+ if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+ if (isempty)
+ goto empty;
return (1);
}
if (len == 0) {
- notfound(sp, key);
+empty: notfound(sp, key);
return (1);
}
@@ -213,8 +183,8 @@ v_chf(sp, ep, vp)
vp->m_stop.cno = p - startp;
/*
- * Non-motion commands move to the end of the range. VC_D
- * and VC_Y stay at the start. Ignore VC_C and VC_DEF.
+ * Non-motion commands move to the end of the range.
+ * Delete and yank stay at the start, ignore others.
*/
vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
return (0);
@@ -224,14 +194,15 @@ v_chf(sp, ep, vp)
* v_chT -- [count]Tc
* Search backward in the line for the character after the next
* occurrence of the specified character.
+ *
+ * PUBLIC: int v_chT __P((SCR *, VICMD *));
*/
int
-v_chT(sp, ep, vp)
+v_chT(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
- if (v_chF(sp, ep, vp))
+ if (v_chF(sp, vp))
return (1);
/*
@@ -240,17 +211,7 @@ v_chT(sp, ep, vp)
* we had to move left for v_chF() to have succeeded.
*/
++vp->m_stop.cno;
-
- /*
- * Make any necessary correction to the motion decision made
- * by the v_chF routine.
- *
- * XXX
- * If you change this, notice that v_chF changes vp->m_start
- * AFTER setting vp->m_final.
- */
- if (!F_ISSET(vp, VC_Y))
- vp->m_final = vp->m_stop;
+ vp->m_final = vp->m_stop;
VIP(sp)->csearchdir = TSEARCH;
return (0);
@@ -260,17 +221,17 @@ v_chT(sp, ep, vp)
* v_chF -- [count]Fc
* Search backward in the line for the next occurrence of the
* specified character.
+ *
+ * PUBLIC: int v_chF __P((SCR *, VICMD *));
*/
int
-v_chF(sp, ep, vp)
+v_chF(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
- recno_t lno;
size_t len;
u_long cnt;
- int key;
+ int isempty, key;
char *endp, *p;
/*
@@ -284,19 +245,14 @@ v_chF(sp, ep, vp)
VIP(sp)->lastckey = key;
VIP(sp)->csearchdir = FSEARCH;
- if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno == 0) {
- notfound(sp, key);
- return (1);
- }
- GETLINE_ERR(sp, vp->m_start.lno);
+ if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+ if (isempty)
+ goto empty;
return (1);
}
if (len == 0) {
- notfound(sp, key);
+empty: notfound(sp, key);
return (1);
}
@@ -313,12 +269,11 @@ v_chF(sp, ep, vp)
vp->m_stop.cno = (p - endp) - 1;
/*
- * VC_D and non-motion commands move to the end of the range,
- * VC_Y stays at the start. Ignore VC_C and VC_DEF. Motion
- * commands adjust the starting point to the character before
- * the current one.
+ * All commands move to the end of the range. Motion commands
+ * adjust the starting point to the character before the current
+ * one.
*/
- vp->m_final = F_ISSET(vp, VC_Y) ? vp->m_start : vp->m_stop;
+ vp->m_final = vp->m_stop;
if (ISMOTION(vp))
--vp->m_start.cno;
return (0);
@@ -328,7 +283,7 @@ static void
noprev(sp)
SCR *sp;
{
- msgq(sp, M_BERR, "No previous F, f, T or t search");
+ msgq(sp, M_BERR, "178|No previous F, f, T or t search");
}
static void
@@ -336,5 +291,5 @@ notfound(sp, ch)
SCR *sp;
ARG_CHAR_T ch;
{
- msgq(sp, M_BERR, "%s not found", KEY_NAME(sp, ch));
+ msgq(sp, M_BERR, "179|%s not found", KEY_NAME(sp, ch));
}
diff --git a/usr.bin/vi/vi/vcmd.c b/contrib/nvi/vi/v_cmd.c
index 59b6e8b34482..cc9e30f79ae4 100644
--- a/usr.bin/vi/vi/vcmd.c
+++ b/contrib/nvi/vi/v_cmd.c
@@ -1,38 +1,16 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)vcmd.c 8.39 (Berkeley) 7/28/94";
+static const char sccsid[] = "@(#)v_cmd.c 10.9 (Berkeley) 3/28/96";
#endif /* not lint */
#include <sys/types.h>
@@ -41,16 +19,10 @@ static char sccsid[] = "@(#)vcmd.c 8.39 (Berkeley) 7/28/94";
#include <bitstring.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
+#include "../common/common.h"
#include "vi.h"
-#include "vcmd.h"
/*
* This array maps keystrokes to vi command functions. It is known
@@ -117,7 +89,7 @@ VIKEYS const vikeys [MAXVIKEY + 1] = {
{v_up, V_CNT|V_MOVE|VM_LMODE|VM_RCM,
"[count]^P",
"^P move up by lines"},
-/* 021 ^Q -- not available, used for hardware flow control. */
+/* 021 ^Q -- same as ^V if not used for hardware flow control. */
{NULL},
/* 022 ^R */
{v_redraw, 0,
@@ -148,13 +120,13 @@ VIKEYS const vikeys [MAXVIKEY + 1] = {
"[count]^Y",
"^Y page up by lines"},
/* 032 ^Z */
- {v_stop, 0,
+ {v_suspend, V_SECURE,
"^Z",
"^Z suspend editor"},
/* 033 ^[ */
{NULL, 0,
"^[ <escape>",
- "^[ <escape> leave input mode, return to command mode"},
+ "^[ <escape> exit input mode, cancel partial commands"},
/* 034 ^\ */
{v_exmode, 0,
"^\\",
@@ -174,14 +146,14 @@ VIKEYS const vikeys [MAXVIKEY + 1] = {
"[count]' '",
" <space> move right by columns"},
/* 041 ! */
- {v_filter, V_CNT|V_DOT|V_MOTION|VC_DEF|VM_RCM_SET,
+ {v_filter, V_CNT|V_DOT|V_MOTION|V_SECURE|VM_RCM_SET,
"[count]![count]motion command(s)",
" ! filter through command(s) to motion"},
/* 042 " */
{NULL},
/* 043 # */
- {v_increment, V_CHAR|V_CNT|V_DOT|V_KEYNUM|VM_RCM_SET,
- "[count]#[#+-]",
+ {v_increment, V_CHAR|V_CNT|V_DOT|VM_RCM_SET,
+ "[count]# +|-|#",
" # number increment/decrement"},
/* 044 $ */
{v_dollar, V_CNT|V_MOVE|VM_RCM_SETLAST,
@@ -196,7 +168,7 @@ VIKEYS const vikeys [MAXVIKEY + 1] = {
"&",
" & repeat substitution"},
/* 047 ' */
- {v_fmark, V_ABS_L|V_CHAR|V_MOVE|VM_LMODE,
+ {v_fmark, V_ABS_L|V_CHAR|V_MOVE|VM_LMODE|VM_RCM_SET,
"'['a-z]",
" ' move to mark (to first non-blank)"},
/* 050 ( */
@@ -260,13 +232,13 @@ VIKEYS const vikeys [MAXVIKEY + 1] = {
"[count];",
" ; repeat last F, f, T or t search"},
/* 074 < */
- {v_shiftl, V_CNT|V_DOT|V_MOTION|VC_DEF|VM_RCM_SET,
+ {v_shiftl, V_CNT|V_DOT|V_MOTION|VM_RCM_SET,
"[count]<[count]motion",
" < shift lines left to motion"},
/* 075 = */
{NULL},
/* 076 > */
- {v_shiftr, V_CNT|V_DOT|V_MOTION|VC_DEF|VM_RCM_SET,
+ {v_shiftr, V_CNT|V_DOT|V_MOTION|VM_RCM_SET,
"[count]>[count]motion",
" > shift lines right to motion"},
/* 077 ? */
@@ -274,7 +246,7 @@ VIKEYS const vikeys [MAXVIKEY + 1] = {
"?RE[? offset]",
" ? search backward"},
/* 100 @ */
- {v_at, V_RBUF|VM_RCM_SET,
+ {v_at, V_CNT|V_RBUF|VM_RCM_SET,
"@buffer",
" @ execute buffer"},
/* 101 A */
@@ -286,12 +258,12 @@ VIKEYS const vikeys [MAXVIKEY + 1] = {
"[count]B",
" B move back bigword"},
/* 103 C */
- {v_Change, V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
+ {NULL, 0,
"[buffer][count]C",
" C change to end-of-line"},
/* 104 D */
- {v_Delete, V_CNT|V_DOT|V_OBUF|VM_RCM_SET,
- "[buffer][count]D",
+ {NULL, 0,
+ "[buffer]D",
" D delete to end-of-line"},
/* 105 E */
{v_wordE, V_CNT|V_MOVE|VM_RCM_SET,
@@ -312,7 +284,7 @@ VIKEYS const vikeys [MAXVIKEY + 1] = {
/* 111 I */
{v_iI, V_CNT|V_DOT|VM_RCM_SET,
"[count]I",
- " I insert at line beginning"},
+ " I insert before first nonblank"},
/* 112 J */
{v_join, V_CNT|V_DOT|VM_RCM_SET,
"[count]J",
@@ -348,7 +320,7 @@ VIKEYS const vikeys [MAXVIKEY + 1] = {
"[count]R",
" R replace characters"},
/* 123 S */
- {v_Subst, V_CNT|V_DOT|V_OBUF|VM_LMODE|VM_RCM_SET,
+ {NULL, 0,
"[buffer][count]S",
" S substitute for the line(s)"},
/* 124 T */
@@ -370,7 +342,7 @@ VIKEYS const vikeys [MAXVIKEY + 1] = {
"[buffer][count]X",
" X delete character before cursor"},
/* 131 Y */
- {v_yank, V_CNT|VM_LMODE|V_OBUF,
+ {NULL, 0,
"[buffer][count]Y",
" Y copy line"},
/* 132 Z */
@@ -417,11 +389,11 @@ VIKEYS const vikeys [MAXVIKEY + 1] = {
"[count]b",
" b move back word"},
/* 143 c */
- {v_change, V_CNT|V_DOT|V_MOTION|V_OBUF|VC_C|VM_RCM_SET,
+ {v_change, V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET,
"[buffer][count]c[count]motion",
" c change to motion"},
/* 144 d */
- {v_delete, V_CNT|V_DOT|V_MOTION|V_OBUF|VC_D|VM_RCM_SET,
+ {v_delete, V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET,
"[buffer][count]d[count]motion",
" d delete to motion"},
/* 145 e */
@@ -503,7 +475,7 @@ VIKEYS const vikeys [MAXVIKEY + 1] = {
"[buffer][count]x",
" x delete character"},
/* 171 y */
- {v_yank, V_CNT|V_MOTION|V_OBUF|VC_Y|VM_RCM_SET,
+ {v_yank, V_CNT|V_DOT|V_MOTION|V_OBUF|VM_RCM_SET,
"[buffer][count]y[count]motion",
" y copy text to motion into a cut buffer"},
/* 172 z */
@@ -511,9 +483,9 @@ VIKEYS const vikeys [MAXVIKEY + 1] = {
* DON'T set the V_CHAR flag, the char isn't required,
* so it's handled specially in getcmd().
*/
- {v_z, V_ABS_L|V_CNT|VM_RCM_SET,
+ {v_z, V_ABS_L|V_CNT|VM_RCM_SETFNB,
"[line]z[window_size][-|.|+|^|<CR>]",
- " z redraw window"},
+ " z reposition the screen"},
/* 173 { */
{v_paragraphb, V_ABS|V_CNT|V_MOVE|VM_CUTREQ|VM_RCM_SET,
"[count]{",
diff --git a/contrib/nvi/vi/v_delete.c b/contrib/nvi/vi/v_delete.c
new file mode 100644
index 000000000000..70df78b22e2c
--- /dev/null
+++ b/contrib/nvi/vi/v_delete.c
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_delete.c 10.9 (Berkeley) 10/23/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_delete -- [buffer][count]d[count]motion
+ * [buffer][count]D
+ * Delete a range of text.
+ *
+ * PUBLIC: int v_delete __P((SCR *, VICMD *));
+ */
+int
+v_delete(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ recno_t nlines;
+ size_t len;
+ int lmode;
+
+ lmode = F_ISSET(vp, VM_LMODE) ? CUT_LINEMODE : 0;
+
+ /* Yank the lines. */
+ if (cut(sp, F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
+ &vp->m_start, &vp->m_stop,
+ lmode | (F_ISSET(vp, VM_CUTREQ) ? CUT_NUMREQ : CUT_NUMOPT)))
+ return (1);
+
+ /* Delete the lines. */
+ if (del(sp, &vp->m_start, &vp->m_stop, lmode))
+ return (1);
+
+ /*
+ * Check for deletion of the entire file. Try to check a close
+ * by line so we don't go to the end of the file unnecessarily.
+ */
+ if (!db_exist(sp, vp->m_final.lno + 1)) {
+ if (db_last(sp, &nlines))
+ return (1);
+ if (nlines == 0) {
+ vp->m_final.lno = 1;
+ vp->m_final.cno = 0;
+ return (0);
+ }
+ }
+
+ /*
+ * One special correction, in case we've deleted the current line or
+ * character. We check it here instead of checking in every command
+ * that can be a motion component.
+ */
+ if (db_get(sp, vp->m_final.lno, 0, NULL, &len)) {
+ if (db_get(sp, nlines, DBG_FATAL, NULL, &len))
+ return (1);
+ vp->m_final.lno = nlines;
+ }
+
+ /*
+ * !!!
+ * Cursor movements, other than those caused by a line mode command
+ * moving to another line, historically reset the relative position.
+ *
+ * This currently matches the check made in v_yank(), I'm hoping that
+ * they should be consistent...
+ */
+ if (!F_ISSET(vp, VM_LMODE)) {
+ F_CLR(vp, VM_RCM_MASK);
+ F_SET(vp, VM_RCM_SET);
+
+ /* Make sure the set cursor position exists. */
+ if (vp->m_final.cno >= len)
+ vp->m_final.cno = len ? len - 1 : 0;
+ }
+
+ /*
+ * !!!
+ * The "dd" command moved to the first non-blank; "d<motion>"
+ * didn't.
+ */
+ if (F_ISSET(vp, VM_LDOUBLE)) {
+ F_CLR(vp, VM_RCM_MASK);
+ F_SET(vp, VM_RCM_SETFNB);
+ }
+ return (0);
+}
diff --git a/contrib/nvi/vi/v_ex.c b/contrib/nvi/vi/v_ex.c
new file mode 100644
index 000000000000..359080c656e3
--- /dev/null
+++ b/contrib/nvi/vi/v_ex.c
@@ -0,0 +1,696 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_ex.c 10.42 (Berkeley) 6/28/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+static int v_ecl __P((SCR *));
+static int v_ecl_init __P((SCR *));
+static int v_ecl_log __P((SCR *, TEXT *));
+static int v_ex_done __P((SCR *, VICMD *));
+static int v_exec_ex __P((SCR *, VICMD *, EXCMD *));
+
+/*
+ * v_again -- &
+ * Repeat the previous substitution.
+ *
+ * PUBLIC: int v_again __P((SCR *, VICMD *));
+ */
+int
+v_again(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ ARGS *ap[2], a;
+ EXCMD cmd;
+
+ ex_cinit(&cmd, C_SUBAGAIN, 2, vp->m_start.lno, vp->m_start.lno, 1, ap);
+ ex_cadd(&cmd, &a, "", 1);
+
+ return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_exmode -- Q
+ * Switch the editor into EX mode.
+ *
+ * PUBLIC: int v_exmode __P((SCR *, VICMD *));
+ */
+int
+v_exmode(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ GS *gp;
+
+ gp = sp->gp;
+
+ /* Try and switch screens -- the screen may not permit it. */
+ if (gp->scr_screen(sp, SC_EX)) {
+ msgq(sp, M_ERR,
+ "207|The Q command requires the ex terminal interface");
+ return (1);
+ }
+ (void)gp->scr_attr(sp, SA_ALTERNATE, 0);
+
+ /* Save the current cursor position. */
+ sp->frp->lno = sp->lno;
+ sp->frp->cno = sp->cno;
+ F_SET(sp->frp, FR_CURSORSET);
+
+ /* Switch to ex mode. */
+ F_CLR(sp, SC_VI | SC_SCR_VI);
+ F_SET(sp, SC_EX);
+
+ /* Move out of the vi screen. */
+ (void)ex_puts(sp, "\n");
+
+ return (0);
+}
+
+/*
+ * v_join -- [count]J
+ * Join lines together.
+ *
+ * PUBLIC: int v_join __P((SCR *, VICMD *));
+ */
+int
+v_join(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ EXCMD cmd;
+ int lno;
+
+ /*
+ * YASC.
+ * The general rule is that '#J' joins # lines, counting the current
+ * line. However, 'J' and '1J' are the same as '2J', i.e. join the
+ * current and next lines. This doesn't map well into the ex command
+ * (which takes two line numbers), so we handle it here. Note that
+ * we never test for EOF -- historically going past the end of file
+ * worked just fine.
+ */
+ lno = vp->m_start.lno + 1;
+ if (F_ISSET(vp, VC_C1SET) && vp->count > 2)
+ lno = vp->m_start.lno + (vp->count - 1);
+
+ ex_cinit(&cmd, C_JOIN, 2, vp->m_start.lno, lno, 0, NULL);
+ return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_shiftl -- [count]<motion
+ * Shift lines left.
+ *
+ * PUBLIC: int v_shiftl __P((SCR *, VICMD *));
+ */
+int
+v_shiftl(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ ARGS *ap[2], a;
+ EXCMD cmd;
+
+ ex_cinit(&cmd, C_SHIFTL, 2, vp->m_start.lno, vp->m_stop.lno, 0, ap);
+ ex_cadd(&cmd, &a, "<", 1);
+ return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_shiftr -- [count]>motion
+ * Shift lines right.
+ *
+ * PUBLIC: int v_shiftr __P((SCR *, VICMD *));
+ */
+int
+v_shiftr(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ ARGS *ap[2], a;
+ EXCMD cmd;
+
+ ex_cinit(&cmd, C_SHIFTR, 2, vp->m_start.lno, vp->m_stop.lno, 0, ap);
+ ex_cadd(&cmd, &a, ">", 1);
+ return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_suspend -- ^Z
+ * Suspend vi.
+ *
+ * PUBLIC: int v_suspend __P((SCR *, VICMD *));
+ */
+int
+v_suspend(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ ARGS *ap[2], a;
+ EXCMD cmd;
+
+ ex_cinit(&cmd, C_STOP, 0, OOBLNO, OOBLNO, 0, ap);
+ ex_cadd(&cmd, &a, "suspend", sizeof("suspend") - 1);
+ return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_switch -- ^^
+ * Switch to the previous file.
+ *
+ * PUBLIC: int v_switch __P((SCR *, VICMD *));
+ */
+int
+v_switch(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ ARGS *ap[2], a;
+ EXCMD cmd;
+ char *name;
+
+ /*
+ * Try the alternate file name, then the previous file
+ * name. Use the real name, not the user's current name.
+ */
+ if ((name = sp->alt_name) == NULL) {
+ msgq(sp, M_ERR, "180|No previous file to edit");
+ return (1);
+ }
+
+ /* If autowrite is set, write out the file. */
+ if (file_m1(sp, 0, FS_ALL))
+ return (1);
+
+ ex_cinit(&cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0, ap);
+ ex_cadd(&cmd, &a, name, strlen(name));
+ return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_tagpush -- ^[
+ * Do a tag search on the cursor keyword.
+ *
+ * PUBLIC: int v_tagpush __P((SCR *, VICMD *));
+ */
+int
+v_tagpush(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ ARGS *ap[2], a;
+ EXCMD cmd;
+
+ ex_cinit(&cmd, C_TAG, 0, OOBLNO, 0, 0, ap);
+ ex_cadd(&cmd, &a, VIP(sp)->keyw, strlen(VIP(sp)->keyw));
+ return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_tagpop -- ^T
+ * Pop the tags stack.
+ *
+ * PUBLIC: int v_tagpop __P((SCR *, VICMD *));
+ */
+int
+v_tagpop(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ EXCMD cmd;
+
+ ex_cinit(&cmd, C_TAGPOP, 0, OOBLNO, 0, 0, NULL);
+ return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_filter -- [count]!motion command(s)
+ * Run range through shell commands, replacing text.
+ *
+ * PUBLIC: int v_filter __P((SCR *, VICMD *));
+ */
+int
+v_filter(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ EXCMD cmd;
+ TEXT *tp;
+
+ /*
+ * !!!
+ * Historical vi permitted "!!" in an empty file, and it's handled
+ * as a special case in the ex_bang routine. Don't modify this setup
+ * without understanding that one. In particular, note that we're
+ * manipulating the ex argument structures behind ex's back.
+ *
+ * !!!
+ * Historical vi did not permit the '!' command to be associated with
+ * a non-line oriented motion command, in general, although it did
+ * with search commands. So, !f; and !w would fail, but !/;<CR>
+ * would succeed, even if they all moved to the same location in the
+ * current line. I don't see any reason to disallow '!' using any of
+ * the possible motion commands.
+ *
+ * !!!
+ * Historical vi ran the last bang command if N or n was used as the
+ * search motion.
+ */
+ if (F_ISSET(vp, VC_ISDOT) ||
+ ISCMD(vp->rkp, 'N') || ISCMD(vp->rkp, 'n')) {
+ ex_cinit(&cmd, C_BANG,
+ 2, vp->m_start.lno, vp->m_stop.lno, 0, NULL);
+ EXP(sp)->argsoff = 0; /* XXX */
+
+ if (argv_exp1(sp, &cmd, "!", 1, 1))
+ return (1);
+ cmd.argc = EXP(sp)->argsoff; /* XXX */
+ cmd.argv = EXP(sp)->args; /* XXX */
+ return (v_exec_ex(sp, vp, &cmd));
+ }
+
+ /* Get the command from the user. */
+ if (v_tcmd(sp, vp,
+ '!', TXT_BS | TXT_CR | TXT_ESCAPE | TXT_FILEC | TXT_PROMPT))
+ return (1);
+
+ /*
+ * Check to see if the user changed their mind.
+ *
+ * !!!
+ * Entering <escape> on an empty line was historically an error,
+ * this implementation doesn't bother.
+ */
+ tp = sp->tiq.cqh_first;
+ if (tp->term != TERM_OK) {
+ vp->m_final.lno = sp->lno;
+ vp->m_final.cno = sp->cno;
+ return (0);
+ }
+
+ /* Home the cursor. */
+ vs_home(sp);
+
+ ex_cinit(&cmd, C_BANG, 2, vp->m_start.lno, vp->m_stop.lno, 0, NULL);
+ EXP(sp)->argsoff = 0; /* XXX */
+
+ if (argv_exp1(sp, &cmd, tp->lb + 1, tp->len - 1, 1))
+ return (1);
+ cmd.argc = EXP(sp)->argsoff; /* XXX */
+ cmd.argv = EXP(sp)->args; /* XXX */
+ return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_event_exec --
+ * Execute some command(s) based on an event.
+ *
+ * PUBLIC: int v_event_exec __P((SCR *, VICMD *));
+ */
+int
+v_event_exec(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ EXCMD cmd;
+
+ switch (vp->ev.e_event) {
+ case E_QUIT:
+ ex_cinit(&cmd, C_QUIT, 0, OOBLNO, OOBLNO, 0, NULL);
+ break;
+ case E_WRITE:
+ ex_cinit(&cmd, C_WRITE, 0, OOBLNO, OOBLNO, 0, NULL);
+ break;
+ default:
+ abort();
+ }
+ return (v_exec_ex(sp, vp, &cmd));
+}
+
+/*
+ * v_exec_ex --
+ * Execute an ex command.
+ */
+static int
+v_exec_ex(sp, vp, exp)
+ SCR *sp;
+ VICMD *vp;
+ EXCMD *exp;
+{
+ int rval;
+
+ rval = exp->cmd->fn(sp, exp);
+ return (v_ex_done(sp, vp) || rval);
+}
+
+/*
+ * v_ex -- :
+ * Execute a colon command line.
+ *
+ * PUBLIC: int v_ex __P((SCR *, VICMD *));
+ */
+int
+v_ex(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ GS *gp;
+ TEXT *tp;
+ int do_cedit, do_resolution, ifcontinue;
+
+ gp = sp->gp;
+
+ /*
+ * !!!
+ * If we put out more than a single line of messages, or ex trashes
+ * the screen, the user may continue entering ex commands. We find
+ * this out when we do the screen/message resolution. We can't enter
+ * completely into ex mode however, because the user can elect to
+ * return into vi mode by entering any key, i.e. we have to be in raw
+ * mode.
+ */
+ for (do_cedit = do_resolution = 0;;) {
+ /*
+ * !!!
+ * There may already be an ex command waiting to run. If
+ * so, we continue with it.
+ */
+ if (!EXCMD_RUNNING(gp)) {
+ /* Get a command. */
+ if (v_tcmd(sp, vp, ':',
+ TXT_BS | TXT_CEDIT | TXT_FILEC | TXT_PROMPT))
+ return (1);
+ tp = sp->tiq.cqh_first;
+
+ /*
+ * If the user entered a single <esc>, they want to
+ * edit their colon command history. If they already
+ * entered some text, move it into the edit history.
+ */
+ if (tp->term == TERM_CEDIT) {
+ if (tp->len > 1 && v_ecl_log(sp, tp))
+ return (1);
+ do_cedit = 1;
+ break;
+ }
+
+ /* If the user didn't enter anything, return. */
+ if (tp->term == TERM_BS)
+ break;
+
+ /* Log the command. */
+ if (O_STR(sp, O_CEDIT) != NULL && v_ecl_log(sp, tp))
+ return (1);
+
+ /* Push a command on the command stack. */
+ if (ex_run_str(sp, NULL, tp->lb, tp->len, 0, 1))
+ return (1);
+ }
+
+ /* Home the cursor. */
+ vs_home(sp);
+
+ /*
+ * !!!
+ * If the editor wrote the screen behind curses back, put out
+ * a <newline> so that we don't overwrite the user's command
+ * with its output or the next want-to-continue? message. This
+ * doesn't belong here, but I can't find another place to put
+ * it. See, we resolved the output from the last ex command,
+ * and the user entered another one. This is the only place
+ * where we have control before the ex command writes output.
+ * We could get control in vs_msg(), but we have no way to know
+ * if command didn't put out any output when we try and resolve
+ * this command. This fixes a bug where combinations of ex
+ * commands, e.g. ":set<CR>:!date<CR>:set" didn't look right.
+ */
+ if (F_ISSET(sp, SC_SCR_EXWROTE))
+ (void)putchar('\n');
+
+ /* Call the ex parser. */
+ (void)ex_cmd(sp);
+
+ /* Flush ex messages. */
+ (void)ex_fflush(sp);
+
+ /* Resolve any messages. */
+ if (vs_ex_resolve(sp, &ifcontinue))
+ return (1);
+
+ /*
+ * Continue or return. If continuing, make sure that we
+ * eventually do resolution.
+ */
+ if (!ifcontinue)
+ break;
+ do_resolution = 1;
+
+ /* If we're continuing, it's a new command. */
+ ++sp->ccnt;
+ }
+
+ /*
+ * If the user previously continued an ex command, we have to do
+ * resolution to clean up the screen. Don't wait, we already did
+ * that.
+ */
+ if (do_resolution) {
+ F_SET(sp, SC_EX_WAIT_NO);
+ if (vs_ex_resolve(sp, &ifcontinue))
+ return (1);
+ }
+
+ /* Cleanup from the ex command. */
+ if (v_ex_done(sp, vp))
+ return (1);
+
+ /* The user may want to edit their colon command history. */
+ if (do_cedit)
+ return (v_ecl(sp));
+
+ return (0);
+}
+
+/*
+ * v_ex_done --
+ * Cleanup from an ex command.
+ */
+static int
+v_ex_done(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ size_t len;
+
+ /*
+ * The only cursor modifications are real, however, the underlying
+ * line may have changed; don't trust anything. This code has been
+ * a remarkably fertile place for bugs. Do a reality check on a
+ * cursor value, and make sure it's okay. If necessary, change it.
+ * Ex keeps track of the line number, but it cares less about the
+ * column and it may have disappeared.
+ *
+ * Don't trust ANYTHING.
+ *
+ * XXX
+ * Ex will soon have to start handling the column correctly; see
+ * the POSIX 1003.2 standard.
+ */
+ if (db_eget(sp, sp->lno, NULL, &len, NULL)) {
+ sp->lno = 1;
+ sp->cno = 0;
+ } else if (sp->cno >= len)
+ sp->cno = len ? len - 1 : 0;
+
+ vp->m_final.lno = sp->lno;
+ vp->m_final.cno = sp->cno;
+
+ /*
+ * Don't re-adjust the cursor after executing an ex command,
+ * and ex movements are permanent.
+ */
+ F_CLR(vp, VM_RCM_MASK);
+ F_SET(vp, VM_RCM_SET);
+
+ return (0);
+}
+
+/*
+ * v_ecl --
+ * Start an edit window on the colon command-line commands.
+ */
+static int
+v_ecl(sp)
+ SCR *sp;
+{
+ GS *gp;
+ SCR *new;
+
+ /* Initialize the screen, if necessary. */
+ gp = sp->gp;
+ if (gp->ccl_sp == NULL && v_ecl_init(sp))
+ return (1);
+
+ /* Get a new screen. */
+ if (screen_init(gp, sp, &new))
+ return (1);
+ if (vs_split(sp, new, 1)) {
+ (void)screen_end(new);
+ return (1);
+ }
+
+ /* Attach to the screen. */
+ new->ep = gp->ccl_sp->ep;
+ ++new->ep->refcnt;
+
+ new->frp = gp->ccl_sp->frp;
+ new->frp->flags = sp->frp->flags;
+
+ /* Move the cursor to the end. */
+ (void)db_last(new, &new->lno);
+ if (new->lno == 0)
+ new->lno = 1;
+
+ /* Remember the originating window. */
+ sp->ccl_parent = sp;
+
+ /* It's a special window. */
+ F_SET(new, SC_COMEDIT);
+
+ /* Set up the switch. */
+ sp->nextdisp = new;
+ F_SET(sp, SC_SSWITCH);
+ return (0);
+}
+
+/*
+ * v_ecl_exec --
+ * Execute a command from a colon command-line window.
+ *
+ * PUBLIC: int v_ecl_exec __P((SCR *));
+ */
+int
+v_ecl_exec(sp)
+ SCR *sp;
+{
+ size_t len;
+ char *p;
+
+ if (db_get(sp, sp->lno, 0, &p, &len) && sp->lno == 1) {
+ v_emsg(sp, NULL, VIM_EMPTY);
+ return (1);
+ }
+ if (len == 0) {
+ msgq(sp, M_BERR, "307|No ex command to execute");
+ return (1);
+ }
+
+ /* Push the command on the command stack. */
+ if (ex_run_str(sp, NULL, p, len, 0, 0))
+ return (1);
+
+ /* Set up the switch. */
+ sp->nextdisp = sp->ccl_parent;
+ F_SET(sp, SC_EXIT);
+ return (0);
+}
+
+/*
+ * v_ecl_log --
+ * Log a command into the colon command-line log file.
+ */
+static int
+v_ecl_log(sp, tp)
+ SCR *sp;
+ TEXT *tp;
+{
+ EXF *save_ep;
+ recno_t lno;
+ int rval;
+
+ /* Initialize the screen, if necessary. */
+ if (sp->gp->ccl_sp == NULL && v_ecl_init(sp))
+ return (1);
+
+ /*
+ * Don't log colon command window commands into the colon command
+ * window...
+ */
+ if (sp->ep == sp->gp->ccl_sp->ep)
+ return (0);
+
+ /*
+ * XXX
+ * Swap the current EXF with the colon command file EXF. This
+ * isn't pretty, but too many routines "know" that sp->ep points
+ * to the current EXF.
+ */
+ save_ep = sp->ep;
+ sp->ep = sp->gp->ccl_sp->ep;
+ if (db_last(sp, &lno)) {
+ sp->ep = save_ep;
+ return (1);
+ }
+ rval = db_append(sp, 0, lno, tp->lb, tp->len);
+ sp->ep = save_ep;
+ return (rval);
+}
+
+/*
+ * v_ecl_init --
+ * Initialize the colon command-line log file.
+ */
+static int
+v_ecl_init(sp)
+ SCR *sp;
+{
+ FREF *frp;
+ GS *gp;
+
+ gp = sp->gp;
+
+ /* Get a temporary file. */
+ if ((frp = file_add(sp, NULL)) == NULL)
+ return (1);
+
+ /*
+ * XXX
+ * Create a screen -- the file initialization code wants one.
+ */
+ if (screen_init(gp, sp, &gp->ccl_sp))
+ return (1);
+ if (file_init(gp->ccl_sp, frp, NULL, 0)) {
+ (void)screen_end(gp->ccl_sp);
+ return (1);
+ }
+
+ /* The underlying file isn't recoverable. */
+ F_CLR(gp->ccl_sp->ep, F_RCV_ON);
+
+ return (0);
+}
diff --git a/contrib/nvi/vi/v_increment.c b/contrib/nvi/vi/v_increment.c
new file mode 100644
index 000000000000..45e763fa5bd5
--- /dev/null
+++ b/contrib/nvi/vi/v_increment.c
@@ -0,0 +1,267 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_increment.c 10.12 (Berkeley) 3/19/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+static char * const fmt[] = {
+#define DEC 0
+ "%ld",
+#define SDEC 1
+ "%+ld",
+#define HEXC 2
+ "0X%0*lX",
+#define HEXL 3
+ "0x%0*lx",
+#define OCTAL 4
+ "%#0*lo",
+};
+
+static void inc_err __P((SCR *, enum nresult));
+
+/*
+ * v_increment -- [count]#[#+-]
+ * Increment/decrement a keyword number.
+ *
+ * PUBLIC: int v_increment __P((SCR *, VICMD *));
+ */
+int
+v_increment(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ enum nresult nret;
+ u_long ulval;
+ long change, ltmp, lval;
+ size_t beg, blen, end, len, nlen, wlen;
+ int base, isempty, rval;
+ char *bp, *ntype, *p, *t, nbuf[100];
+
+ /* Validate the operator. */
+ if (vp->character == '#')
+ vp->character = '+';
+ if (vp->character != '+' && vp->character != '-') {
+ v_emsg(sp, vp->kp->usage, VIM_USAGE);
+ return (1);
+ }
+
+ /* If new value set, save it off, but it has to fit in a long. */
+ if (F_ISSET(vp, VC_C1SET)) {
+ if (vp->count > LONG_MAX) {
+ inc_err(sp, NUM_OVER);
+ return (1);
+ }
+ change = vp->count;
+ } else
+ change = 1;
+
+ /* Get the line. */
+ if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+ if (isempty)
+ goto nonum;
+ return (1);
+ }
+
+ /*
+ * Skip any leading space before the number. Getting a cursor word
+ * implies moving the cursor to its beginning, if we moved, refresh
+ * now.
+ */
+ for (beg = vp->m_start.cno; beg < len && isspace(p[beg]); ++beg);
+ if (beg >= len)
+ goto nonum;
+ if (beg != vp->m_start.cno) {
+ sp->cno = beg;
+ (void)vs_refresh(sp, 0);
+ }
+
+#undef ishex
+#define ishex(c) (isdigit(c) || strchr("abcdefABCDEF", c))
+#undef isoctal
+#define isoctal(c) (isdigit(c) && (c) != '8' && (c) != '9')
+
+ /*
+ * Look for 0[Xx], or leading + or - signs, guess at the base.
+ * The character after that must be a number. Wlen is set to
+ * the remaining characters in the line that could be part of
+ * the number.
+ */
+ wlen = len - beg;
+ if (p[beg] == '0' && wlen > 2 &&
+ (p[beg + 1] == 'X' || p[beg + 1] == 'x')) {
+ base = 16;
+ end = beg + 2;
+ if (!ishex(p[end]))
+ goto decimal;
+ ntype = p[beg + 1] == 'X' ? fmt[HEXC] : fmt[HEXL];
+ } else if (p[beg] == '0' && wlen > 1) {
+ base = 8;
+ end = beg + 1;
+ if (!isoctal(p[end]))
+ goto decimal;
+ ntype = fmt[OCTAL];
+ } else if (wlen >= 1 && (p[beg] == '+' || p[beg] == '-')) {
+ base = 10;
+ end = beg + 1;
+ ntype = fmt[SDEC];
+ if (!isdigit(p[end]))
+ goto nonum;
+ } else {
+decimal: base = 10;
+ end = beg;
+ ntype = fmt[DEC];
+ if (!isdigit(p[end])) {
+nonum: msgq(sp, M_ERR, "181|Cursor not in a number");
+ return (1);
+ }
+ }
+
+ /* Find the end of the word, possibly correcting the base. */
+ while (++end < len) {
+ switch (base) {
+ case 8:
+ if (isoctal(p[end]))
+ continue;
+ if (p[end] == '8' || p[end] == '9') {
+ base = 10;
+ ntype = fmt[DEC];
+ continue;
+ }
+ break;
+ case 10:
+ if (isdigit(p[end]))
+ continue;
+ break;
+ case 16:
+ if (ishex(p[end]))
+ continue;
+ break;
+ default:
+ abort();
+ /* NOTREACHED */
+ }
+ break;
+ }
+ wlen = (end - beg);
+
+ /*
+ * XXX
+ * If the line was at the end of the buffer, we have to copy it
+ * so we can guarantee that it's NULL-terminated. We make the
+ * buffer big enough to fit the line changes as well, and only
+ * allocate once.
+ */
+ GET_SPACE_RET(sp, bp, blen, len + 50);
+ if (end == len) {
+ memmove(bp, &p[beg], wlen);
+ bp[wlen] = '\0';
+ t = bp;
+ } else
+ t = &p[beg];
+
+ /*
+ * Octal or hex deal in unsigned longs, everything else is done
+ * in signed longs.
+ */
+ if (base == 10) {
+ if ((nret = nget_slong(&lval, t, NULL, 10)) != NUM_OK)
+ goto err;
+ ltmp = vp->character == '-' ? -change : change;
+ if (lval > 0 && ltmp > 0 && !NPFITS(LONG_MAX, lval, ltmp)) {
+ nret = NUM_OVER;
+ goto err;
+ }
+ if (lval < 0 && ltmp < 0 && !NNFITS(LONG_MIN, lval, ltmp)) {
+ nret = NUM_UNDER;
+ goto err;
+ }
+ lval += ltmp;
+ /* If we cross 0, signed numbers lose their sign. */
+ if (lval == 0 && ntype == fmt[SDEC])
+ ntype = fmt[DEC];
+ nlen = snprintf(nbuf, sizeof(nbuf), ntype, lval);
+ } else {
+ if ((nret = nget_uslong(&ulval, t, NULL, base)) != NUM_OK)
+ goto err;
+ if (vp->character == '+') {
+ if (!NPFITS(ULONG_MAX, ulval, change)) {
+ nret = NUM_OVER;
+ goto err;
+ }
+ ulval += change;
+ } else {
+ if (ulval < change) {
+ nret = NUM_UNDER;
+ goto err;
+ }
+ ulval -= change;
+ }
+
+ /* Correct for literal "0[Xx]" in format. */
+ if (base == 16)
+ wlen -= 2;
+
+ nlen = snprintf(nbuf, sizeof(nbuf), ntype, wlen, ulval);
+ }
+
+ /* Build the new line. */
+ memmove(bp, p, beg);
+ memmove(bp + beg, nbuf, nlen);
+ memmove(bp + beg + nlen, p + end, len - beg - (end - beg));
+ len = beg + nlen + (len - beg - (end - beg));
+
+ nret = NUM_OK;
+ rval = db_set(sp, vp->m_start.lno, bp, len);
+
+ if (0) {
+err: rval = 1;
+ inc_err(sp, nret);
+ }
+ if (bp != NULL)
+ FREE_SPACE(sp, bp, blen);
+ return (rval);
+}
+
+static void
+inc_err(sp, nret)
+ SCR *sp;
+ enum nresult nret;
+{
+ switch (nret) {
+ case NUM_ERR:
+ break;
+ case NUM_OK:
+ abort();
+ /* NOREACHED */
+ case NUM_OVER:
+ msgq(sp, M_ERR, "182|Resulting number too large");
+ break;
+ case NUM_UNDER:
+ msgq(sp, M_ERR, "183|Resulting number too small");
+ break;
+ }
+}
diff --git a/contrib/nvi/vi/v_init.c b/contrib/nvi/vi/v_init.c
new file mode 100644
index 000000000000..ee58de377ada
--- /dev/null
+++ b/contrib/nvi/vi/v_init.c
@@ -0,0 +1,126 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_init.c 10.8 (Berkeley) 3/30/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_screen_copy --
+ * Copy vi screen.
+ *
+ * PUBLIC: int v_screen_copy __P((SCR *, SCR *));
+ */
+int
+v_screen_copy(orig, sp)
+ SCR *orig, *sp;
+{
+ VI_PRIVATE *ovip, *nvip;
+
+ /* Create the private vi structure. */
+ CALLOC_RET(orig, nvip, VI_PRIVATE *, 1, sizeof(VI_PRIVATE));
+ sp->vi_private = nvip;
+
+ /* Invalidate the line size cache. */
+ VI_SCR_CFLUSH(nvip);
+
+ if (orig == NULL) {
+ nvip->csearchdir = CNOTSET;
+ } else {
+ ovip = VIP(orig);
+
+ /* User can replay the last input, but nothing else. */
+ if (ovip->rep_len != 0) {
+ MALLOC_RET(orig, nvip->rep, EVENT *, ovip->rep_len);
+ memmove(nvip->rep, ovip->rep, ovip->rep_len);
+ nvip->rep_len = ovip->rep_len;
+ }
+
+ /* Copy the paragraph/section information. */
+ if (ovip->ps != NULL && (nvip->ps =
+ v_strdup(sp, ovip->ps, strlen(ovip->ps))) == NULL)
+ return (1);
+
+ nvip->lastckey = ovip->lastckey;
+ nvip->csearchdir = ovip->csearchdir;
+
+ nvip->srows = ovip->srows;
+ }
+ return (0);
+}
+
+/*
+ * v_screen_end --
+ * End a vi screen.
+ *
+ * PUBLIC: int v_screen_end __P((SCR *));
+ */
+int
+v_screen_end(sp)
+ SCR *sp;
+{
+ VI_PRIVATE *vip;
+
+ if ((vip = VIP(sp)) == NULL)
+ return (0);
+ if (vip->keyw != NULL)
+ free(vip->keyw);
+ if (vip->rep != NULL)
+ free(vip->rep);
+ if (vip->ps != NULL)
+ free(vip->ps);
+
+ if (HMAP != NULL)
+ free(HMAP);
+
+ free(vip);
+ sp->vi_private = NULL;
+
+ return (0);
+}
+
+/*
+ * v_optchange --
+ * Handle change of options for vi.
+ *
+ * PUBLIC: int v_optchange __P((SCR *, int, char *, u_long *));
+ */
+int
+v_optchange(sp, offset, str, valp)
+ SCR *sp;
+ int offset;
+ char *str;
+ u_long *valp;
+{
+ switch (offset) {
+ case O_PARAGRAPHS:
+ return (v_buildps(sp, str, O_STR(sp, O_SECTIONS)));
+ case O_SECTIONS:
+ return (v_buildps(sp, O_STR(sp, O_PARAGRAPHS), str));
+ case O_WINDOW:
+ return (vs_crel(sp, *valp));
+ }
+ return (0);
+}
diff --git a/contrib/nvi/vi/v_itxt.c b/contrib/nvi/vi/v_itxt.c
new file mode 100644
index 000000000000..6cf93773ac3d
--- /dev/null
+++ b/contrib/nvi/vi/v_itxt.c
@@ -0,0 +1,537 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_itxt.c 10.16 (Berkeley) 10/23/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * !!!
+ * Repeated input in the historic vi is mostly wrong and this isn't very
+ * backward compatible. For example, if the user entered "3Aab\ncd" in
+ * the historic vi, the "ab" was repeated 3 times, and the "\ncd" was then
+ * appended to the result. There was also a hack which I don't remember
+ * right now, where "3o" would open 3 lines and then let the user fill them
+ * in, to make screen movements on 300 baud modems more tolerable. I don't
+ * think it's going to be missed.
+ *
+ * !!!
+ * There's a problem with the way that we do logging for change commands with
+ * implied motions (e.g. A, I, O, cc, etc.). Since the main vi loop logs the
+ * starting cursor position before the change command "moves" the cursor, the
+ * cursor position to which we return on undo will be where the user entered
+ * the change command, not the start of the change. Several of the following
+ * routines re-log the cursor to make this work correctly. Historic vi tried
+ * to do the same thing, and mostly got it right. (The only spectacular way
+ * it fails is if the user entered 'o' from anywhere but the last character of
+ * the line, the undo returned the cursor to the start of the line. If the
+ * user was on the last character of the line, the cursor returned to that
+ * position.) We also check for mapped keys waiting, i.e. if we're in the
+ * middle of a map, don't bother logging the cursor.
+ */
+#define LOG_CORRECT { \
+ if (!MAPPED_KEYS_WAITING(sp)) \
+ (void)log_cursor(sp); \
+}
+
+static u_int32_t set_txt_std __P((SCR *, VICMD *, u_int32_t));
+
+/*
+ * v_iA -- [count]A
+ * Append text to the end of the line.
+ *
+ * PUBLIC: int v_iA __P((SCR *, VICMD *));
+ */
+int
+v_iA(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ size_t len;
+
+ if (!db_get(sp, vp->m_start.lno, 0, NULL, &len))
+ sp->cno = len == 0 ? 0 : len - 1;
+
+ LOG_CORRECT;
+
+ return (v_ia(sp, vp));
+}
+
+/*
+ * v_ia -- [count]a
+ * [count]A
+ * Append text to the cursor position.
+ *
+ * PUBLIC: int v_ia __P((SCR *, VICMD *));
+ */
+int
+v_ia(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ size_t len;
+ u_int32_t flags;
+ int isempty;
+ char *p;
+
+ flags = set_txt_std(sp, vp, 0);
+ sp->showmode = SM_APPEND;
+ sp->lno = vp->m_start.lno;
+
+ /* Move the cursor one column to the right and repaint the screen. */
+ if (db_eget(sp, sp->lno, &p, &len, &isempty)) {
+ if (!isempty)
+ return (1);
+ len = 0;
+ LF_SET(TXT_APPENDEOL);
+ } else if (len) {
+ if (len == sp->cno + 1) {
+ sp->cno = len;
+ LF_SET(TXT_APPENDEOL);
+ } else
+ ++sp->cno;
+ } else
+ LF_SET(TXT_APPENDEOL);
+
+ return (v_txt(sp, vp, NULL, p, len,
+ 0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags));
+}
+
+/*
+ * v_iI -- [count]I
+ * Insert text at the first nonblank.
+ *
+ * PUBLIC: int v_iI __P((SCR *, VICMD *));
+ */
+int
+v_iI(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ sp->cno = 0;
+ if (nonblank(sp, vp->m_start.lno, &sp->cno))
+ return (1);
+
+ LOG_CORRECT;
+
+ return (v_ii(sp, vp));
+}
+
+/*
+ * v_ii -- [count]i
+ * [count]I
+ * Insert text at the cursor position.
+ *
+ * PUBLIC: int v_ii __P((SCR *, VICMD *));
+ */
+int
+v_ii(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ size_t len;
+ u_int32_t flags;
+ int isempty;
+ char *p;
+
+ flags = set_txt_std(sp, vp, 0);
+ sp->showmode = SM_INSERT;
+ sp->lno = vp->m_start.lno;
+
+ if (db_eget(sp, sp->lno, &p, &len, &isempty)) {
+ if (!isempty)
+ return (1);
+ len = 0;
+ }
+
+ if (len == 0)
+ LF_SET(TXT_APPENDEOL);
+ return (v_txt(sp, vp, NULL, p, len,
+ 0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags));
+}
+
+enum which { o_cmd, O_cmd };
+static int io __P((SCR *, VICMD *, enum which));
+
+/*
+ * v_iO -- [count]O
+ * Insert text above this line.
+ *
+ * PUBLIC: int v_iO __P((SCR *, VICMD *));
+ */
+int
+v_iO(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ return (io(sp, vp, O_cmd));
+}
+
+/*
+ * v_io -- [count]o
+ * Insert text after this line.
+ *
+ * PUBLIC: int v_io __P((SCR *, VICMD *));
+ */
+int
+v_io(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ return (io(sp, vp, o_cmd));
+}
+
+static int
+io(sp, vp, cmd)
+ SCR *sp;
+ VICMD *vp;
+ enum which cmd;
+{
+ recno_t ai_line, lno;
+ size_t len;
+ u_int32_t flags;
+ char *p;
+
+ flags = set_txt_std(sp, vp, TXT_ADDNEWLINE | TXT_APPENDEOL);
+ sp->showmode = SM_INSERT;
+
+ if (sp->lno == 1) {
+ if (db_last(sp, &lno))
+ return (1);
+ if (lno != 0)
+ goto insert;
+ p = NULL;
+ len = 0;
+ ai_line = OOBLNO;
+ } else {
+insert: p = "";
+ sp->cno = 0;
+ LOG_CORRECT;
+
+ if (cmd == O_cmd) {
+ if (db_insert(sp, sp->lno, p, 0))
+ return (1);
+ if (db_get(sp, sp->lno, DBG_FATAL, &p, &len))
+ return (1);
+ ai_line = sp->lno + 1;
+ } else {
+ if (db_append(sp, 1, sp->lno, p, 0))
+ return (1);
+ if (db_get(sp, ++sp->lno, DBG_FATAL, &p, &len))
+ return (1);
+ ai_line = sp->lno - 1;
+ }
+ }
+ return (v_txt(sp, vp, NULL, p, len,
+ 0, ai_line, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags));
+}
+
+/*
+ * v_change -- [buffer][count]c[count]motion
+ * [buffer][count]C
+ * [buffer][count]S
+ * Change command.
+ *
+ * PUBLIC: int v_change __P((SCR *, VICMD *));
+ */
+int
+v_change(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ size_t blen, len;
+ u_int32_t flags;
+ int isempty, lmode, rval;
+ char *bp, *p;
+
+ /*
+ * 'c' can be combined with motion commands that set the resulting
+ * cursor position, i.e. "cG". Clear the VM_RCM flags and make the
+ * resulting cursor position stick, inserting text has its own rules
+ * for cursor positioning.
+ */
+ F_CLR(vp, VM_RCM_MASK);
+ F_SET(vp, VM_RCM_SET);
+
+ /*
+ * Find out if the file is empty, it's easier to handle it as a
+ * special case.
+ */
+ if (vp->m_start.lno == vp->m_stop.lno &&
+ db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+ if (!isempty)
+ return (1);
+ return (v_ia(sp, vp));
+ }
+
+ flags = set_txt_std(sp, vp, 0);
+ sp->showmode = SM_CHANGE;
+
+ /*
+ * Move the cursor to the start of the change. Note, if autoindent
+ * is turned on, the cc command in line mode changes from the first
+ * *non-blank* character of the line, not the first character. And,
+ * to make it just a bit more exciting, the initial space is handled
+ * as auto-indent characters.
+ */
+ lmode = F_ISSET(vp, VM_LMODE) ? CUT_LINEMODE : 0;
+ if (lmode) {
+ vp->m_start.cno = 0;
+ if (O_ISSET(sp, O_AUTOINDENT)) {
+ if (nonblank(sp, vp->m_start.lno, &vp->m_start.cno))
+ return (1);
+ LF_SET(TXT_AICHARS);
+ }
+ }
+ sp->lno = vp->m_start.lno;
+ sp->cno = vp->m_start.cno;
+
+ LOG_CORRECT;
+
+ /*
+ * If not in line mode and changing within a single line, copy the
+ * text and overwrite it.
+ */
+ if (!lmode && vp->m_start.lno == vp->m_stop.lno) {
+ /*
+ * !!!
+ * Historic practice, c did not cut into the numeric buffers,
+ * only the unnamed one.
+ */
+ if (cut(sp,
+ F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
+ &vp->m_start, &vp->m_stop, lmode))
+ return (1);
+ if (len == 0)
+ LF_SET(TXT_APPENDEOL);
+ LF_SET(TXT_EMARK | TXT_OVERWRITE);
+ return (v_txt(sp, vp, &vp->m_stop, p, len,
+ 0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags));
+ }
+
+ /*
+ * It's trickier if in line mode or changing over multiple lines. If
+ * we're in line mode delete all of the lines and insert a replacement
+ * line which the user edits. If there was leading whitespace in the
+ * first line being changed, we copy it and use it as the replacement.
+ * If we're not in line mode, we delete the text and start inserting.
+ *
+ * !!!
+ * Copy the text. Historic practice, c did not cut into the numeric
+ * buffers, only the unnamed one.
+ */
+ if (cut(sp,
+ F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
+ &vp->m_start, &vp->m_stop, lmode))
+ return (1);
+
+ /* If replacing entire lines and there's leading text. */
+ if (lmode && vp->m_start.cno) {
+ /*
+ * Get a copy of the first line changed, and copy out the
+ * leading text.
+ */
+ if (db_get(sp, vp->m_start.lno, DBG_FATAL, &p, &len))
+ return (1);
+ GET_SPACE_RET(sp, bp, blen, vp->m_start.cno);
+ memmove(bp, p, vp->m_start.cno);
+ } else
+ bp = NULL;
+
+ /* Delete the text. */
+ if (del(sp, &vp->m_start, &vp->m_stop, lmode))
+ return (1);
+
+ /* If replacing entire lines, insert a replacement line. */
+ if (lmode) {
+ if (db_insert(sp, vp->m_start.lno, bp, vp->m_start.cno))
+ return (1);
+ sp->lno = vp->m_start.lno;
+ len = sp->cno = vp->m_start.cno;
+ }
+
+ /* Get the line we're editing. */
+ if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+ if (!isempty)
+ return (1);
+ len = 0;
+ }
+
+ /* Check to see if we're appending to the line. */
+ if (vp->m_start.cno >= len)
+ LF_SET(TXT_APPENDEOL);
+
+ rval = v_txt(sp, vp, NULL, p, len,
+ 0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags);
+
+ if (bp != NULL)
+ FREE_SPACE(sp, bp, blen);
+ return (rval);
+}
+
+/*
+ * v_Replace -- [count]R
+ * Overwrite multiple characters.
+ *
+ * PUBLIC: int v_Replace __P((SCR *, VICMD *));
+ */
+int
+v_Replace(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ size_t len;
+ u_int32_t flags;
+ int isempty;
+ char *p;
+
+ flags = set_txt_std(sp, vp, 0);
+ sp->showmode = SM_REPLACE;
+
+ if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+ if (!isempty)
+ return (1);
+ len = 0;
+ LF_SET(TXT_APPENDEOL);
+ } else {
+ if (len == 0)
+ LF_SET(TXT_APPENDEOL);
+ LF_SET(TXT_OVERWRITE | TXT_REPLACE);
+ }
+ vp->m_stop.lno = vp->m_start.lno;
+ vp->m_stop.cno = len ? len - 1 : 0;
+
+ return (v_txt(sp, vp, &vp->m_stop, p, len,
+ 0, OOBLNO, F_ISSET(vp, VC_C1SET) ? vp->count : 1, flags));
+}
+
+/*
+ * v_subst -- [buffer][count]s
+ * Substitute characters.
+ *
+ * PUBLIC: int v_subst __P((SCR *, VICMD *));
+ */
+int
+v_subst(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ size_t len;
+ u_int32_t flags;
+ int isempty;
+ char *p;
+
+ flags = set_txt_std(sp, vp, 0);
+ sp->showmode = SM_CHANGE;
+
+ if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+ if (!isempty)
+ return (1);
+ len = 0;
+ LF_SET(TXT_APPENDEOL);
+ } else {
+ if (len == 0)
+ LF_SET(TXT_APPENDEOL);
+ LF_SET(TXT_EMARK | TXT_OVERWRITE);
+ }
+
+ vp->m_stop.lno = vp->m_start.lno;
+ vp->m_stop.cno =
+ vp->m_start.cno + (F_ISSET(vp, VC_C1SET) ? vp->count - 1 : 0);
+ if (vp->m_stop.cno > len - 1)
+ vp->m_stop.cno = len - 1;
+
+ if (p != NULL && cut(sp,
+ F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
+ &vp->m_start, &vp->m_stop, 0))
+ return (1);
+
+ return (v_txt(sp, vp, &vp->m_stop, p, len, 0, OOBLNO, 1, flags));
+}
+
+/*
+ * set_txt_std --
+ * Initialize text processing flags.
+ */
+static u_int32_t
+set_txt_std(sp, vp, flags)
+ SCR *sp;
+ VICMD *vp;
+ u_int32_t flags;
+{
+ LF_SET(TXT_CNTRLT |
+ TXT_ESCAPE | TXT_MAPINPUT | TXT_RECORD | TXT_RESOLVE);
+
+ if (F_ISSET(vp, VC_ISDOT))
+ LF_SET(TXT_REPLAY);
+
+ if (O_ISSET(sp, O_ALTWERASE))
+ LF_SET(TXT_ALTWERASE);
+ if (O_ISSET(sp, O_AUTOINDENT))
+ LF_SET(TXT_AUTOINDENT);
+ if (O_ISSET(sp, O_BEAUTIFY))
+ LF_SET(TXT_BEAUTIFY);
+ if (O_ISSET(sp, O_SHOWMATCH))
+ LF_SET(TXT_SHOWMATCH);
+ if (F_ISSET(sp, SC_SCRIPT))
+ LF_SET(TXT_CR);
+ if (O_ISSET(sp, O_TTYWERASE))
+ LF_SET(TXT_TTYWERASE);
+
+ /*
+ * !!!
+ * Mapped keys were sometimes unaffected by the wrapmargin option
+ * in the historic 4BSD vi. Consider the following commands, where
+ * each is executed on an empty line, in an 80 column screen, with
+ * the wrapmargin value set to 60.
+ *
+ * aABC DEF <ESC>....
+ * :map K aABC DEF ^V<ESC><CR>KKKKK
+ * :map K 5aABC DEF ^V<ESC><CR>K
+ *
+ * The first and second commands are affected by wrapmargin. The
+ * third is not. (If the inserted text is itself longer than the
+ * wrapmargin value, i.e. if the "ABC DEF " string is replaced by
+ * something that's longer than 60 columns from the beginning of
+ * the line, the first two commands behave as before, but the third
+ * command gets fairly strange.) The problem is that people wrote
+ * macros that depended on the third command NOT being affected by
+ * wrapmargin, as in this gem which centers lines:
+ *
+ * map #c $mq81a ^V^[81^V^V|D`qld0:s/ / /g^V^M$p
+ *
+ * For compatibility reasons, we try and make it all work here. I
+ * offer no hope that this is right, but it's probably pretty close.
+ *
+ * XXX
+ * Once I work my courage up, this is all gonna go away. It's too
+ * evil to survive.
+ */
+ if ((O_ISSET(sp, O_WRAPLEN) || O_ISSET(sp, O_WRAPMARGIN)) &&
+ (!MAPPED_KEYS_WAITING(sp) || !F_ISSET(vp, VC_C1SET)))
+ LF_SET(TXT_WRAPMARGIN);
+ return (flags);
+}
diff --git a/contrib/nvi/vi/v_left.c b/contrib/nvi/vi/v_left.c
new file mode 100644
index 000000000000..cfed80c74bf4
--- /dev/null
+++ b/contrib/nvi/vi/v_left.c
@@ -0,0 +1,293 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_left.c 10.7 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_left -- [count]^H, [count]h
+ * Move left by columns.
+ *
+ * PUBLIC: int v_left __P((SCR *, VICMD *));
+ */
+int
+v_left(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ recno_t cnt;
+
+ /*
+ * !!!
+ * The ^H and h commands always failed in the first column.
+ */
+ if (vp->m_start.cno == 0) {
+ v_sol(sp);
+ return (1);
+ }
+
+ /* Find the end of the range. */
+ cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+ if (vp->m_start.cno > cnt)
+ vp->m_stop.cno = vp->m_start.cno - cnt;
+ else
+ vp->m_stop.cno = 0;
+
+ /*
+ * All commands move to the end of the range. Motion commands
+ * adjust the starting point to the character before the current
+ * one.
+ */
+ if (ISMOTION(vp))
+ --vp->m_start.cno;
+ vp->m_final = vp->m_stop;
+ return (0);
+}
+
+/*
+ * v_cfirst -- [count]_
+ * Move to the first non-blank character in a line.
+ *
+ * PUBLIC: int v_cfirst __P((SCR *, VICMD *));
+ */
+int
+v_cfirst(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ recno_t cnt, lno;
+
+ /*
+ * !!!
+ * If the _ is a motion component, it makes the command a line motion
+ * e.g. "d_" deletes the line. It also means that the cursor doesn't
+ * move.
+ *
+ * The _ command never failed in the first column.
+ */
+ if (ISMOTION(vp))
+ F_SET(vp, VM_LMODE);
+ /*
+ * !!!
+ * Historically a specified count makes _ move down count - 1
+ * rows, so, "3_" is the same as "2j_".
+ */
+ cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+ if (cnt != 1) {
+ --vp->count;
+ return (v_down(sp, vp));
+ }
+
+ /*
+ * Move to the first non-blank.
+ *
+ * Can't just use RCM_SET_FNB, in case _ is used as the motion
+ * component of another command.
+ */
+ vp->m_stop.cno = 0;
+ if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
+ return (1);
+
+ /*
+ * !!!
+ * The _ command has to fail if the file is empty and we're doing
+ * a delete. If deleting line 1, and 0 is the first nonblank,
+ * make the check.
+ */
+ if (vp->m_stop.lno == 1 &&
+ vp->m_stop.cno == 0 && ISCMD(vp->rkp, 'd')) {
+ if (db_last(sp, &lno))
+ return (1);
+ if (lno == 0) {
+ v_sol(sp);
+ return (1);
+ }
+ }
+
+ /*
+ * Delete and non-motion commands move to the end of the range,
+ * yank stays at the start. Ignore others.
+ */
+ vp->m_final =
+ ISMOTION(vp) && ISCMD(vp->rkp, 'y') ? vp->m_start : vp->m_stop;
+ return (0);
+}
+
+/*
+ * v_first -- ^
+ * Move to the first non-blank character in this line.
+ *
+ * PUBLIC: int v_first __P((SCR *, VICMD *));
+ */
+int
+v_first(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ /*
+ * !!!
+ * Yielding to none in our quest for compatibility with every
+ * historical blemish of vi, no matter how strange it might be,
+ * we permit the user to enter a count and then ignore it.
+ */
+
+ /*
+ * Move to the first non-blank.
+ *
+ * Can't just use RCM_SET_FNB, in case ^ is used as the motion
+ * component of another command.
+ */
+ vp->m_stop.cno = 0;
+ if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
+ return (1);
+
+ /*
+ * !!!
+ * The ^ command succeeded if used as a command when the cursor was
+ * on the first non-blank in the line, but failed if used as a motion
+ * component in the same situation.
+ */
+ if (ISMOTION(vp) && vp->m_start.cno == vp->m_stop.cno) {
+ v_sol(sp);
+ return (1);
+ }
+
+ /*
+ * If moving right, non-motion commands move to the end of the range.
+ * Delete and yank stay at the start. Motion commands adjust the
+ * ending point to the character before the current ending charcter.
+ *
+ * If moving left, all commands move to the end of the range. Motion
+ * commands adjust the starting point to the character before the
+ * current starting character.
+ */
+ if (vp->m_start.cno < vp->m_stop.cno)
+ if (ISMOTION(vp)) {
+ --vp->m_stop.cno;
+ vp->m_final = vp->m_start;
+ } else
+ vp->m_final = vp->m_stop;
+ else {
+ if (ISMOTION(vp))
+ --vp->m_start.cno;
+ vp->m_final = vp->m_stop;
+ }
+ return (0);
+}
+
+/*
+ * v_ncol -- [count]|
+ * Move to column count or the first column on this line. If the
+ * requested column is past EOL, move to EOL. The nasty part is
+ * that we have to know character column widths to make this work.
+ *
+ * PUBLIC: int v_ncol __P((SCR *, VICMD *));
+ */
+int
+v_ncol(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ if (F_ISSET(vp, VC_C1SET) && vp->count > 1) {
+ --vp->count;
+ vp->m_stop.cno =
+ vs_colpos(sp, vp->m_start.lno, (size_t)vp->count);
+ /*
+ * !!!
+ * The | command succeeded if used as a command and the cursor
+ * didn't move, but failed if used as a motion component in the
+ * same situation.
+ */
+ if (ISMOTION(vp) && vp->m_stop.cno == vp->m_start.cno) {
+ v_nomove(sp);
+ return (1);
+ }
+ } else {
+ /*
+ * !!!
+ * The | command succeeded if used as a command in column 0
+ * without a count, but failed if used as a motion component
+ * in the same situation.
+ */
+ if (ISMOTION(vp) && vp->m_start.cno == 0) {
+ v_sol(sp);
+ return (1);
+ }
+ vp->m_stop.cno = 0;
+ }
+
+ /*
+ * If moving right, non-motion commands move to the end of the range.
+ * Delete and yank stay at the start. Motion commands adjust the
+ * ending point to the character before the current ending charcter.
+ *
+ * If moving left, all commands move to the end of the range. Motion
+ * commands adjust the starting point to the character before the
+ * current starting character.
+ */
+ if (vp->m_start.cno < vp->m_stop.cno)
+ if (ISMOTION(vp)) {
+ --vp->m_stop.cno;
+ vp->m_final = vp->m_start;
+ } else
+ vp->m_final = vp->m_stop;
+ else {
+ if (ISMOTION(vp))
+ --vp->m_start.cno;
+ vp->m_final = vp->m_stop;
+ }
+ return (0);
+}
+
+/*
+ * v_zero -- 0
+ * Move to the first column on this line.
+ *
+ * PUBLIC: int v_zero __P((SCR *, VICMD *));
+ */
+int
+v_zero(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ /*
+ * !!!
+ * The 0 command succeeded if used as a command in the first column
+ * but failed if used as a motion component in the same situation.
+ */
+ if (ISMOTION(vp) && vp->m_start.cno == 0) {
+ v_sol(sp);
+ return (1);
+ }
+
+ /*
+ * All commands move to the end of the range. Motion commands
+ * adjust the starting point to the character before the current
+ * one.
+ */
+ vp->m_stop.cno = 0;
+ if (ISMOTION(vp))
+ --vp->m_start.cno;
+ vp->m_final = vp->m_stop;
+ return (0);
+}
diff --git a/contrib/nvi/vi/v_mark.c b/contrib/nvi/vi/v_mark.c
new file mode 100644
index 000000000000..447430efabe8
--- /dev/null
+++ b/contrib/nvi/vi/v_mark.c
@@ -0,0 +1,234 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_mark.c 10.8 (Berkeley) 9/20/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_mark -- m[a-z]
+ * Set a mark.
+ *
+ * PUBLIC: int v_mark __P((SCR *, VICMD *));
+ */
+int
+v_mark(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ return (mark_set(sp, vp->character, &vp->m_start, 1));
+}
+
+enum which {BQMARK, FQMARK};
+static int mark __P((SCR *, VICMD *, enum which));
+
+
+/*
+ * v_bmark -- `['`a-z]
+ * Move to a mark.
+ *
+ * Moves to a mark, setting both row and column.
+ *
+ * !!!
+ * Although not commonly known, the "'`" and "'`" forms are historically
+ * valid. The behavior is determined by the first character, so "`'" is
+ * the same as "``". Remember this fact -- you'll be amazed at how many
+ * people don't know it and will be delighted that you are able to tell
+ * them.
+ *
+ * PUBLIC: int v_bmark __P((SCR *, VICMD *));
+ */
+int
+v_bmark(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ return (mark(sp, vp, BQMARK));
+}
+
+/*
+ * v_fmark -- '['`a-z]
+ * Move to a mark.
+ *
+ * Move to the first nonblank character of the line containing the mark.
+ *
+ * PUBLIC: int v_fmark __P((SCR *, VICMD *));
+ */
+int
+v_fmark(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ return (mark(sp, vp, FQMARK));
+}
+
+/*
+ * mark --
+ * Mark commands.
+ */
+static int
+mark(sp, vp, cmd)
+ SCR *sp;
+ VICMD *vp;
+ enum which cmd;
+{
+ dir_t dir;
+ MARK m;
+ size_t len;
+
+ if (mark_get(sp, vp->character, &vp->m_stop, M_BERR))
+ return (1);
+
+ /*
+ * !!!
+ * Historically, BQMARKS for character positions that no longer
+ * existed acted as FQMARKS.
+ *
+ * FQMARKS move to the first non-blank.
+ */
+ switch (cmd) {
+ case BQMARK:
+ if (db_get(sp, vp->m_stop.lno, DBG_FATAL, NULL, &len))
+ return (1);
+ if (vp->m_stop.cno < len ||
+ vp->m_stop.cno == len && len == 0)
+ break;
+
+ if (ISMOTION(vp))
+ F_SET(vp, VM_LMODE);
+ cmd = FQMARK;
+ /* FALLTHROUGH */
+ case FQMARK:
+ vp->m_stop.cno = 0;
+ if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
+ return (1);
+ break;
+ default:
+ abort();
+ }
+
+ /* Non-motion commands move to the end of the range. */
+ if (!ISMOTION(vp)) {
+ vp->m_final = vp->m_stop;
+ return (0);
+ }
+
+ /*
+ * !!!
+ * If a motion component to a BQMARK, the cursor has to move.
+ */
+ if (cmd == BQMARK &&
+ vp->m_stop.lno == vp->m_start.lno &&
+ vp->m_stop.cno == vp->m_start.cno) {
+ v_nomove(sp);
+ return (1);
+ }
+
+ /*
+ * If the motion is in the reverse direction, switch the start and
+ * stop MARK's so that it's in a forward direction. (There's no
+ * reason for this other than to make the tests below easier. The
+ * code in vi.c:vi() would have done the switch.) Both forward
+ * and backward motions can happen for any kind of search command.
+ */
+ if (vp->m_start.lno > vp->m_stop.lno ||
+ vp->m_start.lno == vp->m_stop.lno &&
+ vp->m_start.cno > vp->m_stop.cno) {
+ m = vp->m_start;
+ vp->m_start = vp->m_stop;
+ vp->m_stop = m;
+ dir = BACKWARD;
+ } else
+ dir = FORWARD;
+
+ /*
+ * Yank cursor motion, when associated with marks as motion commands,
+ * historically behaved as follows:
+ *
+ * ` motion ' motion
+ * Line change? Line change?
+ * Y N Y N
+ * -------------- ---------------
+ * FORWARD: | NM NM | NM NM
+ * | |
+ * BACKWARD: | M M | M NM(1)
+ *
+ * where NM means the cursor didn't move, and M means the cursor
+ * moved to the mark.
+ *
+ * As the cursor was usually moved for yank commands associated
+ * with backward motions, this implementation regularizes it by
+ * changing the NM at position (1) to be an M. This makes mark
+ * motions match search motions, which is probably A Good Thing.
+ *
+ * Delete cursor motion was always to the start of the text region,
+ * regardless. Ignore other motion commands.
+ */
+#ifdef HISTORICAL_PRACTICE
+ if (ISCMD(vp->rkp, 'y')) {
+ if ((cmd == BQMARK ||
+ cmd == FQMARK && vp->m_start.lno != vp->m_stop.lno) &&
+ (vp->m_start.lno > vp->m_stop.lno ||
+ vp->m_start.lno == vp->m_stop.lno &&
+ vp->m_start.cno > vp->m_stop.cno))
+ vp->m_final = vp->m_stop;
+ } else if (ISCMD(vp->rkp, 'd'))
+ if (vp->m_start.lno > vp->m_stop.lno ||
+ vp->m_start.lno == vp->m_stop.lno &&
+ vp->m_start.cno > vp->m_stop.cno)
+ vp->m_final = vp->m_stop;
+#else
+ vp->m_final = vp->m_start;
+#endif
+
+ /*
+ * Forward marks are always line oriented, and it's set in the
+ * vcmd.c table.
+ */
+ if (cmd == FQMARK)
+ return (0);
+
+ /*
+ * BQMARK'S moving backward and starting at column 0, and ones moving
+ * forward and ending at column 0 are corrected to the last column of
+ * the previous line. Otherwise, adjust the starting/ending point to
+ * the character before the current one (this is safe because we know
+ * the search had to move to succeed).
+ *
+ * Mark motions become line mode opertions if they start at the first
+ * nonblank and end at column 0 of another line.
+ */
+ if (vp->m_start.lno < vp->m_stop.lno && vp->m_stop.cno == 0) {
+ if (db_get(sp, --vp->m_stop.lno, DBG_FATAL, NULL, &len))
+ return (1);
+ vp->m_stop.cno = len ? len - 1 : 0;
+ len = 0;
+ if (nonblank(sp, vp->m_start.lno, &len))
+ return (1);
+ if (vp->m_start.cno <= len)
+ F_SET(vp, VM_LMODE);
+ } else
+ --vp->m_stop.cno;
+
+ return (0);
+}
diff --git a/contrib/nvi/vi/v_match.c b/contrib/nvi/vi/v_match.c
new file mode 100644
index 000000000000..3996560aaa73
--- /dev/null
+++ b/contrib/nvi/vi/v_match.c
@@ -0,0 +1,170 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_match.c 10.8 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_match -- %
+ * Search to matching character.
+ *
+ * PUBLIC: int v_match __P((SCR *, VICMD *));
+ */
+int
+v_match(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ VCS cs;
+ MARK *mp;
+ size_t cno, len, off;
+ int cnt, isempty, matchc, startc, (*gc)__P((SCR *, VCS *));
+ char *p;
+
+ /*
+ * !!!
+ * Historic practice; ignore the count.
+ *
+ * !!!
+ * Historical practice was to search for the initial character in the
+ * forward direction only.
+ */
+ if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+ if (isempty)
+ goto nomatch;
+ return (1);
+ }
+ for (off = vp->m_start.cno;; ++off) {
+ if (off >= len) {
+nomatch: msgq(sp, M_BERR, "184|No match character on this line");
+ return (1);
+ }
+ switch (startc = p[off]) {
+ case '(':
+ matchc = ')';
+ gc = cs_next;
+ break;
+ case ')':
+ matchc = '(';
+ gc = cs_prev;
+ break;
+ case '[':
+ matchc = ']';
+ gc = cs_next;
+ break;
+ case ']':
+ matchc = '[';
+ gc = cs_prev;
+ break;
+ case '{':
+ matchc = '}';
+ gc = cs_next;
+ break;
+ case '}':
+ matchc = '{';
+ gc = cs_prev;
+ break;
+ case '<':
+ matchc = '>';
+ gc = cs_next;
+ break;
+ case '>':
+ matchc = '<';
+ gc = cs_prev;
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+
+ cs.cs_lno = vp->m_start.lno;
+ cs.cs_cno = off;
+ if (cs_init(sp, &cs))
+ return (1);
+ for (cnt = 1;;) {
+ if (gc(sp, &cs))
+ return (1);
+ if (cs.cs_flags != 0) {
+ if (cs.cs_flags == CS_EOF || cs.cs_flags == CS_SOF)
+ break;
+ continue;
+ }
+ if (cs.cs_ch == startc)
+ ++cnt;
+ else if (cs.cs_ch == matchc && --cnt == 0)
+ break;
+ }
+ if (cnt) {
+ msgq(sp, M_BERR, "185|Matching character not found");
+ return (1);
+ }
+
+ vp->m_stop.lno = cs.cs_lno;
+ vp->m_stop.cno = cs.cs_cno;
+
+ /*
+ * If moving right, non-motion commands move to the end of the range.
+ * Delete and yank stay at the start.
+ *
+ * If moving left, all commands move to the end of the range.
+ *
+ * !!!
+ * Don't correct for leftward movement -- historic vi deleted the
+ * starting cursor position when deleting to a match.
+ */
+ if (vp->m_start.lno < vp->m_stop.lno ||
+ vp->m_start.lno == vp->m_stop.lno &&
+ vp->m_start.cno < vp->m_stop.cno)
+ vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
+ else
+ vp->m_final = vp->m_stop;
+
+ /*
+ * !!!
+ * If the motion is across lines, and the earliest cursor position
+ * is at or before any non-blank characters in the line, i.e. the
+ * movement is cutting all of the line's text, and the later cursor
+ * position has nothing other than whitespace characters between it
+ * and the end of its line, the buffer is in line mode.
+ */
+ if (!ISMOTION(vp) || vp->m_start.lno == vp->m_stop.lno)
+ return (0);
+ mp = vp->m_start.lno < vp->m_stop.lno ? &vp->m_start : &vp->m_stop;
+ if (mp->cno != 0) {
+ cno = 0;
+ if (nonblank(sp, mp->lno, &cno))
+ return (1);
+ if (cno < mp->cno)
+ return (0);
+ }
+ mp = vp->m_start.lno < vp->m_stop.lno ? &vp->m_stop : &vp->m_start;
+ if (db_get(sp, mp->lno, DBG_FATAL, &p, &len))
+ return (1);
+ for (p += mp->cno + 1, len -= mp->cno; --len; ++p)
+ if (!isblank(*p))
+ return (0);
+ F_SET(vp, VM_LMODE);
+ return (0);
+}
diff --git a/usr.bin/vi/vi/v_paragraph.c b/contrib/nvi/vi/v_paragraph.c
index 590718dd7fdb..762e38e01671 100644
--- a/usr.bin/vi/vi/v_paragraph.c
+++ b/contrib/nvi/vi/v_paragraph.c
@@ -1,38 +1,16 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)v_paragraph.c 8.18 (Berkeley) 7/29/94";
+static const char sccsid[] = "@(#)v_paragraph.c 10.7 (Berkeley) 3/6/96";
#endif /* not lint */
#include <sys/types.h>
@@ -42,18 +20,12 @@ static char sccsid[] = "@(#)v_paragraph.c 8.18 (Berkeley) 7/29/94";
#include <bitstring.h>
#include <errno.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
+#include "../common/common.h"
#include "vi.h"
-#include "vcmd.h"
#define INTEXT_CHECK { \
if (len == 0 || v_isempty(p, len)) { \
@@ -88,16 +60,18 @@ static char sccsid[] = "@(#)v_paragraph.c 8.18 (Berkeley) 7/29/94";
*
* Paragraphs are empty lines after text, formfeed characters, or values
* from the paragraph or section options.
+ *
+ * PUBLIC: int v_paragraphf __P((SCR *, VICMD *));
*/
int
-v_paragraphf(sp, ep, vp)
+v_paragraphf(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
enum { P_INTEXT, P_INBLANK } pstate;
size_t lastlen, len;
recno_t cnt, lastlno, lno;
+ int isempty;
char *p, *lp;
/*
@@ -120,7 +94,7 @@ v_paragraphf(sp, ep, vp)
else {
vp->m_stop = vp->m_start;
vp->m_stop.cno = 0;
- if (nonblank(sp, ep, vp->m_stop.lno, &vp->m_stop.cno))
+ if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
return (1);
if (vp->m_start.cno <= vp->m_stop.cno)
F_SET(vp, VM_LMODE);
@@ -128,7 +102,7 @@ v_paragraphf(sp, ep, vp)
/* Figure out what state we're currently in. */
lno = vp->m_start.lno;
- if ((p = file_gline(sp, ep, lno, &len)) == NULL)
+ if (db_get(sp, lno, 0, &p, &len))
goto eof;
/*
@@ -147,7 +121,7 @@ v_paragraphf(sp, ep, vp)
for (;;) {
lastlno = lno;
lastlen = len;
- if ((p = file_gline(sp, ep, ++lno, &len)) == NULL)
+ if (db_get(sp, ++lno, 0, &p, &len))
goto eof;
switch (pstate) {
case P_INTEXT:
@@ -163,11 +137,11 @@ v_paragraphf(sp, ep, vp)
/*
* !!!
* Non-motion commands move to the end of the range,
- * VC_D and VC_Y stay at the start. Ignore VC_C and
- * VC_DEF. Adjust the end of the range for motion
- * commands; historically, a motion component was to
- * the end of the previous line, whereas the movement
- * command was to the start of the new "paragraph".
+ * delete and yank stay at the start. Ignore others.
+ * Adjust the end of the range for motion commands;
+ * historically, a motion component was to the end of
+ * the previous line, whereas the movement command was
+ * to the start of the new "paragraph".
*/
found: if (ISMOTION(vp)) {
vp->m_stop.lno = lastlno;
@@ -193,30 +167,26 @@ found: if (ISMOTION(vp)) {
* have to make it okay.
*/
eof: if (vp->m_start.lno == lno || vp->m_start.lno == lno - 1) {
- if (file_gline(sp, ep, vp->m_start.lno, &len) == NULL) {
- if (file_lline(sp, ep, &lno))
+ if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
+ if (!isempty)
return (1);
- if (vp->m_start.lno != 1 || lno != 0) {
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
vp->m_start.cno = 0;
return (0);
}
if (vp->m_start.cno == (len ? len - 1 : 0)) {
- v_eof(sp, ep, NULL);
+ v_eof(sp, NULL);
return (1);
}
}
/*
* !!!
- * Non-motion commands move to the end of the range, VC_D
- * and VC_Y stay at the start. Ignore VC_C and VC_DEF.
+ * Non-motion commands move to the end of the range, delete
+ * and yank stay at the start. Ignore others.
*
* If deleting the line (which happens if deleting to EOF), then
* cursor movement is to the first nonblank.
*/
- if (F_ISSET(vp, VC_D)) {
+ if (ISMOTION(vp) && ISCMD(vp->rkp, 'd')) {
F_CLR(vp, VM_RCM_MASK);
F_SET(vp, VM_RCM_SETFNB);
}
@@ -229,12 +199,13 @@ eof: if (vp->m_start.lno == lno || vp->m_start.lno == lno - 1) {
/*
* v_paragraphb -- [count]{
* Move backward count paragraphs.
+ *
+ * PUBLIC: int v_paragraphb __P((SCR *, VICMD *));
*/
int
-v_paragraphb(sp, ep, vp)
+v_paragraphb(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
enum { P_INTEXT, P_INBLANK } pstate;
size_t len;
@@ -276,7 +247,7 @@ v_paragraphb(sp, ep, vp)
goto sof;
/* Figure out what state we're currently in. */
- if ((p = file_gline(sp, ep, lno, &len)) == NULL)
+ if (db_get(sp, lno, 0, &p, &len))
goto sof;
/*
@@ -301,7 +272,7 @@ v_paragraphb(sp, ep, vp)
}
for (;;) {
- if ((p = file_gline(sp, ep, --lno, &len)) == NULL)
+ if (db_get(sp, --lno, 0, &p, &len))
goto sof;
switch (pstate) {
case P_INTEXT:
@@ -336,21 +307,24 @@ found: vp->m_stop.lno = lno;
/*
* v_buildps --
* Build the paragraph command search pattern.
+ *
+ * PUBLIC: int v_buildps __P((SCR *, char *, char *));
*/
int
-v_buildps(sp)
+v_buildps(sp, p_p, s_p)
SCR *sp;
+ char *p_p, *s_p;
{
VI_PRIVATE *vip;
size_t p_len, s_len;
- char *p, *p_p, *s_p;
+ char *p;
/*
* The vi paragraph command searches for either a paragraph or
* section option macro.
*/
- p_len = (p_p = O_STR(sp, O_PARAGRAPHS)) == NULL ? 0 : strlen(p_p);
- s_len = (s_p = O_STR(sp, O_SECTIONS)) == NULL ? 0 : strlen(s_p);
+ p_len = p_p == NULL ? 0 : strlen(p_p);
+ s_len = s_p == NULL ? 0 : strlen(s_p);
if (p_len == 0 && s_len == 0)
return (0);
diff --git a/usr.bin/vi/vi/v_put.c b/contrib/nvi/vi/v_put.c
index 8206d1621d35..77220ea14ff9 100644
--- a/usr.bin/vi/vi/v_put.c
+++ b/contrib/nvi/vi/v_put.c
@@ -1,38 +1,16 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)v_put.c 8.9 (Berkeley) 5/2/94";
+static const char sccsid[] = "@(#)v_put.c 10.5 (Berkeley) 3/6/96";
#endif /* not lint */
#include <sys/types.h>
@@ -41,28 +19,23 @@ static char sccsid[] = "@(#)v_put.c 8.9 (Berkeley) 5/2/94";
#include <bitstring.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
+#include "../common/common.h"
#include "vi.h"
-#include "vcmd.h"
-static void inc_buf __P((SCR *, VICMDARG *));
+static void inc_buf __P((SCR *, VICMD *));
/*
* v_Put -- [buffer]P
* Insert the contents of the buffer before the cursor.
+ *
+ * PUBLIC: int v_Put __P((SCR *, VICMD *));
*/
int
-v_Put(sp, ep, vp)
+v_Put(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
u_long cnt;
@@ -75,11 +48,13 @@ v_Put(sp, ep, vp)
* commands. It's useful, so we do.
*/
for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
- if (put(sp, ep, NULL,
+ if (put(sp, NULL,
F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
&vp->m_start, &vp->m_final, 0))
return (1);
vp->m_start = vp->m_final;
+ if (INTERRUPTED(sp))
+ return (1);
}
return (0);
}
@@ -87,12 +62,13 @@ v_Put(sp, ep, vp)
/*
* v_put -- [buffer]p
* Insert the contents of the buffer after the cursor.
+ *
+ * PUBLIC: int v_put __P((SCR *, VICMD *));
*/
int
-v_put(sp, ep, vp)
+v_put(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
u_long cnt;
@@ -105,11 +81,13 @@ v_put(sp, ep, vp)
* commands. It's useful, so we do.
*/
for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
- if (put(sp, ep, NULL,
+ if (put(sp, NULL,
F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
&vp->m_start, &vp->m_final, 1))
return (1);
vp->m_start = vp->m_final;
+ if (INTERRUPTED(sp))
+ return (1);
}
return (0);
}
@@ -132,7 +110,7 @@ v_put(sp, ep, vp)
static void
inc_buf(sp, vp)
SCR *sp;
- VICMDARG *vp;
+ VICMD *vp;
{
CHAR_T v;
diff --git a/contrib/nvi/vi/v_redraw.c b/contrib/nvi/vi/v_redraw.c
new file mode 100644
index 000000000000..4c965c713913
--- /dev/null
+++ b/contrib/nvi/vi/v_redraw.c
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_redraw.c 10.6 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_redraw -- ^L, ^R
+ * Redraw the screen.
+ *
+ * PUBLIC: int v_redraw __P((SCR *, VICMD *));
+ */
+int
+v_redraw(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ return (sp->gp->scr_refresh(sp, 1));
+}
diff --git a/contrib/nvi/vi/v_replace.c b/contrib/nvi/vi/v_replace.c
new file mode 100644
index 000000000000..a4712b683a91
--- /dev/null
+++ b/contrib/nvi/vi/v_replace.c
@@ -0,0 +1,203 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_replace.c 10.17 (Berkeley) 6/30/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_replace -- [count]r<char>
+ *
+ * !!!
+ * The r command in historic vi was almost beautiful in its badness. For
+ * example, "r<erase>" and "r<word erase>" beeped the terminal and deleted
+ * a single character. "Nr<carriage return>", where N was greater than 1,
+ * inserted a single carriage return. "r<escape>" did cancel the command,
+ * but "r<literal><escape>" erased a single character. To enter a literal
+ * <literal> character, it required three <literal> characters after the
+ * command. This may not be right, but at least it's not insane.
+ *
+ * PUBLIC: int v_replace __P((SCR *, VICMD *));
+ */
+int
+v_replace(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ EVENT ev;
+ VI_PRIVATE *vip;
+ TEXT *tp;
+ size_t blen, len;
+ u_long cnt;
+ int quote, rval;
+ char *bp, *p;
+
+ vip = VIP(sp);
+
+ /*
+ * If the line doesn't exist, or it's empty, replacement isn't
+ * allowed. It's not hard to implement, but:
+ *
+ * 1: It's historic practice (vi beeped before the replacement
+ * character was even entered).
+ * 2: For consistency, this change would require that the more
+ * general case, "Nr", when the user is < N characters from
+ * the end of the line, also work, which would be a bit odd.
+ * 3: Replacing with a <newline> has somewhat odd semantics.
+ */
+ if (db_get(sp, vp->m_start.lno, DBG_FATAL, &p, &len))
+ return (1);
+ if (len == 0) {
+ msgq(sp, M_BERR, "186|No characters to replace");
+ return (1);
+ }
+
+ /*
+ * Figure out how many characters to be replace. For no particular
+ * reason (other than that the semantics of replacing the newline
+ * are confusing) only permit the replacement of the characters in
+ * the current line. I suppose we could append replacement characters
+ * to the line, but I see no compelling reason to do so. Check this
+ * before we get the character to match historic practice, where Nr
+ * failed immediately if there were less than N characters from the
+ * cursor to the end of the line.
+ */
+ cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+ vp->m_stop.lno = vp->m_start.lno;
+ vp->m_stop.cno = vp->m_start.cno + cnt - 1;
+ if (vp->m_stop.cno > len - 1) {
+ v_eol(sp, &vp->m_start);
+ return (1);
+ }
+
+ /*
+ * If it's not a repeat, reset the current mode and get a replacement
+ * character.
+ */
+ quote = 0;
+ if (!F_ISSET(vp, VC_ISDOT)) {
+ sp->showmode = SM_REPLACE;
+ if (vs_refresh(sp, 0))
+ return (1);
+next: if (v_event_get(sp, &ev, 0, 0))
+ return (1);
+
+ switch (ev.e_event) {
+ case E_CHARACTER:
+ /*
+ * <literal_next> means escape the next character.
+ * <escape> means they changed their minds.
+ */
+ if (!quote) {
+ if (ev.e_value == K_VLNEXT) {
+ quote = 1;
+ goto next;
+ }
+ if (ev.e_value == K_ESCAPE)
+ return (0);
+ }
+ vip->rlast = ev.e_c;
+ vip->rvalue = ev.e_value;
+ break;
+ case E_ERR:
+ case E_EOF:
+ F_SET(sp, SC_EXIT_FORCE);
+ return (1);
+ case E_INTERRUPT:
+ /* <interrupt> means they changed their minds. */
+ return (0);
+ case E_WRESIZE:
+ /* <resize> interrupts the input mode. */
+ v_emsg(sp, NULL, VIM_WRESIZE);
+ return (0);
+ case E_REPAINT:
+ if (vs_repaint(sp, &ev))
+ return (1);
+ goto next;
+ default:
+ v_event_err(sp, &ev);
+ return (0);
+ }
+ }
+
+ /* Copy the line. */
+ GET_SPACE_RET(sp, bp, blen, len);
+ memmove(bp, p, len);
+ p = bp;
+
+ /*
+ * Versions of nvi before 1.57 created N new lines when they replaced
+ * N characters with <carriage-return> or <newline> characters. This
+ * is different from the historic vi, which replaced N characters with
+ * a single new line. Users complained, so we match historic practice.
+ */
+ if (!quote && vip->rvalue == K_CR || vip->rvalue == K_NL) {
+ /* Set return line. */
+ vp->m_stop.lno = vp->m_start.lno + 1;
+ vp->m_stop.cno = 0;
+
+ /* The first part of the current line. */
+ if (db_set(sp, vp->m_start.lno, p, vp->m_start.cno))
+ goto err_ret;
+
+ /*
+ * The rest of the current line. And, of course, now it gets
+ * tricky. If there are characters left in the line and if
+ * the autoindent edit option is set, white space after the
+ * replaced character is discarded, autoindent is applied, and
+ * the cursor moves to the last indent character.
+ */
+ p += vp->m_start.cno + cnt;
+ len -= vp->m_start.cno + cnt;
+ if (len != 0 && O_ISSET(sp, O_AUTOINDENT))
+ for (; len && isblank(*p); --len, ++p);
+
+ if ((tp = text_init(sp, p, len, len)) == NULL)
+ goto err_ret;
+
+ if (len != 0 && O_ISSET(sp, O_AUTOINDENT)) {
+ if (v_txt_auto(sp, vp->m_start.lno, NULL, 0, tp))
+ goto err_ret;
+ vp->m_stop.cno = tp->ai ? tp->ai - 1 : 0;
+ } else
+ vp->m_stop.cno = 0;
+
+ vp->m_stop.cno = tp->ai ? tp->ai - 1 : 0;
+ if (db_append(sp, 1, vp->m_start.lno, tp->lb, tp->len))
+err_ret: rval = 1;
+ else {
+ text_free(tp);
+ rval = 0;
+ }
+ } else {
+ memset(bp + vp->m_start.cno, vip->rlast, cnt);
+ rval = db_set(sp, vp->m_start.lno, bp, len);
+ }
+ FREE_SPACE(sp, bp, blen);
+
+ vp->m_final = vp->m_stop;
+ return (rval);
+}
diff --git a/contrib/nvi/vi/v_right.c b/contrib/nvi/vi/v_right.c
new file mode 100644
index 000000000000..c2f349eb2328
--- /dev/null
+++ b/contrib/nvi/vi/v_right.c
@@ -0,0 +1,145 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_right.c 10.7 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_right -- [count]' ', [count]l
+ * Move right by columns.
+ *
+ * PUBLIC: int v_right __P((SCR *, VICMD *));
+ */
+int
+v_right(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ size_t len;
+ int isempty;
+
+ if (db_eget(sp, vp->m_start.lno, NULL, &len, &isempty)) {
+ if (isempty)
+ goto eol;
+ return (1);
+ }
+
+ /* It's always illegal to move right on empty lines. */
+ if (len == 0) {
+eol: v_eol(sp, NULL);
+ return (1);
+ }
+
+ /*
+ * Non-motion commands move to the end of the range. Delete and
+ * yank stay at the start. Ignore others. Adjust the end of the
+ * range for motion commands.
+ *
+ * !!!
+ * Historically, "[cdsy]l" worked at the end of a line. Also,
+ * EOL is a count sink.
+ */
+ vp->m_stop.cno = vp->m_start.cno +
+ (F_ISSET(vp, VC_C1SET) ? vp->count : 1);
+ if (vp->m_start.cno == len - 1 && !ISMOTION(vp)) {
+ v_eol(sp, NULL);
+ return (1);
+ }
+ if (vp->m_stop.cno >= len) {
+ vp->m_stop.cno = len - 1;
+ vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
+ } else if (ISMOTION(vp)) {
+ --vp->m_stop.cno;
+ vp->m_final = vp->m_start;
+ } else
+ vp->m_final = vp->m_stop;
+ return (0);
+}
+
+/*
+ * v_dollar -- [count]$
+ * Move to the last column.
+ *
+ * PUBLIC: int v_dollar __P((SCR *, VICMD *));
+ */
+int
+v_dollar(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ size_t len;
+ int isempty;
+
+ /*
+ * !!!
+ * A count moves down count - 1 rows, so, "3$" is the same as "2j$".
+ */
+ if ((F_ISSET(vp, VC_C1SET) ? vp->count : 1) != 1) {
+ /*
+ * !!!
+ * Historically, if the $ is a motion, and deleting from
+ * at or before the first non-blank of the line, it's a
+ * line motion, and the line motion flag is set.
+ */
+ vp->m_stop.cno = 0;
+ if (nonblank(sp, vp->m_start.lno, &vp->m_stop.cno))
+ return (1);
+ if (ISMOTION(vp) && vp->m_start.cno <= vp->m_stop.cno)
+ F_SET(vp, VM_LMODE);
+
+ --vp->count;
+ if (v_down(sp, vp))
+ return (1);
+ }
+
+ /*
+ * !!!
+ * Historically, it was illegal to use $ as a motion command on
+ * an empty line. Unfortunately, even though C was historically
+ * aliased to c$, it (and not c$) was special cased to work on
+ * empty lines. Since we alias C to c$ too, we have a problem.
+ * To fix it, we let c$ go through, on the assumption that it's
+ * not a problem for it to work.
+ */
+ if (db_eget(sp, vp->m_stop.lno, NULL, &len, &isempty)) {
+ if (!isempty)
+ return (1);
+ len = 0;
+ }
+
+ if (len == 0) {
+ if (ISMOTION(vp) && !ISCMD(vp->rkp, 'c')) {
+ v_eol(sp, NULL);
+ return (1);
+ }
+ return (0);
+ }
+
+ /*
+ * Non-motion commands move to the end of the range. Delete
+ * and yank stay at the start. Ignore others.
+ */
+ vp->m_stop.cno = len ? len - 1 : 0;
+ vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
+ return (0);
+}
diff --git a/contrib/nvi/vi/v_screen.c b/contrib/nvi/vi/v_screen.c
new file mode 100644
index 000000000000..85cd1e32bca0
--- /dev/null
+++ b/contrib/nvi/vi/v_screen.c
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_screen.c 10.10 (Berkeley) 4/27/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_screen -- ^W
+ * Switch screens.
+ *
+ * PUBLIC: int v_screen __P((SCR *, VICMD *));
+ */
+int
+v_screen(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ /*
+ * You can't leave a colon command-line edit window -- it's not that
+ * it won't work, but it gets real weird, real fast when you execute
+ * a colon command out of a window that was forked from a window that's
+ * now backgrounded... You get the idea.
+ */
+ if (F_ISSET(sp, SC_COMEDIT)) {
+ msgq(sp, M_ERR,
+ "308|Enter <CR> to execute a command, :q to exit");
+ return (1);
+ }
+
+ /*
+ * Try for the next lower screen, or, go back to the first
+ * screen on the stack.
+ */
+ if (sp->q.cqe_next != (void *)&sp->gp->dq)
+ sp->nextdisp = sp->q.cqe_next;
+ else if (sp->gp->dq.cqh_first == sp) {
+ msgq(sp, M_ERR, "187|No other screen to switch to");
+ return (1);
+ } else
+ sp->nextdisp = sp->gp->dq.cqh_first;
+
+ F_SET(sp->nextdisp, SC_STATUS);
+ F_SET(sp, SC_SSWITCH | SC_STATUS);
+ return (0);
+}
diff --git a/usr.bin/vi/vi/v_scroll.c b/contrib/nvi/vi/v_scroll.c
index b381dc550517..92def4b3e48d 100644
--- a/usr.bin/vi/vi/v_scroll.c
+++ b/contrib/nvi/vi/v_scroll.c
@@ -1,38 +1,16 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)v_scroll.c 8.20 (Berkeley) 7/27/94";
+static const char sccsid[] = "@(#)v_scroll.c 10.9 (Berkeley) 4/27/96";
#endif /* not lint */
#include <sys/types.h>
@@ -42,19 +20,12 @@ static char sccsid[] = "@(#)v_scroll.c 8.20 (Berkeley) 7/27/94";
#include <bitstring.h>
#include <errno.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
+#include "../common/common.h"
#include "vi.h"
-#include "excmd.h"
-#include "vcmd.h"
-static void goto_adjust __P((VICMDARG *));
+static void goto_adjust __P((VICMD *));
/*
* The historic vi had a problem in that all movements were by physical
@@ -92,23 +63,34 @@ static void goto_adjust __P((VICMDARG *));
* v_lgoto -- [count]G
* Go to first non-blank character of the line count, the last line
* of the file by default.
+ *
+ * PUBLIC: int v_lgoto __P((SCR *, VICMD *));
*/
int
-v_lgoto(sp, ep, vp)
+v_lgoto(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
recno_t nlines;
if (F_ISSET(vp, VC_C1SET)) {
- if (file_gline(sp, ep, vp->count, NULL) == NULL) {
- v_eof(sp, ep, &vp->m_start);
+ if (!db_exist(sp, vp->count)) {
+ /*
+ * !!!
+ * Historically, 1G was legal in an empty file.
+ */
+ if (vp->count == 1) {
+ if (db_last(sp, &nlines))
+ return (1);
+ if (nlines == 0)
+ return (0);
+ }
+ v_eof(sp, &vp->m_start);
return (1);
}
vp->m_stop.lno = vp->count;
} else {
- if (file_lline(sp, ep, &nlines))
+ if (db_last(sp, &nlines))
return (1);
vp->m_stop.lno = nlines ? nlines : 1;
}
@@ -120,14 +102,15 @@ v_lgoto(sp, ep, vp)
* v_home -- [count]H
* Move to the first non-blank character of the logical line
* count - 1 from the top of the screen, 0 by default.
+ *
+ * PUBLIC: int v_home __P((SCR *, VICMD *));
*/
int
-v_home(sp, ep, vp)
+v_home(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
- if (sp->s_position(sp, ep, &vp->m_stop,
+ if (vs_sm_position(sp, &vp->m_stop,
F_ISSET(vp, VC_C1SET) ? vp->count - 1 : 0, P_TOP))
return (1);
goto_adjust(vp);
@@ -138,19 +121,20 @@ v_home(sp, ep, vp)
* v_middle -- M
* Move to the first non-blank character of the logical line
* in the middle of the screen.
+ *
+ * PUBLIC: int v_middle __P((SCR *, VICMD *));
*/
int
-v_middle(sp, ep, vp)
+v_middle(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
/*
* Yielding to none in our quest for compatibility with every
* historical blemish of vi, no matter how strange it might be,
* we permit the user to enter a count and then ignore it.
*/
- if (sp->s_position(sp, ep, &vp->m_stop, 0, P_MIDDLE))
+ if (vs_sm_position(sp, &vp->m_stop, 0, P_MIDDLE))
return (1);
goto_adjust(vp);
return (0);
@@ -160,14 +144,15 @@ v_middle(sp, ep, vp)
* v_bottom -- [count]L
* Move to the first non-blank character of the logical line
* count - 1 from the bottom of the screen, 0 by default.
+ *
+ * PUBLIC: int v_bottom __P((SCR *, VICMD *));
*/
int
-v_bottom(sp, ep, vp)
+v_bottom(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
- if (sp->s_position(sp, ep, &vp->m_stop,
+ if (vs_sm_position(sp, &vp->m_stop,
F_ISSET(vp, VC_C1SET) ? vp->count - 1 : 0, P_BOTTOM))
return (1);
goto_adjust(vp);
@@ -176,7 +161,7 @@ v_bottom(sp, ep, vp)
static void
goto_adjust(vp)
- VICMDARG *vp;
+ VICMD *vp;
{
/* Guess that it's the end of the range. */
vp->m_final = vp->m_stop;
@@ -208,15 +193,15 @@ goto_adjust(vp)
return;
/*
- * If moving backward in the file, VC_D and VC_Y move to the end
- * of the range, unless the line didn't change, in which case VC_Y
- * doesn't move. If moving forward in the file, VC_D and VC_Y stay
- * at the start of the range. Ignore VC_C and VC_DEF.
+ * If moving backward in the file, delete and yank move to the end
+ * of the range, unless the line didn't change, in which case yank
+ * doesn't move. If moving forward in the file, delete and yank
+ * stay at the start of the range. Ignore others.
*/
if (vp->m_stop.lno < vp->m_start.lno ||
vp->m_stop.lno == vp->m_start.lno &&
vp->m_stop.cno < vp->m_start.cno) {
- if (F_ISSET(vp, VC_Y) && vp->m_stop.lno == vp->m_start.lno)
+ if (ISCMD(vp->rkp, 'y') && vp->m_stop.lno == vp->m_start.lno)
vp->m_final = vp->m_start;
} else
vp->m_final = vp->m_start;
@@ -225,12 +210,13 @@ goto_adjust(vp)
/*
* v_up -- [count]^P, [count]k, [count]-
* Move up by lines.
+ *
+ * PUBLIC: int v_up __P((SCR *, VICMD *));
*/
int
-v_up(sp, ep, vp)
+v_up(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
recno_t lno;
@@ -248,36 +234,42 @@ v_up(sp, ep, vp)
* v_cr -- [count]^M
* In a script window, send the line to the shell.
* In a regular window, move down by lines.
+ *
+ * PUBLIC: int v_cr __P((SCR *, VICMD *));
*/
int
-v_cr(sp, ep, vp)
+v_cr(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
- /*
- * If it's a script window, exec the line,
- * otherwise it's the same as v_down().
- */
- return (F_ISSET(sp, S_SCRIPT) ?
- sscr_exec(sp, ep, vp->m_start.lno) : v_down(sp, ep, vp));
+ /* If it's a colon command-line edit window, it's an ex command. */
+ if (F_ISSET(sp, SC_COMEDIT))
+ return (v_ecl_exec(sp));
+
+ /* If it's a script window, exec the line. */
+ if (F_ISSET(sp, SC_SCRIPT))
+ return (sscr_exec(sp, vp->m_start.lno));
+
+ /* Otherwise, it's the same as v_down(). */
+ return (v_down(sp, vp));
}
/*
* v_down -- [count]^J, [count]^N, [count]j, [count]^M, [count]+
* Move down by lines.
+ *
+ * PUBLIC: int v_down __P((SCR *, VICMD *));
*/
int
-v_down(sp, ep, vp)
+v_down(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
recno_t lno;
lno = vp->m_start.lno + (F_ISSET(vp, VC_C1SET) ? vp->count : 1);
- if (file_gline(sp, ep, lno, NULL) == NULL) {
- v_eof(sp, ep, &vp->m_start);
+ if (!db_exist(sp, lno)) {
+ v_eof(sp, &vp->m_start);
return (1);
}
vp->m_stop.lno = lno;
@@ -288,12 +280,13 @@ v_down(sp, ep, vp)
/*
* v_hpageup -- [count]^U
* Page up half screens.
+ *
+ * PUBLIC: int v_hpageup __P((SCR *, VICMD *));
*/
int
-v_hpageup(sp, ep, vp)
+v_hpageup(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
/*
* Half screens always succeed unless already at SOF.
@@ -304,7 +297,7 @@ v_hpageup(sp, ep, vp)
*/
if (F_ISSET(vp, VC_C1SET))
sp->defscroll = vp->count;
- if (sp->s_scroll(sp, ep, &vp->m_stop, sp->defscroll, CNTRL_U))
+ if (vs_sm_scroll(sp, &vp->m_stop, sp->defscroll, CNTRL_U))
return (1);
vp->m_final = vp->m_stop;
return (0);
@@ -313,12 +306,13 @@ v_hpageup(sp, ep, vp)
/*
* v_hpagedown -- [count]^D
* Page down half screens.
+ *
+ * PUBLIC: int v_hpagedown __P((SCR *, VICMD *));
*/
int
-v_hpagedown(sp, ep, vp)
+v_hpagedown(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
/*
* Half screens always succeed unless already at EOF.
@@ -329,7 +323,7 @@ v_hpagedown(sp, ep, vp)
*/
if (F_ISSET(vp, VC_C1SET))
sp->defscroll = vp->count;
- if (sp->s_scroll(sp, ep, &vp->m_stop, sp->defscroll, CNTRL_D))
+ if (vs_sm_scroll(sp, &vp->m_stop, sp->defscroll, CNTRL_D))
return (1);
vp->m_final = vp->m_stop;
return (0);
@@ -342,12 +336,13 @@ v_hpagedown(sp, ep, vp)
* Historic vi did not move to the EOF if the screen couldn't move, i.e.
* if EOF was already displayed on the screen. This implementation does
* move to EOF in that case, making ^F more like the the historic ^D.
+ *
+ * PUBLIC: int v_pagedown __P((SCR *, VICMD *));
*/
int
-v_pagedown(sp, ep, vp)
+v_pagedown(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
recno_t offset;
@@ -364,25 +359,18 @@ v_pagedown(sp, ep, vp)
* i.e. the two line "overlap" was only subtracted once. Which
* makes no sense, but then again, an overlap makes no sense for
* any screen but the "next" one anyway. We do it the historical
- * was as there's no good reason to change it.
+ * way as there's no good reason to change it.
*
* If the screen has been split, use the smaller of the current
* window size and the window option value.
*
- * Given a one-line screen with the cursor on line 1, it would be
- * possible for this to fail, i.e. "1 + 1 * 1 - 2 = 0". Move at
+ * It possible for this calculation to be less than 1; move at
* least one line.
*/
-#define IS_SPLIT_SCREEN(sp) \
- ((sp)->q.cqe_prev != (void *)&(sp)->gp->dq || \
- (sp)->q.cqe_next != (void *)&(sp)->gp->dq)
-
- offset = (F_ISSET(vp, VC_C1SET) ? vp->count : 1) *
- (IS_SPLIT_SCREEN(sp) ?
- MIN(sp->t_maxrows, O_VAL(sp, O_WINDOW)) : O_VAL(sp, O_WINDOW)) - 2;
- if (offset == 0)
- offset = 1;
- if (sp->s_scroll(sp, ep, &vp->m_stop, offset, CNTRL_F))
+ offset = (F_ISSET(vp, VC_C1SET) ? vp->count : 1) * (IS_SPLIT(sp) ?
+ MIN(sp->t_maxrows, O_VAL(sp, O_WINDOW)) : O_VAL(sp, O_WINDOW));
+ offset = offset <= 2 ? 1 : offset - 2;
+ if (vs_sm_scroll(sp, &vp->m_stop, offset, CNTRL_F))
return (1);
vp->m_final = vp->m_stop;
return (0);
@@ -396,12 +384,13 @@ v_pagedown(sp, ep, vp)
* Historic vi did not move to the SOF if the screen couldn't move, i.e.
* if SOF was already displayed on the screen. This implementation does
* move to SOF in that case, making ^B more like the the historic ^U.
+ *
+ * PUBLIC: int v_pageup __P((SCR *, VICMD *));
*/
int
-v_pageup(sp, ep, vp)
+v_pageup(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
recno_t offset;
@@ -428,16 +417,13 @@ v_pageup(sp, ep, vp)
* If the screen has been split, use the smaller of the current
* window size and the window option value.
*
- * Given a one-line screen with the cursor on line 1, it would be
- * possible for this to fail, i.e. "1 + 1 * 1 - 2 = 0". Move at
+ * It possible for this calculation to be less than 1; move at
* least one line.
*/
- offset = (F_ISSET(vp, VC_C1SET) ? vp->count : 1) *
- (IS_SPLIT_SCREEN(sp) ?
- MIN(sp->t_maxrows, O_VAL(sp, O_WINDOW)) : O_VAL(sp, O_WINDOW)) - 2;
- if (offset == 0)
- offset = 1;
- if (sp->s_scroll(sp, ep, &vp->m_stop, offset, CNTRL_B))
+ offset = (F_ISSET(vp, VC_C1SET) ? vp->count : 1) * (IS_SPLIT(sp) ?
+ MIN(sp->t_maxrows, O_VAL(sp, O_WINDOW)) : O_VAL(sp, O_WINDOW));
+ offset = offset <= 2 ? 1 : offset - 2;
+ if (vs_sm_scroll(sp, &vp->m_stop, offset, CNTRL_B))
return (1);
vp->m_final = vp->m_stop;
return (0);
@@ -446,18 +432,19 @@ v_pageup(sp, ep, vp)
/*
* v_lineup -- [count]^Y
* Page up by lines.
+ *
+ * PUBLIC: int v_lineup __P((SCR *, VICMD *));
*/
int
-v_lineup(sp, ep, vp)
+v_lineup(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
/*
* The cursor moves down, staying with its original line, unless it
* reaches the bottom of the screen.
*/
- if (sp->s_scroll(sp, ep,
+ if (vs_sm_scroll(sp,
&vp->m_stop, F_ISSET(vp, VC_C1SET) ? vp->count : 1, CNTRL_Y))
return (1);
vp->m_final = vp->m_stop;
@@ -467,18 +454,19 @@ v_lineup(sp, ep, vp)
/*
* v_linedown -- [count]^E
* Page down by lines.
+ *
+ * PUBLIC: int v_linedown __P((SCR *, VICMD *));
*/
int
-v_linedown(sp, ep, vp)
+v_linedown(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
/*
* The cursor moves up, staying with its original line, unless it
* reaches the top of the screen.
*/
- if (sp->s_scroll(sp, ep,
+ if (vs_sm_scroll(sp,
&vp->m_stop, F_ISSET(vp, VC_C1SET) ? vp->count : 1, CNTRL_E))
return (1);
vp->m_final = vp->m_stop;
diff --git a/contrib/nvi/vi/v_search.c b/contrib/nvi/vi/v_search.c
new file mode 100644
index 000000000000..4f7a2671ab8e
--- /dev/null
+++ b/contrib/nvi/vi/v_search.c
@@ -0,0 +1,515 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_search.c 10.18 (Berkeley) 9/19/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+static int v_exaddr __P((SCR *, VICMD *, dir_t));
+static int v_search __P((SCR *, VICMD *, char *, size_t, u_int, dir_t));
+
+/*
+ * v_srch -- [count]?RE[? offset]
+ * Ex address search backward.
+ *
+ * PUBLIC: int v_searchb __P((SCR *, VICMD *));
+ */
+int
+v_searchb(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ return (v_exaddr(sp, vp, BACKWARD));
+}
+
+/*
+ * v_searchf -- [count]/RE[/ offset]
+ * Ex address search forward.
+ *
+ * PUBLIC: int v_searchf __P((SCR *, VICMD *));
+ */
+int
+v_searchf(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ return (v_exaddr(sp, vp, FORWARD));
+}
+
+/*
+ * v_exaddr --
+ * Do a vi search (which is really an ex address).
+ */
+static int
+v_exaddr(sp, vp, dir)
+ SCR *sp;
+ VICMD *vp;
+ dir_t dir;
+{
+ static EXCMDLIST fake = { "search" };
+ EXCMD *cmdp;
+ GS *gp;
+ TEXT *tp;
+ recno_t s_lno;
+ size_t len, s_cno, tlen;
+ int err, nb, type;
+ char *cmd, *t, buf[20];
+
+ /*
+ * !!!
+ * If using the search command as a motion, any addressing components
+ * are lost, i.e. y/ptrn/+2, when repeated, is the same as y/ptrn/.
+ */
+ if (F_ISSET(vp, VC_ISDOT))
+ return (v_search(sp, vp,
+ NULL, 0, SEARCH_PARSE | SEARCH_MSG | SEARCH_SET, dir));
+
+ /* Get the search pattern. */
+ if (v_tcmd(sp, vp, dir == BACKWARD ? CH_BSEARCH : CH_FSEARCH,
+ TXT_BS | TXT_CR | TXT_ESCAPE | TXT_PROMPT |
+ (O_ISSET(sp, O_SEARCHINCR) ? TXT_SEARCHINCR : 0)))
+ return (1);
+
+ tp = sp->tiq.cqh_first;
+
+ /* If the user backspaced over the prompt, do nothing. */
+ if (tp->term == TERM_BS)
+ return (1);
+
+ /*
+ * If the user was doing an incremental search, then we've already
+ * updated the cursor and moved to the right location. Return the
+ * correct values, we're done.
+ */
+ if (tp->term == TERM_SEARCH) {
+ vp->m_stop.lno = sp->lno;
+ vp->m_stop.cno = sp->cno;
+ if (ISMOTION(vp))
+ return (v_correct(sp, vp, 0));
+ vp->m_final = vp->m_stop;
+ return (0);
+ }
+
+ /*
+ * If the user entered <escape> or <carriage-return>, the length is
+ * 1 and the right thing will happen, i.e. the prompt will be used
+ * as a command character.
+ *
+ * Build a fake ex command structure.
+ */
+ gp = sp->gp;
+ gp->excmd.cp = tp->lb;
+ gp->excmd.clen = tp->len;
+ F_INIT(&gp->excmd, E_VISEARCH);
+
+ /*
+ * XXX
+ * Warn if the search wraps. This is a pretty special case, but it's
+ * nice feature that wasn't in the original implementations of ex/vi.
+ * (It was added at some point to System V's version.) This message
+ * is only displayed if there are no keys in the queue. The problem is
+ * the command is going to succeed, and the message is informational,
+ * not an error. If a macro displays it repeatedly, e.g., the pattern
+ * only occurs once in the file and wrapscan is set, you lose big. For
+ * example, if the macro does something like:
+ *
+ * :map K /pattern/^MjK
+ *
+ * Each search will display the message, but the following "/pattern/"
+ * will immediately overwrite it, with strange results. The System V
+ * vi displays the "wrapped" message multiple times, but because it's
+ * overwritten each time, it's not as noticeable. As we don't discard
+ * messages, it's a real problem for us.
+ */
+ if (!KEYS_WAITING(sp))
+ F_SET(&gp->excmd, E_SEARCH_WMSG);
+
+ /* Save the current line/column. */
+ s_lno = sp->lno;
+ s_cno = sp->cno;
+
+ /*
+ * !!!
+ * Historically, vi / and ? commands were full-blown ex addresses,
+ * including ';' delimiters, trailing <blank>'s, multiple search
+ * strings (separated by semi-colons) and, finally, full-blown z
+ * commands after the / and ? search strings. (If the search was
+ * being used as a motion, the trailing z command was ignored.
+ * Also, we do some argument checking on the z command, to be sure
+ * that it's not some other random command.) For multiple search
+ * strings, leading <blank>'s at the second and subsequent strings
+ * were eaten as well. This has some (unintended?) side-effects:
+ * the command /ptrn/;3 is legal and results in moving to line 3.
+ * I suppose you could use it to optionally move to line 3...
+ *
+ * !!!
+ * Historically, if any part of the search command failed, the cursor
+ * remained unmodified (even if ; was used). We have to play games
+ * because the underlying ex parser thinks we're modifying the cursor
+ * as we go, but I think we're compatible with historic practice.
+ *
+ * !!!
+ * Historically, the command "/STRING/; " failed, apparently it
+ * confused the parser. We're not that compatible.
+ */
+ cmdp = &gp->excmd;
+ if (ex_range(sp, cmdp, &err))
+ return (1);
+
+ /*
+ * Remember where any remaining command information is, and clean
+ * up the fake ex command.
+ */
+ cmd = cmdp->cp;
+ len = cmdp->clen;
+ gp->excmd.clen = 0;
+
+ if (err)
+ goto err2;
+
+ /* Copy out the new cursor position and make sure it's okay. */
+ switch (cmdp->addrcnt) {
+ case 1:
+ vp->m_stop = cmdp->addr1;
+ break;
+ case 2:
+ vp->m_stop = cmdp->addr2;
+ break;
+ }
+ if (!db_exist(sp, vp->m_stop.lno)) {
+ ex_badaddr(sp, &fake,
+ vp->m_stop.lno == 0 ? A_ZERO : A_EOF, NUM_OK);
+ goto err2;
+ }
+
+ /*
+ * !!!
+ * Historic practice is that a trailing 'z' was ignored if it was a
+ * motion command. Should probably be an error, but not worth the
+ * effort.
+ */
+ if (ISMOTION(vp))
+ return (v_correct(sp, vp, F_ISSET(cmdp, E_DELTA)));
+
+ /*
+ * !!!
+ * Historically, if it wasn't a motion command, a delta in the search
+ * pattern turns it into a first nonblank movement.
+ */
+ nb = F_ISSET(cmdp, E_DELTA);
+
+ /* Check for the 'z' command. */
+ if (len != 0) {
+ if (*cmd != 'z')
+ goto err1;
+
+ /* No blanks, just like the z command. */
+ for (t = cmd + 1, tlen = len - 1; tlen > 0; ++t, --tlen)
+ if (!isdigit(*t))
+ break;
+ if (tlen &&
+ (*t == '-' || *t == '.' || *t == '+' || *t == '^')) {
+ ++t;
+ --tlen;
+ type = 1;
+ } else
+ type = 0;
+ if (tlen)
+ goto err1;
+
+ /* The z command will do the nonblank for us. */
+ nb = 0;
+
+ /* Default to z+. */
+ if (!type &&
+ v_event_push(sp, NULL, "+", 1, CH_NOMAP | CH_QUOTED))
+ return (1);
+
+ /* Push the user's command. */
+ if (v_event_push(sp, NULL, cmd, len, CH_NOMAP | CH_QUOTED))
+ return (1);
+
+ /* Push line number so get correct z display. */
+ tlen = snprintf(buf,
+ sizeof(buf), "%lu", (u_long)vp->m_stop.lno);
+ if (v_event_push(sp, NULL, buf, tlen, CH_NOMAP | CH_QUOTED))
+ return (1);
+
+ /* Don't refresh until after 'z' happens. */
+ F_SET(VIP(sp), VIP_S_REFRESH);
+ }
+
+ /* Non-motion commands move to the end of the range. */
+ vp->m_final = vp->m_stop;
+ if (nb) {
+ F_CLR(vp, VM_RCM_MASK);
+ F_SET(vp, VM_RCM_SETFNB);
+ }
+ return (0);
+
+err1: msgq(sp, M_ERR,
+ "188|Characters after search string, line offset and/or z command");
+err2: vp->m_final.lno = s_lno;
+ vp->m_final.cno = s_cno;
+ return (1);
+}
+
+/*
+ * v_searchN -- N
+ * Reverse last search.
+ *
+ * PUBLIC: int v_searchN __P((SCR *, VICMD *));
+ */
+int
+v_searchN(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ dir_t dir;
+
+ switch (sp->searchdir) {
+ case BACKWARD:
+ dir = FORWARD;
+ break;
+ case FORWARD:
+ dir = BACKWARD;
+ break;
+ default:
+ dir = sp->searchdir;
+ break;
+ }
+ return (v_search(sp, vp, NULL, 0, SEARCH_PARSE, dir));
+}
+
+/*
+ * v_searchn -- n
+ * Repeat last search.
+ *
+ * PUBLIC: int v_searchn __P((SCR *, VICMD *));
+ */
+int
+v_searchn(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ return (v_search(sp, vp, NULL, 0, SEARCH_PARSE, sp->searchdir));
+}
+
+/*
+ * v_searchw -- [count]^A
+ * Search for the word under the cursor.
+ *
+ * PUBLIC: int v_searchw __P((SCR *, VICMD *));
+ */
+int
+v_searchw(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ size_t blen, len;
+ int rval;
+ char *bp;
+
+ len = VIP(sp)->klen + sizeof(RE_WSTART) + sizeof(RE_WSTOP);
+ GET_SPACE_RET(sp, bp, blen, len);
+ len = snprintf(bp, blen, "%s%s%s", RE_WSTART, VIP(sp)->keyw, RE_WSTOP);
+
+ rval = v_search(sp, vp, bp, len, SEARCH_SET, FORWARD);
+
+ FREE_SPACE(sp, bp, blen);
+ return (rval);
+}
+
+/*
+ * v_search --
+ * The search commands.
+ */
+static int
+v_search(sp, vp, ptrn, plen, flags, dir)
+ SCR *sp;
+ VICMD *vp;
+ u_int flags;
+ char *ptrn;
+ size_t plen;
+ dir_t dir;
+{
+ /* Display messages. */
+ LF_SET(SEARCH_MSG);
+
+ /* If it's a motion search, offset past end-of-line is okay. */
+ if (ISMOTION(vp))
+ LF_SET(SEARCH_EOL);
+
+ /*
+ * XXX
+ * Warn if the search wraps. See the comment above, in v_exaddr().
+ */
+ if (!KEYS_WAITING(sp))
+ LF_SET(SEARCH_WMSG);
+
+ switch (dir) {
+ case BACKWARD:
+ if (b_search(sp,
+ &vp->m_start, &vp->m_stop, ptrn, plen, NULL, flags))
+ return (1);
+ break;
+ case FORWARD:
+ if (f_search(sp,
+ &vp->m_start, &vp->m_stop, ptrn, plen, NULL, flags))
+ return (1);
+ break;
+ case NOTSET:
+ msgq(sp, M_ERR, "189|No previous search pattern");
+ return (1);
+ default:
+ abort();
+ }
+
+ /* Correct motion commands, otherwise, simply move to the location. */
+ if (ISMOTION(vp)) {
+ if (v_correct(sp, vp, 0))
+ return(1);
+ } else
+ vp->m_final = vp->m_stop;
+ return (0);
+}
+
+/*
+ * v_correct --
+ * Handle command with a search as the motion.
+ *
+ * !!!
+ * Historically, commands didn't affect the line searched to/from if the
+ * motion command was a search and the final position was the start/end
+ * of the line. There were some special cases and vi was not consistent;
+ * it was fairly easy to confuse it. For example, given the two lines:
+ *
+ * abcdefghi
+ * ABCDEFGHI
+ *
+ * placing the cursor on the 'A' and doing y?$ would so confuse it that 'h'
+ * 'k' and put would no longer work correctly. In any case, we try to do
+ * the right thing, but it's not going to exactly match historic practice.
+ *
+ * PUBLIC: int v_correct __P((SCR *, VICMD *, int));
+ */
+int
+v_correct(sp, vp, isdelta)
+ SCR *sp;
+ VICMD *vp;
+ int isdelta;
+{
+ dir_t dir;
+ MARK m;
+ size_t len;
+
+ /*
+ * !!!
+ * We may have wrapped if wrapscan was set, and we may have returned
+ * to the position where the cursor started. Historic vi didn't cope
+ * with this well. Yank wouldn't beep, but the first put after the
+ * yank would move the cursor right one column (without adding any
+ * text) and the second would put a copy of the current line. The
+ * change and delete commands would beep, but would leave the cursor
+ * on the colon command line. I believe that there are macros that
+ * depend on delete, at least, failing. For now, commands that use
+ * search as a motion component fail when the search returns to the
+ * original cursor position.
+ */
+ if (vp->m_start.lno == vp->m_stop.lno &&
+ vp->m_start.cno == vp->m_stop.cno) {
+ msgq(sp, M_BERR, "190|Search wrapped to original position");
+ return (1);
+ }
+
+ /*
+ * !!!
+ * Searches become line mode operations if there was a delta specified
+ * to the search pattern.
+ */
+ if (isdelta)
+ F_SET(vp, VM_LMODE);
+
+ /*
+ * If the motion is in the reverse direction, switch the start and
+ * stop MARK's so that it's in a forward direction. (There's no
+ * reason for this other than to make the tests below easier. The
+ * code in vi.c:vi() would have done the switch.) Both forward
+ * and backward motions can happen for any kind of search command
+ * because of the wrapscan option.
+ */
+ if (vp->m_start.lno > vp->m_stop.lno ||
+ vp->m_start.lno == vp->m_stop.lno &&
+ vp->m_start.cno > vp->m_stop.cno) {
+ m = vp->m_start;
+ vp->m_start = vp->m_stop;
+ vp->m_stop = m;
+ dir = BACKWARD;
+ } else
+ dir = FORWARD;
+
+ /*
+ * BACKWARD:
+ * Delete and yank commands move to the end of the range.
+ * Ignore others.
+ *
+ * FORWARD:
+ * Delete and yank commands don't move. Ignore others.
+ */
+ vp->m_final = vp->m_start;
+
+ /*
+ * !!!
+ * Delta'd searches don't correct based on column positions.
+ */
+ if (isdelta)
+ return (0);
+
+ /*
+ * !!!
+ * Backward searches starting at column 0, and forward searches ending
+ * at column 0 are corrected to the last column of the previous line.
+ * Otherwise, adjust the starting/ending point to the character before
+ * the current one (this is safe because we know the search had to move
+ * to succeed).
+ *
+ * Searches become line mode operations if they start at the first
+ * nonblank and end at column 0 of another line.
+ */
+ if (vp->m_start.lno < vp->m_stop.lno && vp->m_stop.cno == 0) {
+ if (db_get(sp, --vp->m_stop.lno, DBG_FATAL, NULL, &len))
+ return (1);
+ vp->m_stop.cno = len ? len - 1 : 0;
+ len = 0;
+ if (nonblank(sp, vp->m_start.lno, &len))
+ return (1);
+ if (vp->m_start.cno <= len)
+ F_SET(vp, VM_LMODE);
+ } else
+ --vp->m_stop.cno;
+
+ return (0);
+}
diff --git a/usr.bin/vi/vi/v_section.c b/contrib/nvi/vi/v_section.c
index 9bc06b678995..20e8ff2808fd 100644
--- a/usr.bin/vi/vi/v_section.c
+++ b/contrib/nvi/vi/v_section.c
@@ -1,38 +1,16 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)v_section.c 8.10 (Berkeley) 7/27/94";
+static const char sccsid[] = "@(#)v_section.c 10.7 (Berkeley) 3/6/96";
#endif /* not lint */
#include <sys/types.h>
@@ -41,17 +19,11 @@ static char sccsid[] = "@(#)v_section.c 8.10 (Berkeley) 7/27/94";
#include <bitstring.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
+#include "../common/common.h"
#include "vi.h"
-#include "vcmd.h"
/*
* !!!
@@ -86,12 +58,13 @@ static char sccsid[] = "@(#)v_section.c 8.10 (Berkeley) 7/27/94";
* match } as well as the usual { and section values. If it matched a { or
* a section, it did NOT include the matched line. If it matched a }, it
* did include the line. No clue why.
+ *
+ * PUBLIC: int v_sectionf __P((SCR *, VICMD *));
*/
int
-v_sectionf(sp, ep, vp)
+v_sectionf(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
recno_t cnt, lno;
size_t len;
@@ -115,15 +88,14 @@ v_sectionf(sp, ep, vp)
else {
vp->m_stop = vp->m_start;
vp->m_stop.cno = 0;
- if (nonblank(sp, ep, vp->m_stop.lno, &vp->m_stop.cno))
+ if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
return (1);
if (vp->m_start.cno <= vp->m_stop.cno)
F_SET(vp, VM_LMODE);
}
cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
- for (lno = vp->m_start.lno;
- (p = file_gline(sp, ep, ++lno, &len)) != NULL;) {
+ for (lno = vp->m_start.lno; !db_get(sp, ++lno, 0, &p, &len);) {
if (len == 0)
continue;
if (p[0] == '{' || ISMOTION(vp) && p[0] == '}') {
@@ -137,7 +109,7 @@ v_sectionf(sp, ep, vp)
/*
* !!!
* Historic documentation (USD:15-11, 4.2) said that formfeed
- * characters (^L) in the first column delimited sections.
+ * characters (^L) in the first column delimited sections.
* The historic code mentions formfeed characters, but never
* implements them. Seems reasonable, do it.
*/
@@ -169,18 +141,18 @@ adjust2: vp->m_stop.lno = lno;
/* If moving forward, reached EOF, check to see if we started there. */
if (vp->m_start.lno == lno - 1) {
- v_eof(sp, ep, NULL);
+ v_eof(sp, NULL);
return (1);
}
-ret1: if (file_gline(sp, ep, --lno, &len) == NULL)
+ret1: if (db_get(sp, --lno, DBG_FATAL, NULL, &len))
return (1);
vp->m_stop.lno = lno;
vp->m_stop.cno = len ? len - 1 : 0;
/*
- * Non-motion commands go to the end of the range. VC_D and
- * VC_Y stay at the start of the range. Ignore VC_C and VC_DEF.
+ * Non-motion commands go to the end of the range. Delete and
+ * yank stay at the start of the range. Ignore others.
*/
ret2: if (ISMOTION(vp)) {
vp->m_final = vp->m_start;
@@ -194,12 +166,13 @@ ret2: if (ISMOTION(vp)) {
/*
* v_sectionb -- [count][[
* Move backward count sections/functions.
+ *
+ * PUBLIC: int v_sectionb __P((SCR *, VICMD *));
*/
int
-v_sectionb(sp, ep, vp)
+v_sectionb(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
size_t len;
recno_t cnt, lno;
@@ -216,8 +189,7 @@ v_sectionb(sp, ep, vp)
return (1);
cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
- for (lno = vp->m_start.lno;
- (p = file_gline(sp, ep, --lno, &len)) != NULL;) {
+ for (lno = vp->m_start.lno; !db_get(sp, --lno, 0, &p, &len);) {
if (len == 0)
continue;
if (p[0] == '{') {
@@ -228,7 +200,7 @@ v_sectionb(sp, ep, vp)
/*
* !!!
* Historic documentation (USD:15-11, 4.2) said that formfeed
- * characters (^L) in the first column delimited sections.
+ * characters (^L) in the first column delimited sections.
* The historic code mentions formfeed characters, but never
* implements them. Seems reasonable, do it.
*/
diff --git a/usr.bin/vi/vi/v_sentence.c b/contrib/nvi/vi/v_sentence.c
index 87c6039ac3f5..a3d9376be403 100644
--- a/usr.bin/vi/vi/v_sentence.c
+++ b/contrib/nvi/vi/v_sentence.c
@@ -1,38 +1,16 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)v_sentence.c 8.15 (Berkeley) 7/27/94";
+static const char sccsid[] = "@(#)v_sentence.c 10.7 (Berkeley) 3/6/96";
#endif /* not lint */
#include <sys/types.h>
@@ -42,16 +20,10 @@ static char sccsid[] = "@(#)v_sentence.c 8.15 (Berkeley) 7/27/94";
#include <bitstring.h>
#include <ctype.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
+#include "../common/common.h"
#include "vi.h"
-#include "vcmd.h"
/*
* !!!
@@ -76,12 +48,13 @@ static char sccsid[] = "@(#)v_sentence.c 8.15 (Berkeley) 7/27/94";
/*
* v_sentencef -- [count])
* Move forward count sentences.
+ *
+ * PUBLIC: int v_sentencef __P((SCR *, VICMD *));
*/
int
-v_sentencef(sp, ep, vp)
+v_sentencef(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
enum { BLANK, NONE, PERIOD } state;
VCS cs;
@@ -90,7 +63,7 @@ v_sentencef(sp, ep, vp)
cs.cs_lno = vp->m_start.lno;
cs.cs_cno = vp->m_start.cno;
- if (cs_init(sp, ep, &cs))
+ if (cs_init(sp, &cs))
return (1);
cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
@@ -102,7 +75,7 @@ v_sentencef(sp, ep, vp)
* what correctly means in that case.
*/
if (cs.cs_flags == CS_EMP || cs.cs_flags == 0 && isblank(cs.cs_ch)) {
- if (cs_fblank(sp, ep, &cs))
+ if (cs_fblank(sp, &cs))
return (1);
if (--cnt == 0) {
if (vp->m_start.lno != cs.cs_lno ||
@@ -113,16 +86,16 @@ v_sentencef(sp, ep, vp)
}
for (state = NONE;;) {
- if (cs_next(sp, ep, &cs))
+ if (cs_next(sp, &cs))
return (1);
if (cs.cs_flags == CS_EOF)
break;
if (cs.cs_flags == CS_EOL) {
if ((state == PERIOD || state == BLANK) && --cnt == 0) {
- if (cs_next(sp, ep, &cs))
+ if (cs_next(sp, &cs))
return (1);
if (cs.cs_flags == 0 &&
- isblank(cs.cs_ch) && cs_fblank(sp, ep, &cs))
+ isblank(cs.cs_ch) && cs_fblank(sp, &cs))
return (1);
goto okret;
}
@@ -132,7 +105,7 @@ v_sentencef(sp, ep, vp)
if (cs.cs_flags == CS_EMP) { /* An EMP is two sentences. */
if (--cnt == 0)
goto okret;
- if (cs_fblank(sp, ep, &cs))
+ if (cs_fblank(sp, &cs))
return (1);
if (--cnt == 0)
goto okret;
@@ -162,7 +135,7 @@ v_sentencef(sp, ep, vp)
break;
}
if (state == BLANK && --cnt == 0) {
- if (cs_fblank(sp, ep, &cs))
+ if (cs_fblank(sp, &cs))
return (1);
goto okret;
}
@@ -175,7 +148,7 @@ v_sentencef(sp, ep, vp)
/* EOF is a movement sink, but it's an error not to have moved. */
if (vp->m_start.lno == cs.cs_lno && vp->m_start.cno == cs.cs_cno) {
- v_eof(sp, ep, NULL);
+ v_eof(sp, NULL);
return (1);
}
@@ -185,24 +158,25 @@ okret: vp->m_stop.lno = cs.cs_lno;
/*
* !!!
* Historic, uh, features, yeah, that's right, call 'em features.
- * If the ending cursor position is at the first column in the
- * line, i.e. the movement is cutting an entire line, the buffer
- * is in line mode, and the ending position is the last character
- * of the previous line.
+ * If the starting and ending cursor positions are at the first
+ * column in their lines, i.e. the movement is cutting entire lines,
+ * the buffer is in line mode, and the ending position is the last
+ * character of the previous line. Note check to make sure that
+ * it's not within a single line.
*
- * Non-motion commands move to the end of the range. VC_D and
- * VC_Y stay at the start. Ignore VC_C and VC_DEF. Adjust the
- * end of the range for motion commands.
+ * Non-motion commands move to the end of the range. Delete and
+ * yank stay at the start. Ignore others. Adjust the end of the
+ * range for motion commands.
*/
if (ISMOTION(vp)) {
if (vp->m_start.cno == 0 &&
(cs.cs_flags != 0 || vp->m_stop.cno == 0)) {
- if (file_gline(sp, ep,
- --vp->m_stop.lno, &len) == NULL) {
- GETLINE_ERR(sp, vp->m_stop.lno);
- return (1);
+ if (vp->m_start.lno < vp->m_stop.lno) {
+ if (db_get(sp,
+ --vp->m_stop.lno, DBG_FATAL, NULL, &len))
+ return (1);
+ vp->m_stop.cno = len ? len - 1 : 0;
}
- vp->m_stop.cno = len ? len - 1 : 0;
F_SET(vp, VM_LMODE);
} else
--vp->m_stop.cno;
@@ -215,12 +189,13 @@ okret: vp->m_stop.lno = cs.cs_lno;
/*
* v_sentenceb -- [count](
* Move backward count sentences.
+ *
+ * PUBLIC: int v_sentenceb __P((SCR *, VICMD *));
*/
int
-v_sentenceb(sp, ep, vp)
+v_sentenceb(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
VCS cs;
recno_t slno;
@@ -237,7 +212,7 @@ v_sentenceb(sp, ep, vp)
cs.cs_lno = vp->m_start.lno;
cs.cs_cno = vp->m_start.cno;
- if (cs_init(sp, ep, &cs))
+ if (cs_init(sp, &cs))
return (1);
cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
@@ -254,24 +229,24 @@ v_sentenceb(sp, ep, vp)
* Berkeley was once a major center of drug activity.
*/
if (cs.cs_flags == CS_EMP) {
- if (cs_bblank(sp, ep, &cs))
+ if (cs_bblank(sp, &cs))
return (1);
for (;;) {
- if (cs_prev(sp, ep, &cs))
+ if (cs_prev(sp, &cs))
return (1);
if (cs.cs_flags != CS_EOL)
break;
}
} else if (cs.cs_flags == 0 && !isblank(cs.cs_ch))
for (;;) {
- if (cs_prev(sp, ep, &cs))
+ if (cs_prev(sp, &cs))
return (1);
if (cs.cs_flags != 0 || isblank(cs.cs_ch))
break;
}
for (last = 0;;) {
- if (cs_prev(sp, ep, &cs))
+ if (cs_prev(sp, &cs))
return (1);
if (cs.cs_flags == CS_SOF) /* SOF is a movement sink. */
break;
@@ -282,7 +257,7 @@ v_sentenceb(sp, ep, vp)
if (cs.cs_flags == CS_EMP) {
if (--cnt == 0)
goto ret;
- if (cs_bblank(sp, ep, &cs))
+ if (cs_bblank(sp, &cs))
return (1);
last = 0;
continue;
@@ -304,13 +279,13 @@ ret: slno = cs.cs_lno;
* and special characters.
*/
do {
- if (cs_next(sp, ep, &cs))
+ if (cs_next(sp, &cs))
return (1);
} while (!cs.cs_flags &&
(cs.cs_ch == ')' || cs.cs_ch == ']' ||
cs.cs_ch == '"' || cs.cs_ch == '\''));
if ((cs.cs_flags || isblank(cs.cs_ch)) &&
- cs_fblank(sp, ep, &cs))
+ cs_fblank(sp, &cs))
return (1);
/*
@@ -328,7 +303,7 @@ ret: slno = cs.cs_lno;
* and the sentence, it could be a real sentence.
*/
for (;;) {
- if (cs_prev(sp, ep, &cs))
+ if (cs_prev(sp, &cs))
return (1);
if (cs.cs_flags == CS_EOL)
continue;
@@ -372,11 +347,9 @@ okret: vp->m_stop.lno = cs.cs_lno;
if (ISMOTION(vp))
if (vp->m_start.cno == 0 &&
(cs.cs_flags != 0 || vp->m_stop.cno == 0)) {
- if (file_gline(sp, ep,
- --vp->m_start.lno, &len) == NULL) {
- GETLINE_ERR(sp, vp->m_start.lno);
+ if (db_get(sp,
+ --vp->m_start.lno, DBG_FATAL, NULL, &len))
return (1);
- }
vp->m_start.cno = len ? len - 1 : 0;
F_SET(vp, VM_LMODE);
} else
diff --git a/contrib/nvi/vi/v_status.c b/contrib/nvi/vi/v_status.c
new file mode 100644
index 000000000000..7095d782c60a
--- /dev/null
+++ b/contrib/nvi/vi/v_status.c
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_status.c 10.9 (Berkeley) 5/15/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_status -- ^G
+ * Show the file status.
+ *
+ * PUBLIC: int v_status __P((SCR *, VICMD *));
+ */
+int
+v_status(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ (void)msgq_status(sp, vp->m_start.lno, MSTAT_SHOWLAST);
+ return (0);
+}
diff --git a/contrib/nvi/vi/v_txt.c b/contrib/nvi/vi/v_txt.c
new file mode 100644
index 000000000000..c47a485686fb
--- /dev/null
+++ b/contrib/nvi/vi/v_txt.c
@@ -0,0 +1,2950 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_txt.c 10.87 (Berkeley) 10/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+static int txt_abbrev __P((SCR *, TEXT *, CHAR_T *, int, int *, int *));
+static void txt_ai_resolve __P((SCR *, TEXT *, int *));
+static TEXT *txt_backup __P((SCR *, TEXTH *, TEXT *, u_int32_t *));
+static int txt_dent __P((SCR *, TEXT *, int));
+static int txt_emark __P((SCR *, TEXT *, size_t));
+static void txt_err __P((SCR *, TEXTH *));
+static int txt_fc __P((SCR *, TEXT *, int *));
+static int txt_fc_col __P((SCR *, int, ARGS **));
+static int txt_hex __P((SCR *, TEXT *));
+static int txt_insch __P((SCR *, TEXT *, CHAR_T *, u_int));
+static int txt_isrch __P((SCR *, VICMD *, TEXT *, u_int8_t *));
+static int txt_map_end __P((SCR *));
+static int txt_map_init __P((SCR *));
+static int txt_margin __P((SCR *, TEXT *, TEXT *, int *, u_int32_t));
+static void txt_nomorech __P((SCR *));
+static void txt_Rresolve __P((SCR *, TEXTH *, TEXT *, const size_t));
+static int txt_resolve __P((SCR *, TEXTH *, u_int32_t));
+static int txt_showmatch __P((SCR *, TEXT *));
+static void txt_unmap __P((SCR *, TEXT *, u_int32_t *));
+
+/* Cursor character (space is hard to track on the screen). */
+#if defined(DEBUG) && 0
+#undef CH_CURSOR
+#define CH_CURSOR '+'
+#endif
+
+/*
+ * v_tcmd --
+ * Fill a buffer from the terminal for vi.
+ *
+ * PUBLIC: int v_tcmd __P((SCR *, VICMD *, ARG_CHAR_T, u_int));
+ */
+int
+v_tcmd(sp, vp, prompt, flags)
+ SCR *sp;
+ VICMD *vp;
+ ARG_CHAR_T prompt;
+ u_int flags;
+{
+ /* Normally, we end up where we started. */
+ vp->m_final.lno = sp->lno;
+ vp->m_final.cno = sp->cno;
+
+ /* Initialize the map. */
+ if (txt_map_init(sp))
+ return (1);
+
+ /* Move to the last line. */
+ sp->lno = TMAP[0].lno;
+ sp->cno = 0;
+
+ /* Don't update the modeline for now. */
+ F_SET(sp, SC_TINPUT_INFO);
+
+ /* Set the input flags. */
+ LF_SET(TXT_APPENDEOL |
+ TXT_CR | TXT_ESCAPE | TXT_INFOLINE | TXT_MAPINPUT);
+ if (O_ISSET(sp, O_ALTWERASE))
+ LF_SET(TXT_ALTWERASE);
+ if (O_ISSET(sp, O_TTYWERASE))
+ LF_SET(TXT_TTYWERASE);
+
+ /* Do the input thing. */
+ if (v_txt(sp, vp, NULL, NULL, 0, prompt, 0, 1, flags))
+ return (1);
+
+ /* Reenable the modeline updates. */
+ F_CLR(sp, SC_TINPUT_INFO);
+
+ /* Clean up the map. */
+ if (txt_map_end(sp))
+ return (1);
+
+ if (IS_ONELINE(sp))
+ F_SET(sp, SC_SCR_REDRAW); /* XXX */
+
+ /* Set the cursor to the resulting position. */
+ sp->lno = vp->m_final.lno;
+ sp->cno = vp->m_final.cno;
+
+ return (0);
+}
+
+/*
+ * txt_map_init
+ * Initialize the screen map for colon command-line input.
+ */
+static int
+txt_map_init(sp)
+ SCR *sp;
+{
+ SMAP *esmp;
+ VI_PRIVATE *vip;
+
+ vip = VIP(sp);
+ if (!IS_ONELINE(sp)) {
+ /*
+ * Fake like the user is doing input on the last line of the
+ * screen. This makes all of the scrolling work correctly,
+ * and allows us the use of the vi text editing routines, not
+ * to mention practically infinite length ex commands.
+ *
+ * Save the current location.
+ */
+ vip->sv_tm_lno = TMAP->lno;
+ vip->sv_tm_soff = TMAP->soff;
+ vip->sv_tm_coff = TMAP->coff;
+ vip->sv_t_maxrows = sp->t_maxrows;
+ vip->sv_t_minrows = sp->t_minrows;
+ vip->sv_t_rows = sp->t_rows;
+
+ /*
+ * If it's a small screen, TMAP may be small for the screen.
+ * Fix it, filling in fake lines as we go.
+ */
+ if (IS_SMALL(sp))
+ for (esmp =
+ HMAP + (sp->t_maxrows - 1); TMAP < esmp; ++TMAP) {
+ TMAP[1].lno = TMAP[0].lno + 1;
+ TMAP[1].coff = HMAP->coff;
+ TMAP[1].soff = 1;
+ }
+
+ /* Build the fake entry. */
+ TMAP[1].lno = TMAP[0].lno + 1;
+ TMAP[1].soff = 1;
+ TMAP[1].coff = 0;
+ SMAP_FLUSH(&TMAP[1]);
+ ++TMAP;
+
+ /* Reset the screen information. */
+ sp->t_rows = sp->t_minrows = ++sp->t_maxrows;
+ }
+ return (0);
+}
+
+/*
+ * txt_map_end
+ * Reset the screen map for colon command-line input.
+ */
+static int
+txt_map_end(sp)
+ SCR *sp;
+{
+ VI_PRIVATE *vip;
+ size_t cnt;
+
+ vip = VIP(sp);
+ if (!IS_ONELINE(sp)) {
+ /* Restore the screen information. */
+ sp->t_rows = vip->sv_t_rows;
+ sp->t_minrows = vip->sv_t_minrows;
+ sp->t_maxrows = vip->sv_t_maxrows;
+
+ /*
+ * If it's a small screen, TMAP may be wrong. Clear any
+ * lines that might have been overwritten.
+ */
+ if (IS_SMALL(sp)) {
+ for (cnt = sp->t_rows; cnt <= sp->t_maxrows; ++cnt) {
+ (void)sp->gp->scr_move(sp, cnt, 0);
+ (void)sp->gp->scr_clrtoeol(sp);
+ }
+ TMAP = HMAP + (sp->t_rows - 1);
+ } else
+ --TMAP;
+
+ /*
+ * The map may be wrong if the user entered more than one
+ * (logical) line. Fix it. If the user entered a whole
+ * screen, this will be slow, but we probably don't care.
+ */
+ if (!O_ISSET(sp, O_LEFTRIGHT))
+ while (vip->sv_tm_lno != TMAP->lno ||
+ vip->sv_tm_soff != TMAP->soff)
+ if (vs_sm_1down(sp))
+ return (1);
+ }
+
+ /*
+ * Invalidate the cursor and the line size cache, the line never
+ * really existed. This fixes bugs where the user searches for
+ * the last line on the screen + 1 and the refresh routine thinks
+ * that's where we just were.
+ */
+ VI_SCR_CFLUSH(vip);
+ F_SET(vip, VIP_CUR_INVALID);
+
+ return (0);
+}
+
+/*
+ * If doing input mapping on the colon command line, may need to unmap
+ * based on the command.
+ */
+#define UNMAP_TST \
+ FL_ISSET(ec_flags, EC_MAPINPUT) && LF_ISSET(TXT_INFOLINE)
+
+/*
+ * Internally, we maintain tp->lno and tp->cno, externally, everyone uses
+ * sp->lno and sp->cno. Make them consistent as necessary.
+ */
+#define UPDATE_POSITION(sp, tp) { \
+ (sp)->lno = (tp)->lno; \
+ (sp)->cno = (tp)->cno; \
+}
+
+/*
+ * v_txt --
+ * Vi text input.
+ *
+ * PUBLIC: int v_txt __P((SCR *, VICMD *, MARK *,
+ * PUBLIC: const char *, size_t, ARG_CHAR_T, recno_t, u_long, u_int32_t));
+ */
+int
+v_txt(sp, vp, tm, lp, len, prompt, ai_line, rcount, flags)
+ SCR *sp;
+ VICMD *vp;
+ MARK *tm; /* To MARK. */
+ const char *lp; /* Input line. */
+ size_t len; /* Input line length. */
+ ARG_CHAR_T prompt; /* Prompt to display. */
+ recno_t ai_line; /* Line number to use for autoindent count. */
+ u_long rcount; /* Replay count. */
+ u_int32_t flags; /* TXT_* flags. */
+{
+ EVENT ev, *evp; /* Current event. */
+ EVENT fc; /* File name completion event. */
+ GS *gp;
+ TEXT *ntp, *tp; /* Input text structures. */
+ TEXT ait; /* Autoindent text structure. */
+ TEXT wmt; /* Wrapmargin text structure. */
+ TEXTH *tiqh;
+ VI_PRIVATE *vip;
+ abb_t abb; /* State of abbreviation checks. */
+ carat_t carat; /* State of the "[^0]^D" sequences. */
+ quote_t quote; /* State of quotation. */
+ size_t owrite, insert; /* Temporary copies of TEXT fields. */
+ size_t margin; /* Wrapmargin value. */
+ size_t rcol; /* 0-N: insert offset in the replay buffer. */
+ size_t tcol; /* Temporary column. */
+ u_int32_t ec_flags; /* Input mapping flags. */
+#define IS_RESTART 0x01 /* Reset the incremental search. */
+#define IS_RUNNING 0x02 /* Incremental search turned on. */
+ u_int8_t is_flags;
+ int abcnt, ab_turnoff; /* Abbreviation character count, switch. */
+ int filec_redraw; /* Redraw after the file completion routine. */
+ int hexcnt; /* Hex character count. */
+ int showmatch; /* Showmatch set on this character. */
+ int wm_set, wm_skip; /* Wrapmargin happened, blank skip flags. */
+ int max, tmp;
+ char *p;
+
+ gp = sp->gp;
+ vip = VIP(sp);
+
+ /*
+ * Set the input flag, so tabs get displayed correctly
+ * and everyone knows that the text buffer is in use.
+ */
+ F_SET(sp, SC_TINPUT);
+
+ /*
+ * Get one TEXT structure with some initial buffer space, reusing
+ * the last one if it's big enough. (All TEXT bookkeeping fields
+ * default to 0 -- text_init() handles this.) If changing a line,
+ * copy it into the TEXT buffer.
+ */
+ tiqh = &sp->tiq;
+ if (tiqh->cqh_first != (void *)tiqh) {
+ tp = tiqh->cqh_first;
+ if (tp->q.cqe_next != (void *)tiqh || tp->lb_len < len + 32) {
+ text_lfree(tiqh);
+ goto newtp;
+ }
+ tp->ai = tp->insert = tp->offset = tp->owrite = 0;
+ if (lp != NULL) {
+ tp->len = len;
+ memmove(tp->lb, lp, len);
+ } else
+ tp->len = 0;
+ } else {
+newtp: if ((tp = text_init(sp, lp, len, len + 32)) == NULL)
+ return (1);
+ CIRCLEQ_INSERT_HEAD(tiqh, tp, q);
+ }
+
+ /* Set default termination condition. */
+ tp->term = TERM_OK;
+
+ /* Set the starting line, column. */
+ tp->lno = sp->lno;
+ tp->cno = sp->cno;
+
+ /*
+ * Set the insert and overwrite counts. If overwriting characters,
+ * do insertion afterward. If not overwriting characters, assume
+ * doing insertion. If change is to a mark, emphasize it with an
+ * CH_ENDMARK character.
+ */
+ if (len) {
+ if (LF_ISSET(TXT_OVERWRITE)) {
+ tp->owrite = (tm->cno - tp->cno) + 1;
+ tp->insert = (len - tm->cno) - 1;
+ } else
+ tp->insert = len - tp->cno;
+
+ if (LF_ISSET(TXT_EMARK) && txt_emark(sp, tp, tm->cno))
+ return (1);
+ }
+
+ /*
+ * Many of the special cases in text input are to handle autoindent
+ * support. Somebody decided that it would be a good idea if "^^D"
+ * and "0^D" deleted all of the autoindented characters. In an editor
+ * that takes single character input from the user, this beggars the
+ * imagination. Note also, "^^D" resets the next lines' autoindent,
+ * but "0^D" doesn't.
+ *
+ * We assume that autoindent only happens on empty lines, so insert
+ * and overwrite will be zero. If doing autoindent, figure out how
+ * much indentation we need and fill it in. Update input column and
+ * screen cursor as necessary.
+ */
+ if (LF_ISSET(TXT_AUTOINDENT) && ai_line != OOBLNO) {
+ if (v_txt_auto(sp, ai_line, NULL, 0, tp))
+ return (1);
+ tp->cno = tp->ai;
+ } else {
+ /*
+ * The cc and S commands have a special feature -- leading
+ * <blank> characters are handled as autoindent characters.
+ * Beauty!
+ */
+ if (LF_ISSET(TXT_AICHARS)) {
+ tp->offset = 0;
+ tp->ai = tp->cno;
+ } else
+ tp->offset = tp->cno;
+ }
+
+ /* If getting a command buffer from the user, there may be a prompt. */
+ if (LF_ISSET(TXT_PROMPT)) {
+ tp->lb[tp->cno++] = prompt;
+ ++tp->len;
+ ++tp->offset;
+ }
+
+ /*
+ * If appending after the end-of-line, add a space into the buffer
+ * and move the cursor right. This space is inserted, i.e. pushed
+ * along, and then deleted when the line is resolved. Assumes that
+ * the cursor is already positioned at the end of the line. This
+ * avoids the nastiness of having the cursor reside on a magical
+ * column, i.e. a column that doesn't really exist. The only down
+ * side is that we may wrap lines or scroll the screen before it's
+ * strictly necessary. Not a big deal.
+ */
+ if (LF_ISSET(TXT_APPENDEOL)) {
+ tp->lb[tp->cno] = CH_CURSOR;
+ ++tp->len;
+ ++tp->insert;
+ (void)vs_change(sp, tp->lno, LINE_RESET);
+ }
+
+ /*
+ * Historic practice is that the wrapmargin value was a distance
+ * from the RIGHT-HAND margin, not the left. It's more useful to
+ * us as a distance from the left-hand margin, i.e. the same as
+ * the wraplen value. The wrapmargin option is historic practice.
+ * Nvi added the wraplen option so that it would be possible to
+ * edit files with consistent margins without knowing the number of
+ * columns in the window.
+ *
+ * XXX
+ * Setting margin causes a significant performance hit. Normally
+ * we don't update the screen if there are keys waiting, but we
+ * have to if margin is set, otherwise the screen routines don't
+ * know where the cursor is.
+ *
+ * !!!
+ * Abbreviated keys were affected by the wrapmargin option in the
+ * historic 4BSD vi. Mapped keys were usually, but sometimes not.
+ * See the comment in vi/v_text():set_txt_std for more information.
+ *
+ * !!!
+ * One more special case. If an inserted <blank> character causes
+ * wrapmargin to split the line, the next user entered character is
+ * discarded if it's a <space> character.
+ */
+ wm_set = wm_skip = 0;
+ if (LF_ISSET(TXT_WRAPMARGIN))
+ if ((margin = O_VAL(sp, O_WRAPMARGIN)) != 0)
+ margin = sp->cols - margin;
+ else
+ margin = O_VAL(sp, O_WRAPLEN);
+ else
+ margin = 0;
+
+ /* Initialize abbreviation checks. */
+ abcnt = ab_turnoff = 0;
+ abb = F_ISSET(gp, G_ABBREV) &&
+ LF_ISSET(TXT_MAPINPUT) ? AB_INWORD : AB_NOTSET;
+
+ /*
+ * Set up the dot command. Dot commands are done by saving the actual
+ * characters and then reevaluating them so that things like wrapmargin
+ * can change between the insert and the replay.
+ *
+ * !!!
+ * Historically, vi did not remap or reabbreviate replayed input. (It
+ * did beep at you if you changed an abbreviation and then replayed the
+ * input. We're not that compatible.) We don't have to do anything to
+ * avoid remapping, as we're not getting characters from the terminal
+ * routines. Turn the abbreviation check off.
+ *
+ * XXX
+ * It would be nice if we could swallow backspaces and such, but it's
+ * not all that easy to do. What we can do is turn off the common
+ * error messages during the replay. Otherwise, when the user enters
+ * an illegal command, e.g., "Ia<erase><erase><erase><erase>b<escape>",
+ * and then does a '.', they get a list of error messages after command
+ * completion.
+ */
+ rcol = 0;
+ if (LF_ISSET(TXT_REPLAY)) {
+ abb = AB_NOTSET;
+ LF_CLR(TXT_RECORD);
+ }
+
+ /* Other text input mode setup. */
+ quote = Q_NOTSET;
+ carat = C_NOTSET;
+ FL_INIT(is_flags,
+ LF_ISSET(TXT_SEARCHINCR) ? IS_RESTART | IS_RUNNING : 0);
+ filec_redraw = hexcnt = showmatch = 0;
+
+ /* Initialize input flags. */
+ ec_flags = LF_ISSET(TXT_MAPINPUT) ? EC_MAPINPUT : 0;
+
+ /* Refresh the screen. */
+ UPDATE_POSITION(sp, tp);
+ if (vs_refresh(sp, 1))
+ return (1);
+
+ /* If it's dot, just do it now. */
+ if (F_ISSET(vp, VC_ISDOT))
+ goto replay;
+
+ /* Get an event. */
+ evp = &ev;
+next: if (v_event_get(sp, evp, 0, ec_flags))
+ return (1);
+
+ /*
+ * If file completion overwrote part of the screen and nothing else has
+ * been displayed, clean up. We don't do this as part of the normal
+ * message resolution because we know the user is on the colon command
+ * line and there's no reason to enter explicit characters to continue.
+ */
+ if (filec_redraw && !F_ISSET(sp, SC_SCR_EXWROTE)) {
+ filec_redraw = 0;
+
+ fc.e_event = E_REPAINT;
+ fc.e_flno = vip->totalcount >=
+ sp->rows ? 1 : sp->rows - vip->totalcount;
+ fc.e_tlno = sp->rows;
+ vip->linecount = vip->lcontinue = vip->totalcount = 0;
+ (void)vs_repaint(sp, &fc);
+ (void)vs_refresh(sp, 1);
+ }
+
+ /* Deal with all non-character events. */
+ switch (evp->e_event) {
+ case E_CHARACTER:
+ break;
+ case E_ERR:
+ case E_EOF:
+ F_SET(sp, SC_EXIT_FORCE);
+ return (1);
+ case E_INTERRUPT:
+ /*
+ * !!!
+ * Historically, <interrupt> exited the user from text input
+ * mode or cancelled a colon command, and returned to command
+ * mode. It also beeped the terminal, but that seems a bit
+ * excessive.
+ */
+ goto k_escape;
+ case E_REPAINT:
+ if (vs_repaint(sp, &ev))
+ return (1);
+ goto next;
+ case E_WRESIZE:
+ /* <resize> interrupts the input mode. */
+ v_emsg(sp, NULL, VIM_WRESIZE);
+ goto k_escape;
+ default:
+ v_event_err(sp, evp);
+ goto k_escape;
+ }
+
+ /*
+ * !!!
+ * If the first character of the input is a nul, replay the previous
+ * input. (Historically, it's okay to replay non-existent input.)
+ * This was not documented as far as I know, and is a great test of vi
+ * clones.
+ */
+ if (rcol == 0 && !LF_ISSET(TXT_REPLAY) && evp->e_c == '\0') {
+ if (vip->rep == NULL)
+ goto done;
+
+ abb = AB_NOTSET;
+ LF_CLR(TXT_RECORD);
+ LF_SET(TXT_REPLAY);
+ goto replay;
+ }
+
+ /*
+ * File name completion and colon command-line editing. We don't
+ * have enough meta characters, so we expect people to overload
+ * them. If the two characters are the same, then we do file name
+ * completion if the cursor is past the first column, and do colon
+ * command-line editing if it's not.
+ */
+ if (quote == Q_NOTSET) {
+ int L__cedit, L__filec;
+
+ L__cedit = L__filec = 0;
+ if (LF_ISSET(TXT_CEDIT) && O_STR(sp, O_CEDIT) != NULL &&
+ O_STR(sp, O_CEDIT)[0] == evp->e_c)
+ L__cedit = 1;
+ if (LF_ISSET(TXT_FILEC) && O_STR(sp, O_FILEC) != NULL &&
+ O_STR(sp, O_FILEC)[0] == evp->e_c)
+ L__filec = 1;
+ if (L__cedit == 1 && (L__filec == 0 || tp->cno == tp->offset)) {
+ tp->term = TERM_CEDIT;
+ goto k_escape;
+ }
+ if (L__filec == 1) {
+ if (txt_fc(sp, tp, &filec_redraw))
+ goto err;
+ goto resolve;
+ }
+ }
+
+ /* Abbreviation overflow check. See comment in txt_abbrev(). */
+#define MAX_ABBREVIATION_EXPANSION 256
+ if (F_ISSET(&evp->e_ch, CH_ABBREVIATED)) {
+ if (++abcnt > MAX_ABBREVIATION_EXPANSION) {
+ if (v_event_flush(sp, CH_ABBREVIATED))
+ msgq(sp, M_ERR,
+"191|Abbreviation exceeded expansion limit: characters discarded");
+ abcnt = 0;
+ if (LF_ISSET(TXT_REPLAY))
+ goto done;
+ goto resolve;
+ }
+ } else
+ abcnt = 0;
+
+ /* Check to see if the character fits into the replay buffers. */
+ if (LF_ISSET(TXT_RECORD)) {
+ BINC_GOTO(sp, vip->rep,
+ vip->rep_len, (rcol + 1) * sizeof(EVENT));
+ vip->rep[rcol++] = *evp;
+ }
+
+replay: if (LF_ISSET(TXT_REPLAY))
+ evp = vip->rep + rcol++;
+
+ /* Wrapmargin check for leading space. */
+ if (wm_skip) {
+ wm_skip = 0;
+ if (evp->e_c == ' ')
+ goto resolve;
+ }
+
+ /* If quoted by someone else, simply insert the character. */
+ if (F_ISSET(&evp->e_ch, CH_QUOTED))
+ goto insq_ch;
+
+ /*
+ * !!!
+ * If this character was quoted by a K_VLNEXT or a backslash, replace
+ * the placeholder (a carat or a backslash) with the new character.
+ * If it was quoted by a K_VLNEXT, we've already adjusted the cursor
+ * because it has to appear on top of the placeholder character. If
+ * it was quoted by a backslash, adjust the cursor now, the cursor
+ * doesn't appear on top of it. Historic practice in both cases.
+ *
+ * Skip tests for abbreviations; ":ab xa XA" followed by "ixa^V<space>"
+ * doesn't perform an abbreviation. Special case, ^V^J (not ^V^M) is
+ * the same as ^J, historically.
+ */
+ if (quote == Q_BTHIS || quote == Q_VTHIS) {
+ FL_CLR(ec_flags, EC_QUOTED);
+ if (LF_ISSET(TXT_MAPINPUT))
+ FL_SET(ec_flags, EC_MAPINPUT);
+
+ if (quote == Q_BTHIS &&
+ (evp->e_value == K_VERASE || evp->e_value == K_VKILL)) {
+ quote = Q_NOTSET;
+ --tp->cno;
+ ++tp->owrite;
+ goto insl_ch;
+ }
+ if (quote == Q_VTHIS && evp->e_value != K_NL) {
+ quote = Q_NOTSET;
+ goto insl_ch;
+ }
+ quote = Q_NOTSET;
+ }
+
+ /*
+ * !!!
+ * Translate "<CH_HEX>[isxdigit()]*" to a character with a hex value:
+ * this test delimits the value by any non-hex character. Offset by
+ * one, we use 0 to mean that we've found <CH_HEX>.
+ */
+ if (hexcnt > 1 && !isxdigit(evp->e_c)) {
+ hexcnt = 0;
+ if (txt_hex(sp, tp))
+ goto err;
+ }
+
+ switch (evp->e_value) {
+ case K_CR: /* Carriage return. */
+ case K_NL: /* New line. */
+ /* Return in script windows and the command line. */
+k_cr: if (LF_ISSET(TXT_CR)) {
+ /*
+ * If this was a map, we may have not displayed
+ * the line. Display it, just in case.
+ *
+ * If a script window and not the colon line,
+ * push a <cr> so it gets executed.
+ */
+ if (LF_ISSET(TXT_INFOLINE)) {
+ if (vs_change(sp, tp->lno, LINE_RESET))
+ goto err;
+ } else if (F_ISSET(sp, SC_SCRIPT))
+ (void)v_event_push(sp, NULL, "\r", 1, CH_NOMAP);
+
+ /* Set term condition: if empty. */
+ if (tp->cno <= tp->offset)
+ tp->term = TERM_CR;
+ /*
+ * Set term condition: if searching incrementally and
+ * the user entered a pattern, return a completed
+ * search, regardless if the entire pattern was found.
+ */
+ if (FL_ISSET(is_flags, IS_RUNNING) &&
+ tp->cno >= tp->offset + 1)
+ tp->term = TERM_SEARCH;
+
+ goto k_escape;
+ }
+
+#define LINE_RESOLVE { \
+ /* \
+ * Handle abbreviations. If there was one, discard the \
+ * replay characters. \
+ */ \
+ if (abb == AB_INWORD && \
+ !LF_ISSET(TXT_REPLAY) && F_ISSET(gp, G_ABBREV)) { \
+ if (txt_abbrev(sp, tp, &evp->e_c, \
+ LF_ISSET(TXT_INFOLINE), &tmp, \
+ &ab_turnoff)) \
+ goto err; \
+ if (tmp) { \
+ if (LF_ISSET(TXT_RECORD)) \
+ rcol -= tmp + 1; \
+ goto resolve; \
+ } \
+ } \
+ if (abb != AB_NOTSET) \
+ abb = AB_NOTWORD; \
+ if (UNMAP_TST) \
+ txt_unmap(sp, tp, &ec_flags); \
+ /* \
+ * Delete any appended cursor. It's possible to get in \
+ * situations where TXT_APPENDEOL is set but tp->insert \
+ * is 0 when using the R command and all the characters \
+ * are tp->owrite characters. \
+ */ \
+ if (LF_ISSET(TXT_APPENDEOL) && tp->insert > 0) { \
+ --tp->len; \
+ --tp->insert; \
+ } \
+}
+ LINE_RESOLVE;
+
+ /*
+ * Save the current line information for restoration in
+ * txt_backup(), and set the line final length.
+ */
+ tp->sv_len = tp->len;
+ tp->sv_cno = tp->cno;
+ tp->len = tp->cno;
+
+ /* Update the old line. */
+ if (vs_change(sp, tp->lno, LINE_RESET))
+ goto err;
+
+ /*
+ * Historic practice, when the autoindent edit option was set,
+ * was to delete <blank> characters following the inserted
+ * newline. This affected the 'R', 'c', and 's' commands; 'c'
+ * and 's' retained the insert characters only, 'R' moved the
+ * overwrite and insert characters into the next TEXT structure.
+ * We keep track of the number of characters erased for the 'R'
+ * command so that the final resolution of the line is correct.
+ */
+ tp->R_erase = 0;
+ owrite = tp->owrite;
+ insert = tp->insert;
+ if (LF_ISSET(TXT_REPLACE) && owrite != 0) {
+ for (p = tp->lb + tp->cno; owrite > 0 && isblank(*p);
+ ++p, --owrite, ++tp->R_erase);
+ if (owrite == 0)
+ for (; insert > 0 && isblank(*p);
+ ++p, ++tp->R_erase, --insert);
+ } else {
+ p = tp->lb + tp->cno + owrite;
+ if (O_ISSET(sp, O_AUTOINDENT))
+ for (; insert > 0 &&
+ isblank(*p); ++p, --insert);
+ owrite = 0;
+ }
+
+ /*
+ * !!!
+ * Create a new line and insert the new TEXT into the queue.
+ * DON'T insert until the old line has been updated, or the
+ * inserted line count in line.c:db_get() will be wrong.
+ */
+ if ((ntp = text_init(sp, p,
+ insert + owrite, insert + owrite + 32)) == NULL)
+ goto err;
+ CIRCLEQ_INSERT_TAIL(&sp->tiq, ntp, q);
+
+ /* Set up bookkeeping for the new line. */
+ ntp->insert = insert;
+ ntp->owrite = owrite;
+ ntp->lno = tp->lno + 1;
+
+ /*
+ * Reset the autoindent line value. 0^D keeps the autoindent
+ * line from changing, ^D changes the level, even if there were
+ * no characters in the old line. Note, if using the current
+ * tp structure, use the cursor as the length, the autoindent
+ * characters may have been erased.
+ */
+ if (LF_ISSET(TXT_AUTOINDENT)) {
+ if (carat == C_NOCHANGE) {
+ if (v_txt_auto(sp, OOBLNO, &ait, ait.ai, ntp))
+ goto err;
+ FREE_SPACE(sp, ait.lb, ait.lb_len);
+ } else
+ if (v_txt_auto(sp, OOBLNO, tp, tp->cno, ntp))
+ goto err;
+ carat = C_NOTSET;
+ }
+
+ /* Reset the cursor. */
+ ntp->cno = ntp->ai;
+
+ /*
+ * If we're here because wrapmargin was set and we've broken a
+ * line, there may be additional information (i.e. the start of
+ * a line) in the wmt structure.
+ */
+ if (wm_set) {
+ if (wmt.offset != 0 ||
+ wmt.owrite != 0 || wmt.insert != 0) {
+#define WMTSPACE wmt.offset + wmt.owrite + wmt.insert
+ BINC_GOTO(sp, ntp->lb,
+ ntp->lb_len, ntp->len + WMTSPACE + 32);
+ memmove(ntp->lb + ntp->cno, wmt.lb, WMTSPACE);
+ ntp->len += WMTSPACE;
+ ntp->cno += wmt.offset;
+ ntp->owrite = wmt.owrite;
+ ntp->insert = wmt.insert;
+ }
+ wm_set = 0;
+ }
+
+ /* New lines are TXT_APPENDEOL. */
+ if (ntp->owrite == 0 && ntp->insert == 0) {
+ BINC_GOTO(sp, ntp->lb, ntp->lb_len, ntp->len + 1);
+ LF_SET(TXT_APPENDEOL);
+ ntp->lb[ntp->cno] = CH_CURSOR;
+ ++ntp->insert;
+ ++ntp->len;
+ }
+
+ /* Swap old and new TEXT's, and update the new line. */
+ tp = ntp;
+ if (vs_change(sp, tp->lno, LINE_INSERT))
+ goto err;
+
+ goto resolve;
+ case K_ESCAPE: /* Escape. */
+ if (!LF_ISSET(TXT_ESCAPE))
+ goto ins_ch;
+
+ /* If we have a count, start replaying the input. */
+ if (rcount > 1) {
+ --rcount;
+
+ rcol = 0;
+ abb = AB_NOTSET;
+ LF_CLR(TXT_RECORD);
+ LF_SET(TXT_REPLAY);
+
+ /*
+ * Some commands (e.g. 'o') need a <newline> for each
+ * repetition.
+ */
+ if (LF_ISSET(TXT_ADDNEWLINE))
+ goto k_cr;
+
+ /*
+ * The R command turns into the 'a' command after the
+ * first repetition.
+ */
+ if (LF_ISSET(TXT_REPLACE)) {
+ tp->insert = tp->owrite;
+ tp->owrite = 0;
+ LF_CLR(TXT_REPLACE);
+ }
+ goto replay;
+ }
+
+ /* Set term condition: if empty. */
+ if (tp->cno <= tp->offset)
+ tp->term = TERM_ESC;
+ /*
+ * Set term condition: if searching incrementally and the user
+ * entered a pattern, return a completed search, regardless if
+ * the entire pattern was found.
+ */
+ if (FL_ISSET(is_flags, IS_RUNNING) && tp->cno >= tp->offset + 1)
+ tp->term = TERM_SEARCH;
+
+k_escape: LINE_RESOLVE;
+
+ /*
+ * Clean up for the 'R' command, restoring overwrite
+ * characters, and making them into insert characters.
+ */
+ if (LF_ISSET(TXT_REPLACE))
+ txt_Rresolve(sp, &sp->tiq, tp, len);
+
+ /*
+ * If there are any overwrite characters, copy down
+ * any insert characters, and decrement the length.
+ */
+ if (tp->owrite) {
+ if (tp->insert)
+ memmove(tp->lb + tp->cno,
+ tp->lb + tp->cno + tp->owrite, tp->insert);
+ tp->len -= tp->owrite;
+ }
+
+ /*
+ * Optionally resolve the lines into the file. If not
+ * resolving the lines into the file, end the line with
+ * a nul. If the line is empty, then set the length to
+ * 0, the termination condition has already been set.
+ *
+ * XXX
+ * This is wrong, should pass back a length.
+ */
+ if (LF_ISSET(TXT_RESOLVE)) {
+ if (txt_resolve(sp, &sp->tiq, flags))
+ goto err;
+ } else {
+ BINC_GOTO(sp, tp->lb, tp->lb_len, tp->len + 1);
+ tp->lb[tp->len] = '\0';
+ }
+
+ /*
+ * Set the return cursor position to rest on the last
+ * inserted character.
+ */
+ if (tp->cno != 0)
+ --tp->cno;
+
+ /* Update the last line. */
+ if (vs_change(sp, tp->lno, LINE_RESET))
+ return (1);
+ goto done;
+ case K_CARAT: /* Delete autoindent chars. */
+ if (tp->cno <= tp->ai && LF_ISSET(TXT_AUTOINDENT))
+ carat = C_CARATSET;
+ goto ins_ch;
+ case K_ZERO: /* Delete autoindent chars. */
+ if (tp->cno <= tp->ai && LF_ISSET(TXT_AUTOINDENT))
+ carat = C_ZEROSET;
+ goto ins_ch;
+ case K_CNTRLD: /* Delete autoindent char. */
+ /*
+ * If in the first column or no characters to erase, ignore
+ * the ^D (this matches historic practice). If not doing
+ * autoindent or already inserted non-ai characters, it's a
+ * literal. The latter test is done in the switch, as the
+ * CARAT forms are N + 1, not N.
+ */
+ if (!LF_ISSET(TXT_AUTOINDENT))
+ goto ins_ch;
+ if (tp->cno == 0)
+ goto resolve;
+
+ switch (carat) {
+ case C_CARATSET: /* ^^D */
+ if (tp->ai == 0 || tp->cno > tp->ai + tp->offset + 1)
+ goto ins_ch;
+
+ /* Save the ai string for later. */
+ ait.lb = NULL;
+ ait.lb_len = 0;
+ BINC_GOTO(sp, ait.lb, ait.lb_len, tp->ai);
+ memmove(ait.lb, tp->lb, tp->ai);
+ ait.ai = ait.len = tp->ai;
+
+ carat = C_NOCHANGE;
+ goto leftmargin;
+ case C_ZEROSET: /* 0^D */
+ if (tp->ai == 0 || tp->cno > tp->ai + tp->offset + 1)
+ goto ins_ch;
+
+ carat = C_NOTSET;
+leftmargin: tp->lb[tp->cno - 1] = ' ';
+ tp->owrite += tp->cno - tp->offset;
+ tp->ai = 0;
+ tp->cno = tp->offset;
+ break;
+ case C_NOTSET: /* ^D */
+ if (tp->ai == 0 || tp->cno > tp->ai + tp->offset)
+ goto ins_ch;
+
+ (void)txt_dent(sp, tp, 0);
+ break;
+ default:
+ abort();
+ }
+ break;
+ case K_VERASE: /* Erase the last character. */
+ /* If can erase over the prompt, return. */
+ if (tp->cno <= tp->offset && LF_ISSET(TXT_BS)) {
+ tp->term = TERM_BS;
+ goto done;
+ }
+
+ /*
+ * If at the beginning of the line, try and drop back to a
+ * previously inserted line.
+ */
+ if (tp->cno == 0) {
+ if ((ntp =
+ txt_backup(sp, &sp->tiq, tp, &flags)) == NULL)
+ goto err;
+ tp = ntp;
+ break;
+ }
+
+ /* If nothing to erase, bell the user. */
+ if (tp->cno <= tp->offset) {
+ if (!LF_ISSET(TXT_REPLAY))
+ txt_nomorech(sp);
+ break;
+ }
+
+ /* Drop back one character. */
+ --tp->cno;
+
+ /*
+ * Historically, vi didn't replace the erased characters with
+ * <blank>s, presumably because it's easier to fix a minor
+ * typing mistake and continue on if the previous letters are
+ * already there. This is a problem for incremental searching,
+ * because the user can no longer tell where they are in the
+ * colon command line because the cursor is at the last search
+ * point in the screen. So, if incrementally searching, erase
+ * the erased characters from the screen.
+ */
+ if (FL_ISSET(is_flags, IS_RUNNING))
+ tp->lb[tp->cno] = ' ';
+
+ /*
+ * Increment overwrite, decrement ai if deleted.
+ *
+ * !!!
+ * Historic vi did not permit users to use erase characters
+ * to delete autoindent characters. We do. Eat hot death,
+ * POSIX.
+ */
+ ++tp->owrite;
+ if (tp->cno < tp->ai)
+ --tp->ai;
+
+ /* Reset if we deleted an incremental search character. */
+ if (FL_ISSET(is_flags, IS_RUNNING))
+ FL_SET(is_flags, IS_RESTART);
+ break;
+ case K_VWERASE: /* Skip back one word. */
+ /*
+ * If at the beginning of the line, try and drop back to a
+ * previously inserted line.
+ */
+ if (tp->cno == 0) {
+ if ((ntp =
+ txt_backup(sp, &sp->tiq, tp, &flags)) == NULL)
+ goto err;
+ tp = ntp;
+ }
+
+ /*
+ * If at offset, nothing to erase so bell the user.
+ */
+ if (tp->cno <= tp->offset) {
+ if (!LF_ISSET(TXT_REPLAY))
+ txt_nomorech(sp);
+ break;
+ }
+
+ /*
+ * The first werase goes back to any autoindent column and the
+ * second werase goes back to the offset.
+ *
+ * !!!
+ * Historic vi did not permit users to use erase characters to
+ * delete autoindent characters.
+ */
+ if (tp->ai && tp->cno > tp->ai)
+ max = tp->ai;
+ else {
+ tp->ai = 0;
+ max = tp->offset;
+ }
+
+ /* Skip over trailing space characters. */
+ while (tp->cno > max && isblank(tp->lb[tp->cno - 1])) {
+ --tp->cno;
+ ++tp->owrite;
+ }
+ if (tp->cno == max)
+ break;
+ /*
+ * There are three types of word erase found on UNIX systems.
+ * They can be identified by how the string /a/b/c is treated
+ * -- as 1, 3, or 6 words. Historic vi had two classes of
+ * characters, and strings were delimited by them and
+ * <blank>'s, so, 6 words. The historic tty interface used
+ * <blank>'s to delimit strings, so, 1 word. The algorithm
+ * offered in the 4.4BSD tty interface (as stty altwerase)
+ * treats it as 3 words -- there are two classes of
+ * characters, and strings are delimited by them and
+ * <blank>'s. The difference is that the type of the first
+ * erased character erased is ignored, which is exactly right
+ * when erasing pathname components. The edit options
+ * TXT_ALTWERASE and TXT_TTYWERASE specify the 4.4BSD tty
+ * interface and the historic tty driver behavior,
+ * respectively, and the default is the same as the historic
+ * vi behavior.
+ *
+ * Overwrite erased characters if doing incremental search;
+ * see comment above.
+ */
+ if (LF_ISSET(TXT_TTYWERASE))
+ while (tp->cno > max) {
+ --tp->cno;
+ ++tp->owrite;
+ if (FL_ISSET(is_flags, IS_RUNNING))
+ tp->lb[tp->cno] = ' ';
+ if (isblank(tp->lb[tp->cno - 1]))
+ break;
+ }
+ else {
+ if (LF_ISSET(TXT_ALTWERASE)) {
+ --tp->cno;
+ ++tp->owrite;
+ if (FL_ISSET(is_flags, IS_RUNNING))
+ tp->lb[tp->cno] = ' ';
+ if (isblank(tp->lb[tp->cno - 1]))
+ break;
+ }
+ if (tp->cno > max)
+ tmp = inword(tp->lb[tp->cno - 1]);
+ while (tp->cno > max) {
+ --tp->cno;
+ ++tp->owrite;
+ if (FL_ISSET(is_flags, IS_RUNNING))
+ tp->lb[tp->cno] = ' ';
+ if (tmp != inword(tp->lb[tp->cno - 1])
+ || isblank(tp->lb[tp->cno - 1]))
+ break;
+ }
+ }
+
+ /* Reset if we deleted an incremental search character. */
+ if (FL_ISSET(is_flags, IS_RUNNING))
+ FL_SET(is_flags, IS_RESTART);
+ break;
+ case K_VKILL: /* Restart this line. */
+ /*
+ * !!!
+ * If at the beginning of the line, try and drop back to a
+ * previously inserted line. Historic vi did not permit
+ * users to go back to previous lines.
+ */
+ if (tp->cno == 0) {
+ if ((ntp =
+ txt_backup(sp, &sp->tiq, tp, &flags)) == NULL)
+ goto err;
+ tp = ntp;
+ }
+
+ /* If at offset, nothing to erase so bell the user. */
+ if (tp->cno <= tp->offset) {
+ if (!LF_ISSET(TXT_REPLAY))
+ txt_nomorech(sp);
+ break;
+ }
+
+ /*
+ * First kill goes back to any autoindent and second kill goes
+ * back to the offset.
+ *
+ * !!!
+ * Historic vi did not permit users to use erase characters to
+ * delete autoindent characters.
+ */
+ if (tp->ai && tp->cno > tp->ai)
+ max = tp->ai;
+ else {
+ tp->ai = 0;
+ max = tp->offset;
+ }
+ tp->owrite += tp->cno - max;
+
+ /*
+ * Overwrite erased characters if doing incremental search;
+ * see comment above.
+ */
+ if (FL_ISSET(is_flags, IS_RUNNING))
+ do {
+ tp->lb[--tp->cno] = ' ';
+ } while (tp->cno > max);
+ else
+ tp->cno = max;
+
+ /* Reset if we deleted an incremental search character. */
+ if (FL_ISSET(is_flags, IS_RUNNING))
+ FL_SET(is_flags, IS_RESTART);
+ break;
+ case K_CNTRLT: /* Add autoindent characters. */
+ if (!LF_ISSET(TXT_CNTRLT))
+ goto ins_ch;
+ if (txt_dent(sp, tp, 1))
+ goto err;
+ goto ebuf_chk;
+ case K_RIGHTBRACE:
+ case K_RIGHTPAREN:
+ if (LF_ISSET(TXT_SHOWMATCH))
+ showmatch = 1;
+ goto ins_ch;
+ case K_BACKSLASH: /* Quote next erase/kill. */
+ /*
+ * !!!
+ * Historic vi tried to make abbreviations after a backslash
+ * escape work. If you did ":ab x y", and inserted "x\^H",
+ * (assuming the erase character was ^H) you got "x^H", and
+ * no abbreviation was done. If you inserted "x\z", however,
+ * it tried to back up and do the abbreviation, i.e. replace
+ * 'x' with 'y'. The problem was it got it wrong, and you
+ * ended up with "zy\".
+ *
+ * This is really hard to do (you have to remember the
+ * word/non-word state, for example), and doesn't make any
+ * sense to me. Both backslash and the characters it
+ * (usually) escapes will individually trigger the
+ * abbreviation, so I don't see why the combination of them
+ * wouldn't. I don't expect to get caught on this one,
+ * particularly since it never worked right, but I've been
+ * wrong before.
+ *
+ * Do the tests for abbreviations, so ":ab xa XA",
+ * "ixa\<K_VERASE>" performs the abbreviation.
+ */
+ quote = Q_BNEXT;
+ goto insq_ch;
+ case K_VLNEXT: /* Quote next character. */
+ evp->e_c = '^';
+ quote = Q_VNEXT;
+ /*
+ * Turn on the quote flag so that the underlying routines
+ * quote the next character where it's possible. Turn off
+ * the input mapbiting flag so that we don't remap the next
+ * character.
+ */
+ FL_SET(ec_flags, EC_QUOTED);
+ FL_CLR(ec_flags, EC_MAPINPUT);
+
+ /*
+ * !!!
+ * Skip the tests for abbreviations, so ":ab xa XA",
+ * "ixa^V<space>" doesn't perform the abbreviation.
+ */
+ goto insl_ch;
+ case K_HEXCHAR:
+ hexcnt = 1;
+ goto insq_ch;
+ default: /* Insert the character. */
+ins_ch: /*
+ * Historically, vi eliminated nul's out of hand. If the
+ * beautify option was set, it also deleted any unknown
+ * ASCII value less than space (040) and the del character
+ * (0177), except for tabs. Unknown is a key word here.
+ * Most vi documentation claims that it deleted everything
+ * but <tab>, <nl> and <ff>, as that's what the original
+ * 4BSD documentation said. This is obviously wrong,
+ * however, as <esc> would be included in that list. What
+ * we do is eliminate any unquoted, iscntrl() character that
+ * wasn't a replay and wasn't handled specially, except
+ * <tab> or <ff>.
+ */
+ if (LF_ISSET(TXT_BEAUTIFY) && iscntrl(evp->e_c) &&
+ evp->e_value != K_FORMFEED && evp->e_value != K_TAB) {
+ msgq(sp, M_BERR,
+ "192|Illegal character; quote to enter");
+ if (LF_ISSET(TXT_REPLAY))
+ goto done;
+ break;
+ }
+
+insq_ch: /*
+ * If entering a non-word character after a word, check for
+ * abbreviations. If there was one, discard replay characters.
+ * If entering a blank character, check for unmap commands,
+ * as well.
+ */
+ if (!inword(evp->e_c)) {
+ if (abb == AB_INWORD &&
+ !LF_ISSET(TXT_REPLAY) && F_ISSET(gp, G_ABBREV)) {
+ if (txt_abbrev(sp, tp, &evp->e_c,
+ LF_ISSET(TXT_INFOLINE), &tmp, &ab_turnoff))
+ goto err;
+ if (tmp) {
+ if (LF_ISSET(TXT_RECORD))
+ rcol -= tmp + 1;
+ goto resolve;
+ }
+ }
+ if (isblank(evp->e_c) && UNMAP_TST)
+ txt_unmap(sp, tp, &ec_flags);
+ }
+ if (abb != AB_NOTSET)
+ abb = inword(evp->e_c) ? AB_INWORD : AB_NOTWORD;
+
+insl_ch: if (txt_insch(sp, tp, &evp->e_c, flags))
+ goto err;
+
+ /*
+ * If we're using K_VLNEXT to quote the next character, then
+ * we want the cursor to position itself on the ^ placeholder
+ * we're displaying, to match historic practice.
+ */
+ if (quote == Q_VNEXT) {
+ --tp->cno;
+ ++tp->owrite;
+ }
+
+ /*
+ * !!!
+ * Translate "<CH_HEX>[isxdigit()]*" to a character with
+ * a hex value: this test delimits the value by the max
+ * number of hex bytes. Offset by one, we use 0 to mean
+ * that we've found <CH_HEX>.
+ */
+ if (hexcnt != 0 && hexcnt++ == sizeof(CHAR_T) * 2 + 1) {
+ hexcnt = 0;
+ if (txt_hex(sp, tp))
+ goto err;
+ }
+
+ /*
+ * Check to see if we've crossed the margin.
+ *
+ * !!!
+ * In the historic vi, the wrapmargin value was figured out
+ * using the display widths of the characters, i.e. <tab>
+ * characters were counted as two characters if the list edit
+ * option is set, but as the tabstop edit option number of
+ * characters otherwise. That's what the vs_column() function
+ * gives us, so we use it.
+ */
+ if (margin != 0) {
+ if (vs_column(sp, &tcol))
+ goto err;
+ if (tcol >= margin) {
+ if (txt_margin(sp, tp, &wmt, &tmp, flags))
+ goto err;
+ if (tmp) {
+ if (isblank(evp->e_c))
+ wm_skip = 1;
+ wm_set = 1;
+ goto k_cr;
+ }
+ }
+ }
+
+ /*
+ * If we've reached the end of the buffer, then we need to
+ * switch into insert mode. This happens when there's a
+ * change to a mark and the user puts in more characters than
+ * the length of the motion.
+ */
+ebuf_chk: if (tp->cno >= tp->len) {
+ BINC_GOTO(sp, tp->lb, tp->lb_len, tp->len + 1);
+ LF_SET(TXT_APPENDEOL);
+
+ tp->lb[tp->cno] = CH_CURSOR;
+ ++tp->insert;
+ ++tp->len;
+ }
+
+ /* Step the quote state forward. */
+ if (quote != Q_NOTSET) {
+ if (quote == Q_BNEXT)
+ quote = Q_BTHIS;
+ if (quote == Q_VNEXT)
+ quote = Q_VTHIS;
+ }
+ break;
+ }
+
+#ifdef DEBUG
+ if (tp->cno + tp->insert + tp->owrite != tp->len) {
+ msgq(sp, M_ERR,
+ "len %u != cno: %u ai: %u insert %u overwrite %u",
+ tp->len, tp->cno, tp->ai, tp->insert, tp->owrite);
+ if (LF_ISSET(TXT_REPLAY))
+ goto done;
+ tp->len = tp->cno + tp->insert + tp->owrite;
+ }
+#endif
+
+resolve:/*
+ * 1: If we don't need to know where the cursor really is and we're
+ * replaying text, keep going.
+ */
+ if (margin == 0 && LF_ISSET(TXT_REPLAY))
+ goto replay;
+
+ /*
+ * 2: Reset the line. Don't bother unless we're about to wait on
+ * a character or we need to know where the cursor really is.
+ * We have to do this before showing matching characters so the
+ * user can see what they're matching.
+ */
+ if ((margin != 0 || !KEYS_WAITING(sp)) &&
+ vs_change(sp, tp->lno, LINE_RESET))
+ return (1);
+
+ /*
+ * 3: If there aren't keys waiting, display the matching character.
+ * We have to do this before resolving any messages, otherwise
+ * the error message from a missing match won't appear correctly.
+ */
+ if (showmatch) {
+ if (!KEYS_WAITING(sp) && txt_showmatch(sp, tp))
+ return (1);
+ showmatch = 0;
+ }
+
+ /*
+ * 4: If there have been messages and we're not editing on the colon
+ * command line or doing file name completion, resolve them.
+ */
+ if ((vip->totalcount != 0 || F_ISSET(gp, G_BELLSCHED)) &&
+ !F_ISSET(sp, SC_TINPUT_INFO) && !filec_redraw &&
+ vs_resolve(sp, NULL, 0))
+ return (1);
+
+ /*
+ * 5: Refresh the screen if we're about to wait on a character or we
+ * need to know where the cursor really is.
+ */
+ if (margin != 0 || !KEYS_WAITING(sp)) {
+ UPDATE_POSITION(sp, tp);
+ if (vs_refresh(sp, margin != 0))
+ return (1);
+ }
+
+ /* 6: Proceed with the incremental search. */
+ if (FL_ISSET(is_flags, IS_RUNNING) && txt_isrch(sp, vp, tp, &is_flags))
+ return (1);
+
+ /* 7: Next character... */
+ if (LF_ISSET(TXT_REPLAY))
+ goto replay;
+ goto next;
+
+done: /* Leave input mode. */
+ F_CLR(sp, SC_TINPUT);
+
+ /* If recording for playback, save it. */
+ if (LF_ISSET(TXT_RECORD))
+ vip->rep_cnt = rcol;
+
+ /*
+ * If not working on the colon command line, set the final cursor
+ * position.
+ */
+ if (!F_ISSET(sp, SC_TINPUT_INFO)) {
+ vp->m_final.lno = tp->lno;
+ vp->m_final.cno = tp->cno;
+ }
+ return (0);
+
+err:
+alloc_err:
+ txt_err(sp, &sp->tiq);
+ return (1);
+}
+
+/*
+ * txt_abbrev --
+ * Handle abbreviations.
+ */
+static int
+txt_abbrev(sp, tp, pushcp, isinfoline, didsubp, turnoffp)
+ SCR *sp;
+ TEXT *tp;
+ CHAR_T *pushcp;
+ int isinfoline, *didsubp, *turnoffp;
+{
+ VI_PRIVATE *vip;
+ CHAR_T ch, *p;
+ SEQ *qp;
+ size_t len, off;
+
+ /* Check to make sure we're not at the start of an append. */
+ *didsubp = 0;
+ if (tp->cno == tp->offset)
+ return (0);
+
+ vip = VIP(sp);
+
+ /*
+ * Find the start of the "word".
+ *
+ * !!!
+ * We match historic practice, which, as far as I can tell, had an
+ * off-by-one error. The way this worked was that when the inserted
+ * text switched from a "word" character to a non-word character,
+ * vi would check for possible abbreviations. It would then take the
+ * type (i.e. word/non-word) of the character entered TWO characters
+ * ago, and move backward in the text until reaching a character that
+ * was not that type, or the beginning of the insert, the line, or
+ * the file. For example, in the string "abc<space>", when the <space>
+ * character triggered the abbreviation check, the type of the 'b'
+ * character was used for moving through the string. Maybe there's a
+ * reason for not using the first (i.e. 'c') character, but I can't
+ * think of one.
+ *
+ * Terminate at the beginning of the insert or the character after the
+ * offset character -- both can be tested for using tp->offset.
+ */
+ off = tp->cno - 1; /* Previous character. */
+ p = tp->lb + off;
+ len = 1; /* One character test. */
+ if (off == tp->offset || isblank(p[-1]))
+ goto search;
+ if (inword(p[-1])) /* Move backward to change. */
+ for (;;) {
+ --off; --p; ++len;
+ if (off == tp->offset || !inword(p[-1]))
+ break;
+ }
+ else
+ for (;;) {
+ --off; --p; ++len;
+ if (off == tp->offset ||
+ inword(p[-1]) || isblank(p[-1]))
+ break;
+ }
+
+ /*
+ * !!!
+ * Historic vi exploded abbreviations on the command line. This has
+ * obvious problems in that unabbreviating the string can be extremely
+ * tricky, particularly if the string has, say, an embedded escape
+ * character. Personally, I think it's a stunningly bad idea. Other
+ * examples of problems this caused in historic vi are:
+ * :ab foo bar
+ * :ab foo baz
+ * results in "bar" being abbreviated to "baz", which wasn't what the
+ * user had in mind at all. Also, the commands:
+ * :ab foo bar
+ * :unab foo<space>
+ * resulted in an error message that "bar" wasn't mapped. Finally,
+ * since the string was already exploded by the time the unabbreviate
+ * command got it, all it knew was that an abbreviation had occurred.
+ * Cleverly, it checked the replacement string for its unabbreviation
+ * match, which meant that the commands:
+ * :ab foo1 bar
+ * :ab foo2 bar
+ * :unab foo2
+ * unabbreviate "foo1", and the commands:
+ * :ab foo bar
+ * :ab bar baz
+ * unabbreviate "foo"!
+ *
+ * Anyway, people neglected to first ask my opinion before they wrote
+ * macros that depend on this stuff, so, we make this work as follows.
+ * When checking for an abbreviation on the command line, if we get a
+ * string which is <blank> terminated and which starts at the beginning
+ * of the line, we check to see it is the abbreviate or unabbreviate
+ * commands. If it is, turn abbreviations off and return as if no
+ * abbreviation was found. Note also, minor trickiness, so that if
+ * the user erases the line and starts another command, we turn the
+ * abbreviations back on.
+ *
+ * This makes the layering look like a Nachos Supreme.
+ */
+search: if (isinfoline)
+ if (off == tp->ai || off == tp->offset)
+ if (ex_is_abbrev(p, len)) {
+ *turnoffp = 1;
+ return (0);
+ } else
+ *turnoffp = 0;
+ else
+ if (*turnoffp)
+ return (0);
+
+ /* Check for any abbreviations. */
+ if ((qp = seq_find(sp, NULL, NULL, p, len, SEQ_ABBREV, NULL)) == NULL)
+ return (0);
+
+ /*
+ * Push the abbreviation onto the tty stack. Historically, characters
+ * resulting from an abbreviation expansion were themselves subject to
+ * map expansions, O_SHOWMATCH matching etc. This means the expanded
+ * characters will be re-tested for abbreviations. It's difficult to
+ * know what historic practice in this case was, since abbreviations
+ * were applied to :colon command lines, so entering abbreviations that
+ * looped was tricky, although possible. In addition, obvious loops
+ * didn't work as expected. (The command ':ab a b|ab b c|ab c a' will
+ * silently only implement and/or display the last abbreviation.)
+ *
+ * This implementation doesn't recover well from such abbreviations.
+ * The main input loop counts abbreviated characters, and, when it
+ * reaches a limit, discards any abbreviated characters on the queue.
+ * It's difficult to back up to the original position, as the replay
+ * queue would have to be adjusted, and the line state when an initial
+ * abbreviated character was received would have to be saved.
+ */
+ ch = *pushcp;
+ if (v_event_push(sp, NULL, &ch, 1, CH_ABBREVIATED))
+ return (1);
+ if (v_event_push(sp, NULL, qp->output, qp->olen, CH_ABBREVIATED))
+ return (1);
+
+ /*
+ * If the size of the abbreviation is larger than or equal to the size
+ * of the original text, move to the start of the replaced characters,
+ * and add their length to the overwrite count.
+ *
+ * If the abbreviation is smaller than the original text, we have to
+ * delete the additional overwrite characters and copy down any insert
+ * characters.
+ */
+ tp->cno -= len;
+ if (qp->olen >= len)
+ tp->owrite += len;
+ else {
+ if (tp->insert)
+ memmove(tp->lb + tp->cno + qp->olen,
+ tp->lb + tp->cno + tp->owrite + len, tp->insert);
+ tp->owrite += qp->olen;
+ tp->len -= len - qp->olen;
+ }
+
+ /*
+ * We return the length of the abbreviated characters. This is so
+ * the calling routine can replace the replay characters with the
+ * abbreviation. This means that subsequent '.' commands will produce
+ * the same text, regardless of intervening :[un]abbreviate commands.
+ * This is historic practice.
+ */
+ *didsubp = len;
+ return (0);
+}
+
+/*
+ * txt_unmap --
+ * Handle the unmap command.
+ */
+static void
+txt_unmap(sp, tp, ec_flagsp)
+ SCR *sp;
+ TEXT *tp;
+ u_int32_t *ec_flagsp;
+{
+ size_t len, off;
+ char *p;
+
+ /* Find the beginning of this "word". */
+ for (off = tp->cno - 1, p = tp->lb + off, len = 0;; --p, --off) {
+ if (isblank(*p)) {
+ ++p;
+ break;
+ }
+ ++len;
+ if (off == tp->ai || off == tp->offset)
+ break;
+ }
+
+ /*
+ * !!!
+ * Historic vi exploded input mappings on the command line. See the
+ * txt_abbrev() routine for an explanation of the problems inherent
+ * in this.
+ *
+ * We make this work as follows. If we get a string which is <blank>
+ * terminated and which starts at the beginning of the line, we check
+ * to see it is the unmap command. If it is, we return that the input
+ * mapping should be turned off. Note also, minor trickiness, so that
+ * if the user erases the line and starts another command, we go ahead
+ * an turn mapping back on.
+ */
+ if ((off == tp->ai || off == tp->offset) && ex_is_unmap(p, len))
+ FL_CLR(*ec_flagsp, EC_MAPINPUT);
+ else
+ FL_SET(*ec_flagsp, EC_MAPINPUT);
+}
+
+/*
+ * txt_ai_resolve --
+ * When a line is resolved by <esc>, review autoindent characters.
+ */
+static void
+txt_ai_resolve(sp, tp, changedp)
+ SCR *sp;
+ TEXT *tp;
+ int *changedp;
+{
+ u_long ts;
+ int del;
+ size_t cno, len, new, old, scno, spaces, tab_after_sp, tabs;
+ char *p;
+
+ *changedp = 0;
+
+ /*
+ * If the line is empty, has an offset, or no autoindent
+ * characters, we're done.
+ */
+ if (!tp->len || tp->offset || !tp->ai)
+ return;
+
+ /*
+ * If the length is less than or equal to the autoindent
+ * characters, delete them.
+ */
+ if (tp->len <= tp->ai) {
+ tp->ai = tp->cno = tp->len = 0;
+ return;
+ }
+
+ /*
+ * The autoindent characters plus any leading <blank> characters
+ * in the line are resolved into the minimum number of characters.
+ * Historic practice.
+ */
+ ts = O_VAL(sp, O_TABSTOP);
+
+ /* Figure out the last <blank> screen column. */
+ for (p = tp->lb, scno = 0, len = tp->len,
+ spaces = tab_after_sp = 0; len-- && isblank(*p); ++p)
+ if (*p == '\t') {
+ if (spaces)
+ tab_after_sp = 1;
+ scno += COL_OFF(scno, ts);
+ } else {
+ ++spaces;
+ ++scno;
+ }
+
+ /*
+ * If there are no spaces, or no tabs after spaces and less than
+ * ts spaces, it's already minimal.
+ */
+ if (!spaces || !tab_after_sp && spaces < ts)
+ return;
+
+ /* Count up spaces/tabs needed to get to the target. */
+ for (cno = 0, tabs = 0; cno + COL_OFF(cno, ts) <= scno; ++tabs)
+ cno += COL_OFF(cno, ts);
+ spaces = scno - cno;
+
+ /*
+ * Figure out how many characters we're dropping -- if we're not
+ * dropping any, it's already minimal, we're done.
+ */
+ old = p - tp->lb;
+ new = spaces + tabs;
+ if (old == new)
+ return;
+
+ /* Shift the rest of the characters down, adjust the counts. */
+ del = old - new;
+ memmove(p - del, p, tp->len - old);
+ tp->len -= del;
+ tp->cno -= del;
+
+ /* Fill in space/tab characters. */
+ for (p = tp->lb; tabs--;)
+ *p++ = '\t';
+ while (spaces--)
+ *p++ = ' ';
+ *changedp = 1;
+}
+
+/*
+ * v_txt_auto --
+ * Handle autoindent. If aitp isn't NULL, use it, otherwise,
+ * retrieve the line.
+ *
+ * PUBLIC: int v_txt_auto __P((SCR *, recno_t, TEXT *, size_t, TEXT *));
+ */
+int
+v_txt_auto(sp, lno, aitp, len, tp)
+ SCR *sp;
+ recno_t lno;
+ TEXT *aitp, *tp;
+ size_t len;
+{
+ size_t nlen;
+ char *p, *t;
+
+ if (aitp == NULL) {
+ /*
+ * If the ex append command is executed with an address of 0,
+ * it's possible to get here with a line number of 0. Return
+ * an indent of 0.
+ */
+ if (lno == 0) {
+ tp->ai = 0;
+ return (0);
+ }
+ if (db_get(sp, lno, DBG_FATAL, &t, &len))
+ return (1);
+ } else
+ t = aitp->lb;
+
+ /* Count whitespace characters. */
+ for (p = t; len > 0; ++p, --len)
+ if (!isblank(*p))
+ break;
+
+ /* Set count, check for no indentation. */
+ if ((nlen = (p - t)) == 0)
+ return (0);
+
+ /* Make sure the buffer's big enough. */
+ BINC_RET(sp, tp->lb, tp->lb_len, tp->len + nlen);
+
+ /* Copy the buffer's current contents up. */
+ if (tp->len != 0)
+ memmove(tp->lb + nlen, tp->lb, tp->len);
+ tp->len += nlen;
+
+ /* Copy the indentation into the new buffer. */
+ memmove(tp->lb, t, nlen);
+
+ /* Set the autoindent count. */
+ tp->ai = nlen;
+ return (0);
+}
+
+/*
+ * txt_backup --
+ * Back up to the previously edited line.
+ */
+static TEXT *
+txt_backup(sp, tiqh, tp, flagsp)
+ SCR *sp;
+ TEXTH *tiqh;
+ TEXT *tp;
+ u_int32_t *flagsp;
+{
+ VI_PRIVATE *vip;
+ TEXT *ntp;
+
+ /* Get a handle on the previous TEXT structure. */
+ if ((ntp = tp->q.cqe_prev) == (void *)tiqh) {
+ if (!FL_ISSET(*flagsp, TXT_REPLAY))
+ msgq(sp, M_BERR,
+ "193|Already at the beginning of the insert");
+ return (tp);
+ }
+
+ /* Bookkeeping. */
+ ntp->len = ntp->sv_len;
+
+ /* Handle appending to the line. */
+ vip = VIP(sp);
+ if (ntp->owrite == 0 && ntp->insert == 0) {
+ ntp->lb[ntp->len] = CH_CURSOR;
+ ++ntp->insert;
+ ++ntp->len;
+ FL_SET(*flagsp, TXT_APPENDEOL);
+ } else
+ FL_CLR(*flagsp, TXT_APPENDEOL);
+
+ /* Release the current TEXT. */
+ CIRCLEQ_REMOVE(tiqh, tp, q);
+ text_free(tp);
+
+ /* Update the old line on the screen. */
+ if (vs_change(sp, ntp->lno + 1, LINE_DELETE))
+ return (NULL);
+
+ /* Return the new/current TEXT. */
+ return (ntp);
+}
+
+/*
+ * Text indentation is truly strange. ^T and ^D do movements to the next or
+ * previous shiftwidth value, i.e. for a 1-based numbering, with shiftwidth=3,
+ * ^T moves a cursor on the 7th, 8th or 9th column to the 10th column, and ^D
+ * moves it back.
+ *
+ * !!!
+ * The ^T and ^D characters in historical vi had special meaning only when they
+ * were the first characters entered after entering text input mode. As normal
+ * erase characters couldn't erase autoindent characters (^T in this case), it
+ * meant that inserting text into previously existing text was strange -- ^T
+ * only worked if it was the first keystroke(s), and then could only be erased
+ * using ^D. This implementation treats ^T specially anywhere it occurs in the
+ * input, and permits the standard erase characters to erase the characters it
+ * inserts.
+ *
+ * !!!
+ * A fun test is to try:
+ * :se sw=4 ai list
+ * i<CR>^Tx<CR>^Tx<CR>^Tx<CR>^Dx<CR>^Dx<CR>^Dx<esc>
+ * Historic vi loses some of the '$' marks on the line ends, but otherwise gets
+ * it right.
+ *
+ * XXX
+ * Technically, txt_dent should be part of the screen interface, as it requires
+ * knowledge of character sizes, including <space>s, on the screen. It's here
+ * because it's a complicated little beast, and I didn't want to shove it down
+ * into the screen. It's probable that KEY_LEN will call into the screen once
+ * there are screens with different character representations.
+ *
+ * txt_dent --
+ * Handle ^T indents, ^D outdents.
+ *
+ * If anything changes here, check the ex version to see if it needs similar
+ * changes.
+ */
+static int
+txt_dent(sp, tp, isindent)
+ SCR *sp;
+ TEXT *tp;
+ int isindent;
+{
+ CHAR_T ch;
+ u_long sw, ts;
+ size_t cno, current, spaces, target, tabs, off;
+ int ai_reset;
+
+ ts = O_VAL(sp, O_TABSTOP);
+ sw = O_VAL(sp, O_SHIFTWIDTH);
+
+ /*
+ * Since we don't know what precedes the character(s) being inserted
+ * (or deleted), the preceding whitespace characters must be resolved.
+ * An example is a <tab>, which doesn't need a full shiftwidth number
+ * of columns because it's preceded by <space>s. This is easy to get
+ * if the user sets shiftwidth to a value less than tabstop (or worse,
+ * something for which tabstop isn't a multiple) and then uses ^T to
+ * indent, and ^D to outdent.
+ *
+ * Figure out the current and target screen columns. In the historic
+ * vi, the autoindent column was NOT determined using display widths
+ * of characters as was the wrapmargin column. For that reason, we
+ * can't use the vs_column() function, but have to calculate it here.
+ * This is slow, but it's normally only on the first few characters of
+ * a line.
+ */
+ for (current = cno = 0; cno < tp->cno; ++cno)
+ current += tp->lb[cno] == '\t' ?
+ COL_OFF(current, ts) : KEY_LEN(sp, tp->lb[cno]);
+
+ target = current;
+ if (isindent)
+ target += COL_OFF(target, sw);
+ else
+ target -= --target % sw;
+
+ /*
+ * The AI characters will be turned into overwrite characters if the
+ * cursor immediately follows them. We test both the cursor position
+ * and the indent flag because there's no single test. (^T can only
+ * be detected by the cursor position, and while we know that the test
+ * is always true for ^D, the cursor can be in more than one place, as
+ * "0^D" and "^D" are different.)
+ */
+ ai_reset = !isindent || tp->cno == tp->ai + tp->offset;
+
+ /*
+ * Back up over any previous <blank> characters, changing them into
+ * overwrite characters (including any ai characters). Then figure
+ * out the current screen column.
+ */
+ for (; tp->cno > tp->offset &&
+ (tp->lb[tp->cno - 1] == ' ' || tp->lb[tp->cno - 1] == '\t');
+ --tp->cno, ++tp->owrite);
+ for (current = cno = 0; cno < tp->cno; ++cno)
+ current += tp->lb[cno] == '\t' ?
+ COL_OFF(current, ts) : KEY_LEN(sp, tp->lb[cno]);
+
+ /*
+ * If we didn't move up to or past the target, it's because there
+ * weren't enough characters to delete, e.g. the first character
+ * of the line was a tp->offset character, and the user entered
+ * ^D to move to the beginning of a line. An example of this is:
+ *
+ * :set ai sw=4<cr>i<space>a<esc>i^T^D
+ *
+ * Otherwise, count up the total spaces/tabs needed to get from the
+ * beginning of the line (or the last non-<blank> character) to the
+ * target.
+ */
+ if (current >= target)
+ spaces = tabs = 0;
+ else {
+ for (cno = current,
+ tabs = 0; cno + COL_OFF(cno, ts) <= target; ++tabs)
+ cno += COL_OFF(cno, ts);
+ spaces = target - cno;
+ }
+
+ /* If we overwrote ai characters, reset the ai count. */
+ if (ai_reset)
+ tp->ai = tabs + spaces;
+
+ /*
+ * Call txt_insch() to insert each character, so that we get the
+ * correct effect when we add a <tab> to replace N <spaces>.
+ */
+ for (ch = '\t'; tabs > 0; --tabs)
+ (void)txt_insch(sp, tp, &ch, 0);
+ for (ch = ' '; spaces > 0; --spaces)
+ (void)txt_insch(sp, tp, &ch, 0);
+ return (0);
+}
+
+/*
+ * txt_fc --
+ * File name completion.
+ */
+static int
+txt_fc(sp, tp, redrawp)
+ SCR *sp;
+ TEXT *tp;
+ int *redrawp;
+{
+ struct stat sb;
+ ARGS **argv;
+ CHAR_T s_ch;
+ EXCMD cmd;
+ size_t indx, len, nlen, off;
+ int argc, trydir;
+ char *p, *t;
+
+ trydir = 0;
+ *redrawp = 0;
+
+ /*
+ * Find the beginning of this "word" -- if we're at the beginning
+ * of the line, it's a special case.
+ */
+ if (tp->cno == 1) {
+ len = 0;
+ p = tp->lb;
+ } else
+retry: for (len = 0,
+ off = tp->cno - 1, p = tp->lb + off;; --off, --p) {
+ if (isblank(*p)) {
+ ++p;
+ break;
+ }
+ ++len;
+ if (off == tp->ai || off == tp->offset)
+ break;
+ }
+
+ /*
+ * Get enough space for a wildcard character.
+ *
+ * XXX
+ * This won't work for "foo\", since the \ will escape the expansion
+ * character. I'm not sure if that's a bug or not...
+ */
+ off = p - tp->lb;
+ BINC_RET(sp, tp->lb, tp->lb_len, tp->len + 1);
+ p = tp->lb + off;
+
+ s_ch = p[len];
+ p[len] = '*';
+
+ /* Build an ex command, and call the ex expansion routines. */
+ ex_cinit(&cmd, 0, 0, OOBLNO, OOBLNO, 0, NULL);
+ if (argv_init(sp, &cmd))
+ return (1);
+ if (argv_exp2(sp, &cmd, p, len + 1)) {
+ p[len] = s_ch;
+ return (0);
+ }
+ argc = cmd.argc;
+ argv = cmd.argv;
+
+ p[len] = s_ch;
+
+ switch (argc) {
+ case 0: /* No matches. */
+ if (!trydir)
+ (void)sp->gp->scr_bell(sp);
+ return (0);
+ case 1: /* One match. */
+ /* If something changed, do the exchange. */
+ nlen = strlen(cmd.argv[0]->bp);
+ if (len != nlen || memcmp(cmd.argv[0]->bp, p, len))
+ break;
+
+ /* If haven't done a directory test, do it now. */
+ if (!trydir &&
+ !stat(cmd.argv[0]->bp, &sb) && S_ISDIR(sb.st_mode)) {
+ p += len;
+ goto isdir;
+ }
+
+ /* If nothing changed, period, ring the bell. */
+ if (!trydir)
+ (void)sp->gp->scr_bell(sp);
+ return (0);
+ default: /* Multiple matches. */
+ *redrawp = 1;
+ if (txt_fc_col(sp, argc, argv))
+ return (1);
+
+ /* Find the length of the shortest match. */
+ for (nlen = cmd.argv[0]->len; --argc > 0;) {
+ if (cmd.argv[argc]->len < nlen)
+ nlen = cmd.argv[argc]->len;
+ for (indx = 0; indx < nlen &&
+ cmd.argv[argc]->bp[indx] == cmd.argv[0]->bp[indx];
+ ++indx);
+ nlen = indx;
+ }
+ break;
+ }
+
+ /* Overwrite the expanded text first. */
+ for (t = cmd.argv[0]->bp; len > 0 && nlen > 0; --len, --nlen)
+ *p++ = *t++;
+
+ /* If lost text, make the remaining old text overwrite characters. */
+ if (len) {
+ tp->cno -= len;
+ tp->owrite += len;
+ }
+
+ /* Overwrite any overwrite characters next. */
+ for (; nlen > 0 && tp->owrite > 0; --nlen, --tp->owrite, ++tp->cno)
+ *p++ = *t++;
+
+ /* Shift remaining text up, and move the cursor to the end. */
+ if (nlen) {
+ off = p - tp->lb;
+ BINC_RET(sp, tp->lb, tp->lb_len, tp->len + nlen);
+ p = tp->lb + off;
+
+ tp->cno += nlen;
+ tp->len += nlen;
+
+ if (tp->insert != 0)
+ (void)memmove(p + nlen, p, tp->insert);
+ while (nlen--)
+ *p++ = *t++;
+ }
+
+ /* If a single match and it's a directory, retry it. */
+ if (argc == 1 && !stat(cmd.argv[0]->bp, &sb) && S_ISDIR(sb.st_mode)) {
+isdir: if (tp->owrite == 0) {
+ off = p - tp->lb;
+ BINC_RET(sp, tp->lb, tp->lb_len, tp->len + 1);
+ p = tp->lb + off;
+ if (tp->insert != 0)
+ (void)memmove(p + 1, p, tp->insert);
+ ++tp->len;
+ } else
+ --tp->owrite;
+
+ ++tp->cno;
+ *p++ = '/';
+
+ trydir = 1;
+ goto retry;
+ }
+ return (0);
+}
+
+/*
+ * txt_fc_col --
+ * Display file names for file name completion.
+ */
+static int
+txt_fc_col(sp, argc, argv)
+ SCR *sp;
+ int argc;
+ ARGS **argv;
+{
+ ARGS **av;
+ CHAR_T *p;
+ GS *gp;
+ size_t base, cnt, col, colwidth, numrows, numcols, prefix, row;
+ int ac, nf, reset;
+
+ gp = sp->gp;
+
+ /* Trim any directory prefix common to all of the files. */
+ if ((p = strrchr(argv[0]->bp, '/')) == NULL)
+ prefix = 0;
+ else {
+ prefix = (p - argv[0]->bp) + 1;
+ for (ac = argc - 1, av = argv + 1; ac > 0; --ac, ++av)
+ if (av[0]->len < prefix ||
+ memcmp(av[0]->bp, argv[0]->bp, prefix)) {
+ prefix = 0;
+ break;
+ }
+ }
+
+ /*
+ * Figure out the column width for the longest name. Output is done on
+ * 6 character "tab" boundaries for no particular reason. (Since we
+ * don't output tab characters, we ignore the terminal's tab settings.)
+ * Ignore the user's tab setting because we have no idea how reasonable
+ * it is.
+ */
+ for (ac = argc, av = argv, colwidth = 0; ac > 0; --ac, ++av) {
+ for (col = 0, p = av[0]->bp + prefix; *p != '\0'; ++p)
+ col += KEY_LEN(sp, *p);
+ if (col > colwidth)
+ colwidth = col;
+ }
+ colwidth += COL_OFF(colwidth, 6);
+
+ /*
+ * Writing to the bottom line of the screen is always turned off when
+ * SC_TINPUT_INFO is set. Turn it back on, we know what we're doing.
+ */
+ if (F_ISSET(sp, SC_TINPUT_INFO)) {
+ reset = 1;
+ F_CLR(sp, SC_TINPUT_INFO);
+ } else
+ reset = 0;
+
+#define CHK_INTR \
+ if (F_ISSET(gp, G_INTERRUPTED)) \
+ goto intr;
+
+ /* If the largest file name is too large, just print them. */
+ if (colwidth > sp->cols) {
+ p = msg_print(sp, av[0]->bp + prefix, &nf);
+ for (ac = argc, av = argv; ac > 0; --ac, ++av) {
+ (void)ex_printf(sp, "%s\n", p);
+ if (F_ISSET(gp, G_INTERRUPTED))
+ break;
+ }
+ if (nf)
+ FREE_SPACE(sp, p, 0);
+ CHK_INTR;
+ } else {
+ /* Figure out the number of columns. */
+ numcols = (sp->cols - 1) / colwidth;
+ if (argc > numcols) {
+ numrows = argc / numcols;
+ if (argc % numcols)
+ ++numrows;
+ } else
+ numrows = 1;
+
+ /* Display the files in sorted order. */
+ for (row = 0; row < numrows; ++row) {
+ for (base = row, col = 0; col < numcols; ++col) {
+ p = msg_print(sp, argv[base]->bp + prefix, &nf);
+ cnt = ex_printf(sp, "%s", p);
+ if (nf)
+ FREE_SPACE(sp, p, 0);
+ CHK_INTR;
+ if ((base += numrows) >= argc)
+ break;
+ (void)ex_printf(sp,
+ "%*s", (int)(colwidth - cnt), "");
+ CHK_INTR;
+ }
+ (void)ex_puts(sp, "\n");
+ CHK_INTR;
+ }
+ (void)ex_puts(sp, "\n");
+ CHK_INTR;
+ }
+ (void)ex_fflush(sp);
+
+ if (0) {
+intr: F_CLR(gp, G_INTERRUPTED);
+ }
+ if (reset)
+ F_SET(sp, SC_TINPUT_INFO);
+
+ return (0);
+}
+
+/*
+ * txt_emark --
+ * Set the end mark on the line.
+ */
+static int
+txt_emark(sp, tp, cno)
+ SCR *sp;
+ TEXT *tp;
+ size_t cno;
+{
+ CHAR_T ch, *kp;
+ size_t chlen, nlen, olen;
+ char *p;
+
+ ch = CH_ENDMARK;
+
+ /*
+ * The end mark may not be the same size as the current character.
+ * Don't let the line shift.
+ */
+ nlen = KEY_LEN(sp, ch);
+ if (tp->lb[cno] == '\t')
+ (void)vs_columns(sp, tp->lb, tp->lno, &cno, &olen);
+ else
+ olen = KEY_LEN(sp, tp->lb[cno]);
+
+ /*
+ * If the line got longer, well, it's weird, but it's easy. If
+ * it's the same length, it's easy. If it got shorter, we have
+ * to fix it up.
+ */
+ if (olen > nlen) {
+ BINC_RET(sp, tp->lb, tp->lb_len, tp->len + olen);
+ chlen = olen - nlen;
+ if (tp->insert != 0)
+ memmove(tp->lb + cno + 1 + chlen,
+ tp->lb + cno + 1, tp->insert);
+
+ tp->len += chlen;
+ tp->owrite += chlen;
+ p = tp->lb + cno;
+ if (tp->lb[cno] == '\t')
+ for (cno += chlen; chlen--;)
+ *p++ = ' ';
+ else
+ for (kp = KEY_NAME(sp, tp->lb[cno]),
+ cno += chlen; chlen--;)
+ *p++ = *kp++;
+ }
+ tp->lb[cno] = ch;
+ return (vs_change(sp, tp->lno, LINE_RESET));
+}
+
+/*
+ * txt_err --
+ * Handle an error during input processing.
+ */
+static void
+txt_err(sp, tiqh)
+ SCR *sp;
+ TEXTH *tiqh;
+{
+ recno_t lno;
+
+ /*
+ * The problem with input processing is that the cursor is at an
+ * indeterminate position since some input may have been lost due
+ * to a malloc error. So, try to go back to the place from which
+ * the cursor started, knowing that it may no longer be available.
+ *
+ * We depend on at least one line number being set in the text
+ * chain.
+ */
+ for (lno = tiqh->cqh_first->lno;
+ !db_exist(sp, lno) && lno > 0; --lno);
+
+ sp->lno = lno == 0 ? 1 : lno;
+ sp->cno = 0;
+
+ /* Redraw the screen, just in case. */
+ F_SET(sp, SC_SCR_REDRAW);
+}
+
+/*
+ * txt_hex --
+ * Let the user insert any character value they want.
+ *
+ * !!!
+ * This is an extension. The pattern "^X[0-9a-fA-F]*" is a way
+ * for the user to specify a character value which their keyboard
+ * may not be able to enter.
+ */
+static int
+txt_hex(sp, tp)
+ SCR *sp;
+ TEXT *tp;
+{
+ CHAR_T savec;
+ size_t len, off;
+ u_long value;
+ char *p, *wp;
+
+ /*
+ * Null-terminate the string. Since nul isn't a legal hex value,
+ * this should be okay, and lets us use a local routine, which
+ * presumably understands the character set, to convert the value.
+ */
+ savec = tp->lb[tp->cno];
+ tp->lb[tp->cno] = 0;
+
+ /* Find the previous CH_HEX character. */
+ for (off = tp->cno - 1, p = tp->lb + off, len = 0;; --p, --off, ++len) {
+ if (*p == CH_HEX) {
+ wp = p + 1;
+ break;
+ }
+ /* Not on this line? Shouldn't happen. */
+ if (off == tp->ai || off == tp->offset)
+ goto nothex;
+ }
+
+ /* If length of 0, then it wasn't a hex value. */
+ if (len == 0)
+ goto nothex;
+
+ /* Get the value. */
+ errno = 0;
+ value = strtol(wp, NULL, 16);
+ if (errno || value > MAX_CHAR_T) {
+nothex: tp->lb[tp->cno] = savec;
+ return (0);
+ }
+
+ /* Restore the original character. */
+ tp->lb[tp->cno] = savec;
+
+ /* Adjust the bookkeeping. */
+ tp->cno -= len;
+ tp->len -= len;
+ tp->lb[tp->cno - 1] = value;
+
+ /* Copy down any overwrite characters. */
+ if (tp->owrite)
+ memmove(tp->lb + tp->cno, tp->lb + tp->cno + len, tp->owrite);
+
+ /* Copy down any insert characters. */
+ if (tp->insert)
+ memmove(tp->lb + tp->cno + tp->owrite,
+ tp->lb + tp->cno + tp->owrite + len, tp->insert);
+
+ return (0);
+}
+
+/*
+ * txt_insch --
+ *
+ * !!!
+ * Historic vi did a special screen optimization for tab characters. As an
+ * example, for the keystrokes "iabcd<esc>0C<tab>", the tab overwrote the
+ * rest of the string when it was displayed.
+ *
+ * Because early versions of this implementation redisplayed the entire line
+ * on each keystroke, the "bcd" was pushed to the right as it ignored that
+ * the user had "promised" to change the rest of the characters. However,
+ * the historic vi implementation had an even worse bug: given the keystrokes
+ * "iabcd<esc>0R<tab><esc>", the "bcd" disappears, and magically reappears
+ * on the second <esc> key.
+ *
+ * POSIX 1003.2 requires (will require) that this be fixed, specifying that
+ * vi overwrite characters the user has committed to changing, on the basis
+ * of the screen space they require, but that it not overwrite other characters.
+ */
+static int
+txt_insch(sp, tp, chp, flags)
+ SCR *sp;
+ TEXT *tp;
+ CHAR_T *chp;
+ u_int flags;
+{
+ CHAR_T *kp, savech;
+ size_t chlen, cno, copydown, olen, nlen;
+ char *p;
+
+ /*
+ * The 'R' command does one-for-one replacement, because there's
+ * no way to know how many characters the user intends to replace.
+ */
+ if (LF_ISSET(TXT_REPLACE)) {
+ if (tp->owrite) {
+ --tp->owrite;
+ tp->lb[tp->cno++] = *chp;
+ return (0);
+ }
+ } else if (tp->owrite) { /* Overwrite a character. */
+ cno = tp->cno;
+
+ /*
+ * If the old or new characters are tabs, then the length of the
+ * display depends on the character position in the display. We
+ * don't even try to handle this here, just ask the screen.
+ */
+ if (*chp == '\t') {
+ savech = tp->lb[cno];
+ tp->lb[cno] = '\t';
+ (void)vs_columns(sp, tp->lb, tp->lno, &cno, &nlen);
+ tp->lb[cno] = savech;
+ } else
+ nlen = KEY_LEN(sp, *chp);
+
+ /*
+ * Eat overwrite characters until we run out of them or we've
+ * handled the length of the new character. If we only eat
+ * part of an overwrite character, break it into its component
+ * elements and display the remaining components.
+ */
+ for (copydown = 0; nlen != 0 && tp->owrite != 0;) {
+ --tp->owrite;
+
+ if (tp->lb[cno] == '\t')
+ (void)vs_columns(sp,
+ tp->lb, tp->lno, &cno, &olen);
+ else
+ olen = KEY_LEN(sp, tp->lb[cno]);
+
+ if (olen == nlen) {
+ nlen = 0;
+ break;
+ }
+ if (olen < nlen) {
+ ++copydown;
+ nlen -= olen;
+ } else {
+ BINC_RET(sp,
+ tp->lb, tp->lb_len, tp->len + olen);
+ chlen = olen - nlen;
+ memmove(tp->lb + cno + 1 + chlen,
+ tp->lb + cno + 1, tp->owrite + tp->insert);
+
+ tp->len += chlen;
+ tp->owrite += chlen;
+ if (tp->lb[cno] == '\t')
+ for (p = tp->lb + cno + 1; chlen--;)
+ *p++ = ' ';
+ else
+ for (kp =
+ KEY_NAME(sp, tp->lb[cno]) + nlen,
+ p = tp->lb + cno + 1; chlen--;)
+ *p++ = *kp++;
+ nlen = 0;
+ break;
+ }
+ }
+
+ /*
+ * If had to erase several characters, we adjust the total
+ * count, and if there are any characters left, shift them
+ * into position.
+ */
+ if (copydown != 0 && (tp->len -= copydown) != 0)
+ memmove(tp->lb + cno, tp->lb + cno + copydown,
+ tp->owrite + tp->insert + copydown);
+
+ /* If we had enough overwrite characters, we're done. */
+ if (nlen == 0) {
+ tp->lb[tp->cno++] = *chp;
+ return (0);
+ }
+ }
+
+ /* Check to see if the character fits into the input buffer. */
+ BINC_RET(sp, tp->lb, tp->lb_len, tp->len + 1);
+
+ ++tp->len;
+ if (tp->insert) { /* Insert a character. */
+ if (tp->insert == 1)
+ tp->lb[tp->cno + 1] = tp->lb[tp->cno];
+ else
+ memmove(tp->lb + tp->cno + 1,
+ tp->lb + tp->cno, tp->owrite + tp->insert);
+ }
+ tp->lb[tp->cno++] = *chp;
+ return (0);
+}
+
+/*
+ * txt_isrch --
+ * Do an incremental search.
+ */
+static int
+txt_isrch(sp, vp, tp, is_flagsp)
+ SCR *sp;
+ VICMD *vp;
+ TEXT *tp;
+ u_int8_t *is_flagsp;
+{
+ MARK start;
+ recno_t lno;
+ u_int sf;
+
+ /* If it's a one-line screen, we don't do incrementals. */
+ if (IS_ONELINE(sp)) {
+ FL_CLR(*is_flagsp, IS_RUNNING);
+ return (0);
+ }
+
+ /*
+ * If the user erases back to the beginning of the buffer, there's
+ * nothing to search for. Reset the cursor to the starting point.
+ */
+ if (tp->cno <= 1) {
+ vp->m_final = vp->m_start;
+ return (0);
+ }
+
+ /*
+ * If it's an RE quote character, and not quoted, ignore it until
+ * we get another character.
+ */
+ if (tp->lb[tp->cno - 1] == '\\' &&
+ (tp->cno == 2 || tp->lb[tp->cno - 2] != '\\'))
+ return (0);
+
+ /*
+ * If it's a magic shell character, and not quoted, reset the cursor
+ * to the starting point.
+ */
+ if (strchr(O_STR(sp, O_SHELLMETA), tp->lb[tp->cno - 1]) != NULL &&
+ (tp->cno == 2 || tp->lb[tp->cno - 2] != '\\'))
+ vp->m_final = vp->m_start;
+
+ /*
+ * If we see the search pattern termination character, then quit doing
+ * an incremental search. There may be more, e.g., ":/foo/;/bar/",
+ * and we can't handle that incrementally. Also, reset the cursor to
+ * the original location, the ex search routines don't know anything
+ * about incremental searches.
+ */
+ if (tp->lb[0] == tp->lb[tp->cno - 1] &&
+ (tp->cno == 2 || tp->lb[tp->cno - 2] != '\\')) {
+ vp->m_final = vp->m_start;
+ FL_CLR(*is_flagsp, IS_RUNNING);
+ return (0);
+ }
+
+ /*
+ * Remember the input line and discard the special input map,
+ * but don't overwrite the input line on the screen.
+ */
+ lno = tp->lno;
+ F_SET(VIP(sp), VIP_S_MODELINE);
+ F_CLR(sp, SC_TINPUT | SC_TINPUT_INFO);
+ if (txt_map_end(sp))
+ return (1);
+
+ /*
+ * Specify a starting point and search. If we find a match, move to
+ * it and refresh the screen. If we didn't find the match, then we
+ * beep the screen. When searching from the original cursor position,
+ * we have to move the cursor, otherwise, we don't want to move the
+ * cursor in case the text at the current position continues to match.
+ */
+ if (FL_ISSET(*is_flagsp, IS_RESTART)) {
+ start = vp->m_start;
+ sf = SEARCH_SET;
+ } else {
+ start = vp->m_final;
+ sf = SEARCH_INCR | SEARCH_SET;
+ }
+
+ if (tp->lb[0] == '/' ?
+ !f_search(sp,
+ &start, &vp->m_final, tp->lb + 1, tp->cno - 1, NULL, sf) :
+ !b_search(sp,
+ &start, &vp->m_final, tp->lb + 1, tp->cno - 1, NULL, sf)) {
+ sp->lno = vp->m_final.lno;
+ sp->cno = vp->m_final.cno;
+ FL_CLR(*is_flagsp, IS_RESTART);
+
+ if (!KEYS_WAITING(sp) && vs_refresh(sp, 0))
+ return (1);
+ } else
+ FL_SET(*is_flagsp, IS_RESTART);
+
+ /* Reinstantiate the special input map. */
+ if (txt_map_init(sp))
+ return (1);
+ F_CLR(VIP(sp), VIP_S_MODELINE);
+ F_SET(sp, SC_TINPUT | SC_TINPUT_INFO);
+
+ /* Reset the line number of the input line. */
+ tp->lno = TMAP[0].lno;
+
+ /*
+ * If the colon command-line moved, i.e. the screen scrolled,
+ * refresh the input line.
+ *
+ * XXX
+ * We shouldn't be calling vs_line, here -- we need dirty bits
+ * on entries in the SMAP array.
+ */
+ if (lno != TMAP[0].lno) {
+ if (vs_line(sp, &TMAP[0], NULL, NULL))
+ return (1);
+ (void)sp->gp->scr_refresh(sp, 0);
+ }
+ return (0);
+}
+
+/*
+ * txt_resolve --
+ * Resolve the input text chain into the file.
+ */
+static int
+txt_resolve(sp, tiqh, flags)
+ SCR *sp;
+ TEXTH *tiqh;
+ u_int32_t flags;
+{
+ VI_PRIVATE *vip;
+ TEXT *tp;
+ recno_t lno;
+ int changed;
+
+ /*
+ * The first line replaces a current line, and all subsequent lines
+ * are appended into the file. Resolve autoindented characters for
+ * each line before committing it. If the latter causes the line to
+ * change, we have to redisplay it, otherwise the information cached
+ * about the line will be wrong.
+ */
+ vip = VIP(sp);
+ tp = tiqh->cqh_first;
+
+ if (LF_ISSET(TXT_AUTOINDENT))
+ txt_ai_resolve(sp, tp, &changed);
+ else
+ changed = 0;
+ if (db_set(sp, tp->lno, tp->lb, tp->len) ||
+ changed && vs_change(sp, tp->lno, LINE_RESET))
+ return (1);
+
+ for (lno = tp->lno; (tp = tp->q.cqe_next) != (void *)&sp->tiq; ++lno) {
+ if (LF_ISSET(TXT_AUTOINDENT))
+ txt_ai_resolve(sp, tp, &changed);
+ else
+ changed = 0;
+ if (db_append(sp, 0, lno, tp->lb, tp->len) ||
+ changed && vs_change(sp, tp->lno, LINE_RESET))
+ return (1);
+ }
+
+ /*
+ * Clear the input flag, the look-aside buffer is no longer valid.
+ * Has to be done as part of text resolution, or upon return we'll
+ * be looking at incorrect data.
+ */
+ F_CLR(sp, SC_TINPUT);
+
+ return (0);
+}
+
+/*
+ * txt_showmatch --
+ * Show a character match.
+ *
+ * !!!
+ * Historic vi tried to display matches even in the :colon command line.
+ * I think not.
+ */
+static int
+txt_showmatch(sp, tp)
+ SCR *sp;
+ TEXT *tp;
+{
+ GS *gp;
+ VCS cs;
+ MARK m;
+ int cnt, endc, startc;
+
+ gp = sp->gp;
+
+ /*
+ * Do a refresh first, in case we haven't done one in awhile,
+ * so the user can see what we're complaining about.
+ */
+ UPDATE_POSITION(sp, tp);
+ if (vs_refresh(sp, 1))
+ return (1);
+
+ /*
+ * We don't display the match if it's not on the screen. Find
+ * out what the first character on the screen is.
+ */
+ if (vs_sm_position(sp, &m, 0, P_TOP))
+ return (1);
+
+ /* Initialize the getc() interface. */
+ cs.cs_lno = tp->lno;
+ cs.cs_cno = tp->cno - 1;
+ if (cs_init(sp, &cs))
+ return (1);
+ startc = (endc = cs.cs_ch) == ')' ? '(' : '{';
+
+ /* Search for the match. */
+ for (cnt = 1;;) {
+ if (cs_prev(sp, &cs))
+ return (1);
+ if (cs.cs_flags != 0) {
+ if (cs.cs_flags == CS_EOF || cs.cs_flags == CS_SOF) {
+ msgq(sp, M_BERR,
+ "Unmatched %s", KEY_NAME(sp, endc));
+ return (0);
+ }
+ continue;
+ }
+ if (cs.cs_ch == endc)
+ ++cnt;
+ else if (cs.cs_ch == startc && --cnt == 0)
+ break;
+ }
+
+ /* If the match is on the screen, move to it. */
+ if (cs.cs_lno < m.lno || cs.cs_lno == m.lno && cs.cs_cno < m.cno)
+ return (0);
+ sp->lno = cs.cs_lno;
+ sp->cno = cs.cs_cno;
+ if (vs_refresh(sp, 1))
+ return (1);
+
+ /* Wait for timeout or character arrival. */
+ return (v_event_get(sp,
+ NULL, O_VAL(sp, O_MATCHTIME) * 100, EC_TIMEOUT));
+}
+
+/*
+ * txt_margin --
+ * Handle margin wrap.
+ */
+static int
+txt_margin(sp, tp, wmtp, didbreak, flags)
+ SCR *sp;
+ TEXT *tp, *wmtp;
+ int *didbreak;
+ u_int32_t flags;
+{
+ VI_PRIVATE *vip;
+ size_t len, off;
+ char *p, *wp;
+
+ /* Find the nearest previous blank. */
+ for (off = tp->cno - 1, p = tp->lb + off, len = 0;; --off, --p, ++len) {
+ if (isblank(*p)) {
+ wp = p + 1;
+ break;
+ }
+
+ /*
+ * If reach the start of the line, there's nowhere to break.
+ *
+ * !!!
+ * Historic vi belled each time a character was entered after
+ * crossing the margin until a space was entered which could
+ * be used to break the line. I don't as it tends to wake the
+ * cats.
+ */
+ if (off == tp->ai || off == tp->offset) {
+ *didbreak = 0;
+ return (0);
+ }
+ }
+
+ /*
+ * Store saved information about the rest of the line in the
+ * wrapmargin TEXT structure.
+ *
+ * !!!
+ * The offset field holds the length of the current characters
+ * that the user entered, but which are getting split to the new
+ * line -- it's going to be used to set the cursor value when we
+ * move to the new line.
+ */
+ vip = VIP(sp);
+ wmtp->lb = p + 1;
+ wmtp->offset = len;
+ wmtp->insert = LF_ISSET(TXT_APPENDEOL) ? tp->insert - 1 : tp->insert;
+ wmtp->owrite = tp->owrite;
+
+ /* Correct current bookkeeping information. */
+ tp->cno -= len;
+ if (LF_ISSET(TXT_APPENDEOL)) {
+ tp->len -= len + tp->owrite + (tp->insert - 1);
+ tp->insert = 1;
+ } else {
+ tp->len -= len + tp->owrite + tp->insert;
+ tp->insert = 0;
+ }
+ tp->owrite = 0;
+
+ /*
+ * !!!
+ * Delete any trailing whitespace from the current line.
+ */
+ for (;; --p, --off) {
+ if (!isblank(*p))
+ break;
+ --tp->cno;
+ --tp->len;
+ if (off == tp->ai || off == tp->offset)
+ break;
+ }
+ *didbreak = 1;
+ return (0);
+}
+
+/*
+ * txt_Rresolve --
+ * Resolve the input line for the 'R' command.
+ */
+static void
+txt_Rresolve(sp, tiqh, tp, orig_len)
+ SCR *sp;
+ TEXTH *tiqh;
+ TEXT *tp;
+ const size_t orig_len;
+{
+ TEXT *ttp;
+ size_t input_len, retain;
+ char *p;
+
+ /*
+ * Check to make sure that the cursor hasn't moved beyond
+ * the end of the line.
+ */
+ if (tp->owrite == 0)
+ return;
+
+ /*
+ * Calculate how many characters the user has entered,
+ * plus the blanks erased by <carriage-return>/<newline>s.
+ */
+ for (ttp = tiqh->cqh_first, input_len = 0;;) {
+ input_len += ttp == tp ? tp->cno : ttp->len + ttp->R_erase;
+ if ((ttp = ttp->q.cqe_next) == (void *)&sp->tiq)
+ break;
+ }
+
+ /*
+ * If the user has entered less characters than the original line
+ * was long, restore any overwriteable characters to the original
+ * characters. These characters are entered as "insert characters",
+ * because they're after the cursor and we don't want to lose them.
+ * (This is okay because the R command has no insert characters.)
+ * We set owrite to 0 so that the insert characters don't get copied
+ * to somewhere else, which means that the line and the length have
+ * to be adjusted here as well.
+ *
+ * We have to retrieve the original line because the original pinned
+ * page has long since been discarded. If it doesn't exist, that's
+ * okay, the user just extended the file.
+ */
+ if (input_len < orig_len) {
+ retain = MIN(tp->owrite, orig_len - input_len);
+ if (db_get(sp,
+ tiqh->cqh_first->lno, DBG_FATAL | DBG_NOCACHE, &p, NULL))
+ return;
+ memcpy(tp->lb + tp->cno, p + input_len, retain);
+ tp->len -= tp->owrite - retain;
+ tp->owrite = 0;
+ tp->insert += retain;
+ }
+}
+
+/*
+ * txt_nomorech --
+ * No more characters message.
+ */
+static void
+txt_nomorech(sp)
+ SCR *sp;
+{
+ msgq(sp, M_BERR, "194|No more characters to erase");
+}
diff --git a/contrib/nvi/vi/v_ulcase.c b/contrib/nvi/vi/v_ulcase.c
new file mode 100644
index 000000000000..179bebabcc11
--- /dev/null
+++ b/contrib/nvi/vi/v_ulcase.c
@@ -0,0 +1,179 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_ulcase.c 10.7 (Berkeley) 3/6/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+static int ulcase __P((SCR *, recno_t, CHAR_T *, size_t, size_t, size_t));
+
+/*
+ * v_ulcase -- [count]~
+ * Toggle upper & lower case letters.
+ *
+ * !!!
+ * Historic vi didn't permit ~ to cross newline boundaries. I can
+ * think of no reason why it shouldn't, which at least lets the user
+ * auto-repeat through a paragraph.
+ *
+ * !!!
+ * In historic vi, the count was ignored. It would have been better
+ * if there had been an associated motion, but it's too late to make
+ * that the default now.
+ *
+ * PUBLIC: int v_ulcase __P((SCR *, VICMD *));
+ */
+int
+v_ulcase(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ recno_t lno;
+ size_t cno, lcnt, len;
+ u_long cnt;
+ char *p;
+
+ lno = vp->m_start.lno;
+ cno = vp->m_start.cno;
+
+ for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt > 0; cno = 0) {
+ /* SOF is an error, EOF is an infinite count sink. */
+ if (db_get(sp, lno, 0, &p, &len)) {
+ if (lno == 1) {
+ v_emsg(sp, NULL, VIM_EMPTY);
+ return (1);
+ }
+ --lno;
+ break;
+ }
+
+ /* Empty lines decrement the count by one. */
+ if (len == 0) {
+ --cnt;
+ vp->m_final.cno = 0;
+ continue;
+ }
+
+ if (cno + cnt >= len) {
+ lcnt = len - 1;
+ cnt -= len - cno;
+
+ vp->m_final.cno = len - 1;
+ } else {
+ lcnt = cno + cnt - 1;
+ cnt = 0;
+
+ vp->m_final.cno = lcnt + 1;
+ }
+
+ if (ulcase(sp, lno, p, len, cno, lcnt))
+ return (1);
+
+ if (cnt > 0)
+ ++lno;
+ }
+
+ vp->m_final.lno = lno;
+ return (0);
+}
+
+/*
+ * v_mulcase -- [count]~[count]motion
+ * Toggle upper & lower case letters over a range.
+ *
+ * PUBLIC: int v_mulcase __P((SCR *, VICMD *));
+ */
+int
+v_mulcase(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ CHAR_T *p;
+ size_t len;
+ recno_t lno;
+
+ for (lno = vp->m_start.lno;;) {
+ if (db_get(sp, lno, DBG_FATAL, &p, &len))
+ return (1);
+ if (len != 0 && ulcase(sp, lno, p, len,
+ lno == vp->m_start.lno ? vp->m_start.cno : 0,
+ !F_ISSET(vp, VM_LMODE) &&
+ lno == vp->m_stop.lno ? vp->m_stop.cno : len))
+ return (1);
+
+ if (++lno > vp->m_stop.lno)
+ break;
+ }
+
+ /*
+ * XXX
+ * I didn't create a new motion command when I added motion semantics
+ * for ~. While that's the correct way to do it, that choice would
+ * have required changes all over the vi directory for little gain.
+ * Instead, we pretend it's a yank command. Note, this means that we
+ * follow the cursor motion rules for yank commands, but that seems
+ * reasonable to me.
+ */
+ return (0);
+}
+
+/*
+ * ulcase --
+ * Change part of a line's case.
+ */
+static int
+ulcase(sp, lno, lp, len, scno, ecno)
+ SCR *sp;
+ recno_t lno;
+ CHAR_T *lp;
+ size_t len, scno, ecno;
+{
+ size_t blen;
+ int change, rval;
+ CHAR_T ch, *p, *t;
+ char *bp;
+
+ GET_SPACE_RET(sp, bp, blen, len);
+ memmove(bp, lp, len);
+
+ change = rval = 0;
+ for (p = bp + scno, t = bp + ecno + 1; p < t; ++p) {
+ ch = *(u_char *)p;
+ if (islower(ch)) {
+ *p = toupper(ch);
+ change = 1;
+ } else if (isupper(ch)) {
+ *p = tolower(ch);
+ change = 1;
+ }
+ }
+
+ if (change && db_set(sp, lno, bp, len))
+ rval = 1;
+
+ FREE_SPACE(sp, bp, blen);
+ return (rval);
+}
diff --git a/usr.bin/vi/vi/v_undo.c b/contrib/nvi/vi/v_undo.c
index 65dc715e189a..d04a8a18810b 100644
--- a/usr.bin/vi/vi/v_undo.c
+++ b/contrib/nvi/vi/v_undo.c
@@ -1,38 +1,16 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)v_undo.c 8.10 (Berkeley) 5/7/94";
+static const char sccsid[] = "@(#)v_undo.c 10.5 (Berkeley) 3/6/96";
#endif /* not lint */
#include <sys/types.h>
@@ -42,28 +20,23 @@ static char sccsid[] = "@(#)v_undo.c 8.10 (Berkeley) 5/7/94";
#include <bitstring.h>
#include <errno.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
+#include "../common/common.h"
#include "vi.h"
-#include "vcmd.h"
/*
* v_Undo -- U
* Undo changes to this line.
+ *
+ * PUBLIC: int v_Undo __P((SCR *, VICMD *));
*/
int
-v_Undo(sp, ep, vp)
+v_Undo(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
/*
* Historically, U reset the cursor to the first column in the line
@@ -84,22 +57,25 @@ v_Undo(sp, ep, vp)
* the line, so starting to replay the changes seems the best way to
* get to there.
*/
- F_SET(ep, F_UNDO);
- ep->lundo = BACKWARD;
+ F_SET(sp->ep, F_UNDO);
+ sp->ep->lundo = BACKWARD;
- return (log_setline(sp, ep));
+ return (log_setline(sp));
}
/*
* v_undo -- u
* Undo the last change.
+ *
+ * PUBLIC: int v_undo __P((SCR *, VICMD *));
*/
int
-v_undo(sp, ep, vp)
+v_undo(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
+ EXF *ep;
+
/* Set the command count. */
VIP(sp)->u_ccnt = sp->ccnt;
@@ -144,6 +120,7 @@ v_undo(sp, ep, vp)
* to completely match historic practice, we'd have to track users line
* changes, too. This isn't worth the effort.
*/
+ ep = sp->ep;
if (!F_ISSET(ep, F_UNDO)) {
F_SET(ep, F_UNDO);
ep->lundo = BACKWARD;
@@ -152,9 +129,9 @@ v_undo(sp, ep, vp)
switch (ep->lundo) {
case BACKWARD:
- return (log_backward(sp, ep, &vp->m_final));
+ return (log_backward(sp, &vp->m_final));
case FORWARD:
- return (log_forward(sp, ep, &vp->m_final));
+ return (log_forward(sp, &vp->m_final));
default:
abort();
}
diff --git a/contrib/nvi/vi/v_util.c b/contrib/nvi/vi/v_util.c
new file mode 100644
index 000000000000..c4c0daa901fd
--- /dev/null
+++ b/contrib/nvi/vi/v_util.c
@@ -0,0 +1,180 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_util.c 10.11 (Berkeley) 6/30/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_eof --
+ * Vi end-of-file error.
+ *
+ * PUBLIC: void v_eof __P((SCR *, MARK *));
+ */
+void
+v_eof(sp, mp)
+ SCR *sp;
+ MARK *mp;
+{
+ recno_t lno;
+
+ if (mp == NULL)
+ v_emsg(sp, NULL, VIM_EOF);
+ else {
+ if (db_last(sp, &lno))
+ return;
+ if (mp->lno >= lno)
+ v_emsg(sp, NULL, VIM_EOF);
+ else
+ msgq(sp, M_BERR, "195|Movement past the end-of-file");
+ }
+}
+
+/*
+ * v_eol --
+ * Vi end-of-line error.
+ *
+ * PUBLIC: void v_eol __P((SCR *, MARK *));
+ */
+void
+v_eol(sp, mp)
+ SCR *sp;
+ MARK *mp;
+{
+ size_t len;
+
+ if (mp == NULL)
+ v_emsg(sp, NULL, VIM_EOL);
+ else {
+ if (db_get(sp, mp->lno, DBG_FATAL, NULL, &len))
+ return;
+ if (mp->cno == len - 1)
+ v_emsg(sp, NULL, VIM_EOL);
+ else
+ msgq(sp, M_BERR, "196|Movement past the end-of-line");
+ }
+}
+
+/*
+ * v_nomove --
+ * Vi no cursor movement error.
+ *
+ * PUBLIC: void v_nomove __P((SCR *));
+ */
+void
+v_nomove(sp)
+ SCR *sp;
+{
+ msgq(sp, M_BERR, "197|No cursor movement made");
+}
+
+/*
+ * v_sof --
+ * Vi start-of-file error.
+ *
+ * PUBLIC: void v_sof __P((SCR *, MARK *));
+ */
+void
+v_sof(sp, mp)
+ SCR *sp;
+ MARK *mp;
+{
+ if (mp == NULL || mp->lno == 1)
+ msgq(sp, M_BERR, "198|Already at the beginning of the file");
+ else
+ msgq(sp, M_BERR, "199|Movement past the beginning of the file");
+}
+
+/*
+ * v_sol --
+ * Vi start-of-line error.
+ *
+ * PUBLIC: void v_sol __P((SCR *));
+ */
+void
+v_sol(sp)
+ SCR *sp;
+{
+ msgq(sp, M_BERR, "200|Already in the first column");
+}
+
+/*
+ * v_isempty --
+ * Return if the line contains nothing but white-space characters.
+ *
+ * PUBLIC: int v_isempty __P((char *, size_t));
+ */
+int
+v_isempty(p, len)
+ char *p;
+ size_t len;
+{
+ for (; len--; ++p)
+ if (!isblank(*p))
+ return (0);
+ return (1);
+}
+
+/*
+ * v_emsg --
+ * Display a few common vi messages.
+ *
+ * PUBLIC: void v_emsg __P((SCR *, char *, vim_t));
+ */
+void
+v_emsg(sp, p, which)
+ SCR *sp;
+ char *p;
+ vim_t which;
+{
+ switch (which) {
+ case VIM_COMBUF:
+ msgq(sp, M_ERR,
+ "201|Buffers should be specified before the command");
+ break;
+ case VIM_EMPTY:
+ msgq(sp, M_BERR, "209|The file is empty");
+ break;
+ case VIM_EOF:
+ msgq(sp, M_BERR, "202|Already at end-of-file");
+ break;
+ case VIM_EOL:
+ msgq(sp, M_BERR, "203|Already at end-of-line");
+ break;
+ case VIM_NOCOM:
+ case VIM_NOCOM_B:
+ msgq(sp,
+ which == VIM_NOCOM_B ? M_BERR : M_ERR,
+ "204|%s isn't a vi command", p);
+ break;
+ case VIM_WRESIZE:
+ msgq(sp, M_ERR, "Window resize interrupted text input mode");
+ break;
+ case VIM_USAGE:
+ msgq(sp, M_ERR, "205|Usage: %s", p);
+ break;
+ }
+}
diff --git a/usr.bin/vi/vi/v_word.c b/contrib/nvi/vi/v_word.c
index 7c53fe98fd67..e6e4a63c57e7 100644
--- a/usr.bin/vi/vi/v_word.c
+++ b/contrib/nvi/vi/v_word.c
@@ -1,38 +1,16 @@
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)v_word.c 8.21 (Berkeley) 7/27/94";
+static const char sccsid[] = "@(#)v_word.c 10.5 (Berkeley) 3/6/96";
#endif /* not lint */
#include <sys/types.h>
@@ -42,16 +20,10 @@ static char sccsid[] = "@(#)v_word.c 8.21 (Berkeley) 7/27/94";
#include <bitstring.h>
#include <ctype.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
+#include "../common/common.h"
#include "vi.h"
-#include "vcmd.h"
/*
* There are two types of "words". Bigwords are easy -- groups of anything
@@ -94,34 +66,36 @@ static char sccsid[] = "@(#)v_word.c 8.21 (Berkeley) 7/27/94";
enum which {BIGWORD, LITTLEWORD};
-static int bword __P((SCR *, EXF *, VICMDARG *, enum which));
-static int eword __P((SCR *, EXF *, VICMDARG *, enum which));
-static int fword __P((SCR *, EXF *, VICMDARG *, enum which));
+static int bword __P((SCR *, VICMD *, enum which));
+static int eword __P((SCR *, VICMD *, enum which));
+static int fword __P((SCR *, VICMD *, enum which));
/*
* v_wordW -- [count]W
* Move forward a bigword at a time.
+ *
+ * PUBLIC: int v_wordW __P((SCR *, VICMD *));
*/
int
-v_wordW(sp, ep, vp)
+v_wordW(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
- return (fword(sp, ep, vp, BIGWORD));
+ return (fword(sp, vp, BIGWORD));
}
/*
* v_wordw -- [count]w
* Move forward a word at a time.
+ *
+ * PUBLIC: int v_wordw __P((SCR *, VICMD *));
*/
int
-v_wordw(sp, ep, vp)
+v_wordw(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
- return (fword(sp, ep, vp, LITTLEWORD));
+ return (fword(sp, vp, LITTLEWORD));
}
/*
@@ -129,10 +103,9 @@ v_wordw(sp, ep, vp)
* Move forward by words.
*/
static int
-fword(sp, ep, vp, type)
+fword(sp, vp, type)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
enum which type;
{
enum { INWORD, NOTWORD } state;
@@ -142,7 +115,7 @@ fword(sp, ep, vp, type)
cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
cs.cs_lno = vp->m_start.lno;
cs.cs_cno = vp->m_start.cno;
- if (cs_init(sp, ep, &cs))
+ if (cs_init(sp, &cs))
return (1);
/*
@@ -153,16 +126,16 @@ fword(sp, ep, vp, type)
* don't move off the end of the line.
*/
if (cs.cs_flags == CS_EMP || cs.cs_flags == 0 && isblank(cs.cs_ch)) {
- if (cs.cs_flags != CS_EMP && cnt == 1) {
- if (F_ISSET(vp, VC_C))
+ if (ISMOTION(vp) && cs.cs_flags != CS_EMP && cnt == 1) {
+ if (ISCMD(vp->rkp, 'c'))
return (0);
- if (F_ISSET(vp, VC_D | VC_Y)) {
- if (cs_fspace(sp, ep, &cs))
+ if (ISCMD(vp->rkp, 'd') || ISCMD(vp->rkp, 'y')) {
+ if (cs_fspace(sp, &cs))
return (1);
goto ret;
}
}
- if (cs_fblank(sp, ep, &cs))
+ if (cs_fblank(sp, &cs))
return (1);
--cnt;
}
@@ -176,7 +149,7 @@ fword(sp, ep, vp, type)
if (type == BIGWORD)
while (cnt--) {
for (;;) {
- if (cs_next(sp, ep, &cs))
+ if (cs_next(sp, &cs))
return (1);
if (cs.cs_flags == CS_EOF)
goto ret;
@@ -190,14 +163,15 @@ fword(sp, ep, vp, type)
* of the line regardless.
*/
if (cnt == 0 && ISMOTION(vp)) {
- if (F_ISSET(vp, VC_D | VC_Y) &&
- cs_fspace(sp, ep, &cs))
+ if ((ISCMD(vp->rkp, 'd') ||
+ ISCMD(vp->rkp, 'y')) &&
+ cs_fspace(sp, &cs))
return (1);
break;
}
/* Eat whitespace characters. */
- if (cs_fblank(sp, ep, &cs))
+ if (cs_fblank(sp, &cs))
return (1);
if (cs.cs_flags == CS_EOF)
goto ret;
@@ -207,7 +181,7 @@ fword(sp, ep, vp, type)
state = cs.cs_flags == 0 &&
inword(cs.cs_ch) ? INWORD : NOTWORD;
for (;;) {
- if (cs_next(sp, ep, &cs))
+ if (cs_next(sp, &cs))
return (1);
if (cs.cs_flags == CS_EOF)
goto ret;
@@ -222,15 +196,16 @@ fword(sp, ep, vp, type)
}
/* See comment above. */
if (cnt == 0 && ISMOTION(vp)) {
- if (F_ISSET(vp, VC_D | VC_Y) &&
- cs_fspace(sp, ep, &cs))
+ if ((ISCMD(vp->rkp, 'd') ||
+ ISCMD(vp->rkp, 'y')) &&
+ cs_fspace(sp, &cs))
return (1);
break;
}
/* Eat whitespace characters. */
if (cs.cs_flags != 0 || isblank(cs.cs_ch))
- if (cs_fblank(sp, ep, &cs))
+ if (cs_fblank(sp, &cs))
return (1);
if (cs.cs_flags == CS_EOF)
goto ret;
@@ -244,7 +219,7 @@ fword(sp, ep, vp, type)
*/
ret: if (!ISMOTION(vp) &&
cs.cs_lno == vp->m_start.lno && cs.cs_cno == vp->m_start.cno) {
- v_eof(sp, ep, &vp->m_start);
+ v_eof(sp, &vp->m_start);
return (1);
}
@@ -255,8 +230,8 @@ ret: if (!ISMOTION(vp) &&
--vp->m_stop.cno;
/*
- * Non-motion commands move to the end of the range. VC_D
- * and VC_Y stay at the start. Ignore VC_C and VC_DEF.
+ * Non-motion commands move to the end of the range. Delete
+ * and yank stay at the start, ignore others.
*/
vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
return (0);
@@ -265,27 +240,29 @@ ret: if (!ISMOTION(vp) &&
/*
* v_wordE -- [count]E
* Move forward to the end of the bigword.
+ *
+ * PUBLIC: int v_wordE __P((SCR *, VICMD *));
*/
int
-v_wordE(sp, ep, vp)
+v_wordE(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
- return (eword(sp, ep, vp, BIGWORD));
+ return (eword(sp, vp, BIGWORD));
}
/*
* v_worde -- [count]e
* Move forward to the end of the word.
+ *
+ * PUBLIC: int v_worde __P((SCR *, VICMD *));
*/
int
-v_worde(sp, ep, vp)
+v_worde(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
- return (eword(sp, ep, vp, LITTLEWORD));
+ return (eword(sp, vp, LITTLEWORD));
}
/*
@@ -293,10 +270,9 @@ v_worde(sp, ep, vp)
* Move forward to the end of the word.
*/
static int
-eword(sp, ep, vp, type)
+eword(sp, vp, type)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
enum which type;
{
enum { INWORD, NOTWORD } state;
@@ -306,7 +282,7 @@ eword(sp, ep, vp, type)
cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
cs.cs_lno = vp->m_start.lno;
cs.cs_cno = vp->m_start.cno;
- if (cs_init(sp, ep, &cs))
+ if (cs_init(sp, &cs))
return (1);
/*
@@ -316,12 +292,12 @@ eword(sp, ep, vp, type)
* past the current one, it sets word "state" for the 'e' command.
*/
if (cs.cs_flags == 0 && !isblank(cs.cs_ch)) {
- if (cs_next(sp, ep, &cs))
+ if (cs_next(sp, &cs))
return (1);
if (cs.cs_flags == 0 && !isblank(cs.cs_ch))
goto start;
}
- if (cs_fblank(sp, ep, &cs))
+ if (cs_fblank(sp, &cs))
return (1);
/*
@@ -333,7 +309,7 @@ eword(sp, ep, vp, type)
start: if (type == BIGWORD)
while (cnt--) {
for (;;) {
- if (cs_next(sp, ep, &cs))
+ if (cs_next(sp, &cs))
return (1);
if (cs.cs_flags == CS_EOF)
goto ret;
@@ -346,13 +322,13 @@ start: if (type == BIGWORD)
* to the end of the previous word.
*/
if (cnt == 0) {
- if (cs.cs_flags == 0 && cs_prev(sp, ep, &cs))
+ if (cs.cs_flags == 0 && cs_prev(sp, &cs))
return (1);
break;
}
/* Eat whitespace characters. */
- if (cs_fblank(sp, ep, &cs))
+ if (cs_fblank(sp, &cs))
return (1);
if (cs.cs_flags == CS_EOF)
goto ret;
@@ -362,7 +338,7 @@ start: if (type == BIGWORD)
state = cs.cs_flags == 0 &&
inword(cs.cs_ch) ? INWORD : NOTWORD;
for (;;) {
- if (cs_next(sp, ep, &cs))
+ if (cs_next(sp, &cs))
return (1);
if (cs.cs_flags == CS_EOF)
goto ret;
@@ -377,14 +353,14 @@ start: if (type == BIGWORD)
}
/* See comment above. */
if (cnt == 0) {
- if (cs.cs_flags == 0 && cs_prev(sp, ep, &cs))
+ if (cs.cs_flags == 0 && cs_prev(sp, &cs))
return (1);
break;
}
/* Eat whitespace characters. */
if (cs.cs_flags != 0 || isblank(cs.cs_ch))
- if (cs_fblank(sp, ep, &cs))
+ if (cs_fblank(sp, &cs))
return (1);
if (cs.cs_flags == CS_EOF)
goto ret;
@@ -398,7 +374,7 @@ start: if (type == BIGWORD)
*/
ret: if (!ISMOTION(vp) &&
cs.cs_lno == vp->m_start.lno && cs.cs_cno == vp->m_start.cno) {
- v_eof(sp, ep, &vp->m_start);
+ v_eof(sp, &vp->m_start);
return (1);
}
@@ -407,8 +383,8 @@ ret: if (!ISMOTION(vp) &&
vp->m_stop.cno = cs.cs_cno;
/*
- * Non-motion commands move to the end of the range. VC_D
- * and VC_Y stay at the start. Ignore VC_C and VC_DEF.
+ * Non-motion commands move to the end of the range.
+ * Delete and yank stay at the start, ignore others.
*/
vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
return (0);
@@ -417,27 +393,29 @@ ret: if (!ISMOTION(vp) &&
/*
* v_WordB -- [count]B
* Move backward a bigword at a time.
+ *
+ * PUBLIC: int v_wordB __P((SCR *, VICMD *));
*/
int
-v_wordB(sp, ep, vp)
+v_wordB(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
- return (bword(sp, ep, vp, BIGWORD));
+ return (bword(sp, vp, BIGWORD));
}
/*
* v_wordb -- [count]b
* Move backward a word at a time.
+ *
+ * PUBLIC: int v_wordb __P((SCR *, VICMD *));
*/
int
-v_wordb(sp, ep, vp)
+v_wordb(sp, vp)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
{
- return (bword(sp, ep, vp, LITTLEWORD));
+ return (bword(sp, vp, LITTLEWORD));
}
/*
@@ -445,10 +423,9 @@ v_wordb(sp, ep, vp)
* Move backward by words.
*/
static int
-bword(sp, ep, vp, type)
+bword(sp, vp, type)
SCR *sp;
- EXF *ep;
- VICMDARG *vp;
+ VICMD *vp;
enum which type;
{
enum { INWORD, NOTWORD } state;
@@ -458,7 +435,7 @@ bword(sp, ep, vp, type)
cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
cs.cs_lno = vp->m_start.lno;
cs.cs_cno = vp->m_start.cno;
- if (cs_init(sp, ep, &cs))
+ if (cs_init(sp, &cs))
return (1);
/*
@@ -469,12 +446,12 @@ bword(sp, ep, vp, type)
* 'b' command.
*/
if (cs.cs_flags == 0 && !isblank(cs.cs_ch)) {
- if (cs_prev(sp, ep, &cs))
+ if (cs_prev(sp, &cs))
return (1);
if (cs.cs_flags == 0 && !isblank(cs.cs_ch))
goto start;
}
- if (cs_bblank(sp, ep, &cs))
+ if (cs_bblank(sp, &cs))
return (1);
/*
@@ -486,7 +463,7 @@ bword(sp, ep, vp, type)
start: if (type == BIGWORD)
while (cnt--) {
for (;;) {
- if (cs_prev(sp, ep, &cs))
+ if (cs_prev(sp, &cs))
return (1);
if (cs.cs_flags == CS_SOF)
goto ret;
@@ -499,13 +476,13 @@ start: if (type == BIGWORD)
* one to the end of the next word.
*/
if (cnt == 0) {
- if (cs.cs_flags == 0 && cs_next(sp, ep, &cs))
+ if (cs.cs_flags == 0 && cs_next(sp, &cs))
return (1);
break;
}
/* Eat whitespace characters. */
- if (cs_bblank(sp, ep, &cs))
+ if (cs_bblank(sp, &cs))
return (1);
if (cs.cs_flags == CS_SOF)
goto ret;
@@ -515,7 +492,7 @@ start: if (type == BIGWORD)
state = cs.cs_flags == 0 &&
inword(cs.cs_ch) ? INWORD : NOTWORD;
for (;;) {
- if (cs_prev(sp, ep, &cs))
+ if (cs_prev(sp, &cs))
return (1);
if (cs.cs_flags == CS_SOF)
goto ret;
@@ -530,14 +507,14 @@ start: if (type == BIGWORD)
}
/* See comment above. */
if (cnt == 0) {
- if (cs.cs_flags == 0 && cs_next(sp, ep, &cs))
+ if (cs.cs_flags == 0 && cs_next(sp, &cs))
return (1);
break;
}
/* Eat whitespace characters. */
if (cs.cs_flags != 0 || isblank(cs.cs_ch))
- if (cs_bblank(sp, ep, &cs))
+ if (cs_bblank(sp, &cs))
return (1);
if (cs.cs_flags == CS_SOF)
goto ret;
diff --git a/contrib/nvi/vi/v_xchar.c b/contrib/nvi/vi/v_xchar.c
new file mode 100644
index 000000000000..15f155ffed33
--- /dev/null
+++ b/contrib/nvi/vi/v_xchar.c
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_xchar.c 10.9 (Berkeley) 10/23/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_xchar -- [buffer] [count]x
+ * Deletes the character(s) on which the cursor sits.
+ *
+ * PUBLIC: int v_xchar __P((SCR *, VICMD *));
+ */
+int
+v_xchar(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ size_t len;
+ int isempty;
+
+ if (db_eget(sp, vp->m_start.lno, NULL, &len, &isempty)) {
+ if (isempty)
+ goto nodel;
+ return (1);
+ }
+ if (len == 0) {
+nodel: msgq(sp, M_BERR, "206|No characters to delete");
+ return (1);
+ }
+
+ /*
+ * Delete from the cursor toward the end of line, w/o moving the
+ * cursor.
+ *
+ * !!!
+ * Note, "2x" at EOL isn't the same as "xx" because the left movement
+ * of the cursor as part of the 'x' command isn't taken into account.
+ * Historically correct.
+ */
+ if (F_ISSET(vp, VC_C1SET))
+ vp->m_stop.cno += vp->count - 1;
+ if (vp->m_stop.cno >= len - 1) {
+ vp->m_stop.cno = len - 1;
+ vp->m_final.cno = vp->m_start.cno ? vp->m_start.cno - 1 : 0;
+ } else
+ vp->m_final.cno = vp->m_start.cno;
+
+ if (cut(sp,
+ F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
+ &vp->m_start, &vp->m_stop, 0))
+ return (1);
+ return (del(sp, &vp->m_start, &vp->m_stop, 0));
+}
+
+/*
+ * v_Xchar -- [buffer] [count]X
+ * Deletes the character(s) immediately before the current cursor
+ * position.
+ *
+ * PUBLIC: int v_Xchar __P((SCR *, VICMD *));
+ */
+int
+v_Xchar(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ u_long cnt;
+
+ if (vp->m_start.cno == 0) {
+ v_sol(sp);
+ return (1);
+ }
+
+ cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
+ if (cnt >= vp->m_start.cno)
+ vp->m_start.cno = 0;
+ else
+ vp->m_start.cno -= cnt;
+ --vp->m_stop.cno;
+ vp->m_final.cno = vp->m_start.cno;
+
+ if (cut(sp,
+ F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
+ &vp->m_start, &vp->m_stop, 0))
+ return (1);
+ return (del(sp, &vp->m_start, &vp->m_stop, 0));
+}
diff --git a/contrib/nvi/vi/v_yank.c b/contrib/nvi/vi/v_yank.c
new file mode 100644
index 000000000000..4708f1996774
--- /dev/null
+++ b/contrib/nvi/vi/v_yank.c
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_yank.c 10.9 (Berkeley) 5/19/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_yank -- [buffer][count]y[count][motion]
+ * [buffer][count]Y
+ * Yank text (or lines of text) into a cut buffer.
+ *
+ * !!!
+ * Historic vi moved the cursor to the from MARK if it was before the current
+ * cursor and on a different line, e.g., "yk" moves the cursor but "yj" and
+ * "yl" do not. Unfortunately, it's too late to change this now. Matching
+ * the historic semantics isn't easy. The line number was always changed and
+ * column movement was usually relative. However, "y'a" moved the cursor to
+ * the first non-blank of the line marked by a, while "y`a" moved the cursor
+ * to the line and column marked by a. Hopefully, the motion component code
+ * got it right... Unlike delete, we make no adjustments here.
+ *
+ * PUBLIC: int v_yank __P((SCR *, VICMD *));
+ */
+int
+v_yank(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ size_t len;
+
+ if (cut(sp,
+ F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL, &vp->m_start,
+ &vp->m_stop, F_ISSET(vp, VM_LMODE) ? CUT_LINEMODE : 0))
+ return (1);
+ sp->rptlines[L_YANKED] += (vp->m_stop.lno - vp->m_start.lno) + 1;
+
+ /*
+ * One special correction, in case we've deleted the current line or
+ * character. We check it here instead of checking in every command
+ * that can be a motion component.
+ */
+ if (db_get(sp, vp->m_final.lno, DBG_FATAL, NULL, &len))
+ return (1);
+
+ /*
+ * !!!
+ * Cursor movements, other than those caused by a line mode command
+ * moving to another line, historically reset the relative position.
+ *
+ * This currently matches the check made in v_delete(), I'm hoping
+ * that they should be consistent...
+ */
+ if (!F_ISSET(vp, VM_LMODE)) {
+ F_CLR(vp, VM_RCM_MASK);
+ F_SET(vp, VM_RCM_SET);
+
+ /* Make sure the set cursor position exists. */
+ if (vp->m_final.cno >= len)
+ vp->m_final.cno = len ? len - 1 : 0;
+ }
+ return (0);
+}
diff --git a/contrib/nvi/vi/v_z.c b/contrib/nvi/vi/v_z.c
new file mode 100644
index 000000000000..5f02ddf5a10b
--- /dev/null
+++ b/contrib/nvi/vi/v_z.c
@@ -0,0 +1,149 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_z.c 10.10 (Berkeley) 5/16/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_z -- [count]z[count][-.+^<CR>]
+ * Move the screen.
+ *
+ * PUBLIC: int v_z __P((SCR *, VICMD *));
+ */
+int
+v_z(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ recno_t lno;
+ u_int value;
+
+ /*
+ * The first count is the line to use. If the value doesn't
+ * exist, use the last line.
+ */
+ if (F_ISSET(vp, VC_C1SET)) {
+ lno = vp->count;
+ if (!db_exist(sp, lno) && db_last(sp, &lno))
+ return (1);
+ } else
+ lno = vp->m_start.lno;
+
+ /* Set default return cursor line. */
+ vp->m_final.lno = lno;
+ vp->m_final.cno = vp->m_start.cno;
+
+ /*
+ * The second count is the displayed window size, i.e. the 'z' command
+ * is another way to get artificially small windows. Note, you can't
+ * grow beyond the size of the window.
+ *
+ * !!!
+ * A window size of 0 was historically allowed, and simply ignored.
+ * This could be much more simply done by modifying the value of the
+ * O_WINDOW option, but that's not how it worked historically.
+ */
+ if (F_ISSET(vp, VC_C2SET) && vp->count2 != 0) {
+ if (vp->count2 > O_VAL(sp, O_WINDOW))
+ vp->count2 = O_VAL(sp, O_WINDOW);
+ if (vs_crel(sp, vp->count2))
+ return (1);
+ }
+
+ switch (vp->character) {
+ case '-': /* Put the line at the bottom. */
+ if (vs_sm_fill(sp, lno, P_BOTTOM))
+ return (1);
+ break;
+ case '.': /* Put the line in the middle. */
+ if (vs_sm_fill(sp, lno, P_MIDDLE))
+ return (1);
+ break;
+ case '+':
+ /*
+ * If the user specified a line number, put that line at the
+ * top and move the cursor to it. Otherwise, scroll forward
+ * a screen from the current screen.
+ */
+ if (F_ISSET(vp, VC_C1SET)) {
+ if (vs_sm_fill(sp, lno, P_TOP))
+ return (1);
+ if (vs_sm_position(sp, &vp->m_final, 0, P_TOP))
+ return (1);
+ } else
+ if (vs_sm_scroll(sp, &vp->m_final, sp->t_rows, Z_PLUS))
+ return (1);
+ break;
+ case '^':
+ /*
+ * If the user specified a line number, put that line at the
+ * bottom, move the cursor to it, and then display the screen
+ * before that one. Otherwise, scroll backward a screen from
+ * the current screen.
+ *
+ * !!!
+ * Note, we match the off-by-one characteristics of historic
+ * vi, here.
+ */
+ if (F_ISSET(vp, VC_C1SET)) {
+ if (vs_sm_fill(sp, lno, P_BOTTOM))
+ return (1);
+ if (vs_sm_position(sp, &vp->m_final, 0, P_TOP))
+ return (1);
+ if (vs_sm_fill(sp, vp->m_final.lno, P_BOTTOM))
+ return (1);
+ } else
+ if (vs_sm_scroll(sp, &vp->m_final, sp->t_rows, Z_CARAT))
+ return (1);
+ break;
+ default: /* Put the line at the top for <cr>. */
+ value = KEY_VAL(sp, vp->character);
+ if (value != K_CR && value != K_NL) {
+ v_emsg(sp, vp->kp->usage, VIM_USAGE);
+ return (1);
+ }
+ if (vs_sm_fill(sp, lno, P_TOP))
+ return (1);
+ break;
+ }
+ return (0);
+}
+
+/*
+ * vs_crel --
+ * Change the relative size of the current screen.
+ *
+ * PUBLIC: int vs_crel __P((SCR *, long));
+ */
+int
+vs_crel(sp, count)
+ SCR *sp;
+ long count;
+{
+ sp->t_minrows = sp->t_rows = count;
+ if (sp->t_rows > sp->rows - 1)
+ sp->t_minrows = sp->t_rows = sp->rows - 1;
+ TMAP = HMAP + (sp->t_rows - 1);
+ F_SET(sp, SC_SCR_REDRAW);
+ return (0);
+}
diff --git a/contrib/nvi/vi/v_zexit.c b/contrib/nvi/vi/v_zexit.c
new file mode 100644
index 000000000000..3e454caa5bea
--- /dev/null
+++ b/contrib/nvi/vi/v_zexit.c
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_zexit.c 10.6 (Berkeley) 4/27/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_zexit -- ZZ
+ * Save the file and exit.
+ *
+ * PUBLIC: int v_zexit __P((SCR *, VICMD *));
+ */
+int
+v_zexit(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ /* Write back any modifications. */
+ if (F_ISSET(sp->ep, F_MODIFIED) &&
+ file_write(sp, NULL, NULL, NULL, FS_ALL))
+ return (1);
+
+ /* Check to make sure it's not a temporary file. */
+ if (file_m3(sp, 0))
+ return (1);
+
+ /* Check for more files to edit. */
+ if (ex_ncheck(sp, 0))
+ return (1);
+
+ F_SET(sp, SC_EXIT);
+ return (0);
+}
diff --git a/contrib/nvi/vi/vi.c b/contrib/nvi/vi/vi.c
new file mode 100644
index 000000000000..d20f7f284e39
--- /dev/null
+++ b/contrib/nvi/vi/vi.c
@@ -0,0 +1,1251 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)vi.c 10.57 (Berkeley) 10/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+typedef enum {
+ GC_ERR, GC_ERR_NOFLUSH, GC_EVENT, GC_FATAL, GC_INTERRUPT, GC_OK
+} gcret_t;
+
+static VIKEYS const
+ *v_alias __P((SCR *, VICMD *, VIKEYS const *));
+static gcret_t v_cmd __P((SCR *, VICMD *, VICMD *, VICMD *, int *, int *));
+static int v_count __P((SCR *, ARG_CHAR_T, u_long *));
+static void v_dtoh __P((SCR *));
+static int v_init __P((SCR *));
+static gcret_t v_key __P((SCR *, int, EVENT *, u_int32_t));
+static int v_keyword __P((SCR *));
+static int v_motion __P((SCR *, VICMD *, VICMD *, int *));
+
+#if defined(DEBUG) && defined(COMLOG)
+static void v_comlog __P((SCR *, VICMD *));
+#endif
+
+/*
+ * Side-effect:
+ * The dot structure can be set by the underlying vi functions,
+ * see v_Put() and v_put().
+ */
+#define DOT (&VIP(sp)->sdot)
+#define DOTMOTION (&VIP(sp)->sdotmotion)
+
+/*
+ * vi --
+ * Main vi command loop.
+ *
+ * PUBLIC: int vi __P((SCR **));
+ */
+int
+vi(spp)
+ SCR **spp;
+{
+ GS *gp;
+ MARK abs;
+ SCR *next, *sp;
+ VICMD cmd, *vp;
+ VI_PRIVATE *vip;
+ int comcount, mapped, rval;
+
+ /* Get the first screen. */
+ sp = *spp;
+ gp = sp->gp;
+
+ /* Initialize the command structure. */
+ vp = &cmd;
+ memset(vp, 0, sizeof(VICMD));
+
+ /* Reset strange attraction. */
+ F_SET(vp, VM_RCM_SET);
+
+ /* Initialize the vi screen. */
+ if (v_init(sp))
+ return (1);
+
+ /* Set the focus. */
+ (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+
+ for (vip = VIP(sp), rval = 0;;) {
+ /* Resolve messages. */
+ if (!MAPPED_KEYS_WAITING(sp) && vs_resolve(sp, NULL, 0))
+ goto ret;
+
+ /*
+ * If not skipping a refresh, return to command mode and
+ * refresh the screen.
+ */
+ if (F_ISSET(vip, VIP_S_REFRESH))
+ F_CLR(vip, VIP_S_REFRESH);
+ else {
+ sp->showmode = SM_COMMAND;
+ if (vs_refresh(sp, 0))
+ goto ret;
+ }
+
+ /* Set the new favorite position. */
+ if (F_ISSET(vp, VM_RCM_SET | VM_RCM_SETFNB | VM_RCM_SETNNB)) {
+ F_CLR(vip, VIP_RCM_LAST);
+ (void)vs_column(sp, &sp->rcm);
+ }
+
+ /*
+ * If not currently in a map, log the cursor position,
+ * and set a flag so that this command can become the
+ * DOT command.
+ */
+ if (MAPPED_KEYS_WAITING(sp))
+ mapped = 1;
+ else {
+ if (log_cursor(sp))
+ goto err;
+ mapped = 0;
+ }
+
+ /*
+ * There may be an ex command waiting, and we returned here
+ * only because we exited a screen or file. In this case,
+ * we simply go back into the ex parser.
+ */
+ if (EXCMD_RUNNING(gp)) {
+ vp->kp = &vikeys[':'];
+ goto ex_continue;
+ }
+
+ /* Refresh the command structure. */
+ memset(vp, 0, sizeof(VICMD));
+
+ /*
+ * We get a command, which may or may not have an associated
+ * motion. If it does, we get it too, calling its underlying
+ * function to get the resulting mark. We then call the
+ * command setting the cursor to the resulting mark.
+ *
+ * !!!
+ * Vi historically flushed mapped characters on error, but
+ * entering extra <escape> characters at the beginning of
+ * a map wasn't considered an error -- in fact, users would
+ * put leading <escape> characters in maps to clean up vi
+ * state before the map was interpreted. Beauty!
+ */
+ switch (v_cmd(sp, DOT, vp, NULL, &comcount, &mapped)) {
+ case GC_ERR:
+ goto err;
+ case GC_ERR_NOFLUSH:
+ goto gc_err_noflush;
+ case GC_EVENT:
+ if (v_event_exec(sp, vp))
+ goto err;
+ goto gc_event;
+ case GC_FATAL:
+ goto ret;
+ case GC_INTERRUPT:
+ goto intr;
+ case GC_OK:
+ break;
+ }
+
+ /* Check for security setting. */
+ if (F_ISSET(vp->kp, V_SECURE) && O_ISSET(sp, O_SECURE)) {
+ ex_emsg(sp, KEY_NAME(sp, vp->key), EXM_SECURE);
+ goto err;
+ }
+
+ /*
+ * Historical practice: if a dot command gets a new count,
+ * any motion component goes away, i.e. "d3w2." deletes a
+ * total of 5 words.
+ */
+ if (F_ISSET(vp, VC_ISDOT) && comcount)
+ DOTMOTION->count = 1;
+
+ /* Copy the key flags into the local structure. */
+ F_SET(vp, vp->kp->flags);
+
+ /* Prepare to set the previous context. */
+ if (F_ISSET(vp, V_ABS | V_ABS_C | V_ABS_L)) {
+ abs.lno = sp->lno;
+ abs.cno = sp->cno;
+ }
+
+ /*
+ * Set the three cursor locations to the current cursor. The
+ * underlying routines don't bother if the cursor doesn't move.
+ * This also handles line commands (e.g. Y) defaulting to the
+ * current line.
+ */
+ vp->m_start.lno = vp->m_stop.lno = vp->m_final.lno = sp->lno;
+ vp->m_start.cno = vp->m_stop.cno = vp->m_final.cno = sp->cno;
+
+ /*
+ * Do any required motion; v_motion sets the from MARK and the
+ * line mode flag, as well as the VM_RCM flags.
+ */
+ if (F_ISSET(vp, V_MOTION) &&
+ v_motion(sp, DOTMOTION, vp, &mapped)) {
+ if (INTERRUPTED(sp))
+ goto intr;
+ goto err;
+ }
+
+ /*
+ * If a count is set and the command is line oriented, set the
+ * to MARK here relative to the cursor/from MARK. This is for
+ * commands that take both counts and motions, i.e. "4yy" and
+ * "y%". As there's no way the command can know which the user
+ * did, we have to do it here. (There are commands that are
+ * line oriented and that take counts ("#G", "#H"), for which
+ * this calculation is either completely meaningless or wrong.
+ * Each command must validate the value for itself.
+ */
+ if (F_ISSET(vp, VC_C1SET) && F_ISSET(vp, VM_LMODE))
+ vp->m_stop.lno += vp->count - 1;
+
+ /* Increment the command count. */
+ ++sp->ccnt;
+
+#if defined(DEBUG) && defined(COMLOG)
+ v_comlog(sp, vp);
+#endif
+ /* Call the function. */
+ex_continue: if (vp->kp->func(sp, vp))
+ goto err;
+gc_event:
+#ifdef DEBUG
+ /* Make sure no function left the temporary space locked. */
+ if (F_ISSET(gp, G_TMP_INUSE)) {
+ F_CLR(gp, G_TMP_INUSE);
+ msgq(sp, M_ERR,
+ "232|vi: temporary buffer not released");
+ }
+#endif
+ /*
+ * If we're exiting this screen, move to the next one, or, if
+ * there aren't any more, return to the main editor loop. The
+ * ordering is careful, don't discard the contents of sp until
+ * the end.
+ */
+ if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) {
+ if (file_end(sp, NULL, F_ISSET(sp, SC_EXIT_FORCE)))
+ goto ret;
+ if (vs_discard(sp, &next))
+ goto ret;
+ if (next == NULL && vs_swap(sp, &next, NULL))
+ goto ret;
+ *spp = next;
+ if (screen_end(sp))
+ goto ret;
+ if (next == NULL)
+ break;
+
+ /* Switch screens, change focus. */
+ sp = next;
+ vip = VIP(sp);
+ (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+
+ /* Don't trust the cursor. */
+ F_SET(vip, VIP_CUR_INVALID);
+
+ continue;
+ }
+
+ /*
+ * Set the dot command structure.
+ *
+ * !!!
+ * Historically, commands which used mapped keys did not
+ * set the dot command, with the exception of the text
+ * input commands.
+ */
+ if (F_ISSET(vp, V_DOT) && !mapped) {
+ *DOT = cmd;
+ F_SET(DOT, VC_ISDOT);
+
+ /*
+ * If a count was supplied for both the command and
+ * its motion, the count was used only for the motion.
+ * Turn the count back on for the dot structure.
+ */
+ if (F_ISSET(vp, VC_C1RESET))
+ F_SET(DOT, VC_C1SET);
+
+ /* VM flags aren't retained. */
+ F_CLR(DOT, VM_COMMASK | VM_RCM_MASK);
+ }
+
+ /*
+ * Some vi row movements are "attracted" to the last position
+ * set, i.e. the VM_RCM commands are moths to the VM_RCM_SET
+ * commands' candle. If the movement is to the EOL the vi
+ * command handles it. If it's to the beginning, we handle it
+ * here.
+ *
+ * Note, some commands (e.g. _, ^) don't set the VM_RCM_SETFNB
+ * flag, but do the work themselves. The reason is that they
+ * have to modify the column in case they're being used as a
+ * motion component. Other similar commands (e.g. +, -) don't
+ * have to modify the column because they are always line mode
+ * operations when used as motions, so the column number isn't
+ * of any interest.
+ *
+ * Does this totally violate the screen and editor layering?
+ * You betcha. As they say, if you think you understand it,
+ * you don't.
+ */
+ switch (F_ISSET(vp, VM_RCM_MASK)) {
+ case 0:
+ case VM_RCM_SET:
+ break;
+ case VM_RCM:
+ vp->m_final.cno = vs_rcm(sp,
+ vp->m_final.lno, F_ISSET(vip, VIP_RCM_LAST));
+ break;
+ case VM_RCM_SETLAST:
+ F_SET(vip, VIP_RCM_LAST);
+ break;
+ case VM_RCM_SETFNB:
+ vp->m_final.cno = 0;
+ /* FALLTHROUGH */
+ case VM_RCM_SETNNB:
+ if (nonblank(sp, vp->m_final.lno, &vp->m_final.cno))
+ goto err;
+ break;
+ default:
+ abort();
+ }
+
+ /* Update the cursor. */
+ sp->lno = vp->m_final.lno;
+ sp->cno = vp->m_final.cno;
+
+ /*
+ * Set the absolute mark -- set even if a tags or similar
+ * command, since the tag may be moving to the same file.
+ */
+ if ((F_ISSET(vp, V_ABS) ||
+ F_ISSET(vp, V_ABS_L) && sp->lno != abs.lno ||
+ F_ISSET(vp, V_ABS_C) &&
+ (sp->lno != abs.lno || sp->cno != abs.cno)) &&
+ mark_set(sp, ABSMARK1, &abs, 1))
+ goto err;
+
+ if (0) {
+err: if (v_event_flush(sp, CH_MAPPED))
+ msgq(sp, M_BERR,
+ "110|Vi command failed: mapped keys discarded");
+ }
+
+ /*
+ * Check and clear interrupts. There's an obvious race, but
+ * it's not worth fixing.
+ */
+gc_err_noflush: if (INTERRUPTED(sp)) {
+intr: CLR_INTERRUPT(sp);
+ if (v_event_flush(sp, CH_MAPPED))
+ msgq(sp, M_ERR,
+ "231|Interrupted: mapped keys discarded");
+ else
+ msgq(sp, M_ERR, "236|Interrupted");
+ }
+
+ /* If the last command switched screens, update. */
+ if (F_ISSET(sp, SC_SSWITCH)) {
+ F_CLR(sp, SC_SSWITCH);
+
+ /*
+ * If the current screen is still displayed, it will
+ * need a new status line.
+ */
+ F_SET(sp, SC_STATUS);
+
+ /* Switch screens, change focus. */
+ sp = sp->nextdisp;
+ vip = VIP(sp);
+ (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+
+ /* Don't trust the cursor. */
+ F_SET(vip, VIP_CUR_INVALID);
+
+ /* Refresh so we can display messages. */
+ if (vs_refresh(sp, 1))
+ return (1);
+ }
+
+ /* If the last command switched files, change focus. */
+ if (F_ISSET(sp, SC_FSWITCH)) {
+ F_CLR(sp, SC_FSWITCH);
+ (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
+ }
+
+ /* If leaving vi, return to the main editor loop. */
+ if (F_ISSET(gp, G_SRESTART) || F_ISSET(sp, SC_EX)) {
+ *spp = sp;
+ v_dtoh(sp);
+ break;
+ }
+ }
+ if (0)
+ret: rval = 1;
+ return (rval);
+}
+
+#define KEY(key, ec_flags) { \
+ if ((gcret = v_key(sp, 0, &ev, ec_flags)) != GC_OK) \
+ return (gcret); \
+ if (ev.e_value == K_ESCAPE) \
+ goto esc; \
+ if (F_ISSET(&ev.e_ch, CH_MAPPED)) \
+ *mappedp = 1; \
+ key = ev.e_c; \
+}
+
+/*
+ * The O_TILDEOP option makes the ~ command take a motion instead
+ * of a straight count. This is the replacement structure we use
+ * instead of the one currently in the VIKEYS table.
+ *
+ * XXX
+ * This should probably be deleted -- it's not all that useful, and
+ * we get help messages wrong.
+ */
+VIKEYS const tmotion = {
+ v_mulcase, V_CNT|V_DOT|V_MOTION|VM_RCM_SET,
+ "[count]~[count]motion",
+ " ~ change case to motion"
+};
+
+/*
+ * v_cmd --
+ *
+ * The command structure for vi is less complex than ex (and don't think
+ * I'm not grateful!) The command syntax is:
+ *
+ * [count] [buffer] [count] key [[motion] | [buffer] [character]]
+ *
+ * and there are several special cases. The motion value is itself a vi
+ * command, with the syntax:
+ *
+ * [count] key [character]
+ */
+static gcret_t
+v_cmd(sp, dp, vp, ismotion, comcountp, mappedp)
+ SCR *sp;
+ VICMD *dp, *vp;
+ VICMD *ismotion; /* Previous key if getting motion component. */
+ int *comcountp, *mappedp;
+{
+ enum { COMMANDMODE, ISPARTIAL, NOTPARTIAL } cpart;
+ EVENT ev;
+ VIKEYS const *kp;
+ gcret_t gcret;
+ u_int flags;
+ CHAR_T key;
+ char *s;
+
+ /*
+ * Get a key.
+ *
+ * <escape> cancels partial commands, i.e. a command where at least
+ * one non-numeric character has been entered. Otherwise, it beeps
+ * the terminal.
+ *
+ * !!!
+ * POSIX 1003.2-1992 explicitly disallows cancelling commands where
+ * all that's been entered is a number, requiring that the terminal
+ * be alerted.
+ */
+ cpart = ismotion == NULL ? COMMANDMODE : ISPARTIAL;
+ if ((gcret =
+ v_key(sp, ismotion == NULL, &ev, EC_MAPCOMMAND)) != GC_OK) {
+ if (gcret == GC_EVENT)
+ vp->ev = ev;
+ return (gcret);
+ }
+ if (ev.e_value == K_ESCAPE)
+ goto esc;
+ if (F_ISSET(&ev.e_ch, CH_MAPPED))
+ *mappedp = 1;
+ key = ev.e_c;
+
+ if (ismotion == NULL)
+ cpart = NOTPARTIAL;
+
+ /* Pick up optional buffer. */
+ if (key == '"') {
+ cpart = ISPARTIAL;
+ if (ismotion != NULL) {
+ v_emsg(sp, NULL, VIM_COMBUF);
+ return (GC_ERR);
+ }
+ KEY(vp->buffer, 0);
+ F_SET(vp, VC_BUFFER);
+
+ KEY(key, EC_MAPCOMMAND);
+ }
+
+ /*
+ * Pick up optional count, where a leading 0 is not a count,
+ * it's a command.
+ */
+ if (isdigit(key) && key != '0') {
+ if (v_count(sp, key, &vp->count))
+ return (GC_ERR);
+ F_SET(vp, VC_C1SET);
+ *comcountp = 1;
+
+ KEY(key, EC_MAPCOMMAND);
+ } else
+ *comcountp = 0;
+
+ /* Pick up optional buffer. */
+ if (key == '"') {
+ cpart = ISPARTIAL;
+ if (F_ISSET(vp, VC_BUFFER)) {
+ msgq(sp, M_ERR, "234|Only one buffer may be specified");
+ return (GC_ERR);
+ }
+ if (ismotion != NULL) {
+ v_emsg(sp, NULL, VIM_COMBUF);
+ return (GC_ERR);
+ }
+ KEY(vp->buffer, 0);
+ F_SET(vp, VC_BUFFER);
+
+ KEY(key, EC_MAPCOMMAND);
+ }
+
+ /* Check for an OOB command key. */
+ cpart = ISPARTIAL;
+ if (key > MAXVIKEY) {
+ v_emsg(sp, KEY_NAME(sp, key), VIM_NOCOM);
+ return (GC_ERR);
+ }
+ kp = &vikeys[vp->key = key];
+
+ /*
+ * !!!
+ * Historically, D accepted and then ignored a count. Match it.
+ */
+ if (vp->key == 'D' && F_ISSET(vp, VC_C1SET)) {
+ *comcountp = 0;
+ vp->count = 0;
+ F_CLR(vp, VC_C1SET);
+ }
+
+ /* Check for command aliases. */
+ if (kp->func == NULL && (kp = v_alias(sp, vp, kp)) == NULL)
+ return (GC_ERR);
+
+ /* The tildeop option makes the ~ command take a motion. */
+ if (key == '~' && O_ISSET(sp, O_TILDEOP))
+ kp = &tmotion;
+
+ vp->kp = kp;
+
+ /*
+ * Find the command. The only legal command with no underlying
+ * function is dot. It's historic practice that <escape> doesn't
+ * just erase the preceding number, it beeps the terminal as well.
+ * It's a common problem, so just beep the terminal unless verbose
+ * was set.
+ */
+ if (kp->func == NULL) {
+ if (key != '.') {
+ v_emsg(sp, KEY_NAME(sp, key),
+ ev.e_value == K_ESCAPE ? VIM_NOCOM_B : VIM_NOCOM);
+ return (GC_ERR);
+ }
+
+ /* If called for a motion command, stop now. */
+ if (dp == NULL)
+ goto usage;
+
+ /*
+ * !!!
+ * If a '.' is immediately entered after an undo command, we
+ * replay the log instead of redoing the last command. This
+ * is necessary because 'u' can't set the dot command -- see
+ * vi/v_undo.c:v_undo for details.
+ */
+ if (VIP(sp)->u_ccnt == sp->ccnt) {
+ vp->kp = &vikeys['u'];
+ F_SET(vp, VC_ISDOT);
+ return (GC_OK);
+ }
+
+ /* Otherwise, a repeatable command must have been executed. */
+ if (!F_ISSET(dp, VC_ISDOT)) {
+ msgq(sp, M_ERR, "208|No command to repeat");
+ return (GC_ERR);
+ }
+
+ /* Set new count/buffer, if any, and return. */
+ if (F_ISSET(vp, VC_C1SET)) {
+ F_SET(dp, VC_C1SET);
+ dp->count = vp->count;
+ }
+ if (F_ISSET(vp, VC_BUFFER))
+ dp->buffer = vp->buffer;
+
+ *vp = *dp;
+ return (GC_OK);
+ }
+
+ /* Set the flags based on the command flags. */
+ flags = kp->flags;
+
+ /* Check for illegal count. */
+ if (F_ISSET(vp, VC_C1SET) && !LF_ISSET(V_CNT))
+ goto usage;
+
+ /* Illegal motion command. */
+ if (ismotion == NULL) {
+ /* Illegal buffer. */
+ if (!LF_ISSET(V_OBUF) && F_ISSET(vp, VC_BUFFER))
+ goto usage;
+
+ /* Required buffer. */
+ if (LF_ISSET(V_RBUF)) {
+ KEY(vp->buffer, 0);
+ F_SET(vp, VC_BUFFER);
+ }
+ }
+
+ /*
+ * Special case: '[', ']' and 'Z' commands. Doesn't the fact that
+ * the *single* characters don't mean anything but the *doubled*
+ * characters do, just frost your shorts?
+ */
+ if (vp->key == '[' || vp->key == ']' || vp->key == 'Z') {
+ /*
+ * Historically, half entered [[, ]] or Z commands weren't
+ * cancelled by <escape>, the terminal was beeped instead.
+ * POSIX.2-1992 probably didn't notice, and requires that
+ * they be cancelled instead of beeping. Seems fine to me.
+ *
+ * Don't set the EC_MAPCOMMAND flag, apparently ] is a popular
+ * vi meta-character, and we don't want the user to wait while
+ * we time out a possible mapping. This *appears* to match
+ * historic vi practice, but with mapping characters, you Just
+ * Never Know.
+ */
+ KEY(key, 0);
+
+ if (vp->key != key) {
+usage: if (ismotion == NULL)
+ s = kp->usage;
+ else if (ismotion->key == '~' && O_ISSET(sp, O_TILDEOP))
+ s = tmotion.usage;
+ else
+ s = vikeys[ismotion->key].usage;
+ v_emsg(sp, s, VIM_USAGE);
+ return (GC_ERR);
+ }
+ }
+ /* Special case: 'z' command. */
+ if (vp->key == 'z') {
+ KEY(vp->character, 0);
+ if (isdigit(vp->character)) {
+ if (v_count(sp, vp->character, &vp->count2))
+ return (GC_ERR);
+ F_SET(vp, VC_C2SET);
+ KEY(vp->character, 0);
+ }
+ }
+
+ /*
+ * Commands that have motion components can be doubled to
+ * imply the current line.
+ */
+ if (ismotion != NULL && ismotion->key != key && !LF_ISSET(V_MOVE)) {
+ msgq(sp, M_ERR, "210|%s may not be used as a motion command",
+ KEY_NAME(sp, key));
+ return (GC_ERR);
+ }
+
+ /* Required character. */
+ if (LF_ISSET(V_CHAR))
+ KEY(vp->character, 0);
+
+ /* Get any associated cursor word. */
+ if (F_ISSET(kp, V_KEYW) && v_keyword(sp))
+ return (GC_ERR);
+
+ return (GC_OK);
+
+esc: switch (cpart) {
+ case COMMANDMODE:
+ msgq(sp, M_BERR, "211|Already in command mode");
+ return (GC_ERR_NOFLUSH);
+ case ISPARTIAL:
+ break;
+ case NOTPARTIAL:
+ (void)sp->gp->scr_bell(sp);
+ break;
+ }
+ return (GC_ERR);
+}
+
+/*
+ * v_motion --
+ *
+ * Get resulting motion mark.
+ */
+static int
+v_motion(sp, dm, vp, mappedp)
+ SCR *sp;
+ VICMD *dm, *vp;
+ int *mappedp;
+{
+ VICMD motion;
+ size_t len;
+ u_long cnt;
+ u_int flags;
+ int tilde_reset, notused;
+
+ /*
+ * If '.' command, use the dot motion, else get the motion command.
+ * Clear any line motion flags, the subsequent motion isn't always
+ * the same, i.e. "/aaa" may or may not be a line motion.
+ */
+ if (F_ISSET(vp, VC_ISDOT)) {
+ motion = *dm;
+ F_SET(&motion, VC_ISDOT);
+ F_CLR(&motion, VM_COMMASK);
+ } else {
+ memset(&motion, 0, sizeof(VICMD));
+ if (v_cmd(sp, NULL, &motion, vp, &notused, mappedp) != GC_OK)
+ return (1);
+ }
+
+ /*
+ * A count may be provided both to the command and to the motion, in
+ * which case the count is multiplicative. For example, "3y4y" is the
+ * same as "12yy". This count is provided to the motion command and
+ * not to the regular function.
+ */
+ cnt = motion.count = F_ISSET(&motion, VC_C1SET) ? motion.count : 1;
+ if (F_ISSET(vp, VC_C1SET)) {
+ motion.count *= vp->count;
+ F_SET(&motion, VC_C1SET);
+
+ /*
+ * Set flags to restore the original values of the command
+ * structure so dot commands can change the count values,
+ * e.g. "2dw" "3." deletes a total of five words.
+ */
+ F_CLR(vp, VC_C1SET);
+ F_SET(vp, VC_C1RESET);
+ }
+
+ /*
+ * Some commands can be repeated to indicate the current line. In
+ * this case, or if the command is a "line command", set the flags
+ * appropriately. If not a doubled command, run the function to get
+ * the resulting mark.
+ */
+ if (vp->key == motion.key) {
+ F_SET(vp, VM_LDOUBLE | VM_LMODE);
+
+ /* Set the origin of the command. */
+ vp->m_start.lno = sp->lno;
+ vp->m_start.cno = 0;
+
+ /*
+ * Set the end of the command.
+ *
+ * If the current line is missing, i.e. the file is empty,
+ * historic vi permitted a "cc" or "!!" command to insert
+ * text.
+ */
+ vp->m_stop.lno = sp->lno + motion.count - 1;
+ if (db_get(sp, vp->m_stop.lno, 0, NULL, &len)) {
+ if (vp->m_stop.lno != 1 ||
+ vp->key != 'c' && vp->key != '!') {
+ v_emsg(sp, NULL, VIM_EMPTY);
+ return (1);
+ }
+ vp->m_stop.cno = 0;
+ } else
+ vp->m_stop.cno = len ? len - 1 : 0;
+ } else {
+ /*
+ * Motion commands change the underlying movement (*snarl*).
+ * For example, "l" is illegal at the end of a line, but "dl"
+ * is not. Set flags so the function knows the situation.
+ */
+ motion.rkp = vp->kp;
+
+ /*
+ * XXX
+ * Use yank instead of creating a new motion command, it's a
+ * lot easier for now.
+ */
+ if (vp->kp == &tmotion) {
+ tilde_reset = 1;
+ vp->kp = &vikeys['y'];
+ } else
+ tilde_reset = 0;
+
+ /*
+ * Copy the key flags into the local structure, except for the
+ * RCM flags -- the motion command will set the RCM flags in
+ * the vp structure if necessary. This means that the motion
+ * command is expected to determine where the cursor ends up!
+ * However, we save off the current RCM mask and restore it if
+ * it no RCM flags are set by the motion command, with a small
+ * modification.
+ *
+ * We replace the VM_RCM_SET flag with the VM_RCM flag. This
+ * is so that cursor movement doesn't set the relative position
+ * unless the motion command explicitly specified it. This
+ * appears to match historic practice, but I've never been able
+ * to develop a hard-and-fast rule.
+ */
+ flags = F_ISSET(vp, VM_RCM_MASK);
+ if (LF_ISSET(VM_RCM_SET)) {
+ LF_SET(VM_RCM);
+ LF_CLR(VM_RCM_SET);
+ }
+ F_CLR(vp, VM_RCM_MASK);
+ F_SET(&motion, motion.kp->flags & ~VM_RCM_MASK);
+
+ /*
+ * Set the three cursor locations to the current cursor. This
+ * permits commands like 'j' and 'k', that are line oriented
+ * motions and have special cursor suck semantics when they are
+ * used as standalone commands, to ignore column positioning.
+ */
+ motion.m_final.lno =
+ motion.m_stop.lno = motion.m_start.lno = sp->lno;
+ motion.m_final.cno =
+ motion.m_stop.cno = motion.m_start.cno = sp->cno;
+
+ /* Run the function. */
+ if ((motion.kp->func)(sp, &motion))
+ return (1);
+
+ /*
+ * If the current line is missing, i.e. the file is empty,
+ * historic vi allowed "c<motion>" or "!<motion>" to insert
+ * text. Otherwise fail -- most motion commands will have
+ * already failed, but some, e.g. G, succeed in empty files.
+ */
+ if (!db_exist(sp, vp->m_stop.lno)) {
+ if (vp->m_stop.lno != 1 ||
+ vp->key != 'c' && vp->key != '!') {
+ v_emsg(sp, NULL, VIM_EMPTY);
+ return (1);
+ }
+ vp->m_stop.cno = 0;
+ }
+
+ /*
+ * XXX
+ * See above.
+ */
+ if (tilde_reset)
+ vp->kp = &tmotion;
+
+ /*
+ * Copy cut buffer, line mode and cursor position information
+ * from the motion command structure, i.e. anything that the
+ * motion command can set for us. The commands can flag the
+ * movement as a line motion (see v_sentence) as well as set
+ * the VM_RCM_* flags explicitly.
+ */
+ F_SET(vp, F_ISSET(&motion, VM_COMMASK | VM_RCM_MASK));
+
+ /*
+ * If the motion command set no relative motion flags, use
+ * the (slightly) modified previous values.
+ */
+ if (!F_ISSET(vp, VM_RCM_MASK))
+ F_SET(vp, flags);
+
+ /*
+ * Commands can change behaviors based on the motion command
+ * used, for example, the ! command repeated the last bang
+ * command if N or n was used as the motion.
+ */
+ vp->rkp = motion.kp;
+
+ /*
+ * Motion commands can reset all of the cursor information.
+ * If the motion is in the reverse direction, switch the
+ * from and to MARK's so that it's in a forward direction.
+ * Motions are from the from MARK to the to MARK (inclusive).
+ */
+ if (motion.m_start.lno > motion.m_stop.lno ||
+ motion.m_start.lno == motion.m_stop.lno &&
+ motion.m_start.cno > motion.m_stop.cno) {
+ vp->m_start = motion.m_stop;
+ vp->m_stop = motion.m_start;
+ } else {
+ vp->m_start = motion.m_start;
+ vp->m_stop = motion.m_stop;
+ }
+ vp->m_final = motion.m_final;
+ }
+
+ /*
+ * If the command sets dot, save the motion structure. The motion
+ * count was changed above and needs to be reset, that's why this
+ * is done here, and not in the calling routine.
+ */
+ if (F_ISSET(vp->kp, V_DOT)) {
+ *dm = motion;
+ dm->count = cnt;
+ }
+ return (0);
+}
+
+/*
+ * v_init --
+ * Initialize the vi screen.
+ */
+static int
+v_init(sp)
+ SCR *sp;
+{
+ GS *gp;
+ VI_PRIVATE *vip;
+
+ gp = sp->gp;
+ vip = VIP(sp);
+
+ /* Switch into vi. */
+ if (gp->scr_screen(sp, SC_VI))
+ return (1);
+ (void)gp->scr_attr(sp, SA_ALTERNATE, 1);
+
+ F_CLR(sp, SC_EX | SC_SCR_EX);
+ F_SET(sp, SC_VI);
+
+ /*
+ * Initialize screen values.
+ *
+ * Small windows: see vs_refresh(), section 6a.
+ *
+ * Setup:
+ * t_minrows is the minimum rows to display
+ * t_maxrows is the maximum rows to display (rows - 1)
+ * t_rows is the rows currently being displayed
+ */
+ sp->rows = vip->srows = O_VAL(sp, O_LINES);
+ sp->cols = O_VAL(sp, O_COLUMNS);
+ sp->t_rows = sp->t_minrows = O_VAL(sp, O_WINDOW);
+ if (sp->rows != 1) {
+ if (sp->t_rows > sp->rows - 1) {
+ sp->t_minrows = sp->t_rows = sp->rows - 1;
+ msgq(sp, M_INFO,
+ "214|Windows option value is too large, max is %u",
+ sp->t_rows);
+ }
+ sp->t_maxrows = sp->rows - 1;
+ } else
+ sp->t_maxrows = 1;
+ sp->woff = 0;
+
+ /* Create a screen map. */
+ CALLOC_RET(sp, HMAP, SMAP *, SIZE_HMAP(sp), sizeof(SMAP));
+ TMAP = HMAP + (sp->t_rows - 1);
+ HMAP->lno = sp->lno;
+ HMAP->coff = 0;
+ HMAP->soff = 1;
+
+ /*
+ * Fill the screen map from scratch -- try and center the line. That
+ * way if we're starting with a file we've seen before, we'll put the
+ * line in the middle, otherwise, it won't work and we'll end up with
+ * the line at the top.
+ */
+ F_SET(sp, SC_SCR_REFORMAT | SC_SCR_CENTER);
+
+ /* Invalidate the cursor. */
+ F_SET(vip, VIP_CUR_INVALID);
+
+ /* Paint the screen image from scratch. */
+ F_SET(vip, VIP_N_EX_PAINT);
+
+ return (0);
+}
+
+/*
+ * v_dtoh --
+ * Move all but the current screen to the hidden queue.
+ */
+static void
+v_dtoh(sp)
+ SCR *sp;
+{
+ GS *gp;
+ SCR *tsp;
+ int hidden;
+
+ /* Move all screens to the hidden queue, tossing screen maps. */
+ for (hidden = 0, gp = sp->gp;
+ (tsp = gp->dq.cqh_first) != (void *)&gp->dq; ++hidden) {
+ if (_HMAP(tsp) != NULL) {
+ free(_HMAP(tsp));
+ _HMAP(tsp) = NULL;
+ }
+ CIRCLEQ_REMOVE(&gp->dq, tsp, q);
+ CIRCLEQ_INSERT_TAIL(&gp->hq, tsp, q);
+ }
+
+ /* Move current screen back to the display queue. */
+ CIRCLEQ_REMOVE(&gp->hq, sp, q);
+ CIRCLEQ_INSERT_TAIL(&gp->dq, sp, q);
+
+ /*
+ * XXX
+ * Don't bother internationalizing this message, it's going to
+ * go away as soon as we have one-line screens. --TK
+ */
+ if (hidden > 1)
+ msgq(sp, M_INFO,
+ "%d screens backgrounded; use :display to list them",
+ hidden - 1);
+}
+
+/*
+ * v_keyword --
+ * Get the word (or non-word) the cursor is on.
+ */
+static int
+v_keyword(sp)
+ SCR *sp;
+{
+ VI_PRIVATE *vip;
+ size_t beg, end, len;
+ int moved, state;
+ char *p;
+
+ if (db_get(sp, sp->lno, DBG_FATAL, &p, &len))
+ return (1);
+
+ /*
+ * !!!
+ * Historically, tag commands skipped over any leading whitespace
+ * characters. Make this true in general when using cursor words.
+ * If movement, getting a cursor word implies moving the cursor to
+ * its beginning. Refresh now.
+ *
+ * !!!
+ * Find the beginning/end of the keyword. Keywords are currently
+ * used for cursor-word searching and for tags. Historical vi
+ * only used the word in a tag search from the cursor to the end
+ * of the word, i.e. if the cursor was on the 'b' in " abc ", the
+ * tag was "bc". For consistency, we make cursor word searches
+ * follow the same rule.
+ */
+ for (moved = 0,
+ beg = sp->cno; beg < len && isspace(p[beg]); moved = 1, ++beg);
+ if (beg >= len) {
+ msgq(sp, M_BERR, "212|Cursor not in a word");
+ return (1);
+ }
+ if (moved) {
+ sp->cno = beg;
+ (void)vs_refresh(sp, 0);
+ }
+
+ /* Find the end of the word. */
+ for (state = inword(p[beg]),
+ end = beg; ++end < len && state == inword(p[end]););
+
+ vip = VIP(sp);
+ len = (end - beg);
+ BINC_RET(sp, vip->keyw, vip->klen, len);
+ memmove(vip->keyw, p + beg, len);
+ vip->keyw[len] = '\0'; /* XXX */
+ return (0);
+}
+
+/*
+ * v_alias --
+ * Check for a command alias.
+ */
+static VIKEYS const *
+v_alias(sp, vp, kp)
+ SCR *sp;
+ VICMD *vp;
+ VIKEYS const *kp;
+{
+ CHAR_T push;
+
+ switch (vp->key) {
+ case 'C': /* C -> c$ */
+ push = '$';
+ vp->key = 'c';
+ break;
+ case 'D': /* D -> d$ */
+ push = '$';
+ vp->key = 'd';
+ break;
+ case 'S': /* S -> c_ */
+ push = '_';
+ vp->key = 'c';
+ break;
+ case 'Y': /* Y -> y_ */
+ push = '_';
+ vp->key = 'y';
+ break;
+ default:
+ return (kp);
+ }
+ return (v_event_push(sp,
+ NULL, &push, 1, CH_NOMAP | CH_QUOTED) ? NULL : &vikeys[vp->key]);
+}
+
+/*
+ * v_count --
+ * Return the next count.
+ */
+static int
+v_count(sp, fkey, countp)
+ SCR *sp;
+ ARG_CHAR_T fkey;
+ u_long *countp;
+{
+ EVENT ev;
+ u_long count, tc;
+
+ ev.e_c = fkey;
+ count = tc = 0;
+ do {
+ /*
+ * XXX
+ * Assume that overflow results in a smaller number.
+ */
+ tc = count * 10 + ev.e_c - '0';
+ if (count > tc) {
+ /* Toss to the next non-digit. */
+ do {
+ if (v_key(sp, 0, &ev,
+ EC_MAPCOMMAND | EC_MAPNODIGIT) != GC_OK)
+ return (1);
+ } while (isdigit(ev.e_c));
+ msgq(sp, M_ERR,
+ "235|Number larger than %lu", ULONG_MAX);
+ return (1);
+ }
+ count = tc;
+ if (v_key(sp, 0, &ev, EC_MAPCOMMAND | EC_MAPNODIGIT) != GC_OK)
+ return (1);
+ } while (isdigit(ev.e_c));
+ *countp = count;
+ return (0);
+}
+
+/*
+ * v_key --
+ * Return the next event.
+ */
+static gcret_t
+v_key(sp, command_events, evp, ec_flags)
+ SCR *sp;
+ int command_events;
+ EVENT *evp;
+ u_int32_t ec_flags;
+{
+ u_int32_t quote;
+
+ for (quote = 0;;) {
+ if (v_event_get(sp, evp, 0, ec_flags | quote))
+ return (GC_FATAL);
+ quote = 0;
+
+ switch (evp->e_event) {
+ case E_CHARACTER:
+ /*
+ * !!!
+ * Historically, ^V was ignored in the command stream,
+ * although it had a useful side-effect of interrupting
+ * mappings. Adding a quoting bit to the call probably
+ * extends historic practice, but it feels right.
+ */
+ if (evp->e_value == K_VLNEXT) {
+ quote = EC_QUOTED;
+ break;
+ }
+ return (GC_OK);
+ case E_ERR:
+ case E_EOF:
+ return (GC_FATAL);
+ case E_INTERRUPT:
+ /*
+ * !!!
+ * Historically, vi beeped on command level interrupts.
+ *
+ * Historically, vi exited to ex mode if no file was
+ * named on the command line, and two interrupts were
+ * generated in a row. (Just figured you might want
+ * to know that.)
+ */
+ (void)sp->gp->scr_bell(sp);
+ return (GC_INTERRUPT);
+ case E_REPAINT:
+ if (vs_repaint(sp, evp))
+ return (GC_FATAL);
+ break;
+ case E_WRESIZE:
+ return (GC_ERR);
+ case E_QUIT:
+ case E_WRITE:
+ if (command_events)
+ return (GC_EVENT);
+ /* FALLTHROUGH */
+ default:
+ v_event_err(sp, evp);
+ return (GC_ERR);
+ }
+ }
+ /* NOTREACHED */
+}
+
+#if defined(DEBUG) && defined(COMLOG)
+/*
+ * v_comlog --
+ * Log the contents of the command structure.
+ */
+static void
+v_comlog(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ TRACE(sp, "vcmd: %c", vp->key);
+ if (F_ISSET(vp, VC_BUFFER))
+ TRACE(sp, " buffer: %c", vp->buffer);
+ if (F_ISSET(vp, VC_C1SET))
+ TRACE(sp, " c1: %lu", vp->count);
+ if (F_ISSET(vp, VC_C2SET))
+ TRACE(sp, " c2: %lu", vp->count2);
+ TRACE(sp, " flags: 0x%x\n", vp->flags);
+}
+#endif
diff --git a/contrib/nvi/vi/vi.h b/contrib/nvi/vi/vi.h
new file mode 100644
index 000000000000..bede3a651817
--- /dev/null
+++ b/contrib/nvi/vi/vi.h
@@ -0,0 +1,377 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ *
+ * @(#)vi.h 10.19 (Berkeley) 6/30/96
+ */
+
+/* Definition of a vi "word". */
+#define inword(ch) (isalnum(ch) || (ch) == '_')
+
+typedef struct _vikeys VIKEYS;
+
+/* Structure passed around to functions implementing vi commands. */
+typedef struct _vicmd {
+ CHAR_T key; /* Command key. */
+ CHAR_T buffer; /* Buffer. */
+ CHAR_T character; /* Character. */
+ u_long count; /* Count. */
+ u_long count2; /* Second count (only used by z). */
+ EVENT ev; /* Associated event. */
+
+#define ISCMD(p, key) ((p) == &vikeys[key])
+ VIKEYS const *kp; /* Command/Motion VIKEYS entry. */
+#define ISMOTION(vp) (vp->rkp != NULL && F_ISSET(vp->rkp, V_MOTION))
+ VIKEYS const *rkp; /* Related C/M VIKEYS entry. */
+
+ /*
+ * Historic vi allowed "dl" when the cursor was on the last column,
+ * deleting the last character, and similarly allowed "dw" when
+ * the cursor was on the last column of the file. It didn't allow
+ * "dh" when the cursor was on column 1, although these cases are
+ * not strictly analogous. The point is that some movements would
+ * succeed if they were associated with a motion command, and fail
+ * otherwise. This is part of the off-by-1 schizophrenia that
+ * plagued vi. Other examples are that "dfb" deleted everything
+ * up to and including the next 'b' character, while "d/b" deleted
+ * everything up to the next 'b' character. While this implementation
+ * regularizes the interface to the extent possible, there are many
+ * special cases that can't be fixed. The special cases are handled
+ * by setting flags per command so that the underlying command and
+ * motion routines know what's really going on.
+ *
+ * The VM_* flags are set in the vikeys array and by the underlying
+ * functions (motion component or command) as well. For this reason,
+ * the flags in the VICMD and VIKEYS structures live in the same name
+ * space.
+ */
+#define VM_CMDFAILED 0x00000001 /* Command failed. */
+#define VM_CUTREQ 0x00000002 /* Always cut into numeric buffers. */
+#define VM_LDOUBLE 0x00000004 /* Doubled command for line mode. */
+#define VM_LMODE 0x00000008 /* Motion is line oriented. */
+#define VM_COMMASK 0x0000000f /* Mask for VM flags. */
+
+ /*
+ * The VM_RCM_* flags are single usage, i.e. if you set one, you have
+ * to clear the others.
+ */
+#define VM_RCM 0x00000010 /* Use relative cursor movment (RCM). */
+#define VM_RCM_SET 0x00000020 /* RCM: set to current position. */
+#define VM_RCM_SETFNB 0x00000040 /* RCM: set to first non-blank (FNB). */
+#define VM_RCM_SETLAST 0x00000080 /* RCM: set to last character. */
+#define VM_RCM_SETNNB 0x00000100 /* RCM: set to next non-blank. */
+#define VM_RCM_MASK 0x000001f0 /* Mask for RCM flags. */
+
+ /* Flags for the underlying function. */
+#define VC_BUFFER 0x00000200 /* The buffer was set. */
+#define VC_C1RESET 0x00000400 /* Reset C1SET flag for dot commands. */
+#define VC_C1SET 0x00000800 /* Count 1 was set. */
+#define VC_C2SET 0x00001000 /* Count 2 was set. */
+#define VC_ISDOT 0x00002000 /* Command was the dot command. */
+ u_int32_t flags;
+
+ /*
+ * There are four cursor locations that we worry about: the initial
+ * cursor position, the start of the range, the end of the range,
+ * and the final cursor position. The initial cursor position and
+ * the start of the range are both m_start, and are always the same.
+ * All locations are initialized to the starting cursor position by
+ * the main vi routines, and the underlying functions depend on this.
+ *
+ * Commands that can be motion components set the end of the range
+ * cursor position, m_stop. All commands must set the ending cursor
+ * position, m_final. The reason that m_stop isn't the same as m_final
+ * is that there are situations where the final position of the cursor
+ * is outside of the cut/delete range (e.g. 'd[[' from the first column
+ * of a line). The final cursor position often varies based on the
+ * direction of the movement, as well as the command. The only special
+ * case that the delete code handles is that it will make adjustments
+ * if the final cursor position is deleted.
+ *
+ * The reason for all of this is that the historic vi semantics were
+ * defined command-by-command. Every function has to roll its own
+ * starting and stopping positions, and adjust them if it's being used
+ * as a motion component. The general rules are as follows:
+ *
+ * 1: If not a motion component, the final cursor is at the end
+ * of the range.
+ * 2: If moving backward in the file, delete and yank move the
+ * final cursor to the end of the range.
+ * 3: If moving forward in the file, delete and yank leave the
+ * final cursor at the start of the range.
+ *
+ * Usually, if moving backward in the file and it's a motion component,
+ * the starting cursor is decremented by a single character (or, in a
+ * few cases, to the end of the previous line) so that the starting
+ * cursor character isn't cut or deleted. No cursor adjustment is
+ * needed for moving forward, because the cut/delete routines handle
+ * m_stop inclusively, i.e. the last character in the range is cut or
+ * deleted. This makes cutting to the EOF/EOL reasonable.
+ *
+ * The 'c', '<', '>', and '!' commands are special cases. We ignore
+ * the final cursor position for all of them: for 'c', the text input
+ * routines set the cursor to the last character inserted; for '<',
+ * '>' and '!', the underlying ex commands that do the operation will
+ * set the cursor for us, usually to something related to the first
+ * <nonblank>.
+ */
+ MARK m_start; /* mark: initial cursor, range start. */
+ MARK m_stop; /* mark: range end. */
+ MARK m_final; /* mark: final cursor position. */
+} VICMD;
+
+/* Vi command table structure. */
+struct _vikeys { /* Underlying function. */
+ int (*func) __P((SCR *, VICMD *));
+#define V_ABS 0x00004000 /* Absolute movement, set '' mark. */
+#define V_ABS_C 0x00008000 /* V_ABS: if the line/column changed. */
+#define V_ABS_L 0x00010000 /* V_ABS: if the line changed. */
+#define V_CHAR 0x00020000 /* Character (required, trailing). */
+#define V_CNT 0x00040000 /* Count (optional, leading). */
+#define V_DOT 0x00080000 /* On success, sets dot command. */
+#define V_KEYW 0x00100000 /* Cursor referenced word. */
+#define V_MOTION 0x00200000 /* Motion (required, trailing). */
+#define V_MOVE 0x00400000 /* Command defines movement. */
+#define V_OBUF 0x00800000 /* Buffer (optional, leading). */
+#define V_RBUF 0x01000000 /* Buffer (required, trailing). */
+#define V_SECURE 0x02000000 /* Permission denied if O_SECURE set. */
+ u_int32_t flags;
+ char *usage; /* Usage line. */
+ char *help; /* Help line. */
+};
+#define MAXVIKEY 126 /* List of vi commands. */
+extern VIKEYS const vikeys[MAXVIKEY + 1];
+extern VIKEYS const tmotion; /* XXX Hacked ~ command. */
+
+/* Character stream structure, prototypes. */
+typedef struct _vcs {
+ recno_t cs_lno; /* Line. */
+ size_t cs_cno; /* Column. */
+ CHAR_T *cs_bp; /* Buffer. */
+ size_t cs_len; /* Length. */
+ CHAR_T cs_ch; /* Character. */
+#define CS_EMP 1 /* Empty line. */
+#define CS_EOF 2 /* End-of-file. */
+#define CS_EOL 3 /* End-of-line. */
+#define CS_SOF 4 /* Start-of-file. */
+ int cs_flags; /* Return flags. */
+} VCS;
+
+int cs_bblank __P((SCR *, VCS *));
+int cs_fblank __P((SCR *, VCS *));
+int cs_fspace __P((SCR *, VCS *));
+int cs_init __P((SCR *, VCS *));
+int cs_next __P((SCR *, VCS *));
+int cs_prev __P((SCR *, VCS *));
+
+/*
+ * We use a single "window" for each set of vi screens. The model would be
+ * simpler with two windows (one for the text, and one for the modeline)
+ * because scrolling the text window down would work correctly then, not
+ * affecting the mode line. As it is we have to play games to make it look
+ * right. The reason for this choice is that it would be difficult for
+ * curses to optimize the movement, i.e. detect that the downward scroll
+ * isn't going to change the modeline, set the scrolling region on the
+ * terminal and only scroll the first part of the text window.
+ *
+ * Structure for mapping lines to the screen. An SMAP is an array, with one
+ * structure element per screen line, which holds information describing the
+ * physical line which is displayed in the screen line. The first two fields
+ * (lno and off) are all that are necessary to describe a line. The rest of
+ * the information is useful to keep information from being re-calculated.
+ *
+ * The SMAP always has an entry for each line of the physical screen, plus a
+ * slot for the colon command line, so there is room to add any screen into
+ * another one at screen exit.
+ *
+ * Lno is the line number. If doing the historic vi long line folding, off
+ * is the screen offset into the line. For example, the pair 2:1 would be
+ * the first screen of line 2, and 2:2 would be the second. In the case of
+ * long lines, the screen map will tend to be staggered, e.g., 1:1, 1:2, 1:3,
+ * 2:1, 3:1, etc. If doing left-right scrolling, the off field is the screen
+ * column offset into the lines, and can take on any value, as it's adjusted
+ * by the user set value O_SIDESCROLL.
+ */
+typedef struct _smap {
+ recno_t lno; /* 1-N: Physical file line number. */
+ size_t coff; /* 0-N: Column offset in the line. */
+ size_t soff; /* 1-N: Screen offset in the line. */
+
+ /* vs_line() cache information. */
+ size_t c_sboff; /* 0-N: offset of first character byte. */
+ size_t c_eboff; /* 0-N: offset of last character byte. */
+ u_int8_t c_scoff; /* 0-N: offset into the first character. */
+ u_int8_t c_eclen; /* 1-N: columns from the last character. */
+ u_int8_t c_ecsize; /* 1-N: size of the last character. */
+} SMAP;
+ /* Macros to flush/test cached information. */
+#define SMAP_CACHE(smp) ((smp)->c_ecsize != 0)
+#define SMAP_FLUSH(smp) ((smp)->c_ecsize = 0)
+
+ /* Character search information. */
+typedef enum { CNOTSET, FSEARCH, fSEARCH, TSEARCH, tSEARCH } cdir_t;
+
+typedef enum { AB_NOTSET, AB_NOTWORD, AB_INWORD } abb_t;
+typedef enum { Q_NOTSET, Q_BNEXT, Q_BTHIS, Q_VNEXT, Q_VTHIS } quote_t;
+
+/* Vi private, per-screen memory. */
+typedef struct _vi_private {
+ VICMD cmd; /* Current command, motion. */
+ VICMD motion;
+
+ /*
+ * !!!
+ * The saved command structure can be modified by the underlying
+ * vi functions, see v_Put() and v_put().
+ */
+ VICMD sdot; /* Saved dot, motion command. */
+ VICMD sdotmotion;
+
+ CHAR_T *keyw; /* Keyword buffer. */
+ size_t klen; /* Keyword length. */
+ size_t keywlen; /* Keyword buffer length. */
+
+ CHAR_T rlast; /* Last 'r' replacement character. */
+ e_key_t rvalue; /* Value of last replacement character. */
+
+ EVENT *rep; /* Input replay buffer. */
+ size_t rep_len; /* Input replay buffer length. */
+ size_t rep_cnt; /* Input replay buffer characters. */
+
+ mtype_t mtype; /* Last displayed message type. */
+ size_t linecount; /* 1-N: Output overwrite count. */
+ size_t lcontinue; /* 1-N: Output line continue value. */
+ size_t totalcount; /* 1-N: Output overwrite count. */
+
+ /* Busy state. */
+ int busy_ref; /* Busy reference count. */
+ int busy_ch; /* Busy character. */
+ size_t busy_fx; /* Busy character x coordinate. */
+ size_t busy_oldy; /* Saved y coordinate. */
+ size_t busy_oldx; /* Saved x coordinate. */
+ struct timeval busy_tv; /* Busy timer. */
+
+ char *ps; /* Paragraph plus section list. */
+
+ u_long u_ccnt; /* Undo command count. */
+
+ CHAR_T lastckey; /* Last search character. */
+ cdir_t csearchdir; /* Character search direction. */
+
+ SMAP *h_smap; /* First slot of the line map. */
+ SMAP *t_smap; /* Last slot of the line map. */
+
+ /*
+ * One extra slot is always allocated for the map so that we can use
+ * it to do vi :colon command input; see v_tcmd().
+ */
+ recno_t sv_tm_lno; /* tcmd: saved TMAP lno field. */
+ size_t sv_tm_coff; /* tcmd: saved TMAP coff field. */
+ size_t sv_tm_soff; /* tcmd: saved TMAP soff field. */
+ size_t sv_t_maxrows; /* tcmd: saved t_maxrows. */
+ size_t sv_t_minrows; /* tcmd: saved t_minrows. */
+ size_t sv_t_rows; /* tcmd: saved t_rows. */
+#define SIZE_HMAP(sp) (VIP(sp)->srows + 1)
+
+ /*
+ * Macros to get to the head/tail of the smap. If the screen only has
+ * one line, HMAP can be equal to TMAP, so the code has to understand
+ * the off-by-one errors that can result. If stepping through an SMAP
+ * and operating on each entry, use sp->t_rows as the count of slots,
+ * don't use a loop that compares <= TMAP.
+ */
+#define _HMAP(sp) (VIP(sp)->h_smap)
+#define HMAP _HMAP(sp)
+#define _TMAP(sp) (VIP(sp)->t_smap)
+#define TMAP _TMAP(sp)
+
+ recno_t ss_lno; /* 1-N: vi_opt_screens cached line number. */
+ size_t ss_screens; /* vi_opt_screens cached return value. */
+#define VI_SCR_CFLUSH(vip) vip->ss_lno = OOBLNO
+
+ size_t srows; /* 1-N: rows in the terminal/window. */
+ recno_t olno; /* 1-N: old cursor file line. */
+ size_t ocno; /* 0-N: old file cursor column. */
+ size_t sc_col; /* 0-N: LOGICAL screen column. */
+ SMAP *sc_smap; /* SMAP entry where sc_col occurs. */
+
+#define VIP_CUR_INVALID 0x0001 /* Cursor position is unknown. */
+#define VIP_DIVIDER 0x0002 /* Divider line was displayed. */
+#define VIP_N_EX_PAINT 0x0004 /* Clear and repaint when ex finishes. */
+#define VIP_N_EX_REDRAW 0x0008 /* Schedule SC_SCR_REDRAW when ex finishes. */
+#define VIP_N_REFRESH 0x0010 /* Repaint (from SMAP) on the next refresh. */
+#define VIP_N_RENUMBER 0x0020 /* Renumber screen on the next refresh. */
+#define VIP_RCM_LAST 0x0040 /* Cursor drawn to the last column. */
+#define VIP_S_MODELINE 0x0080 /* Skip next modeline refresh. */
+#define VIP_S_REFRESH 0x0100 /* Skip next refresh. */
+ u_int16_t flags;
+} VI_PRIVATE;
+
+/* Vi private area. */
+#define VIP(sp) ((VI_PRIVATE *)((sp)->vi_private))
+
+#define O_NUMBER_FMT "%7lu " /* O_NUMBER format, length. */
+#define O_NUMBER_LENGTH 8
+#define SCREEN_COLS(sp) /* Screen columns. */ \
+ ((O_ISSET(sp, O_NUMBER) ? (sp)->cols - O_NUMBER_LENGTH : (sp)->cols))
+
+/*
+ * LASTLINE is the zero-based, last line in the screen. Note that it is correct
+ * regardless of the changes in the screen to permit text input on the last line
+ * of the screen, or the existence of small screens.
+ */
+#define LASTLINE(sp) \
+ ((sp)->t_maxrows < (sp)->rows ? (sp)->t_maxrows : (sp)->rows - 1)
+
+/*
+ * Small screen (see vs_refresh.c, section 6a) and one-line screen test.
+ * Note, both cannot be true for the same screen.
+ */
+#define IS_SMALL(sp) ((sp)->t_minrows != (sp)->t_maxrows)
+#define IS_ONELINE(sp) ((sp)->rows == 1)
+
+#define HALFTEXT(sp) /* Half text. */ \
+ ((sp)->t_rows == 1 ? 1 : (sp)->t_rows / 2)
+#define HALFSCREEN(sp) /* Half text screen. */ \
+ ((sp)->t_maxrows == 1 ? 1 : (sp)->t_maxrows / 2)
+
+/*
+ * Next tab offset.
+ *
+ * !!!
+ * There are problems with how the historical vi handled tabs. For example,
+ * by doing "set ts=3" and building lines that fold, you can get it to step
+ * through tabs as if they were spaces and move inserted characters to new
+ * positions when <esc> is entered. I believe that nvi does tabs correctly,
+ * but there are some historical incompatibilities.
+ */
+#define TAB_OFF(c) COL_OFF((c), O_VAL(sp, O_TABSTOP))
+
+/* If more than one screen being shown. */
+#define IS_SPLIT(sp) \
+ ((sp)->q.cqe_next != (void *)&(sp)->gp->dq || \
+ (sp)->q.cqe_prev != (void *)&(sp)->gp->dq)
+
+/* Screen adjustment operations. */
+typedef enum { A_DECREASE, A_INCREASE, A_SET } adj_t;
+
+/* Screen position operations. */
+typedef enum { P_BOTTOM, P_FILL, P_MIDDLE, P_TOP } pos_t;
+
+/* Scrolling operations. */
+typedef enum {
+ CNTRL_B, CNTRL_D, CNTRL_E, CNTRL_F,
+ CNTRL_U, CNTRL_Y, Z_CARAT, Z_PLUS
+} scroll_t;
+
+/* Vi common error messages. */
+typedef enum {
+ VIM_COMBUF, VIM_EMPTY, VIM_EOF, VIM_EOL,
+ VIM_NOCOM, VIM_NOCOM_B, VIM_USAGE, VIM_WRESIZE
+} vim_t;
+
+#include "vi_extern.h"
diff --git a/contrib/nvi/vi/vs_line.c b/contrib/nvi/vi/vs_line.c
new file mode 100644
index 000000000000..b439de925ce1
--- /dev/null
+++ b/contrib/nvi/vi/vs_line.c
@@ -0,0 +1,514 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)vs_line.c 10.19 (Berkeley) 9/26/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+#ifdef VISIBLE_TAB_CHARS
+#define TABCH '-'
+#else
+#define TABCH ' '
+#endif
+
+/*
+ * vs_line --
+ * Update one line on the screen.
+ *
+ * PUBLIC: int vs_line __P((SCR *, SMAP *, size_t *, size_t *));
+ */
+int
+vs_line(sp, smp, yp, xp)
+ SCR *sp;
+ SMAP *smp;
+ size_t *xp, *yp;
+{
+ CHAR_T *kp;
+ GS *gp;
+ SMAP *tsmp;
+ size_t chlen, cno_cnt, cols_per_screen, len, nlen;
+ size_t offset_in_char, offset_in_line, oldx, oldy;
+ size_t scno, skip_cols, skip_screens;
+ int ch, dne, is_cached, is_partial, is_tab;
+ int list_tab, list_dollar;
+ char *p, *cbp, *ecbp, cbuf[128];
+
+#if defined(DEBUG) && 0
+ TRACE(sp, "vs_line: row %u: line: %u off: %u\n",
+ smp - HMAP, smp->lno, smp->off);
+#endif
+ /*
+ * If ex modifies the screen after ex output is already on the screen,
+ * don't touch it -- we'll get scrolling wrong, at best.
+ */
+ if (!F_ISSET(sp, SC_TINPUT_INFO) && VIP(sp)->totalcount > 1)
+ return (0);
+ if (F_ISSET(sp, SC_SCR_EXWROTE) && smp - HMAP != LASTLINE(sp))
+ return (0);
+
+ /*
+ * Assume that, if the cache entry for the line is filled in, the
+ * line is already on the screen, and all we need to do is return
+ * the cursor position. If the calling routine doesn't need the
+ * cursor position, we can just return.
+ */
+ is_cached = SMAP_CACHE(smp);
+ if (yp == NULL && is_cached)
+ return (0);
+
+ /*
+ * A nasty side effect of this routine is that it returns the screen
+ * position for the "current" character. Not pretty, but this is the
+ * only routine that really knows what's out there.
+ *
+ * Move to the line. This routine can be called by vs_sm_position(),
+ * which uses it to fill in the cache entry so it can figure out what
+ * the real contents of the screen are. Because of this, we have to
+ * return to whereever we started from.
+ */
+ gp = sp->gp;
+ (void)gp->scr_cursor(sp, &oldy, &oldx);
+ (void)gp->scr_move(sp, smp - HMAP, 0);
+
+ /* Get the line. */
+ dne = db_get(sp, smp->lno, 0, &p, &len);
+
+ /*
+ * Special case if we're printing the info/mode line. Skip printing
+ * the leading number, as well as other minor setup. The only time
+ * this code paints the mode line is when the user is entering text
+ * for a ":" command, so we can put the code here instead of dealing
+ * with the empty line logic below. This is a kludge, but it's pretty
+ * much confined to this module.
+ *
+ * Set the number of columns for this screen.
+ * Set the number of chars or screens to skip until a character is to
+ * be displayed.
+ */
+ cols_per_screen = sp->cols;
+ if (O_ISSET(sp, O_LEFTRIGHT)) {
+ skip_screens = 0;
+ skip_cols = smp->coff;
+ } else {
+ skip_screens = smp->soff - 1;
+ skip_cols = skip_screens * cols_per_screen;
+ }
+
+ list_tab = O_ISSET(sp, O_LIST);
+ if (F_ISSET(sp, SC_TINPUT_INFO))
+ list_dollar = 0;
+ else {
+ list_dollar = list_tab;
+
+ /*
+ * If O_NUMBER is set, the line doesn't exist and it's line
+ * number 1, i.e., an empty file, display the line number.
+ *
+ * If O_NUMBER is set, the line exists and the first character
+ * on the screen is the first character in the line, display
+ * the line number.
+ *
+ * !!!
+ * If O_NUMBER set, decrement the number of columns in the
+ * first screen. DO NOT CHANGE THIS -- IT'S RIGHT! The
+ * rest of the code expects this to reflect the number of
+ * columns in the first screen, regardless of the number of
+ * columns we're going to skip.
+ */
+ if (O_ISSET(sp, O_NUMBER)) {
+ cols_per_screen -= O_NUMBER_LENGTH;
+ if ((!dne || smp->lno == 1) && skip_cols == 0) {
+ nlen = snprintf(cbuf,
+ sizeof(cbuf), O_NUMBER_FMT, smp->lno);
+ (void)gp->scr_addstr(sp, cbuf, nlen);
+ }
+ }
+ }
+
+ /*
+ * Special case non-existent lines and the first line of an empty
+ * file. In both cases, the cursor position is 0, but corrected
+ * as necessary for the O_NUMBER field, if it was displayed.
+ */
+ if (dne || len == 0) {
+ /* Fill in the cursor. */
+ if (yp != NULL && smp->lno == sp->lno) {
+ *yp = smp - HMAP;
+ *xp = sp->cols - cols_per_screen;
+ }
+
+ /* If the line is on the screen, quit. */
+ if (is_cached)
+ goto ret1;
+
+ /* Set line cache information. */
+ smp->c_sboff = smp->c_eboff = 0;
+ smp->c_scoff = smp->c_eclen = 0;
+
+ /*
+ * Lots of special cases for empty lines, but they only apply
+ * if we're displaying the first screen of the line.
+ */
+ if (skip_cols == 0)
+ if (dne) {
+ if (smp->lno == 1) {
+ if (list_dollar) {
+ ch = '$';
+ goto empty;
+ }
+ } else {
+ ch = '~';
+ goto empty;
+ }
+ } else
+ if (list_dollar) {
+ ch = '$';
+empty: (void)gp->scr_addstr(sp,
+ KEY_NAME(sp, ch), KEY_LEN(sp, ch));
+ }
+
+ (void)gp->scr_clrtoeol(sp);
+ (void)gp->scr_move(sp, oldy, oldx);
+ return (0);
+ }
+
+ /*
+ * If we just wrote this or a previous line, we cached the starting
+ * and ending positions of that line. The way it works is we keep
+ * information about the lines displayed in the SMAP. If we're
+ * painting the screen in the forward direction, this saves us from
+ * reformatting the physical line for every line on the screen. This
+ * wins big on binary files with 10K lines.
+ *
+ * Test for the first screen of the line, then the current screen line,
+ * then the line behind us, then do the hard work. Note, it doesn't
+ * do us any good to have a line in front of us -- it would be really
+ * hard to try and figure out tabs in the reverse direction, i.e. how
+ * many spaces a tab takes up in the reverse direction depends on
+ * what characters preceded it.
+ *
+ * Test for the first screen of the line.
+ */
+ if (skip_cols == 0) {
+ smp->c_sboff = offset_in_line = 0;
+ smp->c_scoff = offset_in_char = 0;
+ p = &p[offset_in_line];
+ goto display;
+ }
+
+ /* Test to see if we've seen this exact line before. */
+ if (is_cached) {
+ offset_in_line = smp->c_sboff;
+ offset_in_char = smp->c_scoff;
+ p = &p[offset_in_line];
+
+ /* Set cols_per_screen to 2nd and later line length. */
+ if (O_ISSET(sp, O_LEFTRIGHT) || skip_cols > cols_per_screen)
+ cols_per_screen = sp->cols;
+ goto display;
+ }
+
+ /* Test to see if we saw an earlier part of this line before. */
+ if (smp != HMAP &&
+ SMAP_CACHE(tsmp = smp - 1) && tsmp->lno == smp->lno) {
+ if (tsmp->c_eclen != tsmp->c_ecsize) {
+ offset_in_line = tsmp->c_eboff;
+ offset_in_char = tsmp->c_eclen;
+ } else {
+ offset_in_line = tsmp->c_eboff + 1;
+ offset_in_char = 0;
+ }
+
+ /* Put starting info for this line in the cache. */
+ smp->c_sboff = offset_in_line;
+ smp->c_scoff = offset_in_char;
+ p = &p[offset_in_line];
+
+ /* Set cols_per_screen to 2nd and later line length. */
+ if (O_ISSET(sp, O_LEFTRIGHT) || skip_cols > cols_per_screen)
+ cols_per_screen = sp->cols;
+ goto display;
+ }
+
+ scno = 0;
+ offset_in_line = 0;
+ offset_in_char = 0;
+
+ /* Do it the hard way, for leftright scrolling screens. */
+ if (O_ISSET(sp, O_LEFTRIGHT)) {
+ for (; offset_in_line < len; ++offset_in_line) {
+ chlen = (ch = *(u_char *)p++) == '\t' && !list_tab ?
+ TAB_OFF(scno) : KEY_LEN(sp, ch);
+ if ((scno += chlen) >= skip_cols)
+ break;
+ }
+
+ /* Set cols_per_screen to 2nd and later line length. */
+ cols_per_screen = sp->cols;
+
+ /* Put starting info for this line in the cache. */
+ if (scno != skip_cols) {
+ smp->c_sboff = offset_in_line;
+ smp->c_scoff =
+ offset_in_char = chlen - (scno - skip_cols);
+ --p;
+ } else {
+ smp->c_sboff = ++offset_in_line;
+ smp->c_scoff = 0;
+ }
+ }
+
+ /* Do it the hard way, for historic line-folding screens. */
+ else {
+ for (; offset_in_line < len; ++offset_in_line) {
+ chlen = (ch = *(u_char *)p++) == '\t' && !list_tab ?
+ TAB_OFF(scno) : KEY_LEN(sp, ch);
+ if ((scno += chlen) < cols_per_screen)
+ continue;
+ scno -= cols_per_screen;
+
+ /* Set cols_per_screen to 2nd and later line length. */
+ cols_per_screen = sp->cols;
+
+ /*
+ * If crossed the last skipped screen boundary, start
+ * displaying the characters.
+ */
+ if (--skip_screens == 0)
+ break;
+ }
+
+ /* Put starting info for this line in the cache. */
+ if (scno != 0) {
+ smp->c_sboff = offset_in_line;
+ smp->c_scoff = offset_in_char = chlen - scno;
+ --p;
+ } else {
+ smp->c_sboff = ++offset_in_line;
+ smp->c_scoff = 0;
+ }
+ }
+
+display:
+ /*
+ * Set the number of characters to skip before reaching the cursor
+ * character. Offset by 1 and use 0 as a flag value. Vs_line is
+ * called repeatedly with a valid pointer to a cursor position.
+ * Don't fill anything in unless it's the right line and the right
+ * character, and the right part of the character...
+ */
+ if (yp == NULL ||
+ smp->lno != sp->lno || sp->cno < offset_in_line ||
+ offset_in_line + cols_per_screen < sp->cno) {
+ cno_cnt = 0;
+ /* If the line is on the screen, quit. */
+ if (is_cached)
+ goto ret1;
+ } else
+ cno_cnt = (sp->cno - offset_in_line) + 1;
+
+ /* This is the loop that actually displays characters. */
+ ecbp = (cbp = cbuf) + sizeof(cbuf) - 1;
+ for (is_partial = 0, scno = 0;
+ offset_in_line < len; ++offset_in_line, offset_in_char = 0) {
+ if ((ch = *(u_char *)p++) == '\t' && !list_tab) {
+ scno += chlen = TAB_OFF(scno) - offset_in_char;
+ is_tab = 1;
+ } else {
+ scno += chlen = KEY_LEN(sp, ch) - offset_in_char;
+ is_tab = 0;
+ }
+
+ /*
+ * Only display up to the right-hand column. Set a flag if
+ * the entire character wasn't displayed for use in setting
+ * the cursor. If reached the end of the line, set the cache
+ * info for the screen. Don't worry about there not being
+ * characters to display on the next screen, its lno/off won't
+ * match up in that case.
+ */
+ if (scno >= cols_per_screen) {
+ if (is_tab == 1) {
+ chlen -= scno - cols_per_screen;
+ smp->c_ecsize = smp->c_eclen = chlen;
+ scno = cols_per_screen;
+ } else {
+ smp->c_ecsize = chlen;
+ chlen -= scno - cols_per_screen;
+ smp->c_eclen = chlen;
+
+ if (scno > cols_per_screen)
+ is_partial = 1;
+ }
+ smp->c_eboff = offset_in_line;
+
+ /* Terminate the loop. */
+ offset_in_line = len;
+ }
+
+ /*
+ * If the caller wants the cursor value, and this was the
+ * cursor character, set the value. There are two ways to
+ * put the cursor on a character -- if it's normal display
+ * mode, it goes on the last column of the character. If
+ * it's input mode, it goes on the first. In normal mode,
+ * set the cursor only if the entire character was displayed.
+ */
+ if (cno_cnt &&
+ --cno_cnt == 0 && (F_ISSET(sp, SC_TINPUT) || !is_partial)) {
+ *yp = smp - HMAP;
+ if (F_ISSET(sp, SC_TINPUT))
+ *xp = scno - chlen;
+ else
+ *xp = scno - 1;
+ if (O_ISSET(sp, O_NUMBER) &&
+ !F_ISSET(sp, SC_TINPUT_INFO) && skip_cols == 0)
+ *xp += O_NUMBER_LENGTH;
+
+ /* If the line is on the screen, quit. */
+ if (is_cached)
+ goto ret1;
+ }
+
+ /* If the line is on the screen, don't display anything. */
+ if (is_cached)
+ continue;
+
+#define FLUSH { \
+ *cbp = '\0'; \
+ (void)gp->scr_addstr(sp, cbuf, cbp - cbuf); \
+ cbp = cbuf; \
+}
+ /*
+ * Display the character. We do tab expansion here because
+ * the screen interface doesn't have any way to set the tab
+ * length. Note, it's theoretically possible for chlen to
+ * be larger than cbuf, if the user set a impossibly large
+ * tabstop.
+ */
+ if (is_tab)
+ while (chlen--) {
+ if (cbp >= ecbp)
+ FLUSH;
+ *cbp++ = TABCH;
+ }
+ else {
+ if (cbp + chlen >= ecbp)
+ FLUSH;
+ for (kp = KEY_NAME(sp, ch) + offset_in_char; chlen--;)
+ *cbp++ = *kp++;
+ }
+ }
+
+ if (scno < cols_per_screen) {
+ /* If didn't paint the whole line, update the cache. */
+ smp->c_ecsize = smp->c_eclen = KEY_LEN(sp, ch);
+ smp->c_eboff = len - 1;
+
+ /*
+ * If not the info/mode line, and O_LIST set, and at the
+ * end of the line, and the line ended on this screen,
+ * add a trailing $.
+ */
+ if (list_dollar) {
+ ++scno;
+
+ chlen = KEY_LEN(sp, '$');
+ if (cbp + chlen >= ecbp)
+ FLUSH;
+ for (kp = KEY_NAME(sp, '$'); chlen--;)
+ *cbp++ = *kp++;
+ }
+
+ /* If still didn't paint the whole line, clear the rest. */
+ if (scno < cols_per_screen)
+ (void)gp->scr_clrtoeol(sp);
+ }
+
+ /* Flush any buffered characters. */
+ if (cbp > cbuf)
+ FLUSH;
+
+ret1: (void)gp->scr_move(sp, oldy, oldx);
+ return (0);
+}
+
+/*
+ * vs_number --
+ * Repaint the numbers on all the lines.
+ *
+ * PUBLIC: int vs_number __P((SCR *));
+ */
+int
+vs_number(sp)
+ SCR *sp;
+{
+ GS *gp;
+ SMAP *smp;
+ VI_PRIVATE *vip;
+ size_t len, oldy, oldx;
+ int exist;
+ char nbuf[10];
+
+ gp = sp->gp;
+ vip = VIP(sp);
+
+ /* No reason to do anything if we're in input mode on the info line. */
+ if (F_ISSET(sp, SC_TINPUT_INFO))
+ return (0);
+
+ /*
+ * Try and avoid getting the last line in the file, by getting the
+ * line after the last line in the screen -- if it exists, we know
+ * we have to to number all the lines in the screen. Get the one
+ * after the last instead of the last, so that the info line doesn't
+ * fool us. (The problem is that file_lline will lie, and tell us
+ * that the info line is the last line in the file.) If that test
+ * fails, we have to check each line for existence.
+ */
+ exist = db_exist(sp, TMAP->lno + 1);
+
+ (void)gp->scr_cursor(sp, &oldy, &oldx);
+ for (smp = HMAP; smp <= TMAP; ++smp) {
+ /* Numbers are only displayed for the first screen line. */
+ if (O_ISSET(sp, O_LEFTRIGHT)) {
+ if (smp->coff != 0)
+ continue;
+ } else
+ if (smp->soff != 1)
+ continue;
+
+ /*
+ * The first line of an empty file gets numbered, otherwise
+ * number any existing line.
+ */
+ if (smp->lno != 1 && !exist && !db_exist(sp, smp->lno))
+ break;
+
+ (void)gp->scr_move(sp, smp - HMAP, 0);
+ len = snprintf(nbuf, sizeof(nbuf), O_NUMBER_FMT, smp->lno);
+ (void)gp->scr_addstr(sp, nbuf, len);
+ }
+ (void)gp->scr_move(sp, oldy, oldx);
+ return (0);
+}
diff --git a/contrib/nvi/vi/vs_msg.c b/contrib/nvi/vi/vs_msg.c
new file mode 100644
index 000000000000..7ef8f5343c15
--- /dev/null
+++ b/contrib/nvi/vi/vs_msg.c
@@ -0,0 +1,927 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)vs_msg.c 10.77 (Berkeley) 10/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+typedef enum {
+ SCROLL_W, /* User wait. */
+ SCROLL_W_EX, /* User wait, or enter : to continue. */
+ SCROLL_W_QUIT /* User wait, or enter q to quit. */
+ /*
+ * SCROLL_W_QUIT has another semantic
+ * -- only wait if the screen is full
+ */
+} sw_t;
+
+static void vs_divider __P((SCR *));
+static void vs_msgsave __P((SCR *, mtype_t, char *, size_t));
+static void vs_output __P((SCR *, mtype_t, const char *, int));
+static void vs_scroll __P((SCR *, int *, sw_t));
+static void vs_wait __P((SCR *, int *, sw_t));
+
+/*
+ * vs_busy --
+ * Display, update or clear a busy message.
+ *
+ * This routine is the default editor interface for vi busy messages. It
+ * implements a standard strategy of stealing lines from the bottom of the
+ * vi text screen. Screens using an alternate method of displaying busy
+ * messages, e.g. X11 clock icons, should set their scr_busy function to the
+ * correct function before calling the main editor routine.
+ *
+ * PUBLIC: void vs_busy __P((SCR *, const char *, busy_t));
+ */
+void
+vs_busy(sp, msg, btype)
+ SCR *sp;
+ const char *msg;
+ busy_t btype;
+{
+ GS *gp;
+ VI_PRIVATE *vip;
+ static const char flagc[] = "|/-\\";
+ struct timeval tv;
+ size_t len, notused;
+ const char *p;
+
+ /* Ex doesn't display busy messages. */
+ if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE))
+ return;
+
+ gp = sp->gp;
+ vip = VIP(sp);
+
+ /*
+ * Most of this routine is to deal with the screen sharing real estate
+ * between the normal edit messages and the busy messages. Logically,
+ * all that's needed is something that puts up a message, periodically
+ * updates it, and then goes away.
+ */
+ switch (btype) {
+ case BUSY_ON:
+ ++vip->busy_ref;
+ if (vip->totalcount != 0 || vip->busy_ref != 1)
+ break;
+
+ /* Initialize state for updates. */
+ vip->busy_ch = 0;
+ (void)gettimeofday(&vip->busy_tv, NULL);
+
+ /* Save the current cursor. */
+ (void)gp->scr_cursor(sp, &vip->busy_oldy, &vip->busy_oldx);
+
+ /* Display the busy message. */
+ p = msg_cat(sp, msg, &len);
+ (void)gp->scr_move(sp, LASTLINE(sp), 0);
+ (void)gp->scr_addstr(sp, p, len);
+ (void)gp->scr_cursor(sp, &notused, &vip->busy_fx);
+ (void)gp->scr_clrtoeol(sp);
+ (void)gp->scr_move(sp, LASTLINE(sp), vip->busy_fx);
+ break;
+ case BUSY_OFF:
+ if (vip->busy_ref == 0)
+ break;
+ --vip->busy_ref;
+
+ /*
+ * If the line isn't in use for another purpose, clear it.
+ * Always return to the original position.
+ */
+ if (vip->totalcount == 0 && vip->busy_ref == 0) {
+ (void)gp->scr_move(sp, LASTLINE(sp), 0);
+ (void)gp->scr_clrtoeol(sp);
+ }
+ (void)gp->scr_move(sp, vip->busy_oldy, vip->busy_oldx);
+ break;
+ case BUSY_UPDATE:
+ if (vip->totalcount != 0 || vip->busy_ref == 0)
+ break;
+
+ /* Update no more than every 1/8 of a second. */
+ (void)gettimeofday(&tv, NULL);
+ if (((tv.tv_sec - vip->busy_tv.tv_sec) * 1000000 +
+ (tv.tv_usec - vip->busy_tv.tv_usec)) < 125000)
+ return;
+ vip->busy_tv = tv;
+
+ /* Display the update. */
+ if (vip->busy_ch == sizeof(flagc) - 1)
+ vip->busy_ch = 0;
+ (void)gp->scr_move(sp, LASTLINE(sp), vip->busy_fx);
+ (void)gp->scr_addstr(sp, flagc + vip->busy_ch++, 1);
+ (void)gp->scr_move(sp, LASTLINE(sp), vip->busy_fx);
+ break;
+ }
+ (void)gp->scr_refresh(sp, 0);
+}
+
+/*
+ * vs_home --
+ * Home the cursor to the bottom row, left-most column.
+ *
+ * PUBLIC: void vs_home __P((SCR *));
+ */
+void
+vs_home(sp)
+ SCR *sp;
+{
+ (void)sp->gp->scr_move(sp, LASTLINE(sp), 0);
+ (void)sp->gp->scr_refresh(sp, 0);
+}
+
+/*
+ * vs_update --
+ * Update a command.
+ *
+ * PUBLIC: void vs_update __P((SCR *, const char *, const char *));
+ */
+void
+vs_update(sp, m1, m2)
+ SCR *sp;
+ const char *m1, *m2;
+{
+ GS *gp;
+ size_t len, mlen, oldx, oldy;
+
+ gp = sp->gp;
+
+ /*
+ * This routine displays a message on the bottom line of the screen,
+ * without updating any of the command structures that would keep it
+ * there for any period of time, i.e. it is overwritten immediately.
+ *
+ * It's used by the ex read and ! commands when the user's command is
+ * expanded, and by the ex substitution confirmation prompt.
+ */
+ if (F_ISSET(sp, SC_SCR_EXWROTE)) {
+ (void)ex_printf(sp,
+ "%s\n", m1 == NULL? "" : m1, m2 == NULL ? "" : m2);
+ (void)ex_fflush(sp);
+ }
+
+ /*
+ * Save the cursor position, the substitute-with-confirmation code
+ * will have already set it correctly.
+ */
+ (void)gp->scr_cursor(sp, &oldy, &oldx);
+
+ /* Clear the bottom line. */
+ (void)gp->scr_move(sp, LASTLINE(sp), 0);
+ (void)gp->scr_clrtoeol(sp);
+
+ /*
+ * XXX
+ * Don't let long file names screw up the screen.
+ */
+ if (m1 != NULL) {
+ mlen = len = strlen(m1);
+ if (len > sp->cols - 2)
+ mlen = len = sp->cols - 2;
+ (void)gp->scr_addstr(sp, m1, mlen);
+ } else
+ len = 0;
+ if (m2 != NULL) {
+ mlen = strlen(m2);
+ if (len + mlen > sp->cols - 2)
+ mlen = (sp->cols - 2) - len;
+ (void)gp->scr_addstr(sp, m2, mlen);
+ }
+
+ (void)gp->scr_move(sp, oldy, oldx);
+ (void)gp->scr_refresh(sp, 0);
+}
+
+/*
+ * vs_msg --
+ * Display ex output or error messages for the screen.
+ *
+ * This routine is the default editor interface for all ex output, and all ex
+ * and vi error/informational messages. It implements the standard strategy
+ * of stealing lines from the bottom of the vi text screen. Screens using an
+ * alternate method of displaying messages, e.g. dialog boxes, should set their
+ * scr_msg function to the correct function before calling the editor.
+ *
+ * PUBLIC: void vs_msg __P((SCR *, mtype_t, char *, size_t));
+ */
+void
+vs_msg(sp, mtype, line, len)
+ SCR *sp;
+ mtype_t mtype;
+ char *line;
+ size_t len;
+{
+ GS *gp;
+ VI_PRIVATE *vip;
+ size_t maxcols, oldx, oldy, padding;
+ const char *e, *s, *t;
+
+ gp = sp->gp;
+ vip = VIP(sp);
+
+ /*
+ * Ring the bell if it's scheduled.
+ *
+ * XXX
+ * Shouldn't we save this, too?
+ */
+ if (F_ISSET(sp, SC_TINPUT_INFO) || F_ISSET(gp, G_BELLSCHED))
+ if (F_ISSET(sp, SC_SCR_VI)) {
+ F_CLR(gp, G_BELLSCHED);
+ (void)gp->scr_bell(sp);
+ } else
+ F_SET(gp, G_BELLSCHED);
+
+ /*
+ * If vi is using the error line for text input, there's no screen
+ * real-estate for the error message. Nothing to do without some
+ * information as to how important the error message is.
+ */
+ if (F_ISSET(sp, SC_TINPUT_INFO))
+ return;
+
+ /*
+ * Ex or ex controlled screen output.
+ *
+ * If output happens during startup, e.g., a .exrc file, we may be
+ * in ex mode but haven't initialized the screen. Initialize here,
+ * and in this case, stay in ex mode.
+ *
+ * If the SC_SCR_EXWROTE bit is set, then we're switching back and
+ * forth between ex and vi, but the screen is trashed and we have
+ * to respect that. Switch to ex mode long enough to put out the
+ * message.
+ *
+ * If the SC_EX_WAIT_NO bit is set, turn it off -- we're writing to
+ * the screen, so previous opinions are ignored.
+ */
+ if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE)) {
+ if (!F_ISSET(sp, SC_SCR_EX))
+ if (F_ISSET(sp, SC_SCR_EXWROTE)) {
+ if (sp->gp->scr_screen(sp, SC_EX))
+ return;
+ } else
+ if (ex_init(sp))
+ return;
+
+ if (mtype == M_ERR)
+ (void)gp->scr_attr(sp, SA_INVERSE, 1);
+ (void)printf("%.*s", (int)len, line);
+ if (mtype == M_ERR)
+ (void)gp->scr_attr(sp, SA_INVERSE, 0);
+ (void)fflush(stdout);
+
+ F_CLR(sp, SC_EX_WAIT_NO);
+
+ if (!F_ISSET(sp, SC_SCR_EX))
+ (void)sp->gp->scr_screen(sp, SC_VI);
+ return;
+ }
+
+ /* If the vi screen isn't ready, save the message. */
+ if (!F_ISSET(sp, SC_SCR_VI)) {
+ (void)vs_msgsave(sp, mtype, line, len);
+ return;
+ }
+
+ /* Save the cursor position. */
+ (void)gp->scr_cursor(sp, &oldy, &oldx);
+
+ /* If it's an ex output message, just write it out. */
+ if (mtype == M_NONE) {
+ vs_output(sp, mtype, line, len);
+ goto ret;
+ }
+
+ /*
+ * If it's a vi message, strip the trailing <newline> so we can
+ * try and paste messages together.
+ */
+ if (line[len - 1] == '\n')
+ --len;
+
+ /*
+ * If a message won't fit on a single line, try to split on a <blank>.
+ * If a subsequent message fits on the same line, write a separator
+ * and output it. Otherwise, put out a newline.
+ *
+ * Need up to two padding characters normally; a semi-colon and a
+ * separating space. If only a single line on the screen, add some
+ * more for the trailing continuation message.
+ *
+ * XXX
+ * Assume that periods and semi-colons take up a single column on the
+ * screen.
+ *
+ * XXX
+ * There are almost certainly pathological cases that will break this
+ * code.
+ */
+ if (IS_ONELINE(sp))
+ (void)msg_cmsg(sp, CMSG_CONT_S, &padding);
+ else
+ padding = 0;
+ padding += 2;
+
+ maxcols = sp->cols - 1;
+ if (vip->lcontinue != 0)
+ if (len + vip->lcontinue + padding > maxcols)
+ vs_output(sp, vip->mtype, ".\n", 2);
+ else {
+ vs_output(sp, vip->mtype, ";", 1);
+ vs_output(sp, M_NONE, " ", 1);
+ }
+ vip->mtype = mtype;
+ for (s = line;; s = t) {
+ for (; len > 0 && isblank(*s); --len, ++s);
+ if (len == 0)
+ break;
+ if (len + vip->lcontinue > maxcols) {
+ for (e = s + (maxcols - vip->lcontinue);
+ e > s && !isblank(*e); --e);
+ if (e == s)
+ e = t = s + (maxcols - vip->lcontinue);
+ else
+ for (t = e; isblank(e[-1]); --e);
+ } else
+ e = t = s + len;
+
+ /*
+ * If the message ends in a period, discard it, we want to
+ * gang messages where possible.
+ */
+ len -= t - s;
+ if (len == 0 && (e - s) > 1 && s[(e - s) - 1] == '.')
+ --e;
+ vs_output(sp, mtype, s, e - s);
+
+ if (len != 0)
+ vs_output(sp, M_NONE, "\n", 1);
+
+ if (INTERRUPTED(sp))
+ break;
+ }
+
+ret: (void)gp->scr_move(sp, oldy, oldx);
+ (void)gp->scr_refresh(sp, 0);
+}
+
+/*
+ * vs_output --
+ * Output the text to the screen.
+ */
+static void
+vs_output(sp, mtype, line, llen)
+ SCR *sp;
+ mtype_t mtype;
+ const char *line;
+ int llen;
+{
+ CHAR_T *kp;
+ GS *gp;
+ VI_PRIVATE *vip;
+ size_t chlen, notused;
+ int ch, len, rlen, tlen;
+ const char *p, *t;
+ char *cbp, *ecbp, cbuf[128];
+
+ gp = sp->gp;
+ vip = VIP(sp);
+ for (p = line, rlen = llen; llen > 0;) {
+ /* Get the next physical line. */
+ if ((p = memchr(line, '\n', llen)) == NULL)
+ len = llen;
+ else
+ len = p - line;
+
+ /*
+ * The max is sp->cols characters, and we may have already
+ * written part of the line.
+ */
+ if (len + vip->lcontinue > sp->cols)
+ len = sp->cols - vip->lcontinue;
+
+ /*
+ * If the first line output, do nothing. If the second line
+ * output, draw the divider line. If drew a full screen, we
+ * remove the divider line. If it's a continuation line, move
+ * to the continuation point, else, move the screen up.
+ */
+ if (vip->lcontinue == 0) {
+ if (!IS_ONELINE(sp)) {
+ if (vip->totalcount == 1) {
+ (void)gp->scr_move(sp,
+ LASTLINE(sp) - 1, 0);
+ (void)gp->scr_clrtoeol(sp);
+ (void)vs_divider(sp);
+ F_SET(vip, VIP_DIVIDER);
+ ++vip->totalcount;
+ ++vip->linecount;
+ }
+ if (vip->totalcount == sp->t_maxrows &&
+ F_ISSET(vip, VIP_DIVIDER)) {
+ --vip->totalcount;
+ --vip->linecount;
+ F_CLR(vip, VIP_DIVIDER);
+ }
+ }
+ if (vip->totalcount != 0)
+ vs_scroll(sp, NULL, SCROLL_W_QUIT);
+
+ (void)gp->scr_move(sp, LASTLINE(sp), 0);
+ ++vip->totalcount;
+ ++vip->linecount;
+
+ if (INTERRUPTED(sp))
+ break;
+ } else
+ (void)gp->scr_move(sp, LASTLINE(sp), vip->lcontinue);
+
+ /* Error messages are in inverse video. */
+ if (mtype == M_ERR)
+ (void)gp->scr_attr(sp, SA_INVERSE, 1);
+
+ /* Display the line, doing character translation. */
+#define FLUSH { \
+ *cbp = '\0'; \
+ (void)gp->scr_addstr(sp, cbuf, cbp - cbuf); \
+ cbp = cbuf; \
+}
+ ecbp = (cbp = cbuf) + sizeof(cbuf) - 1;
+ for (t = line, tlen = len; tlen--; ++t) {
+ ch = *t;
+ /*
+ * Replace tabs with spaces, there are places in
+ * ex that do column calculations without looking
+ * at <tabs> -- and all routines that care about
+ * <tabs> do their own expansions. This catches
+ * <tabs> in things like tag search strings.
+ */
+ if (ch == '\t')
+ ch = ' ';
+ chlen = KEY_LEN(sp, ch);
+ if (cbp + chlen >= ecbp)
+ FLUSH;
+ for (kp = KEY_NAME(sp, ch); chlen--;)
+ *cbp++ = *kp++;
+ }
+ if (cbp > cbuf)
+ FLUSH;
+ if (mtype == M_ERR)
+ (void)gp->scr_attr(sp, SA_INVERSE, 0);
+
+ /* Clear the rest of the line. */
+ (void)gp->scr_clrtoeol(sp);
+
+ /* If we loop, it's a new line. */
+ vip->lcontinue = 0;
+
+ /* Reset for the next line. */
+ line += len;
+ llen -= len;
+ if (p != NULL) {
+ ++line;
+ --llen;
+ }
+ }
+
+ /* Set up next continuation line. */
+ if (p == NULL)
+ gp->scr_cursor(sp, &notused, &vip->lcontinue);
+}
+
+/*
+ * vs_ex_resolve --
+ * Deal with ex message output.
+ *
+ * This routine is called when exiting a colon command to resolve any ex
+ * output that may have occurred.
+ *
+ * PUBLIC: int vs_ex_resolve __P((SCR *, int *));
+ */
+int
+vs_ex_resolve(sp, continuep)
+ SCR *sp;
+ int *continuep;
+{
+ EVENT ev;
+ GS *gp;
+ VI_PRIVATE *vip;
+ sw_t wtype;
+
+ gp = sp->gp;
+ vip = VIP(sp);
+ *continuep = 0;
+
+ /* If we ran any ex command, we can't trust the cursor position. */
+ F_SET(vip, VIP_CUR_INVALID);
+
+ /* Terminate any partially written message. */
+ if (vip->lcontinue != 0) {
+ vs_output(sp, vip->mtype, ".", 1);
+ vip->lcontinue = 0;
+
+ vip->mtype = M_NONE;
+ }
+
+ /*
+ * If we switched out of the vi screen into ex, switch back while we
+ * figure out what to do with the screen and potentially get another
+ * command to execute.
+ *
+ * If we didn't switch into ex, we're not required to wait, and less
+ * than 2 lines of output, we can continue without waiting for the
+ * wait.
+ *
+ * Note, all other code paths require waiting, so we leave the report
+ * of modified lines until later, so that we won't wait for no other
+ * reason than a threshold number of lines were modified. This means
+ * we display cumulative line modification reports for groups of ex
+ * commands. That seems right to me (well, at least not wrong).
+ */
+ if (F_ISSET(sp, SC_SCR_EXWROTE)) {
+ if (sp->gp->scr_screen(sp, SC_VI))
+ return (1);
+ } else
+ if (!F_ISSET(sp, SC_EX_WAIT_YES) && vip->totalcount < 2) {
+ F_CLR(sp, SC_EX_WAIT_NO);
+ return (0);
+ }
+
+ /* Clear the required wait flag, it's no longer needed. */
+ F_CLR(sp, SC_EX_WAIT_YES);
+
+ /*
+ * Wait, unless explicitly told not to wait or the user interrupted
+ * the command. If the user is leaving the screen, for any reason,
+ * they can't continue with further ex commands.
+ */
+ if (!F_ISSET(sp, SC_EX_WAIT_NO) && !INTERRUPTED(sp)) {
+ wtype = F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE |
+ SC_FSWITCH | SC_SSWITCH) ? SCROLL_W : SCROLL_W_EX;
+ if (F_ISSET(sp, SC_SCR_EXWROTE))
+ vs_wait(sp, continuep, wtype);
+ else
+ vs_scroll(sp, continuep, wtype);
+ if (*continuep)
+ return (0);
+ }
+
+ /* If ex wrote on the screen, refresh the screen image. */
+ if (F_ISSET(sp, SC_SCR_EXWROTE))
+ F_SET(vip, VIP_N_EX_PAINT);
+
+ /*
+ * If we're not the bottom of the split screen stack, the screen
+ * image itself is wrong, so redraw everything.
+ */
+ if (sp->q.cqe_next != (void *)&sp->gp->dq)
+ F_SET(sp, SC_SCR_REDRAW);
+
+ /* If ex changed the underlying file, the map itself is wrong. */
+ if (F_ISSET(vip, VIP_N_EX_REDRAW))
+ F_SET(sp, SC_SCR_REFORMAT);
+
+ /* Ex may have switched out of the alternate screen, return. */
+ (void)gp->scr_attr(sp, SA_ALTERNATE, 1);
+
+ /*
+ * Whew. We're finally back home, after what feels like years.
+ * Kiss the ground.
+ */
+ F_CLR(sp, SC_SCR_EXWROTE | SC_EX_WAIT_NO);
+
+ /*
+ * We may need to repaint some of the screen, e.g.:
+ *
+ * :set
+ * :!ls
+ *
+ * gives us a combination of some lines that are "wrong", and a need
+ * for a full refresh.
+ */
+ if (vip->totalcount > 1) {
+ /* Set up the redraw of the overwritten lines. */
+ ev.e_event = E_REPAINT;
+ ev.e_flno = vip->totalcount >=
+ sp->rows ? 1 : sp->rows - vip->totalcount;
+ ev.e_tlno = sp->rows;
+
+ /* Reset the count of overwriting lines. */
+ vip->linecount = vip->lcontinue = vip->totalcount = 0;
+
+ /* Redraw. */
+ (void)vs_repaint(sp, &ev);
+ } else
+ /* Reset the count of overwriting lines. */
+ vip->linecount = vip->lcontinue = vip->totalcount = 0;
+
+ return (0);
+}
+
+/*
+ * vs_resolve --
+ * Deal with message output.
+ *
+ * PUBLIC: int vs_resolve __P((SCR *, SCR *, int));
+ */
+int
+vs_resolve(sp, csp, forcewait)
+ SCR *sp, *csp;
+ int forcewait;
+{
+ EVENT ev;
+ GS *gp;
+ MSGS *mp;
+ VI_PRIVATE *vip;
+ size_t oldy, oldx;
+ int redraw;
+
+ /*
+ * Vs_resolve is called from the main vi loop and the refresh function
+ * to periodically ensure that the user has seen any messages that have
+ * been displayed and that any status lines are correct. The sp screen
+ * is the screen we're checking, usually the current screen. When it's
+ * not, csp is the current screen, used for final cursor positioning.
+ */
+ gp = sp->gp;
+ vip = VIP(sp);
+ if (csp == NULL)
+ csp = sp;
+
+ /* Save the cursor position. */
+ (void)gp->scr_cursor(csp, &oldy, &oldx);
+
+ /* Ring the bell if it's scheduled. */
+ if (F_ISSET(gp, G_BELLSCHED)) {
+ F_CLR(gp, G_BELLSCHED);
+ (void)gp->scr_bell(sp);
+ }
+
+ /* Display new file status line. */
+ if (F_ISSET(sp, SC_STATUS)) {
+ F_CLR(sp, SC_STATUS);
+ msgq_status(sp, sp->lno, MSTAT_TRUNCATE);
+ }
+
+ /* Report on line modifications. */
+ mod_rpt(sp);
+
+ /*
+ * Flush any saved messages. If the screen isn't ready, refresh
+ * it. (A side-effect of screen refresh is that we can display
+ * messages.) Once this is done, don't trust the cursor. That
+ * extra refresh screwed the pooch.
+ */
+ if (gp->msgq.lh_first != NULL) {
+ if (!F_ISSET(sp, SC_SCR_VI) && vs_refresh(sp, 1))
+ return (1);
+ while ((mp = gp->msgq.lh_first) != NULL) {
+ gp->scr_msg(sp, mp->mtype, mp->buf, mp->len);
+ LIST_REMOVE(mp, q);
+ free(mp->buf);
+ free(mp);
+ }
+ F_SET(vip, VIP_CUR_INVALID);
+ }
+
+ switch (vip->totalcount) {
+ case 0:
+ redraw = 0;
+ break;
+ case 1:
+ /*
+ * If we're switching screens, we have to wait for messages,
+ * regardless. If we don't wait, skip updating the modeline.
+ */
+ if (forcewait)
+ vs_scroll(sp, NULL, SCROLL_W);
+ else
+ F_SET(vip, VIP_S_MODELINE);
+
+ redraw = 0;
+ break;
+ default:
+ /*
+ * If >1 message line in use, prompt the user to continue and
+ * repaint overwritten lines.
+ */
+ vs_scroll(sp, NULL, SCROLL_W);
+
+ ev.e_event = E_REPAINT;
+ ev.e_flno = vip->totalcount >=
+ sp->rows ? 1 : sp->rows - vip->totalcount;
+ ev.e_tlno = sp->rows;
+
+ redraw = 1;
+ break;
+ }
+
+ /* Reset the count of overwriting lines. */
+ vip->linecount = vip->lcontinue = vip->totalcount = 0;
+
+ /* Redraw. */
+ if (redraw)
+ (void)vs_repaint(sp, &ev);
+
+ /* Restore the cursor position. */
+ (void)gp->scr_move(csp, oldy, oldx);
+
+ return (0);
+}
+
+/*
+ * vs_scroll --
+ * Scroll the screen for output.
+ */
+static void
+vs_scroll(sp, continuep, wtype)
+ SCR *sp;
+ int *continuep;
+ sw_t wtype;
+{
+ GS *gp;
+ VI_PRIVATE *vip;
+
+ gp = sp->gp;
+ vip = VIP(sp);
+ if (!IS_ONELINE(sp)) {
+ /*
+ * Scroll the screen. Instead of scrolling the entire screen,
+ * delete the line above the first line output so preserve the
+ * maximum amount of the screen.
+ */
+ (void)gp->scr_move(sp, vip->totalcount <
+ sp->rows ? LASTLINE(sp) - vip->totalcount : 0, 0);
+ (void)gp->scr_deleteln(sp);
+
+ /* If there are screens below us, push them back into place. */
+ if (sp->q.cqe_next != (void *)&sp->gp->dq) {
+ (void)gp->scr_move(sp, LASTLINE(sp), 0);
+ (void)gp->scr_insertln(sp);
+ }
+ }
+ if (wtype == SCROLL_W_QUIT && vip->linecount < sp->t_maxrows)
+ return;
+ vs_wait(sp, continuep, wtype);
+}
+
+/*
+ * vs_wait --
+ * Prompt the user to continue.
+ */
+static void
+vs_wait(sp, continuep, wtype)
+ SCR *sp;
+ int *continuep;
+ sw_t wtype;
+{
+ EVENT ev;
+ VI_PRIVATE *vip;
+ const char *p;
+ GS *gp;
+ size_t len;
+
+ gp = sp->gp;
+ vip = VIP(sp);
+
+ (void)gp->scr_move(sp, LASTLINE(sp), 0);
+ if (IS_ONELINE(sp))
+ p = msg_cmsg(sp, CMSG_CONT_S, &len);
+ else
+ switch (wtype) {
+ case SCROLL_W_QUIT:
+ p = msg_cmsg(sp, CMSG_CONT_Q, &len);
+ break;
+ case SCROLL_W_EX:
+ p = msg_cmsg(sp, CMSG_CONT_EX, &len);
+ break;
+ case SCROLL_W:
+ p = msg_cmsg(sp, CMSG_CONT, &len);
+ break;
+ default:
+ abort();
+ /* NOTREACHED */
+ }
+ (void)gp->scr_addstr(sp, p, len);
+
+ ++vip->totalcount;
+ vip->linecount = 0;
+
+ (void)gp->scr_clrtoeol(sp);
+ (void)gp->scr_refresh(sp, 0);
+
+ /* Get a single character from the terminal. */
+ if (continuep != NULL)
+ *continuep = 0;
+ for (;;) {
+ if (v_event_get(sp, &ev, 0, 0))
+ return;
+ if (ev.e_event == E_CHARACTER)
+ break;
+ if (ev.e_event == E_INTERRUPT) {
+ ev.e_c = CH_QUIT;
+ F_SET(gp, G_INTERRUPTED);
+ break;
+ }
+ (void)gp->scr_bell(sp);
+ }
+ switch (wtype) {
+ case SCROLL_W_QUIT:
+ if (ev.e_c == CH_QUIT)
+ F_SET(gp, G_INTERRUPTED);
+ break;
+ case SCROLL_W_EX:
+ if (ev.e_c == ':' && continuep != NULL)
+ *continuep = 1;
+ break;
+ case SCROLL_W:
+ break;
+ }
+}
+
+/*
+ * vs_divider --
+ * Draw a dividing line between the screen and the output.
+ */
+static void
+vs_divider(sp)
+ SCR *sp;
+{
+ GS *gp;
+ size_t len;
+
+#define DIVIDESTR "+=+=+=+=+=+=+=+"
+ len =
+ sizeof(DIVIDESTR) - 1 > sp->cols ? sp->cols : sizeof(DIVIDESTR) - 1;
+ gp = sp->gp;
+ (void)gp->scr_attr(sp, SA_INVERSE, 1);
+ (void)gp->scr_addstr(sp, DIVIDESTR, len);
+ (void)gp->scr_attr(sp, SA_INVERSE, 0);
+}
+
+/*
+ * vs_msgsave --
+ * Save a message for later display.
+ */
+static void
+vs_msgsave(sp, mt, p, len)
+ SCR *sp;
+ mtype_t mt;
+ char *p;
+ size_t len;
+{
+ GS *gp;
+ MSGS *mp_c, *mp_n;
+
+ /*
+ * We have to handle messages before we have any place to put them.
+ * If there's no screen support yet, allocate a msg structure, copy
+ * in the message, and queue it on the global structure. If we can't
+ * allocate memory here, we're genuinely screwed, dump the message
+ * to stderr in the (probably) vain hope that someone will see it.
+ */
+ CALLOC_GOTO(sp, mp_n, MSGS *, 1, sizeof(MSGS));
+ MALLOC_GOTO(sp, mp_n->buf, char *, len);
+
+ memmove(mp_n->buf, p, len);
+ mp_n->len = len;
+ mp_n->mtype = mt;
+
+ gp = sp->gp;
+ if ((mp_c = gp->msgq.lh_first) == NULL) {
+ LIST_INSERT_HEAD(&gp->msgq, mp_n, q);
+ } else {
+ for (; mp_c->q.le_next != NULL; mp_c = mp_c->q.le_next);
+ LIST_INSERT_AFTER(mp_c, mp_n, q);
+ }
+ return;
+
+alloc_err:
+ if (mp_n != NULL)
+ free(mp_n);
+ (void)fprintf(stderr, "%.*s\n", (int)len, p);
+}
diff --git a/contrib/nvi/vi/vs_refresh.c b/contrib/nvi/vi/vs_refresh.c
new file mode 100644
index 000000000000..81587608c1a2
--- /dev/null
+++ b/contrib/nvi/vi/vs_refresh.c
@@ -0,0 +1,885 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)vs_refresh.c 10.44 (Berkeley) 10/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+#define UPDATE_CURSOR 0x01 /* Update the cursor. */
+#define UPDATE_SCREEN 0x02 /* Flush to screen. */
+
+static void vs_modeline __P((SCR *));
+static int vs_paint __P((SCR *, u_int));
+
+/*
+ * v_repaint --
+ * Repaint selected lines from the screen.
+ *
+ * PUBLIC: int vs_repaint __P((SCR *, EVENT *));
+ */
+int
+vs_repaint(sp, evp)
+ SCR *sp;
+ EVENT *evp;
+{
+ SMAP *smp;
+
+ for (; evp->e_flno <= evp->e_tlno; ++evp->e_flno) {
+ smp = HMAP + evp->e_flno - 1;
+ SMAP_FLUSH(smp);
+ if (vs_line(sp, smp, NULL, NULL))
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * vs_refresh --
+ * Refresh all screens.
+ *
+ * PUBLIC: int vs_refresh __P((SCR *, int));
+ */
+int
+vs_refresh(sp, forcepaint)
+ SCR *sp;
+ int forcepaint;
+{
+ GS *gp;
+ SCR *tsp;
+ int need_refresh;
+ u_int priv_paint, pub_paint;
+
+ gp = sp->gp;
+
+ /*
+ * 1: Refresh the screen.
+ *
+ * If SC_SCR_REDRAW is set in the current screen, repaint everything
+ * that we can find, including status lines.
+ */
+ if (F_ISSET(sp, SC_SCR_REDRAW))
+ for (tsp = gp->dq.cqh_first;
+ tsp != (void *)&gp->dq; tsp = tsp->q.cqe_next)
+ if (tsp != sp)
+ F_SET(tsp, SC_SCR_REDRAW | SC_STATUS);
+
+ /*
+ * 2: Related or dirtied screens, or screens with messages.
+ *
+ * If related screens share a view into a file, they may have been
+ * modified as well. Refresh any screens that aren't exiting that
+ * have paint or dirty bits set. Always update their screens, we
+ * are not likely to get another chance. Finally, if we refresh any
+ * screens other than the current one, the cursor will be trashed.
+ */
+ pub_paint = SC_SCR_REFORMAT | SC_SCR_REDRAW;
+ priv_paint = VIP_CUR_INVALID | VIP_N_REFRESH;
+ if (O_ISSET(sp, O_NUMBER))
+ priv_paint |= VIP_N_RENUMBER;
+ for (tsp = gp->dq.cqh_first;
+ tsp != (void *)&gp->dq; tsp = tsp->q.cqe_next)
+ if (tsp != sp && !F_ISSET(tsp, SC_EXIT | SC_EXIT_FORCE) &&
+ (F_ISSET(tsp, pub_paint) ||
+ F_ISSET(VIP(tsp), priv_paint))) {
+ (void)vs_paint(tsp,
+ (F_ISSET(VIP(tsp), VIP_CUR_INVALID) ?
+ UPDATE_CURSOR : 0) | UPDATE_SCREEN);
+ F_SET(VIP(sp), VIP_CUR_INVALID);
+ }
+
+ /*
+ * 3: Refresh the current screen.
+ *
+ * Always refresh the current screen, it may be a cursor movement.
+ * Also, always do it last -- that way, SC_SCR_REDRAW can be set
+ * in the current screen only, and the screen won't flash.
+ */
+ if (vs_paint(sp, UPDATE_CURSOR | (!forcepaint &&
+ F_ISSET(sp, SC_SCR_VI) && KEYS_WAITING(sp) ? 0 : UPDATE_SCREEN)))
+ return (1);
+
+ /*
+ * 4: Paint any missing status lines.
+ *
+ * XXX
+ * This is fairly evil. Status lines are written using the vi message
+ * mechanism, since we have no idea how long they are. Since we may be
+ * painting screens other than the current one, we don't want to make
+ * the user wait. We depend heavily on there not being any other lines
+ * currently waiting to be displayed and the message truncation code in
+ * the msgq_status routine working.
+ *
+ * And, finally, if we updated any status lines, make sure the cursor
+ * gets back to where it belongs.
+ */
+ for (need_refresh = 0, tsp = gp->dq.cqh_first;
+ tsp != (void *)&gp->dq; tsp = tsp->q.cqe_next)
+ if (F_ISSET(tsp, SC_STATUS)) {
+ need_refresh = 1;
+ vs_resolve(tsp, sp, 0);
+ }
+ if (need_refresh)
+ (void)gp->scr_refresh(sp, 0);
+
+ /*
+ * A side-effect of refreshing the screen is that it's now ready
+ * for everything else, i.e. messages.
+ */
+ F_SET(sp, SC_SCR_VI);
+ return (0);
+}
+
+/*
+ * vs_paint --
+ * This is the guts of the vi curses screen code. The idea is that
+ * the SCR structure passed in contains the new coordinates of the
+ * screen. What makes this hard is that we don't know how big
+ * characters are, doing input can put the cursor in illegal places,
+ * and we're frantically trying to avoid repainting unless it's
+ * absolutely necessary. If you change this code, you'd better know
+ * what you're doing. It's subtle and quick to anger.
+ */
+static int
+vs_paint(sp, flags)
+ SCR *sp;
+ u_int flags;
+{
+ GS *gp;
+ SMAP *smp, tmp;
+ VI_PRIVATE *vip;
+ recno_t lastline, lcnt;
+ size_t cwtotal, cnt, len, notused, off, y;
+ int ch, didpaint, isempty, leftright_warp;
+ char *p;
+
+#define LNO sp->lno /* Current file line. */
+#define OLNO vip->olno /* Remembered file line. */
+#define CNO sp->cno /* Current file column. */
+#define OCNO vip->ocno /* Remembered file column. */
+#define SCNO vip->sc_col /* Current screen column. */
+
+ gp = sp->gp;
+ vip = VIP(sp);
+ didpaint = leftright_warp = 0;
+
+ /*
+ * 5: Reformat the lines.
+ *
+ * If the lines themselves have changed (:set list, for example),
+ * fill in the map from scratch. Adjust the screen that's being
+ * displayed if the leftright flag is set.
+ */
+ if (F_ISSET(sp, SC_SCR_REFORMAT)) {
+ /* Invalidate the line size cache. */
+ VI_SCR_CFLUSH(vip);
+
+ /* Toss vs_line() cached information. */
+ if (F_ISSET(sp, SC_SCR_TOP)) {
+ if (vs_sm_fill(sp, LNO, P_TOP))
+ return (1);
+ }
+ else if (F_ISSET(sp, SC_SCR_CENTER)) {
+ if (vs_sm_fill(sp, LNO, P_MIDDLE))
+ return (1);
+ } else
+ if (vs_sm_fill(sp, OOBLNO, P_TOP))
+ return (1);
+ F_SET(sp, SC_SCR_REDRAW);
+ }
+
+ /*
+ * 6: Line movement.
+ *
+ * Line changes can cause the top line to change as well. As
+ * before, if the movement is large, the screen is repainted.
+ *
+ * 6a: Small screens.
+ *
+ * Users can use the window, w300, w1200 and w9600 options to make
+ * the screen artificially small. The behavior of these options
+ * in the historic vi wasn't all that consistent, and, in fact, it
+ * was never documented how various screen movements affected the
+ * screen size. Generally, one of three things would happen:
+ * 1: The screen would expand in size, showing the line
+ * 2: The screen would scroll, showing the line
+ * 3: The screen would compress to its smallest size and
+ * repaint.
+ * In general, scrolling didn't cause compression (200^D was handled
+ * the same as ^D), movement to a specific line would (:N where N
+ * was 1 line below the screen caused a screen compress), and cursor
+ * movement would scroll if it was 11 lines or less, and compress if
+ * it was more than 11 lines. (And, no, I have no idea where the 11
+ * comes from.)
+ *
+ * What we do is try and figure out if the line is less than half of
+ * a full screen away. If it is, we expand the screen if there's
+ * room, and then scroll as necessary. The alternative is to compress
+ * and repaint.
+ *
+ * !!!
+ * This code is a special case from beginning to end. Unfortunately,
+ * home modems are still slow enough that it's worth having.
+ *
+ * XXX
+ * If the line a really long one, i.e. part of the line is on the
+ * screen but the column offset is not, we'll end up in the adjust
+ * code, when we should probably have compressed the screen.
+ */
+ if (IS_SMALL(sp))
+ if (LNO < HMAP->lno) {
+ lcnt = vs_sm_nlines(sp, HMAP, LNO, sp->t_maxrows);
+ if (lcnt <= HALFSCREEN(sp))
+ for (; lcnt && sp->t_rows != sp->t_maxrows;
+ --lcnt, ++sp->t_rows) {
+ ++TMAP;
+ if (vs_sm_1down(sp))
+ return (1);
+ }
+ else
+ goto small_fill;
+ } else if (LNO > TMAP->lno) {
+ lcnt = vs_sm_nlines(sp, TMAP, LNO, sp->t_maxrows);
+ if (lcnt <= HALFSCREEN(sp))
+ for (; lcnt && sp->t_rows != sp->t_maxrows;
+ --lcnt, ++sp->t_rows) {
+ if (vs_sm_next(sp, TMAP, TMAP + 1))
+ return (1);
+ ++TMAP;
+ if (vs_line(sp, TMAP, NULL, NULL))
+ return (1);
+ }
+ else {
+small_fill: (void)gp->scr_move(sp, LASTLINE(sp), 0);
+ (void)gp->scr_clrtoeol(sp);
+ for (; sp->t_rows > sp->t_minrows;
+ --sp->t_rows, --TMAP) {
+ (void)gp->scr_move(sp, TMAP - HMAP, 0);
+ (void)gp->scr_clrtoeol(sp);
+ }
+ if (vs_sm_fill(sp, LNO, P_FILL))
+ return (1);
+ F_SET(sp, SC_SCR_REDRAW);
+ goto adjust;
+ }
+ }
+
+ /*
+ * 6b: Line down, or current screen.
+ */
+ if (LNO >= HMAP->lno) {
+ /* Current screen. */
+ if (LNO <= TMAP->lno)
+ goto adjust;
+ if (F_ISSET(sp, SC_SCR_TOP))
+ goto top;
+ if (F_ISSET(sp, SC_SCR_CENTER))
+ goto middle;
+
+ /*
+ * If less than half a screen above the line, scroll down
+ * until the line is on the screen.
+ */
+ lcnt = vs_sm_nlines(sp, TMAP, LNO, HALFTEXT(sp));
+ if (lcnt < HALFTEXT(sp)) {
+ while (lcnt--)
+ if (vs_sm_1up(sp))
+ return (1);
+ goto adjust;
+ }
+ goto bottom;
+ }
+
+ /*
+ * 6c: If not on the current screen, may request center or top.
+ */
+ if (F_ISSET(sp, SC_SCR_TOP))
+ goto top;
+ if (F_ISSET(sp, SC_SCR_CENTER))
+ goto middle;
+
+ /*
+ * 6d: Line up.
+ */
+ lcnt = vs_sm_nlines(sp, HMAP, LNO, HALFTEXT(sp));
+ if (lcnt < HALFTEXT(sp)) {
+ /*
+ * If less than half a screen below the line, scroll up until
+ * the line is the first line on the screen. Special check so
+ * that if the screen has been emptied, we refill it.
+ */
+ if (db_exist(sp, HMAP->lno)) {
+ while (lcnt--)
+ if (vs_sm_1down(sp))
+ return (1);
+ goto adjust;
+ }
+
+ /*
+ * If less than a half screen from the bottom of the file,
+ * put the last line of the file on the bottom of the screen.
+ */
+bottom: if (db_last(sp, &lastline))
+ return (1);
+ tmp.lno = LNO;
+ tmp.coff = HMAP->coff;
+ tmp.soff = 1;
+ lcnt = vs_sm_nlines(sp, &tmp, lastline, sp->t_rows);
+ if (lcnt < HALFTEXT(sp)) {
+ if (vs_sm_fill(sp, lastline, P_BOTTOM))
+ return (1);
+ F_SET(sp, SC_SCR_REDRAW);
+ goto adjust;
+ }
+ /* It's not close, just put the line in the middle. */
+ goto middle;
+ }
+
+ /*
+ * If less than half a screen from the top of the file, put the first
+ * line of the file at the top of the screen. Otherwise, put the line
+ * in the middle of the screen.
+ */
+ tmp.lno = 1;
+ tmp.coff = HMAP->coff;
+ tmp.soff = 1;
+ lcnt = vs_sm_nlines(sp, &tmp, LNO, HALFTEXT(sp));
+ if (lcnt < HALFTEXT(sp)) {
+ if (vs_sm_fill(sp, 1, P_TOP))
+ return (1);
+ } else
+middle: if (vs_sm_fill(sp, LNO, P_MIDDLE))
+ return (1);
+ if (0) {
+top: if (vs_sm_fill(sp, LNO, P_TOP))
+ return (1);
+ }
+ F_SET(sp, SC_SCR_REDRAW);
+
+ /*
+ * At this point we know part of the line is on the screen. Since
+ * scrolling is done using logical lines, not physical, all of the
+ * line may not be on the screen. While that's not necessarily bad,
+ * if the part the cursor is on isn't there, we're going to lose.
+ * This can be tricky; if the line covers the entire screen, lno
+ * may be the same as both ends of the map, that's why we test BOTH
+ * the top and the bottom of the map. This isn't a problem for
+ * left-right scrolling, the cursor movement code handles the problem.
+ *
+ * There's a performance issue here if editing *really* long lines.
+ * This gets to the right spot by scrolling, and, in a binary, by
+ * scrolling hundreds of lines. If the adjustment looks like it's
+ * going to be a serious problem, refill the screen and repaint.
+ */
+adjust: if (!O_ISSET(sp, O_LEFTRIGHT) &&
+ (LNO == HMAP->lno || LNO == TMAP->lno)) {
+ cnt = vs_screens(sp, LNO, &CNO);
+ if (LNO == HMAP->lno && cnt < HMAP->soff)
+ if ((HMAP->soff - cnt) > HALFTEXT(sp)) {
+ HMAP->soff = cnt;
+ vs_sm_fill(sp, OOBLNO, P_TOP);
+ F_SET(sp, SC_SCR_REDRAW);
+ } else
+ while (cnt < HMAP->soff)
+ if (vs_sm_1down(sp))
+ return (1);
+ if (LNO == TMAP->lno && cnt > TMAP->soff)
+ if ((cnt - TMAP->soff) > HALFTEXT(sp)) {
+ TMAP->soff = cnt;
+ vs_sm_fill(sp, OOBLNO, P_BOTTOM);
+ F_SET(sp, SC_SCR_REDRAW);
+ } else
+ while (cnt > TMAP->soff)
+ if (vs_sm_1up(sp))
+ return (1);
+ }
+
+ /*
+ * If the screen needs to be repainted, skip cursor optimization.
+ * However, in the code above we skipped leftright scrolling on
+ * the grounds that the cursor code would handle it. Make sure
+ * the right screen is up.
+ */
+ if (F_ISSET(sp, SC_SCR_REDRAW)) {
+ if (O_ISSET(sp, O_LEFTRIGHT))
+ goto slow;
+ goto paint;
+ }
+
+ /*
+ * 7: Cursor movements (current screen only).
+ */
+ if (!LF_ISSET(UPDATE_CURSOR))
+ goto number;
+
+ /*
+ * Decide cursor position. If the line has changed, the cursor has
+ * moved over a tab, or don't know where the cursor was, reparse the
+ * line. Otherwise, we've just moved over fixed-width characters,
+ * and can calculate the left/right scrolling and cursor movement
+ * without reparsing the line. Note that we don't know which (if any)
+ * of the characters between the old and new cursor positions changed.
+ *
+ * XXX
+ * With some work, it should be possible to handle tabs quickly, at
+ * least in obvious situations, like moving right and encountering
+ * a tab, without reparsing the whole line.
+ *
+ * If the line we're working with has changed, reread it..
+ */
+ if (F_ISSET(vip, VIP_CUR_INVALID) || LNO != OLNO)
+ goto slow;
+
+ /* Otherwise, if nothing's changed, ignore the cursor. */
+ if (CNO == OCNO)
+ goto fast;
+
+ /*
+ * Get the current line. If this fails, we either have an empty
+ * file and can just repaint, or there's a real problem. This
+ * isn't a performance issue because there aren't any ways to get
+ * here repeatedly.
+ */
+ if (db_eget(sp, LNO, &p, &len, &isempty)) {
+ if (isempty)
+ goto slow;
+ return (1);
+ }
+
+#ifdef DEBUG
+ /* Sanity checking. */
+ if (CNO >= len && len != 0) {
+ msgq(sp, M_ERR, "Error: %s/%d: cno (%u) >= len (%u)",
+ tail(__FILE__), __LINE__, CNO, len);
+ return (1);
+ }
+#endif
+ /*
+ * The basic scheme here is to look at the characters in between
+ * the old and new positions and decide how big they are on the
+ * screen, and therefore, how many screen positions to move.
+ */
+ if (CNO < OCNO) {
+ /*
+ * 7a: Cursor moved left.
+ *
+ * Point to the old character. The old cursor position can
+ * be past EOL if, for example, we just deleted the rest of
+ * the line. In this case, since we don't know the width of
+ * the characters we traversed, we have to do it slowly.
+ */
+ p += OCNO;
+ cnt = (OCNO - CNO) + 1;
+ if (OCNO >= len)
+ goto slow;
+
+ /*
+ * Quick sanity check -- it's hard to figure out exactly when
+ * we cross a screen boundary as we do in the cursor right
+ * movement. If cnt is so large that we're going to cross the
+ * boundary no matter what, stop now.
+ */
+ if (SCNO + 1 + MAX_CHARACTER_COLUMNS < cnt)
+ goto slow;
+
+ /*
+ * Count up the widths of the characters. If it's a tab
+ * character, go do it the the slow way.
+ */
+ for (cwtotal = 0; cnt--; cwtotal += KEY_LEN(sp, ch))
+ if ((ch = *(u_char *)p--) == '\t')
+ goto slow;
+
+ /*
+ * Decrement the screen cursor by the total width of the
+ * characters minus 1.
+ */
+ cwtotal -= 1;
+
+ /*
+ * If we're moving left, and there's a wide character in the
+ * current position, go to the end of the character.
+ */
+ if (KEY_LEN(sp, ch) > 1)
+ cwtotal -= KEY_LEN(sp, ch) - 1;
+
+ /*
+ * If the new column moved us off of the current logical line,
+ * calculate a new one. If doing leftright scrolling, we've
+ * moved off of the current screen, as well.
+ */
+ if (SCNO < cwtotal)
+ goto slow;
+ SCNO -= cwtotal;
+ } else {
+ /*
+ * 7b: Cursor moved right.
+ *
+ * Point to the first character to the right.
+ */
+ p += OCNO + 1;
+ cnt = CNO - OCNO;
+
+ /*
+ * Count up the widths of the characters. If it's a tab
+ * character, go do it the the slow way. If we cross a
+ * screen boundary, we can quit.
+ */
+ for (cwtotal = SCNO; cnt--;) {
+ if ((ch = *(u_char *)p++) == '\t')
+ goto slow;
+ if ((cwtotal += KEY_LEN(sp, ch)) >= SCREEN_COLS(sp))
+ break;
+ }
+
+ /*
+ * Increment the screen cursor by the total width of the
+ * characters.
+ */
+ SCNO = cwtotal;
+
+ /* See screen change comment in section 6a. */
+ if (SCNO >= SCREEN_COLS(sp))
+ goto slow;
+ }
+
+ /*
+ * 7c: Fast cursor update.
+ *
+ * We have the current column, retrieve the current row.
+ */
+fast: (void)gp->scr_cursor(sp, &y, &notused);
+ goto done_cursor;
+
+ /*
+ * 7d: Slow cursor update.
+ *
+ * Walk through the map and find the current line.
+ */
+slow: for (smp = HMAP; smp->lno != LNO; ++smp);
+
+ /*
+ * 7e: Leftright scrolling adjustment.
+ *
+ * If doing left-right scrolling and the cursor movement has changed
+ * the displayed screen, scroll the screen left or right, unless we're
+ * updating the info line in which case we just scroll that one line.
+ * We adjust the offset up or down until we have a window that covers
+ * the current column, making sure that we adjust differently for the
+ * first screen as compared to subsequent ones.
+ */
+ if (O_ISSET(sp, O_LEFTRIGHT)) {
+ /*
+ * Get the screen column for this character, and correct
+ * for the number option offset.
+ */
+ cnt = vs_columns(sp, NULL, LNO, &CNO, NULL);
+ if (O_ISSET(sp, O_NUMBER))
+ cnt -= O_NUMBER_LENGTH;
+
+ /* Adjust the window towards the beginning of the line. */
+ off = smp->coff;
+ if (off >= cnt) {
+ do {
+ if (off >= O_VAL(sp, O_SIDESCROLL))
+ off -= O_VAL(sp, O_SIDESCROLL);
+ else {
+ off = 0;
+ break;
+ }
+ } while (off >= cnt);
+ goto shifted;
+ }
+
+ /* Adjust the window towards the end of the line. */
+ if (off == 0 && off + SCREEN_COLS(sp) < cnt ||
+ off != 0 && off + sp->cols < cnt) {
+ do {
+ off += O_VAL(sp, O_SIDESCROLL);
+ } while (off + sp->cols < cnt);
+
+shifted: /* Fill in screen map with the new offset. */
+ if (F_ISSET(sp, SC_TINPUT_INFO))
+ smp->coff = off;
+ else {
+ for (smp = HMAP; smp <= TMAP; ++smp)
+ smp->coff = off;
+ leftright_warp = 1;
+ }
+ goto paint;
+ }
+
+ /*
+ * We may have jumped here to adjust a leftright screen because
+ * redraw was set. If so, we have to paint the entire screen.
+ */
+ if (F_ISSET(sp, SC_SCR_REDRAW))
+ goto paint;
+ }
+
+ /*
+ * Update the screen lines for this particular file line until we
+ * have a new screen cursor position.
+ */
+ for (y = -1,
+ vip->sc_smap = NULL; smp <= TMAP && smp->lno == LNO; ++smp) {
+ if (vs_line(sp, smp, &y, &SCNO))
+ return (1);
+ if (y != -1) {
+ vip->sc_smap = smp;
+ break;
+ }
+ }
+ goto done_cursor;
+
+ /*
+ * 8: Repaint the entire screen.
+ *
+ * Lost big, do what you have to do. We flush the cache, since
+ * SC_SCR_REDRAW gets set when the screen isn't worth fixing, and
+ * it's simpler to repaint. So, don't trust anything that we
+ * think we know about it.
+ */
+paint: for (smp = HMAP; smp <= TMAP; ++smp)
+ SMAP_FLUSH(smp);
+ for (y = -1, vip->sc_smap = NULL, smp = HMAP; smp <= TMAP; ++smp) {
+ if (vs_line(sp, smp, &y, &SCNO))
+ return (1);
+ if (y != -1 && vip->sc_smap == NULL)
+ vip->sc_smap = smp;
+ }
+ /*
+ * If it's a small screen and we're redrawing, clear the unused lines,
+ * ex may have overwritten them.
+ */
+ if (F_ISSET(sp, SC_SCR_REDRAW) && IS_SMALL(sp))
+ for (cnt = sp->t_rows; cnt <= sp->t_maxrows; ++cnt) {
+ (void)gp->scr_move(sp, cnt, 0);
+ (void)gp->scr_clrtoeol(sp);
+ }
+
+ didpaint = 1;
+
+done_cursor:
+ /*
+ * Sanity checking. When the repainting code messes up, the usual
+ * result is we don't repaint the cursor and so sc_smap will be
+ * NULL. If we're debugging, die, otherwise restart from scratch.
+ */
+#ifdef DEBUG
+ if (vip->sc_smap == NULL)
+ abort();
+#else
+ if (vip->sc_smap == NULL) {
+ F_SET(sp, SC_SCR_REFORMAT);
+ return (vs_paint(sp, flags));
+ }
+#endif
+
+ /*
+ * 9: Set the remembered cursor values.
+ */
+ OCNO = CNO;
+ OLNO = LNO;
+
+ /*
+ * 10: Repaint the line numbers.
+ *
+ * If O_NUMBER is set and the VIP_N_RENUMBER bit is set, and we
+ * didn't repaint the screen, repaint all of the line numbers,
+ * they've changed.
+ */
+number: if (O_ISSET(sp, O_NUMBER) &&
+ F_ISSET(vip, VIP_N_RENUMBER) && !didpaint && vs_number(sp))
+ return (1);
+
+ /*
+ * 11: Update the mode line, position the cursor, and flush changes.
+ *
+ * If we warped the screen, we have to refresh everything.
+ */
+ if (leftright_warp)
+ LF_SET(UPDATE_CURSOR | UPDATE_SCREEN);
+
+ if (LF_ISSET(UPDATE_SCREEN) && !IS_ONELINE(sp) &&
+ !F_ISSET(vip, VIP_S_MODELINE) && !F_ISSET(sp, SC_TINPUT_INFO))
+ vs_modeline(sp);
+
+ if (LF_ISSET(UPDATE_CURSOR)) {
+ (void)gp->scr_move(sp, y, SCNO);
+
+ /*
+ * XXX
+ * If the screen shifted, we recalculate the "most favorite"
+ * cursor position. Vi won't know that we've warped the
+ * screen, so it's going to have a wrong idea about where the
+ * cursor should be. This is vi's problem, and fixing it here
+ * is a gross layering violation.
+ */
+ if (leftright_warp)
+ (void)vs_column(sp, &sp->rcm);
+ }
+
+ if (LF_ISSET(UPDATE_SCREEN))
+ (void)gp->scr_refresh(sp, F_ISSET(vip, VIP_N_EX_PAINT));
+
+ /* 12: Clear the flags that are handled by this routine. */
+ F_CLR(sp, SC_SCR_CENTER | SC_SCR_REDRAW | SC_SCR_REFORMAT | SC_SCR_TOP);
+ F_CLR(vip, VIP_CUR_INVALID |
+ VIP_N_EX_PAINT | VIP_N_REFRESH | VIP_N_RENUMBER | VIP_S_MODELINE);
+
+ return (0);
+
+#undef LNO
+#undef OLNO
+#undef CNO
+#undef OCNO
+#undef SCNO
+}
+
+/*
+ * vs_modeline --
+ * Update the mode line.
+ */
+static void
+vs_modeline(sp)
+ SCR *sp;
+{
+ static char * const modes[] = {
+ "215|Append", /* SM_APPEND */
+ "216|Change", /* SM_CHANGE */
+ "217|Command", /* SM_COMMAND */
+ "218|Insert", /* SM_INSERT */
+ "219|Replace", /* SM_REPLACE */
+ };
+ GS *gp;
+ size_t cols, curcol, curlen, endpoint, len, midpoint;
+ const char *t;
+ int ellipsis;
+ char *p, buf[20];
+
+ gp = sp->gp;
+
+ /*
+ * We put down the file name, the ruler, the mode and the dirty flag.
+ * If there's not enough room, there's not enough room, we don't play
+ * any special games. We try to put the ruler in the middle and the
+ * mode and dirty flag at the end.
+ *
+ * !!!
+ * Leave the last character blank, in case it's a really dumb terminal
+ * with hardware scroll. Second, don't paint the last character in the
+ * screen, SunOS 4.1.1 and Ultrix 4.2 curses won't let you.
+ *
+ * Move to the last line on the screen.
+ */
+ (void)gp->scr_move(sp, LASTLINE(sp), 0);
+
+ /* If more than one screen in the display, show the file name. */
+ curlen = 0;
+ if (IS_SPLIT(sp)) {
+ for (p = sp->frp->name; *p != '\0'; ++p);
+ for (ellipsis = 0, cols = sp->cols / 2; --p > sp->frp->name;) {
+ if (*p == '/') {
+ ++p;
+ break;
+ }
+ if ((curlen += KEY_LEN(sp, *p)) > cols) {
+ ellipsis = 3;
+ curlen +=
+ KEY_LEN(sp, '.') * 3 + KEY_LEN(sp, ' ');
+ while (curlen > cols) {
+ ++p;
+ curlen -= KEY_LEN(sp, *p);
+ }
+ break;
+ }
+ }
+ if (ellipsis) {
+ while (ellipsis--)
+ (void)gp->scr_addstr(sp,
+ KEY_NAME(sp, '.'), KEY_LEN(sp, '.'));
+ (void)gp->scr_addstr(sp,
+ KEY_NAME(sp, ' '), KEY_LEN(sp, ' '));
+ }
+ for (; *p != '\0'; ++p)
+ (void)gp->scr_addstr(sp,
+ KEY_NAME(sp, *p), KEY_LEN(sp, *p));
+ }
+
+ /* Clear the rest of the line. */
+ (void)gp->scr_clrtoeol(sp);
+
+ /*
+ * Display the ruler. If we're not at the midpoint yet, move there.
+ * Otherwise, add in two extra spaces.
+ *
+ * Adjust the current column for the fact that the editor uses it as
+ * a zero-based number.
+ *
+ * XXX
+ * Assume that numbers, commas, and spaces only take up a single
+ * column on the screen.
+ */
+ cols = sp->cols - 1;
+ if (O_ISSET(sp, O_RULER)) {
+ vs_column(sp, &curcol);
+ len =
+ snprintf(buf, sizeof(buf), "%lu,%lu", sp->lno, curcol + 1);
+
+ midpoint = (cols - ((len + 1) / 2)) / 2;
+ if (curlen < midpoint) {
+ (void)gp->scr_move(sp, LASTLINE(sp), midpoint);
+ curlen += len;
+ } else if (curlen + 2 + len < cols) {
+ (void)gp->scr_addstr(sp, " ", 2);
+ curlen += 2 + len;
+ }
+ (void)gp->scr_addstr(sp, buf, len);
+ }
+
+ /*
+ * Display the mode and the modified flag, as close to the end of the
+ * line as possible, but guaranteeing at least two spaces between the
+ * ruler and the modified flag.
+ */
+#define MODESIZE 9
+ endpoint = cols;
+ if (O_ISSET(sp, O_SHOWMODE)) {
+ if (F_ISSET(sp->ep, F_MODIFIED))
+ --endpoint;
+ t = msg_cat(sp, modes[sp->showmode], &len);
+ endpoint -= len;
+ }
+
+ if (endpoint > curlen + 2) {
+ (void)gp->scr_move(sp, LASTLINE(sp), endpoint);
+ if (O_ISSET(sp, O_SHOWMODE)) {
+ if (F_ISSET(sp->ep, F_MODIFIED))
+ (void)gp->scr_addstr(sp,
+ KEY_NAME(sp, '*'), KEY_LEN(sp, '*'));
+ (void)gp->scr_addstr(sp, t, len);
+ }
+ }
+}
diff --git a/contrib/nvi/vi/vs_relative.c b/contrib/nvi/vi/vs_relative.c
new file mode 100644
index 000000000000..c92c10c43e2e
--- /dev/null
+++ b/contrib/nvi/vi/vs_relative.c
@@ -0,0 +1,305 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)vs_relative.c 10.11 (Berkeley) 5/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * vs_column --
+ * Return the logical column of the cursor in the line.
+ *
+ * PUBLIC: int vs_column __P((SCR *, size_t *));
+ */
+int
+vs_column(sp, colp)
+ SCR *sp;
+ size_t *colp;
+{
+ VI_PRIVATE *vip;
+
+ vip = VIP(sp);
+
+ *colp = (O_ISSET(sp, O_LEFTRIGHT) ?
+ vip->sc_smap->coff : (vip->sc_smap->soff - 1) * sp->cols) +
+ vip->sc_col - (O_ISSET(sp, O_NUMBER) ? O_NUMBER_LENGTH : 0);
+ return (0);
+}
+
+/*
+ * vs_screens --
+ * Return the screens necessary to display the line, or if specified,
+ * the physical character column within the line, including space
+ * required for the O_NUMBER and O_LIST options.
+ *
+ * PUBLIC: size_t vs_screens __P((SCR *, recno_t, size_t *));
+ */
+size_t
+vs_screens(sp, lno, cnop)
+ SCR *sp;
+ recno_t lno;
+ size_t *cnop;
+{
+ size_t cols, screens;
+
+ /* Left-right screens are simple, it's always 1. */
+ if (O_ISSET(sp, O_LEFTRIGHT))
+ return (1);
+
+ /*
+ * Check for a cached value. We maintain a cache because, if the
+ * line is large, this routine gets called repeatedly. One other
+ * hack, lots of time the cursor is on column one, which is an easy
+ * one.
+ */
+ if (cnop == NULL) {
+ if (VIP(sp)->ss_lno == lno)
+ return (VIP(sp)->ss_screens);
+ } else if (*cnop == 0)
+ return (1);
+
+ /* Figure out how many columns the line/column needs. */
+ cols = vs_columns(sp, NULL, lno, cnop, NULL);
+
+ screens = (cols / sp->cols + (cols % sp->cols ? 1 : 0));
+ if (screens == 0)
+ screens = 1;
+
+ /* Cache the value. */
+ if (cnop == NULL) {
+ VIP(sp)->ss_lno = lno;
+ VIP(sp)->ss_screens = screens;
+ }
+ return (screens);
+}
+
+/*
+ * vs_columns --
+ * Return the screen columns necessary to display the line, or,
+ * if specified, the physical character column within the line.
+ *
+ * PUBLIC: size_t vs_columns __P((SCR *, char *, recno_t, size_t *, size_t *));
+ */
+size_t
+vs_columns(sp, lp, lno, cnop, diffp)
+ SCR *sp;
+ char *lp;
+ recno_t lno;
+ size_t *cnop, *diffp;
+{
+ size_t chlen, cno, curoff, last, len, scno;
+ int ch, leftright, listset;
+ char *p;
+
+ /* Need the line to go any further. */
+ if (lp == NULL) {
+ (void)db_get(sp, lno, 0, &lp, &len);
+ if (len == 0)
+ goto done;
+ }
+
+ /* Missing or empty lines are easy. */
+ if (lp == NULL) {
+done: if (diffp != NULL) /* XXX */
+ *diffp = 0;
+ return (0);
+ }
+
+ /* Store away the values of the list and leftright edit options. */
+ listset = O_ISSET(sp, O_LIST);
+ leftright = O_ISSET(sp, O_LEFTRIGHT);
+
+ /*
+ * Initialize the pointer into the buffer and screen and current
+ * offsets.
+ */
+ p = lp;
+ curoff = scno = 0;
+
+ /* Leading number if O_NUMBER option set. */
+ if (O_ISSET(sp, O_NUMBER))
+ scno += O_NUMBER_LENGTH;
+
+ /* Macro to return the display length of any signal character. */
+#define CHLEN(val) (ch = *(u_char *)p++) == '\t' && \
+ !listset ? TAB_OFF(val) : KEY_LEN(sp, ch);
+
+ /*
+ * If folding screens (the historic vi screen format), past the end
+ * of the current screen, and the character was a tab, reset the
+ * current screen column to 0, and the total screen columns to the
+ * last column of the screen. Otherwise, display the rest of the
+ * character in the next screen.
+ */
+#define TAB_RESET { \
+ curoff += chlen; \
+ if (!leftright && curoff >= sp->cols) \
+ if (ch == '\t') { \
+ curoff = 0; \
+ scno -= scno % sp->cols; \
+ } else \
+ curoff -= sp->cols; \
+}
+ if (cnop == NULL)
+ while (len--) {
+ chlen = CHLEN(curoff);
+ last = scno;
+ scno += chlen;
+ TAB_RESET;
+ }
+ else
+ for (cno = *cnop;; --cno) {
+ chlen = CHLEN(curoff);
+ last = scno;
+ scno += chlen;
+ TAB_RESET;
+ if (cno == 0)
+ break;
+ }
+
+ /* Add the trailing '$' if the O_LIST option set. */
+ if (listset && cnop == NULL)
+ scno += KEY_LEN(sp, '$');
+
+ /*
+ * The text input screen code needs to know how much additional
+ * room the last two characters required, so that it can handle
+ * tab character displays correctly.
+ */
+ if (diffp != NULL)
+ *diffp = scno - last;
+ return (scno);
+}
+
+/*
+ * vs_rcm --
+ * Return the physical column from the line that will display a
+ * character closest to the currently most attractive character
+ * position (which is stored as a screen column).
+ *
+ * PUBLIC: size_t vs_rcm __P((SCR *, recno_t, int));
+ */
+size_t
+vs_rcm(sp, lno, islast)
+ SCR *sp;
+ recno_t lno;
+ int islast;
+{
+ size_t len;
+
+ /* Last character is easy, and common. */
+ if (islast) {
+ if (db_get(sp, lno, 0, NULL, &len) || len == 0)
+ return (0);
+ return (len - 1);
+ }
+
+ /* First character is easy, and common. */
+ if (sp->rcm == 0)
+ return (0);
+
+ return (vs_colpos(sp, lno, sp->rcm));
+}
+
+/*
+ * vs_colpos --
+ * Return the physical column from the line that will display a
+ * character closest to the specified screen column.
+ *
+ * PUBLIC: size_t vs_colpos __P((SCR *, recno_t, size_t));
+ */
+size_t
+vs_colpos(sp, lno, cno)
+ SCR *sp;
+ recno_t lno;
+ size_t cno;
+{
+ size_t chlen, curoff, len, llen, off, scno;
+ int ch, leftright, listset;
+ char *lp, *p;
+
+ /* Need the line to go any further. */
+ (void)db_get(sp, lno, 0, &lp, &llen);
+
+ /* Missing or empty lines are easy. */
+ if (lp == NULL || llen == 0)
+ return (0);
+
+ /* Store away the values of the list and leftright edit options. */
+ listset = O_ISSET(sp, O_LIST);
+ leftright = O_ISSET(sp, O_LEFTRIGHT);
+
+ /* Discard screen (logical) lines. */
+ off = cno / sp->cols;
+ cno %= sp->cols;
+ for (scno = 0, p = lp, len = llen; off--;) {
+ for (; len && scno < sp->cols; --len)
+ scno += CHLEN(scno);
+
+ /*
+ * If reached the end of the physical line, return the last
+ * physical character in the line.
+ */
+ if (len == 0)
+ return (llen - 1);
+
+ /*
+ * If folding screens (the historic vi screen format), past
+ * the end of the current screen, and the character was a tab,
+ * reset the current screen column to 0. Otherwise, the rest
+ * of the character is displayed in the next screen.
+ */
+ if (leftright && ch == '\t')
+ scno = 0;
+ else
+ scno -= sp->cols;
+ }
+
+ /* Step through the line until reach the right character or EOL. */
+ for (curoff = scno; len--;) {
+ chlen = CHLEN(curoff);
+
+ /*
+ * If we've reached the specific character, there are three
+ * cases.
+ *
+ * 1: scno == cno, i.e. the current character ends at the
+ * screen character we care about.
+ * a: off < llen - 1, i.e. not the last character in
+ * the line, return the offset of the next character.
+ * b: else return the offset of the last character.
+ * 2: scno != cno, i.e. this character overruns the character
+ * we care about, return the offset of this character.
+ */
+ if ((scno += chlen) >= cno) {
+ off = p - lp;
+ return (scno == cno ?
+ (off < llen - 1 ? off : llen - 1) : off - 1);
+ }
+
+ TAB_RESET;
+ }
+
+ /* No such character; return the start of the last character. */
+ return (llen - 1);
+}
diff --git a/usr.bin/vi/svi/svi_smap.c b/contrib/nvi/vi/vs_smap.c
index 6d06d8ecd784..af38057e815f 100644
--- a/usr.bin/vi/svi/svi_smap.c
+++ b/contrib/nvi/vi/vs_smap.c
@@ -1,38 +1,16 @@
/*-
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * See the LICENSE file for redistribution information.
*/
+#include "config.h"
+
#ifndef lint
-static char sccsid[] = "@(#)svi_smap.c 8.46 (Berkeley) 8/14/94";
+static const char sccsid[] = "@(#)vs_smap.c 10.25 (Berkeley) 7/12/96";
#endif /* not lint */
#include <sys/types.h>
@@ -41,45 +19,56 @@ static char sccsid[] = "@(#)svi_smap.c 8.46 (Berkeley) 8/14/94";
#include <bitstring.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
+#include "../common/common.h"
#include "vi.h"
-#include "../vi/vcmd.h"
-#include "svi_screen.h"
-
-static int svi_deleteln __P((SCR *, int));
-static int svi_insertln __P((SCR *, int));
-static int svi_sm_delete __P((SCR *, EXF *, recno_t));
-static int svi_sm_down __P((SCR *, EXF *,
- MARK *, recno_t, enum sctype, SMAP *));
-static int svi_sm_erase __P((SCR *));
-static int svi_sm_insert __P((SCR *, EXF *, recno_t));
-static int svi_sm_reset __P((SCR *, EXF *, recno_t));
-static int svi_sm_up __P((SCR *, EXF *,
- MARK *, recno_t, enum sctype, SMAP *));
+
+static int vs_deleteln __P((SCR *, int));
+static int vs_insertln __P((SCR *, int));
+static int vs_sm_delete __P((SCR *, recno_t));
+static int vs_sm_down __P((SCR *, MARK *, recno_t, scroll_t, SMAP *));
+static int vs_sm_erase __P((SCR *));
+static int vs_sm_insert __P((SCR *, recno_t));
+static int vs_sm_reset __P((SCR *, recno_t));
+static int vs_sm_up __P((SCR *, MARK *, recno_t, scroll_t, SMAP *));
/*
- * svi_change --
+ * vs_change --
* Make a change to the screen.
+ *
+ * PUBLIC: int vs_change __P((SCR *, recno_t, lnop_t));
*/
int
-svi_change(sp, ep, lno, op)
+vs_change(sp, lno, op)
SCR *sp;
- EXF *ep;
recno_t lno;
- enum operation op;
+ lnop_t op;
{
+ VI_PRIVATE *vip;
SMAP *p;
- size_t oldy, oldx;
+ size_t cnt, oldy, oldx;
+
+ vip = VIP(sp);
+
+ /*
+ * XXX
+ * Very nasty special case. The historic vi code displays a single
+ * space (or a '$' if the list option is set) for the first line in
+ * an "empty" file. If we "insert" a line, that line gets scrolled
+ * down, not repainted, so it's incorrect when we refresh the screen.
+ * The vi text input functions detect it explicitly and don't insert
+ * a new line.
+ *
+ * Check for line #2 before going to the end of the file.
+ */
+ if ((op == LINE_APPEND && lno == 0 || op == LINE_INSERT && lno == 1) &&
+ !db_exist(sp, 2)) {
+ lno = 1;
+ op = LINE_RESET;
+ }
/* Appending is the same as inserting, if the line is incremented. */
if (op == LINE_APPEND) {
@@ -102,18 +91,18 @@ svi_change(sp, ep, lno, op)
abort();
/* NOTREACHED */
case LINE_DELETE:
- for (p = HMAP; p <= TMAP; ++p)
+ for (p = HMAP, cnt = sp->t_rows; cnt--; ++p)
--p->lno;
if (sp->lno >= lno)
--sp->lno;
- F_SET(sp, S_RENUMBER);
+ F_SET(vip, VIP_N_RENUMBER);
break;
case LINE_INSERT:
- for (p = HMAP; p <= TMAP; ++p)
+ for (p = HMAP, cnt = sp->t_rows; cnt--; ++p)
++p->lno;
if (sp->lno >= lno)
++sp->lno;
- F_SET(sp, S_RENUMBER);
+ F_SET(vip, VIP_N_RENUMBER);
break;
case LINE_RESET:
break;
@@ -121,43 +110,55 @@ svi_change(sp, ep, lno, op)
return (0);
}
- F_SET(SVP(sp), SVI_SCREENDIRTY);
+ F_SET(vip, VIP_N_REFRESH);
- /* Invalidate the cursor, if it's on this line. */
+ /*
+ * Invalidate the line size cache, and invalidate the cursor if it's
+ * on this line,
+ */
+ VI_SCR_CFLUSH(vip);
if (sp->lno == lno)
- F_SET(SVP(sp), SVI_CUR_INVALID);
+ F_SET(vip, VIP_CUR_INVALID);
- /* Invalidate the line size cache. */
- SVI_SCR_CFLUSH(SVP(sp));
+ /*
+ * If ex modifies the screen after ex output is already on the screen
+ * or if we've switched into ex canonical mode, don't touch it -- we'll
+ * get scrolling wrong, at best.
+ */
+ if (!F_ISSET(sp, SC_TINPUT_INFO) &&
+ (F_ISSET(sp, SC_SCR_EXWROTE) || VIP(sp)->totalcount > 1)) {
+ F_SET(vip, VIP_N_EX_REDRAW);
+ return (0);
+ }
- getyx(stdscr, oldy, oldx);
+ /* Save and restore the cursor for these routines. */
+ (void)sp->gp->scr_cursor(sp, &oldy, &oldx);
switch (op) {
case LINE_DELETE:
- if (svi_sm_delete(sp, ep, lno))
+ if (vs_sm_delete(sp, lno))
return (1);
- F_SET(sp, S_RENUMBER);
+ F_SET(vip, VIP_N_RENUMBER);
break;
case LINE_INSERT:
- if (svi_sm_insert(sp, ep, lno))
+ if (vs_sm_insert(sp, lno))
return (1);
- F_SET(sp, S_RENUMBER);
+ F_SET(vip, VIP_N_RENUMBER);
break;
case LINE_RESET:
- if (svi_sm_reset(sp, ep, lno))
+ if (vs_sm_reset(sp, lno))
return (1);
break;
default:
abort();
}
- MOVEA(sp, oldy, oldx);
-
+ (void)sp->gp->scr_move(sp, oldy, oldx);
return (0);
}
/*
- * svi_sm_fill --
+ * vs_sm_fill --
* Fill in the screen map, placing the specified line at the
* right position. There isn't any way to tell if an SMAP
* entry has been filled in, so this routine had better be
@@ -167,82 +168,96 @@ svi_change(sp, ep, lno, op)
* Unexported interface: if lno is OOBLNO, P_TOP means that the HMAP
* slot is already filled in, P_BOTTOM means that the TMAP slot is
* already filled in, and we just finish up the job.
+ *
+ * PUBLIC: int vs_sm_fill __P((SCR *, recno_t, pos_t));
*/
int
-svi_sm_fill(sp, ep, lno, pos)
+vs_sm_fill(sp, lno, pos)
SCR *sp;
- EXF *ep;
recno_t lno;
- enum position pos;
+ pos_t pos;
{
SMAP *p, tmp;
+ size_t cnt;
/* Flush all cached information from the SMAP. */
- for (p = HMAP; p <= TMAP; ++p)
+ for (p = HMAP, cnt = sp->t_rows; cnt--; ++p)
SMAP_FLUSH(p);
- /* If the map is filled, the screen must be redrawn. */
- F_SET(sp, S_REDRAW);
+ /*
+ * If the map is filled, the screen must be redrawn.
+ *
+ * XXX
+ * This is a bug. We should try and figure out if the desired line
+ * is already in the map or close by -- scrolling the screen would
+ * be a lot better than redrawing.
+ */
+ F_SET(sp, SC_SCR_REDRAW);
switch (pos) {
case P_FILL:
tmp.lno = 1;
- tmp.off = 1;
+ tmp.coff = 0;
+ tmp.soff = 1;
/* See if less than half a screen from the top. */
- if (svi_sm_nlines(sp, ep,
+ if (vs_sm_nlines(sp,
&tmp, lno, HALFTEXT(sp)) <= HALFTEXT(sp)) {
lno = 1;
goto top;
}
/* See if less than half a screen from the bottom. */
- if (file_lline(sp, ep, &tmp.lno))
+ if (db_last(sp, &tmp.lno))
return (1);
- if (!O_ISSET(sp, O_LEFTRIGHT))
- tmp.off = svi_opt_screens(sp, ep, tmp.lno, NULL);
- if (svi_sm_nlines(sp, ep,
+ tmp.coff = 0;
+ tmp.soff = vs_screens(sp, tmp.lno, NULL);
+ if (vs_sm_nlines(sp,
&tmp, lno, HALFTEXT(sp)) <= HALFTEXT(sp)) {
TMAP->lno = tmp.lno;
- if (!O_ISSET(sp, O_LEFTRIGHT))
- TMAP->off = tmp.off;
+ TMAP->coff = tmp.coff;
+ TMAP->soff = tmp.soff;
goto bottom;
}
goto middle;
case P_TOP:
if (lno != OOBLNO) {
top: HMAP->lno = lno;
- HMAP->off = 1;
+ HMAP->coff = 0;
+ HMAP->soff = 1;
}
/* If we fail, just punt. */
- for (p = HMAP; p < TMAP; ++p)
- if (svi_sm_next(sp, ep, p, p + 1))
+ for (p = HMAP, cnt = sp->t_rows; --cnt; ++p)
+ if (vs_sm_next(sp, p, p + 1))
goto err;
break;
case P_MIDDLE:
/* If we fail, guess that the file is too small. */
-middle: p = HMAP + (TMAP - HMAP) / 2;
- for (p->lno = lno, p->off = 1; p > HMAP; --p)
- if (svi_sm_prev(sp, ep, p, p - 1)) {
+middle: p = HMAP + sp->t_rows / 2;
+ p->lno = lno;
+ p->coff = 0;
+ p->soff = 1;
+ for (; p > HMAP; --p)
+ if (vs_sm_prev(sp, p, p - 1)) {
lno = 1;
goto top;
}
/* If we fail, just punt. */
- p = HMAP + (TMAP - HMAP) / 2;
+ p = HMAP + sp->t_rows / 2;
for (; p < TMAP; ++p)
- if (svi_sm_next(sp, ep, p, p + 1))
+ if (vs_sm_next(sp, p, p + 1))
goto err;
break;
case P_BOTTOM:
if (lno != OOBLNO) {
TMAP->lno = lno;
- if (!O_ISSET(sp, O_LEFTRIGHT))
- TMAP->off = svi_opt_screens(sp, ep, lno, NULL);
+ TMAP->coff = 0;
+ TMAP->soff = vs_screens(sp, lno, NULL);
}
/* If we fail, guess that the file is too small. */
bottom: for (p = TMAP; p > HMAP; --p)
- if (svi_sm_prev(sp, ep, p, p - 1)) {
+ if (vs_sm_prev(sp, p, p - 1)) {
lno = 1;
goto top;
}
@@ -253,46 +268,39 @@ bottom: for (p = TMAP; p > HMAP; --p)
return (0);
/*
- * Try and put *something* on the screen. If this fails,
- * we have a serious hard error.
+ * Try and put *something* on the screen. If this fails, we have a
+ * serious hard error.
*/
err: HMAP->lno = 1;
- HMAP->off = 1;
+ HMAP->coff = 0;
+ HMAP->soff = 1;
for (p = HMAP; p < TMAP; ++p)
- if (svi_sm_next(sp, ep, p, p + 1))
+ if (vs_sm_next(sp, p, p + 1))
return (1);
return (0);
}
/*
- * For the routines svi_sm_reset, svi_sm_delete and svi_sm_insert: if the
- * screen only contains one line, or, if the line is the entire screen, this
- * gets fairly exciting. Skip the fun and simply return if there's only one
- * line in the screen, or just call fill. Fill may not be entirely accurate,
- * i.e. we may be painting the screen with something not even close to the
- * cursor, but it's not like we're into serious performance issues here, and
- * the refresh routine will fix it for us.
+ * For the routines vs_sm_reset, vs_sm_delete and vs_sm_insert: if the
+ * screen contains only a single line (whether because the screen is small
+ * or the line large), it gets fairly exciting. Skip the fun, set a flag
+ * so the screen map is refilled and the screen redrawn, and return. This
+ * is amazingly slow, but it's not clear that anyone will care.
*/
-#define TOO_WEIRD { \
- if (cnt_orig >= sp->t_rows) { \
- if (cnt_orig == 1) \
- return (0); \
- if (file_gline(sp, ep, lno, NULL) == NULL) \
- if (file_lline(sp, ep, &lno)) \
- return (1); \
- F_SET(sp, S_REDRAW); \
- return (svi_sm_fill(sp, ep, lno, P_TOP)); \
+#define HANDLE_WEIRDNESS(cnt) { \
+ if (cnt >= sp->t_rows) { \
+ F_SET(sp, SC_SCR_REFORMAT); \
+ return (0); \
} \
}
/*
- * svi_sm_delete --
+ * vs_sm_delete --
* Delete a line out of the SMAP.
*/
static int
-svi_sm_delete(sp, ep, lno)
+vs_sm_delete(sp, lno)
SCR *sp;
- EXF *ep;
recno_t lno;
{
SMAP *p, *t;
@@ -309,11 +317,11 @@ svi_sm_delete(sp, ep, lno)
for (cnt_orig = 1, t = p + 1;
t <= TMAP && t->lno == lno; ++cnt_orig, ++t);
- TOO_WEIRD;
+ HANDLE_WEIRDNESS(cnt_orig);
/* Delete that many lines from the screen. */
- MOVE(sp, p - HMAP, 0);
- if (svi_deleteln(sp, cnt_orig))
+ (void)sp->gp->scr_move(sp, p - HMAP, 0);
+ if (vs_deleteln(sp, cnt_orig))
return (1);
/* Shift the screen map up. */
@@ -325,10 +333,10 @@ svi_sm_delete(sp, ep, lno)
/* Display the new lines. */
for (p = TMAP - cnt_orig;;) {
- if (p < TMAP && svi_sm_next(sp, ep, p, p + 1))
+ if (p < TMAP && vs_sm_next(sp, p, p + 1))
return (1);
- /* svi_sm_next() flushed the cache. */
- if (svi_line(sp, ep, ++p, NULL, NULL))
+ /* vs_sm_next() flushed the cache. */
+ if (vs_line(sp, ++p, NULL, NULL))
return (1);
if (p == TMAP)
break;
@@ -337,29 +345,28 @@ svi_sm_delete(sp, ep, lno)
}
/*
- * svi_sm_insert --
+ * vs_sm_insert --
* Insert a line into the SMAP.
*/
static int
-svi_sm_insert(sp, ep, lno)
+vs_sm_insert(sp, lno)
SCR *sp;
- EXF *ep;
recno_t lno;
{
SMAP *p, *t;
- size_t cnt_orig, cnt;
+ size_t cnt_orig, cnt, coff;
+
+ /* Save the offset. */
+ coff = HMAP->coff;
/*
* Find the line in the map, find out how many screen lines
* needed to display the line.
*/
for (p = HMAP; p->lno != lno; ++p);
- if (O_ISSET(sp, O_LEFTRIGHT))
- cnt_orig = 1;
- else
- cnt_orig = svi_opt_screens(sp, ep, lno, NULL);
- TOO_WEIRD;
+ cnt_orig = vs_screens(sp, lno, NULL);
+ HANDLE_WEIRDNESS(cnt_orig);
/*
* The lines left in the screen override the number of screen
@@ -370,8 +377,8 @@ svi_sm_insert(sp, ep, lno)
cnt_orig = cnt;
/* Push down that many lines. */
- MOVE(sp, p - HMAP, 0);
- if (svi_insertln(sp, cnt_orig))
+ (void)sp->gp->scr_move(sp, p - HMAP, 0);
+ if (vs_insertln(sp, cnt_orig))
return (1);
/* Shift the screen map down. */
@@ -384,22 +391,22 @@ svi_sm_insert(sp, ep, lno)
/* Fill in the SMAP for the new lines, and display. */
for (cnt = 1, t = p; cnt <= cnt_orig; ++t, ++cnt) {
t->lno = lno;
- t->off = cnt;
+ t->coff = coff;
+ t->soff = cnt;
SMAP_FLUSH(t);
- if (svi_line(sp, ep, t, NULL, NULL))
+ if (vs_line(sp, t, NULL, NULL))
return (1);
}
return (0);
}
/*
- * svi_sm_reset --
+ * vs_sm_reset --
* Reset a line in the SMAP.
*/
static int
-svi_sm_reset(sp, ep, lno)
+vs_sm_reset(sp, lno)
SCR *sp;
- EXF *ep;
recno_t lno;
{
SMAP *p, *t;
@@ -417,15 +424,15 @@ svi_sm_reset(sp, ep, lno)
} else {
for (cnt_orig = 0,
t = p; t <= TMAP && t->lno == lno; ++cnt_orig, ++t);
- cnt_new = svi_opt_screens(sp, ep, lno, NULL);
+ cnt_new = vs_screens(sp, lno, NULL);
}
- TOO_WEIRD;
+ HANDLE_WEIRDNESS(cnt_orig);
if (cnt_orig == cnt_new) {
do {
SMAP_FLUSH(p);
- if (svi_line(sp, ep, p, NULL, NULL))
+ if (vs_line(sp, p, NULL, NULL))
return (1);
} while (++p < t);
return (0);
@@ -443,20 +450,23 @@ svi_sm_reset(sp, ep, lno)
if (diff > cnt)
diff = cnt;
- /* Push down the extra lines. */
- MOVE(sp, p - HMAP, 0);
- if (svi_insertln(sp, diff))
- return (1);
+ /* If there are any following lines, push them down. */
+ if (cnt > 1) {
+ (void)sp->gp->scr_move(sp, p - HMAP, 0);
+ if (vs_insertln(sp, diff))
+ return (1);
- /* Shift the screen map down. */
- memmove(p + diff, p, (((TMAP - p) - diff) + 1) * sizeof(SMAP));
+ /* Shift the screen map down. */
+ memmove(p + diff, p,
+ (((TMAP - p) - diff) + 1) * sizeof(SMAP));
+ }
/* Fill in the SMAP for the replaced line, and display. */
for (cnt = 1, t = p; cnt_new-- && t <= TMAP; ++t, ++cnt) {
t->lno = lno;
- t->off = cnt;
+ t->soff = cnt;
SMAP_FLUSH(t);
- if (svi_line(sp, ep, t, NULL, NULL))
+ if (vs_line(sp, t, NULL, NULL))
return (1);
}
} else {
@@ -464,8 +474,8 @@ svi_sm_reset(sp, ep, lno)
diff = cnt_orig - cnt_new;
/* Delete that many lines from the screen. */
- MOVE(sp, p - HMAP, 0);
- if (svi_deleteln(sp, diff))
+ (void)sp->gp->scr_move(sp, p - HMAP, 0);
+ if (vs_deleteln(sp, diff))
return (1);
/* Shift the screen map up. */
@@ -474,18 +484,18 @@ svi_sm_reset(sp, ep, lno)
/* Fill in the SMAP for the replaced line, and display. */
for (cnt = 1, t = p; cnt_new--; ++t, ++cnt) {
t->lno = lno;
- t->off = cnt;
+ t->soff = cnt;
SMAP_FLUSH(t);
- if (svi_line(sp, ep, t, NULL, NULL))
+ if (vs_line(sp, t, NULL, NULL))
return (1);
}
/* Display the new lines at the bottom of the screen. */
for (t = TMAP - diff;;) {
- if (t < TMAP && svi_sm_next(sp, ep, t, t + 1))
+ if (t < TMAP && vs_sm_next(sp, t, t + 1))
return (1);
- /* svi_sm_next() flushed the cache. */
- if (svi_line(sp, ep, ++t, NULL, NULL))
+ /* vs_sm_next() flushed the cache. */
+ if (vs_line(sp, ++t, NULL, NULL))
return (1);
if (t == TMAP)
break;
@@ -495,17 +505,18 @@ svi_sm_reset(sp, ep, lno)
}
/*
- * svi_sm_scroll
+ * vs_sm_scroll
* Scroll the SMAP up/down count logical lines. Different
* semantics based on the vi command, *sigh*.
+ *
+ * PUBLIC: int vs_sm_scroll __P((SCR *, MARK *, recno_t, scroll_t));
*/
int
-svi_sm_scroll(sp, ep, rp, count, scmd)
+vs_sm_scroll(sp, rp, count, scmd)
SCR *sp;
- EXF *ep;
MARK *rp;
recno_t count;
- enum sctype scmd;
+ scroll_t scmd;
{
SMAP *smp;
@@ -514,10 +525,10 @@ svi_sm_scroll(sp, ep, rp, count, scmd)
* (although for ^E and ^Y it may not). In any case, the scroll
* routines move the cursor to draw things.
*/
- F_SET(SVP(sp), SVI_CUR_INVALID);
+ F_SET(VIP(sp), VIP_CUR_INVALID);
/* Find the cursor in the screen. */
- if (svi_sm_cursor(sp, ep, &smp))
+ if (vs_sm_cursor(sp, &smp))
return (1);
switch (scmd) {
@@ -525,14 +536,14 @@ svi_sm_scroll(sp, ep, rp, count, scmd)
case CNTRL_U:
case CNTRL_Y:
case Z_CARAT:
- if (svi_sm_down(sp, ep, rp, count, scmd, smp))
+ if (vs_sm_down(sp, rp, count, scmd, smp))
return (1);
break;
case CNTRL_D:
case CNTRL_E:
case CNTRL_F:
case Z_PLUS:
- if (svi_sm_up(sp, ep, rp, count, scmd, smp))
+ if (vs_sm_up(sp, rp, count, scmd, smp))
return (1);
break;
default:
@@ -551,27 +562,26 @@ svi_sm_scroll(sp, ep, rp, count, scmd)
* Live with it.
*/
if (scmd != CNTRL_E && scmd != CNTRL_Y &&
- rp->cno == 0 && nonblank(sp, ep, rp->lno, &rp->cno))
+ rp->cno == 0 && nonblank(sp, rp->lno, &rp->cno))
return (1);
return (0);
}
/*
- * svi_sm_up --
+ * vs_sm_up --
* Scroll the SMAP up count logical lines.
*/
static int
-svi_sm_up(sp, ep, rp, count, scmd, smp)
+vs_sm_up(sp, rp, count, scmd, smp)
SCR *sp;
- EXF *ep;
MARK *rp;
- enum sctype scmd;
+ scroll_t scmd;
recno_t count;
SMAP *smp;
{
int cursor_set, echanged, zset;
- SMAP s1, s2;
+ SMAP *ssmp, s1, s2;
/*
* Check to see if movement is possible.
@@ -584,67 +594,67 @@ svi_sm_up(sp, ep, rp, count, scmd, smp)
* the cursor wasn't at the end of the map, test to see if the map
* is mostly empty.
*/
- if (svi_sm_next(sp, ep, TMAP, &s1))
+ if (vs_sm_next(sp, TMAP, &s1))
return (1);
- if (s1.lno > TMAP->lno && !file_gline(sp, ep, s1.lno, NULL)) {
+ if (s1.lno > TMAP->lno && !db_exist(sp, s1.lno)) {
if (scmd == CNTRL_E || scmd == Z_PLUS || smp == TMAP) {
- v_eof(sp, ep, NULL);
+ v_eof(sp, NULL);
return (1);
}
- if (svi_sm_next(sp, ep, smp, &s1))
+ if (vs_sm_next(sp, smp, &s1))
return (1);
- if (s1.lno > smp->lno && !file_gline(sp, ep, s1.lno, NULL)) {
- v_eof(sp, ep, NULL);
+ if (s1.lno > smp->lno && !db_exist(sp, s1.lno)) {
+ v_eof(sp, NULL);
return (1);
}
}
/*
- * Small screens: see svi/svi_refresh.c:svi_refresh, section 2b.
+ * Small screens: see vs_refresh.c section 6a.
*
* If it's a small screen, and the movement isn't larger than a
* screen, i.e some context will remain, open up the screen and
- * display by scrolling. In this case, the cursor moves to the
- * first line displayed. Otherwise, erase/compress and repaint,
- * and move the cursor to the first line in the screen. Note,
- * the ^F command is always in the latter case, for historical
+ * display by scrolling. In this case, the cursor moves down one
+ * line for each line displayed. Otherwise, erase/compress and
+ * repaint, and move the cursor to the first line in the screen.
+ * Note, the ^F command is always in the latter case, for historical
* reasons.
*/
cursor_set = 0;
- if (ISSMALLSCREEN(sp)) {
+ if (IS_SMALL(sp)) {
if (count >= sp->t_maxrows || scmd == CNTRL_F) {
s1 = TMAP[0];
- if (svi_sm_erase(sp))
+ if (vs_sm_erase(sp))
return (1);
for (; count--; s1 = s2) {
- if (svi_sm_next(sp, ep, &s1, &s2))
+ if (vs_sm_next(sp, &s1, &s2))
return (1);
- if (s2.lno != s1.lno &&
- !file_gline(sp, ep, s2.lno, NULL))
+ if (s2.lno != s1.lno && !db_exist(sp, s2.lno))
break;
}
TMAP[0] = s2;
- if (svi_sm_fill(sp, ep, OOBLNO, P_BOTTOM))
+ if (vs_sm_fill(sp, OOBLNO, P_BOTTOM))
return (1);
- return (svi_sm_position(sp, ep, rp, 0, P_TOP));
+ return (vs_sm_position(sp, rp, 0, P_TOP));
}
+ cursor_set = scmd == CNTRL_E || vs_sm_cursor(sp, &ssmp);
for (; count &&
sp->t_rows != sp->t_maxrows; --count, ++sp->t_rows) {
- if (svi_sm_next(sp, ep, TMAP, &s1))
+ if (vs_sm_next(sp, TMAP, &s1))
return (1);
- if (TMAP->lno != s1.lno &&
- !file_gline(sp, ep, s1.lno, NULL))
+ if (TMAP->lno != s1.lno && !db_exist(sp, s1.lno))
break;
*++TMAP = s1;
- /* svi_sm_next() flushed the cache. */
- if (svi_line(sp, ep, TMAP, NULL, NULL))
+ /* vs_sm_next() flushed the cache. */
+ if (vs_line(sp, TMAP, NULL, NULL))
return (1);
- if (scmd != CNTRL_E && !cursor_set) {
- cursor_set = 1;
- rp->lno = TMAP->lno;
- rp->cno = TMAP->c_sboff;
- }
+ if (!cursor_set)
+ ++ssmp;
+ }
+ if (!cursor_set) {
+ rp->lno = ssmp->lno;
+ rp->cno = ssmp->c_sboff;
}
if (count == 0)
return (0);
@@ -652,15 +662,15 @@ svi_sm_up(sp, ep, rp, count, scmd, smp)
for (echanged = zset = 0; count; --count) {
/* Decide what would show up on the screen. */
- if (svi_sm_next(sp, ep, TMAP, &s1))
+ if (vs_sm_next(sp, TMAP, &s1))
return (1);
/* If the line doesn't exist, we're done. */
- if (TMAP->lno != s1.lno && !file_gline(sp, ep, s1.lno, NULL))
+ if (TMAP->lno != s1.lno && !db_exist(sp, s1.lno))
break;
/* Scroll the screen cursor up one logical line. */
- if (svi_sm_1up(sp, ep))
+ if (vs_sm_1up(sp))
return (1);
switch (scmd) {
case CNTRL_E:
@@ -696,14 +706,16 @@ svi_sm_up(sp, ep, rp, count, scmd, smp)
*/
if (echanged) {
rp->lno = smp->lno;
- rp->cno =
- svi_cm_private(sp, ep, smp->lno, smp->off, sp->rcm);
+ rp->cno = vs_colpos(sp, smp->lno,
+ (O_ISSET(sp, O_LEFTRIGHT) ?
+ smp->coff : (smp->soff - 1) * sp->cols) +
+ sp->rcm % sp->cols);
}
return (0);
case CNTRL_F:
/*
- * If there are more lines, the ^F command is always
- * positioned at the first line of the screen.
+ * If there are more lines, the ^F command is positioned at
+ * the first line of the screen.
*/
if (!count) {
smp = HMAP;
@@ -718,8 +730,7 @@ svi_sm_up(sp, ep, rp, count, scmd, smp)
* file is smaller than the screen.)
*/
for (; count; --count, ++smp)
- if (smp == TMAP ||
- !file_gline(sp, ep, smp[1].lno, NULL))
+ if (smp == TMAP || !db_exist(sp, smp[1].lno))
break;
break;
case Z_PLUS:
@@ -729,7 +740,7 @@ svi_sm_up(sp, ep, rp, count, scmd, smp)
abort();
}
- if (!SMAP_CACHE(smp) && svi_line(sp, ep, smp, NULL, NULL))
+ if (!SMAP_CACHE(smp) && vs_line(sp, smp, NULL, NULL))
return (1);
rp->lno = smp->lno;
rp->cno = smp->c_sboff;
@@ -737,122 +748,129 @@ svi_sm_up(sp, ep, rp, count, scmd, smp)
}
/*
- * svi_sm_1up --
+ * vs_sm_1up --
* Scroll the SMAP up one.
+ *
+ * PUBLIC: int vs_sm_1up __P((SCR *));
*/
int
-svi_sm_1up(sp, ep)
+vs_sm_1up(sp)
SCR *sp;
- EXF *ep;
{
/*
- * Delete the top line of the screen. Shift the screen map up.
- * Display a new line at the bottom of the screen.
+ * Delete the top line of the screen. Shift the screen map
+ * up and display a new line at the bottom of the screen.
*/
- MOVE(sp, 0, 0);
- if (svi_deleteln(sp, 1))
+ (void)sp->gp->scr_move(sp, 0, 0);
+ if (vs_deleteln(sp, 1))
return (1);
/* One-line screens can fail. */
- if (HMAP == TMAP) {
- if (svi_sm_next(sp, ep, TMAP, TMAP))
+ if (IS_ONELINE(sp)) {
+ if (vs_sm_next(sp, TMAP, TMAP))
return (1);
} else {
memmove(HMAP, HMAP + 1, (sp->rows - 1) * sizeof(SMAP));
- if (svi_sm_next(sp, ep, TMAP - 1, TMAP))
+ if (vs_sm_next(sp, TMAP - 1, TMAP))
return (1);
}
- /* svi_sm_next() flushed the cache. */
- if (svi_line(sp, ep, TMAP, NULL, NULL))
- return (1);
- return (0);
+ /* vs_sm_next() flushed the cache. */
+ return (vs_line(sp, TMAP, NULL, NULL));
}
/*
- * svi_deleteln --
+ * vs_deleteln --
* Delete a line a la curses, make sure to put the information
* line and other screens back.
*/
static int
-svi_deleteln(sp, cnt)
+vs_deleteln(sp, cnt)
SCR *sp;
int cnt;
{
+ GS *gp;
size_t oldy, oldx;
- getyx(stdscr, oldy, oldx);
- while (cnt--) {
- deleteln();
- MOVE(sp, INFOLINE(sp) - 1, 0);
- insertln();
- MOVEA(sp, oldy, oldx);
+ gp = sp->gp;
+ if (IS_ONELINE(sp))
+ (void)gp->scr_clrtoeol(sp);
+ else {
+ (void)gp->scr_cursor(sp, &oldy, &oldx);
+ while (cnt--) {
+ (void)gp->scr_deleteln(sp);
+ (void)gp->scr_move(sp, LASTLINE(sp), 0);
+ (void)gp->scr_insertln(sp);
+ (void)gp->scr_move(sp, oldy, oldx);
+ }
}
return (0);
}
/*
- * svi_sm_down --
+ * vs_sm_down --
* Scroll the SMAP down count logical lines.
*/
static int
-svi_sm_down(sp, ep, rp, count, scmd, smp)
+vs_sm_down(sp, rp, count, scmd, smp)
SCR *sp;
- EXF *ep;
MARK *rp;
recno_t count;
SMAP *smp;
- enum sctype scmd;
+ scroll_t scmd;
{
- SMAP s1, s2;
+ SMAP *ssmp, s1, s2;
int cursor_set, ychanged, zset;
/* Check to see if movement is possible. */
- if (HMAP->lno == 1 && HMAP->off == 1 &&
+ if (HMAP->lno == 1 &&
+ (O_ISSET(sp, O_LEFTRIGHT) || HMAP->soff == 1) &&
(scmd == CNTRL_Y || scmd == Z_CARAT || smp == HMAP)) {
v_sof(sp, NULL);
return (1);
}
/*
- * Small screens: see svi/svi_refresh.c:svi_refresh, section 2b.
+ * Small screens: see vs_refresh.c section 6a.
*
* If it's a small screen, and the movement isn't larger than a
* screen, i.e some context will remain, open up the screen and
- * display by scrolling. In this case, the cursor moves to the
- * first line displayed. Otherwise, erase/compress and repaint,
- * and move the cursor to the first line in the screen. Note,
- * the ^B command is always in the latter case, for historical
+ * display by scrolling. In this case, the cursor moves up one
+ * line for each line displayed. Otherwise, erase/compress and
+ * repaint, and move the cursor to the first line in the screen.
+ * Note, the ^B command is always in the latter case, for historical
* reasons.
*/
cursor_set = scmd == CNTRL_Y;
- if (ISSMALLSCREEN(sp)) {
+ if (IS_SMALL(sp)) {
if (count >= sp->t_maxrows || scmd == CNTRL_B) {
s1 = HMAP[0];
- if (svi_sm_erase(sp))
+ if (vs_sm_erase(sp))
return (1);
for (; count--; s1 = s2) {
- if (svi_sm_prev(sp, ep, &s1, &s2))
+ if (vs_sm_prev(sp, &s1, &s2))
return (1);
- if (s2.lno == 1 && s2.off == 1)
+ if (s2.lno == 1 &&
+ (O_ISSET(sp, O_LEFTRIGHT) || s2.soff == 1))
break;
}
HMAP[0] = s2;
- if (svi_sm_fill(sp, ep, OOBLNO, P_TOP))
+ if (vs_sm_fill(sp, OOBLNO, P_TOP))
return (1);
- return (svi_sm_position(sp, ep, rp, 0, P_BOTTOM));
+ return (vs_sm_position(sp, rp, 0, P_BOTTOM));
}
+ cursor_set = scmd == CNTRL_Y || vs_sm_cursor(sp, &ssmp);
for (; count &&
sp->t_rows != sp->t_maxrows; --count, ++sp->t_rows) {
- if (HMAP->lno == 1 || HMAP->off == 1)
+ if (HMAP->lno == 1 &&
+ (O_ISSET(sp, O_LEFTRIGHT) || HMAP->soff == 1))
break;
++TMAP;
- if (svi_sm_1down(sp, ep))
+ if (vs_sm_1down(sp))
return (1);
- if (scmd != CNTRL_Y && !cursor_set) {
- cursor_set = 1;
- if (svi_sm_position(sp, ep, rp, 0, P_BOTTOM))
- return (1);
- }
+ }
+ if (!cursor_set) {
+ rp->lno = ssmp->lno;
+ rp->cno = ssmp->c_sboff;
}
if (count == 0)
return (0);
@@ -860,11 +878,12 @@ svi_sm_down(sp, ep, rp, count, scmd, smp)
for (ychanged = zset = 0; count; --count) {
/* If the line doesn't exist, we're done. */
- if (HMAP->lno == 1 && HMAP->off == 1)
+ if (HMAP->lno == 1 &&
+ (O_ISSET(sp, O_LEFTRIGHT) || HMAP->soff == 1))
break;
/* Scroll the screen and cursor down one logical line. */
- if (svi_sm_1down(sp, ep))
+ if (vs_sm_1down(sp))
return (1);
switch (scmd) {
case CNTRL_Y:
@@ -893,11 +912,14 @@ svi_sm_down(sp, ep, rp, count, scmd, smp)
switch (scmd) {
case CNTRL_B:
/*
- * If there are more lines, the ^B command is always
- * positioned at the last line of the screen.
+ * If there are more lines, the ^B command is positioned at
+ * the last line of the screen. However, the line may not
+ * exist.
*/
if (!count) {
- smp = TMAP;
+ for (smp = TMAP; smp > HMAP; --smp)
+ if (db_exist(sp, smp->lno))
+ break;
break;
}
/* FALLTHROUGH */
@@ -920,8 +942,10 @@ svi_sm_down(sp, ep, rp, count, scmd, smp)
*/
if (ychanged) {
rp->lno = smp->lno;
- rp->cno =
- svi_cm_private(sp, ep, smp->lno, smp->off, sp->rcm);
+ rp->cno = vs_colpos(sp, smp->lno,
+ (O_ISSET(sp, O_LEFTRIGHT) ?
+ smp->coff : (smp->soff - 1) * sp->cols) +
+ sp->rcm % sp->cols);
}
return (0);
case Z_CARAT:
@@ -931,7 +955,7 @@ svi_sm_down(sp, ep, rp, count, scmd, smp)
abort();
}
- if (!SMAP_CACHE(smp) && svi_line(sp, ep, smp, NULL, NULL))
+ if (!SMAP_CACHE(smp) && vs_line(sp, smp, NULL, NULL))
return (1);
rp->lno = smp->lno;
rp->cno = smp->c_sboff;
@@ -939,80 +963,94 @@ svi_sm_down(sp, ep, rp, count, scmd, smp)
}
/*
- * svi_sm_erase --
+ * vs_sm_erase --
* Erase the small screen area for the scrolling functions.
*/
static int
-svi_sm_erase(sp)
+vs_sm_erase(sp)
SCR *sp;
{
- MOVE(sp, INFOLINE(sp), 0);
- clrtoeol();
+ GS *gp;
+
+ gp = sp->gp;
+ (void)gp->scr_move(sp, LASTLINE(sp), 0);
+ (void)gp->scr_clrtoeol(sp);
for (; sp->t_rows > sp->t_minrows; --sp->t_rows, --TMAP) {
- MOVE(sp, TMAP - HMAP, 0);
- clrtoeol();
+ (void)gp->scr_move(sp, TMAP - HMAP, 0);
+ (void)gp->scr_clrtoeol(sp);
}
return (0);
}
/*
- * svi_sm_1down --
+ * vs_sm_1down --
* Scroll the SMAP down one.
+ *
+ * PUBLIC: int vs_sm_1down __P((SCR *));
*/
int
-svi_sm_1down(sp, ep)
+vs_sm_1down(sp)
SCR *sp;
- EXF *ep;
{
/*
- * Clear the bottom line of the screen, insert a line at the top
- * of the screen. Shift the screen map down, display a new line
- * at the top of the screen.
+ * Insert a line at the top of the screen. Shift the screen map
+ * down and display a new line at the top of the screen.
*/
- MOVE(sp, sp->t_rows, 0);
- clrtoeol();
- MOVE(sp, 0, 0);
- if (svi_insertln(sp, 1))
+ (void)sp->gp->scr_move(sp, 0, 0);
+ if (vs_insertln(sp, 1))
return (1);
- memmove(HMAP + 1, HMAP, (sp->rows - 1) * sizeof(SMAP));
- if (svi_sm_prev(sp, ep, HMAP + 1, HMAP))
- return (1);
- /* svi_sm_prev() flushed the cache. */
- if (svi_line(sp, ep, HMAP, NULL, NULL))
- return (1);
- return (0);
+
+ /* One-line screens can fail. */
+ if (IS_ONELINE(sp)) {
+ if (vs_sm_prev(sp, HMAP, HMAP))
+ return (1);
+ } else {
+ memmove(HMAP + 1, HMAP, (sp->rows - 1) * sizeof(SMAP));
+ if (vs_sm_prev(sp, HMAP + 1, HMAP))
+ return (1);
+ }
+ /* vs_sm_prev() flushed the cache. */
+ return (vs_line(sp, HMAP, NULL, NULL));
}
/*
- * svi_insertln --
+ * vs_insertln --
* Insert a line a la curses, make sure to put the information
* line and other screens back.
*/
static int
-svi_insertln(sp, cnt)
+vs_insertln(sp, cnt)
SCR *sp;
int cnt;
{
+ GS *gp;
size_t oldy, oldx;
- getyx(stdscr, oldy, oldx);
- while (cnt--) {
- MOVE(sp, INFOLINE(sp) - 1, 0);
- deleteln();
- MOVEA(sp, oldy, oldx);
- insertln();
+ gp = sp->gp;
+ if (IS_ONELINE(sp)) {
+ (void)gp->scr_move(sp, LASTLINE(sp), 0);
+ (void)gp->scr_clrtoeol(sp);
+ } else {
+ (void)gp->scr_cursor(sp, &oldy, &oldx);
+ while (cnt--) {
+ (void)gp->scr_move(sp, LASTLINE(sp) - 1, 0);
+ (void)gp->scr_deleteln(sp);
+ (void)gp->scr_move(sp, oldy, oldx);
+ (void)gp->scr_insertln(sp);
+ }
}
return (0);
}
/*
- * svi_sm_next --
+ * vs_sm_next --
* Fill in the next entry in the SMAP.
+ *
+ * PUBLIC: int vs_sm_next __P((SCR *, SMAP *, SMAP *));
*/
int
-svi_sm_next(sp, ep, p, t)
+vs_sm_next(sp, p, t)
SCR *sp;
- EXF *ep;
SMAP *p, *t;
{
size_t lcnt;
@@ -1020,52 +1058,56 @@ svi_sm_next(sp, ep, p, t)
SMAP_FLUSH(t);
if (O_ISSET(sp, O_LEFTRIGHT)) {
t->lno = p->lno + 1;
- t->off = p->off;
+ t->coff = p->coff;
} else {
- lcnt = svi_opt_screens(sp, ep, p->lno, NULL);
- if (lcnt == p->off) {
+ lcnt = vs_screens(sp, p->lno, NULL);
+ if (lcnt == p->soff) {
t->lno = p->lno + 1;
- t->off = 1;
+ t->soff = 1;
} else {
t->lno = p->lno;
- t->off = p->off + 1;
+ t->soff = p->soff + 1;
}
}
return (0);
}
/*
- * svi_sm_prev --
+ * vs_sm_prev --
* Fill in the previous entry in the SMAP.
+ *
+ * PUBLIC: int vs_sm_prev __P((SCR *, SMAP *, SMAP *));
*/
int
-svi_sm_prev(sp, ep, p, t)
+vs_sm_prev(sp, p, t)
SCR *sp;
- EXF *ep;
SMAP *p, *t;
{
SMAP_FLUSH(t);
if (O_ISSET(sp, O_LEFTRIGHT)) {
t->lno = p->lno - 1;
- t->off = p->off;
- } else if (p->off != 1) {
- t->lno = p->lno;
- t->off = p->off - 1;
+ t->coff = p->coff;
} else {
- t->lno = p->lno - 1;
- t->off = svi_opt_screens(sp, ep, t->lno, NULL);
+ if (p->soff != 1) {
+ t->lno = p->lno;
+ t->soff = p->soff - 1;
+ } else {
+ t->lno = p->lno - 1;
+ t->soff = vs_screens(sp, t->lno, NULL);
+ }
}
return (t->lno == 0);
}
/*
- * svi_sm_cursor --
+ * vs_sm_cursor --
* Return the SMAP entry referenced by the cursor.
+ *
+ * PUBLIC: int vs_sm_cursor __P((SCR *, SMAP **));
*/
int
-svi_sm_cursor(sp, ep, smpp)
+vs_sm_cursor(sp, smpp)
SCR *sp;
- EXF *ep;
SMAP **smpp;
{
SMAP *p;
@@ -1084,7 +1126,7 @@ svi_sm_cursor(sp, ep, smpp)
*smpp = p;
return (0);
}
- if (!SMAP_CACHE(p) && svi_line(sp, ep, p, NULL, NULL))
+ if (!SMAP_CACHE(p) && vs_line(sp, p, NULL, NULL))
return (1);
if (p->c_eboff >= sp->cno) {
*smpp = p;
@@ -1097,18 +1139,19 @@ svi_sm_cursor(sp, ep, smpp)
}
/*
- * svi_sm_position --
+ * vs_sm_position --
* Return the line/column of the top, middle or last line on the screen.
* (The vi H, M and L commands.) Here because only the screen routines
* know what's really out there.
+ *
+ * PUBLIC: int vs_sm_position __P((SCR *, MARK *, u_long, pos_t));
*/
int
-svi_sm_position(sp, ep, rp, cnt, pos)
+vs_sm_position(sp, rp, cnt, pos)
SCR *sp;
- EXF *ep;
MARK *rp;
u_long cnt;
- enum position pos;
+ pos_t pos;
{
SMAP *smp;
recno_t last;
@@ -1124,8 +1167,8 @@ svi_sm_position(sp, ep, rp, cnt, pos)
if (cnt > TMAP - HMAP)
goto sof;
smp = HMAP + cnt;
- if (cnt && file_gline(sp, ep, smp->lno, NULL) == NULL) {
-sof: msgq(sp, M_BERR, "Movement past the end-of-screen");
+ if (cnt && !db_exist(sp, smp->lno)) {
+sof: msgq(sp, M_BERR, "220|Movement past the end-of-screen");
return (1);
}
break;
@@ -1136,8 +1179,8 @@ sof: msgq(sp, M_BERR, "Movement past the end-of-screen");
* If the screen isn't filled, find the middle of what's
* real and move there.
*/
- if (file_gline(sp, ep, TMAP->lno, NULL) == NULL) {
- if (file_lline(sp, ep, &last))
+ if (!db_exist(sp, TMAP->lno)) {
+ if (db_last(sp, &last))
return (1);
for (smp = TMAP; smp->lno > last && smp > HMAP; --smp);
if (smp > HMAP)
@@ -1155,13 +1198,13 @@ sof: msgq(sp, M_BERR, "Movement past the end-of-screen");
if (cnt > TMAP - HMAP)
goto eof;
smp = TMAP - cnt;
- if (file_gline(sp, ep, smp->lno, NULL) == NULL) {
- if (file_lline(sp, ep, &last))
+ if (!db_exist(sp, smp->lno)) {
+ if (db_last(sp, &last))
return (1);
for (; smp->lno > last && smp > HMAP; --smp);
if (cnt > smp - HMAP) {
eof: msgq(sp, M_BERR,
- "Movement past the beginning-of-screen");
+ "221|Movement past the beginning-of-screen");
return (1);
}
smp -= cnt;
@@ -1172,7 +1215,7 @@ eof: msgq(sp, M_BERR,
}
/* Make sure that the cached information is valid. */
- if (!SMAP_CACHE(smp) && svi_line(sp, ep, smp, NULL, NULL))
+ if (!SMAP_CACHE(smp) && vs_line(sp, smp, NULL, NULL))
return (1);
rp->lno = smp->lno;
rp->cno = smp->c_sboff;
@@ -1181,14 +1224,15 @@ eof: msgq(sp, M_BERR,
}
/*
- * svi_sm_nlines --
+ * vs_sm_nlines --
* Return the number of screen lines from an SMAP entry to the
* start of some file line, less than a maximum value.
+ *
+ * PUBLIC: recno_t vs_sm_nlines __P((SCR *, SMAP *, recno_t, size_t));
*/
recno_t
-svi_sm_nlines(sp, ep, from_sp, to_lno, max)
+vs_sm_nlines(sp, from_sp, to_lno, max)
SCR *sp;
- EXF *ep;
SMAP *from_sp;
recno_t to_lno;
size_t max;
@@ -1200,17 +1244,17 @@ svi_sm_nlines(sp, ep, from_sp, to_lno, max)
from_sp->lno - to_lno : to_lno - from_sp->lno);
if (from_sp->lno == to_lno)
- return (from_sp->off - 1);
+ return (from_sp->soff - 1);
if (from_sp->lno > to_lno) {
- lcnt = from_sp->off - 1; /* Correct for off-by-one. */
+ lcnt = from_sp->soff - 1; /* Correct for off-by-one. */
for (lno = from_sp->lno; --lno >= to_lno && lcnt <= max;)
- lcnt += svi_opt_screens(sp, ep, lno, NULL);
+ lcnt += vs_screens(sp, lno, NULL);
} else {
lno = from_sp->lno;
- lcnt = (svi_opt_screens(sp, ep, lno, NULL) - from_sp->off) + 1;
+ lcnt = (vs_screens(sp, lno, NULL) - from_sp->soff) + 1;
for (; ++lno < to_lno && lcnt <= max;)
- lcnt += svi_opt_screens(sp, ep, lno, NULL);
+ lcnt += vs_screens(sp, lno, NULL);
}
return (lcnt);
}
diff --git a/contrib/nvi/vi/vs_split.c b/contrib/nvi/vi/vs_split.c
new file mode 100644
index 000000000000..d01735490e69
--- /dev/null
+++ b/contrib/nvi/vi/vs_split.c
@@ -0,0 +1,607 @@
+/*-
+ * Copyright (c) 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)vs_split.c 10.31 (Berkeley) 10/13/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+static SCR *vs_getbg __P((SCR *, char *));
+
+/*
+ * vs_split --
+ * Create a new screen.
+ *
+ * PUBLIC: int vs_split __P((SCR *, SCR *, int));
+ */
+int
+vs_split(sp, new, ccl)
+ SCR *sp, *new;
+ int ccl; /* Colon-command line split. */
+{
+ GS *gp;
+ SMAP *smp;
+ size_t half;
+ int issmallscreen, splitup;
+
+ gp = sp->gp;
+
+ /* Check to see if it's possible. */
+ /* XXX: The IS_ONELINE fix will change this, too. */
+ if (sp->rows < 4) {
+ msgq(sp, M_ERR,
+ "222|Screen must be larger than %d lines to split", 4 - 1);
+ return (1);
+ }
+
+ /* Wait for any messages in the screen. */
+ vs_resolve(sp, NULL, 1);
+
+ half = sp->rows / 2;
+ if (ccl && half > 6)
+ half = 6;
+
+ /* Get a new screen map. */
+ CALLOC(sp, _HMAP(new), SMAP *, SIZE_HMAP(sp), sizeof(SMAP));
+ if (_HMAP(new) == NULL)
+ return (1);
+ _HMAP(new)->lno = sp->lno;
+ _HMAP(new)->coff = 0;
+ _HMAP(new)->soff = 1;
+
+ /*
+ * Small screens: see vs_refresh.c section 6a. Set a flag so
+ * we know to fix the screen up later.
+ */
+ issmallscreen = IS_SMALL(sp);
+
+ /* The columns in the screen don't change. */
+ new->cols = sp->cols;
+
+ /*
+ * Split the screen, and link the screens together. If creating a
+ * screen to edit the colon command line or the cursor is in the top
+ * half of the current screen, the new screen goes under the current
+ * screen. Else, it goes above the current screen.
+ *
+ * Recalculate current cursor position based on sp->lno, we're called
+ * with the cursor on the colon command line. Then split the screen
+ * in half and update the shared information.
+ */
+ splitup =
+ !ccl && (vs_sm_cursor(sp, &smp) ? 0 : (smp - HMAP) + 1) >= half;
+ if (splitup) { /* Old is bottom half. */
+ new->rows = sp->rows - half; /* New. */
+ new->woff = sp->woff;
+ sp->rows = half; /* Old. */
+ sp->woff += new->rows;
+ /* Link in before old. */
+ CIRCLEQ_INSERT_BEFORE(&gp->dq, sp, new, q);
+
+ /*
+ * If the parent is the bottom half of the screen, shift
+ * the map down to match on-screen text.
+ */
+ memmove(_HMAP(sp), _HMAP(sp) + new->rows,
+ (sp->t_maxrows - new->rows) * sizeof(SMAP));
+ } else { /* Old is top half. */
+ new->rows = half; /* New. */
+ sp->rows -= half; /* Old. */
+ new->woff = sp->woff + sp->rows;
+ /* Link in after old. */
+ CIRCLEQ_INSERT_AFTER(&gp->dq, sp, new, q);
+ }
+
+ /* Adjust maximum text count. */
+ sp->t_maxrows = IS_ONELINE(sp) ? 1 : sp->rows - 1;
+ new->t_maxrows = IS_ONELINE(new) ? 1 : new->rows - 1;
+
+ /*
+ * Small screens: see vs_refresh.c, section 6a.
+ *
+ * The child may have different screen options sizes than the parent,
+ * so use them. Guarantee that text counts aren't larger than the
+ * new screen sizes.
+ */
+ if (issmallscreen) {
+ /* Fix the text line count for the parent. */
+ if (splitup)
+ sp->t_rows -= new->rows;
+
+ /* Fix the parent screen. */
+ if (sp->t_rows > sp->t_maxrows)
+ sp->t_rows = sp->t_maxrows;
+ if (sp->t_minrows > sp->t_maxrows)
+ sp->t_minrows = sp->t_maxrows;
+
+ /* Fix the child screen. */
+ new->t_minrows = new->t_rows = O_VAL(sp, O_WINDOW);
+ if (new->t_rows > new->t_maxrows)
+ new->t_rows = new->t_maxrows;
+ if (new->t_minrows > new->t_maxrows)
+ new->t_minrows = new->t_maxrows;
+ } else {
+ sp->t_minrows = sp->t_rows = IS_ONELINE(sp) ? 1 : sp->rows - 1;
+
+ /*
+ * The new screen may be a small screen, even if the parent
+ * was not. Don't complain if O_WINDOW is too large, we're
+ * splitting the screen so the screen is much smaller than
+ * normal.
+ */
+ new->t_minrows = new->t_rows = O_VAL(sp, O_WINDOW);
+ if (new->t_rows > new->rows - 1)
+ new->t_minrows = new->t_rows =
+ IS_ONELINE(new) ? 1 : new->rows - 1;
+ }
+
+ /* Adjust the ends of the new and old maps. */
+ _TMAP(sp) = IS_ONELINE(sp) ?
+ _HMAP(sp) : _HMAP(sp) + (sp->t_rows - 1);
+ _TMAP(new) = IS_ONELINE(new) ?
+ _HMAP(new) : _HMAP(new) + (new->t_rows - 1);
+
+ /* Reset the length of the default scroll. */
+ if ((sp->defscroll = sp->t_maxrows / 2) == 0)
+ sp->defscroll = 1;
+ if ((new->defscroll = new->t_maxrows / 2) == 0)
+ new->defscroll = 1;
+
+ /*
+ * Initialize the screen flags:
+ *
+ * If we're in vi mode in one screen, we don't have to reinitialize.
+ * This isn't just a cosmetic fix. The path goes like this:
+ *
+ * return into vi(), SC_SSWITCH set
+ * call vs_refresh() with SC_STATUS set
+ * call vs_resolve to display the status message
+ * call vs_refresh() because the SC_SCR_VI bit isn't set
+ *
+ * Things go downhill at this point.
+ *
+ * Draw the new screen from scratch, and add a status line.
+ */
+ F_SET(new,
+ SC_SCR_REFORMAT | SC_STATUS |
+ F_ISSET(sp, SC_EX | SC_VI | SC_SCR_VI | SC_SCR_EX));
+ return (0);
+}
+
+/*
+ * vs_discard --
+ * Discard the screen, folding the real-estate into a related screen,
+ * if one exists, and return that screen.
+ *
+ * PUBLIC: int vs_discard __P((SCR *, SCR **));
+ */
+int
+vs_discard(sp, spp)
+ SCR *sp, **spp;
+{
+ SCR *nsp;
+ dir_t dir;
+
+ /*
+ * Save the old screen's cursor information.
+ *
+ * XXX
+ * If called after file_end(), and the underlying file was a tmp
+ * file, it may have gone away.
+ */
+ if (sp->frp != NULL) {
+ sp->frp->lno = sp->lno;
+ sp->frp->cno = sp->cno;
+ F_SET(sp->frp, FR_CURSORSET);
+ }
+
+ /*
+ * Add into a previous screen and then into a subsequent screen, as
+ * they're the closest to the current screen. If that doesn't work,
+ * there was no screen to join.
+ */
+ if ((nsp = sp->q.cqe_prev) != (void *)&sp->gp->dq) {
+ nsp->rows += sp->rows;
+ sp = nsp;
+ dir = FORWARD;
+ } else if ((nsp = sp->q.cqe_next) != (void *)&sp->gp->dq) {
+ nsp->woff = sp->woff;
+ nsp->rows += sp->rows;
+ sp = nsp;
+ dir = BACKWARD;
+ } else
+ sp = NULL;
+
+ if (spp != NULL)
+ *spp = sp;
+ if (sp == NULL)
+ return (0);
+
+ /*
+ * Make no effort to clean up the discarded screen's information. If
+ * it's not exiting, we'll do the work when the user redisplays it.
+ *
+ * Small screens: see vs_refresh.c section 6a. Adjust text line info,
+ * unless it's a small screen.
+ *
+ * Reset the length of the default scroll.
+ */
+ if (!IS_SMALL(sp))
+ sp->t_rows = sp->t_minrows = sp->rows - 1;
+ sp->t_maxrows = sp->rows - 1;
+ sp->defscroll = sp->t_maxrows / 2;
+ *(HMAP + (sp->t_rows - 1)) = *TMAP;
+ TMAP = HMAP + (sp->t_rows - 1);
+
+ /*
+ * Draw the new screen from scratch, and add a status line.
+ *
+ * XXX
+ * We could play games with the map, if this were ever to be a
+ * performance problem, but I wrote the code a few times and it
+ * was never clean or easy.
+ */
+ switch (dir) {
+ case FORWARD:
+ vs_sm_fill(sp, OOBLNO, P_TOP);
+ break;
+ case BACKWARD:
+ vs_sm_fill(sp, OOBLNO, P_BOTTOM);
+ break;
+ default:
+ abort();
+ }
+
+ F_SET(sp, SC_STATUS);
+ return (0);
+}
+
+/*
+ * vs_fg --
+ * Background the current screen, and foreground a new one.
+ *
+ * PUBLIC: int vs_fg __P((SCR *, SCR **, CHAR_T *, int));
+ */
+int
+vs_fg(sp, nspp, name, newscreen)
+ SCR *sp, **nspp;
+ CHAR_T *name;
+ int newscreen;
+{
+ GS *gp;
+ SCR *nsp;
+
+ gp = sp->gp;
+
+ if (newscreen)
+ /* Get the specified background screen. */
+ nsp = vs_getbg(sp, name);
+ else
+ /* Swap screens. */
+ if (vs_swap(sp, &nsp, name))
+ return (1);
+
+ if ((*nspp = nsp) == NULL) {
+ msgq_str(sp, M_ERR, name,
+ name == NULL ?
+ "223|There are no background screens" :
+ "224|There's no background screen editing a file named %s");
+ return (1);
+ }
+
+ if (newscreen) {
+ /* Remove the new screen from the background queue. */
+ CIRCLEQ_REMOVE(&gp->hq, nsp, q);
+
+ /* Split the screen; if we fail, hook the screen back in. */
+ if (vs_split(sp, nsp, 0)) {
+ CIRCLEQ_INSERT_TAIL(&gp->hq, nsp, q);
+ return (1);
+ }
+ } else {
+ /* Move the old screen to the background queue. */
+ CIRCLEQ_REMOVE(&gp->dq, sp, q);
+ CIRCLEQ_INSERT_TAIL(&gp->hq, sp, q);
+ }
+ return (0);
+}
+
+/*
+ * vs_bg --
+ * Background the screen, and switch to the next one.
+ *
+ * PUBLIC: int vs_bg __P((SCR *));
+ */
+int
+vs_bg(sp)
+ SCR *sp;
+{
+ GS *gp;
+ SCR *nsp;
+
+ gp = sp->gp;
+
+ /* Try and join with another screen. */
+ if (vs_discard(sp, &nsp))
+ return (1);
+ if (nsp == NULL) {
+ msgq(sp, M_ERR,
+ "225|You may not background your only displayed screen");
+ return (1);
+ }
+
+ /* Move the old screen to the background queue. */
+ CIRCLEQ_REMOVE(&gp->dq, sp, q);
+ CIRCLEQ_INSERT_TAIL(&gp->hq, sp, q);
+
+ /* Toss the screen map. */
+ free(_HMAP(sp));
+ _HMAP(sp) = NULL;
+
+ /* Switch screens. */
+ sp->nextdisp = nsp;
+ F_SET(sp, SC_SSWITCH);
+
+ return (0);
+}
+
+/*
+ * vs_swap --
+ * Swap the current screen with a backgrounded one.
+ *
+ * PUBLIC: int vs_swap __P((SCR *, SCR **, char *));
+ */
+int
+vs_swap(sp, nspp, name)
+ SCR *sp, **nspp;
+ char *name;
+{
+ GS *gp;
+ SCR *nsp;
+
+ gp = sp->gp;
+
+ /* Get the specified background screen. */
+ if ((*nspp = nsp = vs_getbg(sp, name)) == NULL)
+ return (0);
+
+ /*
+ * Save the old screen's cursor information.
+ *
+ * XXX
+ * If called after file_end(), and the underlying file was a tmp
+ * file, it may have gone away.
+ */
+ if (sp->frp != NULL) {
+ sp->frp->lno = sp->lno;
+ sp->frp->cno = sp->cno;
+ F_SET(sp->frp, FR_CURSORSET);
+ }
+
+ /* Switch screens. */
+ sp->nextdisp = nsp;
+ F_SET(sp, SC_SSWITCH);
+
+ /* Initialize terminal information. */
+ VIP(nsp)->srows = VIP(sp)->srows;
+
+ /* Initialize screen information. */
+ nsp->cols = sp->cols;
+ nsp->rows = sp->rows; /* XXX: Only place in vi that sets rows. */
+ nsp->woff = sp->woff;
+
+ /*
+ * Small screens: see vs_refresh.c, section 6a.
+ *
+ * The new screens may have different screen options sizes than the
+ * old one, so use them. Make sure that text counts aren't larger
+ * than the new screen sizes.
+ */
+ if (IS_SMALL(nsp)) {
+ nsp->t_minrows = nsp->t_rows = O_VAL(nsp, O_WINDOW);
+ if (nsp->t_rows > sp->t_maxrows)
+ nsp->t_rows = nsp->t_maxrows;
+ if (nsp->t_minrows > sp->t_maxrows)
+ nsp->t_minrows = nsp->t_maxrows;
+ } else
+ nsp->t_rows = nsp->t_maxrows = nsp->t_minrows = nsp->rows - 1;
+
+ /* Reset the length of the default scroll. */
+ nsp->defscroll = nsp->t_maxrows / 2;
+
+ /* Allocate a new screen map. */
+ CALLOC_RET(nsp, _HMAP(nsp), SMAP *, SIZE_HMAP(nsp), sizeof(SMAP));
+ _TMAP(nsp) = _HMAP(nsp) + (nsp->t_rows - 1);
+
+ /* Fill the map. */
+ if (vs_sm_fill(nsp, nsp->lno, P_FILL))
+ return (1);
+
+ /*
+ * The new screen replaces the old screen in the parent/child list.
+ * We insert the new screen after the old one. If we're exiting,
+ * the exit will delete the old one, if we're foregrounding, the fg
+ * code will move the old one to the background queue.
+ */
+ CIRCLEQ_REMOVE(&gp->hq, nsp, q);
+ CIRCLEQ_INSERT_AFTER(&gp->dq, sp, nsp, q);
+
+ /*
+ * Don't change the screen's cursor information other than to
+ * note that the cursor is wrong.
+ */
+ F_SET(VIP(nsp), VIP_CUR_INVALID);
+
+ /* Draw the new screen from scratch, and add a status line. */
+ F_SET(nsp, SC_SCR_REDRAW | SC_STATUS);
+ return (0);
+}
+
+/*
+ * vs_resize --
+ * Change the absolute size of the current screen.
+ *
+ * PUBLIC: int vs_resize __P((SCR *, long, adj_t));
+ */
+int
+vs_resize(sp, count, adj)
+ SCR *sp;
+ long count;
+ adj_t adj;
+{
+ GS *gp;
+ SCR *g, *s;
+ size_t g_off, s_off;
+
+ gp = sp->gp;
+
+ /*
+ * Figure out which screens will grow, which will shrink, and
+ * make sure it's possible.
+ */
+ if (count == 0)
+ return (0);
+ if (adj == A_SET) {
+ if (sp->t_maxrows == count)
+ return (0);
+ if (sp->t_maxrows > count) {
+ adj = A_DECREASE;
+ count = sp->t_maxrows - count;
+ } else {
+ adj = A_INCREASE;
+ count = count - sp->t_maxrows;
+ }
+ }
+
+ g_off = s_off = 0;
+ if (adj == A_DECREASE) {
+ if (count < 0)
+ count = -count;
+ s = sp;
+ if (s->t_maxrows < MINIMUM_SCREEN_ROWS + count)
+ goto toosmall;
+ if ((g = sp->q.cqe_prev) == (void *)&gp->dq) {
+ if ((g = sp->q.cqe_next) == (void *)&gp->dq)
+ goto toobig;
+ g_off = -count;
+ } else
+ s_off = count;
+ } else {
+ g = sp;
+ if ((s = sp->q.cqe_next) != (void *)&gp->dq)
+ if (s->t_maxrows < MINIMUM_SCREEN_ROWS + count)
+ s = NULL;
+ else
+ s_off = count;
+ else
+ s = NULL;
+ if (s == NULL) {
+ if ((s = sp->q.cqe_prev) == (void *)&gp->dq) {
+toobig: msgq(sp, M_BERR, adj == A_DECREASE ?
+ "227|The screen cannot shrink" :
+ "228|The screen cannot grow");
+ return (1);
+ }
+ if (s->t_maxrows < MINIMUM_SCREEN_ROWS + count) {
+toosmall: msgq(sp, M_BERR,
+ "226|The screen can only shrink to %d rows",
+ MINIMUM_SCREEN_ROWS);
+ return (1);
+ }
+ g_off = -count;
+ }
+ }
+
+ /*
+ * Fix up the screens; we could optimize the reformatting of the
+ * screen, but this isn't likely to be a common enough operation
+ * to make it worthwhile.
+ */
+ s->rows += -count;
+ s->woff += s_off;
+ g->rows += count;
+ g->woff += g_off;
+
+ g->t_rows += count;
+ if (g->t_minrows == g->t_maxrows)
+ g->t_minrows += count;
+ g->t_maxrows += count;
+ _TMAP(g) += count;
+ F_SET(g, SC_SCR_REFORMAT | SC_STATUS);
+
+ s->t_rows -= count;
+ s->t_maxrows -= count;
+ if (s->t_minrows > s->t_maxrows)
+ s->t_minrows = s->t_maxrows;
+ _TMAP(s) -= count;
+ F_SET(s, SC_SCR_REFORMAT | SC_STATUS);
+
+ return (0);
+}
+
+/*
+ * vs_getbg --
+ * Get the specified background screen, or, if name is NULL, the first
+ * background screen.
+ */
+static SCR *
+vs_getbg(sp, name)
+ SCR *sp;
+ char *name;
+{
+ GS *gp;
+ SCR *nsp;
+ char *p;
+
+ gp = sp->gp;
+
+ /* If name is NULL, return the first background screen on the list. */
+ if (name == NULL) {
+ nsp = gp->hq.cqh_first;
+ return (nsp == (void *)&gp->hq ? NULL : nsp);
+ }
+
+ /* Search for a full match. */
+ for (nsp = gp->hq.cqh_first;
+ nsp != (void *)&gp->hq; nsp = nsp->q.cqe_next)
+ if (!strcmp(nsp->frp->name, name))
+ break;
+ if (nsp != (void *)&gp->hq)
+ return (nsp);
+
+ /* Search for a last-component match. */
+ for (nsp = gp->hq.cqh_first;
+ nsp != (void *)&gp->hq; nsp = nsp->q.cqe_next) {
+ if ((p = strrchr(nsp->frp->name, '/')) == NULL)
+ p = nsp->frp->name;
+ else
+ ++p;
+ if (!strcmp(p, name))
+ break;
+ }
+ if (nsp != (void *)&gp->hq)
+ return (nsp);
+
+ return (NULL);
+}
diff --git a/usr.bin/vi/Makefile b/usr.bin/vi/Makefile
deleted file mode 100644
index 9777077acf56..000000000000
--- a/usr.bin/vi/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-SUBDIR= common
-
-.include <bsd.subdir.mk>
diff --git a/usr.bin/vi/USD.doc/edit/Makefile b/usr.bin/vi/USD.doc/edit/Makefile
deleted file mode 100644
index 3d30bc919644..000000000000
--- a/usr.bin/vi/USD.doc/edit/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-# @(#)Makefile 8.1 (Berkeley) 6/8/93
-
-DIR= usd/11.edit
-SRCS= edittut.ms
-MACROS= -msU
-
-paper.ps: ${SRCS}
- ${TBL} ${SRCS} | ${ROFF} > ${.TARGET}
-
-# index for versatec is different from the one in edit.tut
-# because the fonts are different and entries reference page
-# rather than section numbers. if you have a typesetter
-# you should just use the index in edit.tut, and ignore editvindex.
-
-editvindex:
- ${TROFF} ${MACROS} -n22 edit.vindex
-
-.include <bsd.doc.mk>
diff --git a/usr.bin/vi/USD.doc/exref/Makefile b/usr.bin/vi/USD.doc/exref/Makefile
deleted file mode 100644
index 11f4e6650dcc..000000000000
--- a/usr.bin/vi/USD.doc/exref/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# @(#)Makefile 8.1 (Berkeley) 6/8/93
-
-DIR= usd/13.ex
-SRCS= ex.rm
-MACROS= -msU
-CLEANFILES=summary.*
-
-paper.ps: ${SRCS} summary.ps
- ${ROFF} ${SRCS} > ${.TARGET}
-
-summary.ps: ex.summary
- ${TBL} ex.summary | ${ROFF} > ${.TARGET}
-
-.include <bsd.doc.mk>
diff --git a/usr.bin/vi/USD.doc/vi.man/Makefile b/usr.bin/vi/USD.doc/vi.man/Makefile
deleted file mode 100644
index fd89b8e3169f..000000000000
--- a/usr.bin/vi/USD.doc/vi.man/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# @(#)Makefile 8.5 (Berkeley) 7/16/94
-
-SRCS= vi.1
-DOCS= vi.0 vi.0.ps
-
-all: ${DOCS}
-
-vi.0: vi.1
- groff -man -Tascii < vi.1 > $@
-vi.0.ps: vi.1
- groff -man < vi.1 > $@
-
-clean:
- rm -f ${DOCS}
diff --git a/usr.bin/vi/USD.doc/vi.man/vi.0 b/usr.bin/vi/USD.doc/vi.man/vi.0
deleted file mode 100644
index e6d9972e390b..000000000000
--- a/usr.bin/vi/USD.doc/vi.man/vi.0
+++ /dev/null
@@ -1,798 +0,0 @@
-EX/VI(1) BSD Reference Manual EX/VI(1)
-
-NNAAMMEE
- eexx,, vvii,, vviieeww - text editors
-
-SSYYNNOOPPSSIISS
- eexx [--eeFFRRrrssvv] [--cc _c_m_d] [--tt _t_a_g] [--ww _s_i_z_e] [_f_i_l_e _._._.]
- vvii [--eeFFRRrrvv] [--cc _c_m_d] [--tt _t_a_g] [--ww _s_i_z_e] [_f_i_l_e _._._.]
- vviieeww [--eeFFRRrrvv] [--cc _c_m_d] [--tt _t_a_g] [--ww _s_i_z_e] [_f_i_l_e _._._.]
-
-DDEESSCCRRIIPPTTIIOONN
- VVii is a screen oriented text editor. EExx is a line-oriented text editor.
- EExx and vvii are different interfaces to the same program, and it is possi-
- ble to switch back and forth during an edit session. VViieeww is the equiva-
- lent of using the --RR (read-only) option of vvii.
-
- This manual page is the one provided with the nneexx//nnvvii versions of the
- eexx//vvii text editors. NNeexx//nnvvii are intended as bug-for-bug compatible re-
- placements for the original Fourth Berkeley Software Distribution (4BSD)
- eexx and vvii programs. For the rest of this manual page, nneexx//nnvvii is used
- only when it's necessary to distinguish it from the historic implementa-
- tions of eexx//vvii.
-
- This manual page is intended for users already familiar with eexx//vvii. Any-
- one else should almost certainly read a good tutorial on the editor be-
- fore this manual page. If you're in an unfamiliar environment, and you
- absolutely have to get work done immediately, read the section after the
- options description, entitled ``Fast Startup''. It's probably enough to
- get you going.
-
- The following options are available:
-
- --cc Execute _c_m_d immediately after starting the edit session. Partic-
- ularly useful for initial positioning in the file, however _c_m_d is
- not limited to positioning commands. This is the POSIX 1003.2
- interface for the historic ``+cmd'' syntax. NNeexx//nnvvii supports
- both the old and new syntax.
-
- --ee Start editing in ex mode, as if the command name were eexx.
-
- --FF Don't copy the entire file when first starting to edit. (The de-
- fault is to make a copy in case someone else modifies the file
- during your edit session.)
-
- --RR Start editing in read-only mode, as if the command name was vviieeww,
- or the readonly option was set.
-
- --rr Recover the specified files, or, if no files are specified, list
- the files that could be recovered. If no recoverable files by
- the specified name exist, the file is edited as if the --rr option
- had not been specified.
-
- --ss Enter batch mode; applicable only to eexx edit sessions. Batch
- mode is useful when running eexx scripts. Prompts, informative
- messages and other user oriented message are turned off, and no
- startup files or environmental variables are read. This is the
- POSIX 1003.2 interface for the historic ``-'' argument. NNeexx//nnvvii
- supports both the old and new syntax.
-
- --tt Start editing at the specified tag. (See ctags(1)).
-
- --ww Set the initial window size to the specified number of lines.
-
-
-
- --vv Start editing in vi mode, as if the command name was vvii or vviieeww.
-
- --XX Reserved for X11 interfaces. _N_o _X_1_1 _s_u_p_p_o_r_t _i_s _c_u_r_r_e_n_t_l_y
- _i_m_p_l_e_m_e_n_t_e_d_.
-
- Command input for eexx//vvii is read from the standard input. In the vvii in-
- terface, it is an error if standard input is not a terminal. In the eexx
- interface, if standard input is not a terminal, eexx will read commands
- from it regardless, however, the session will be a batch mode session,
- exactly as if the --ss option had been specified.
-
- EExx//vvii exits 0 on success, and greater than 0 if an error occurs.
-
-FFAASSTT SSTTAARRTTUUPP
- This section will tell you the minimum amount that you need to do simple
- editing tasks using vvii. If you've never used any screen editor before,
- you're likely to have problems even with this simple introduction. In
- that case you should find someone that already knows vvii and have them
- walk you through this section.
-
- VVii is a screen editor. This means that it takes up almost the entire
- screen, displaying part of the file on each screen line, except for the
- last line of the screen. The last line of the screen is used for you to
- give commands to vvii, and for vvii to give information to you.
-
- The other fact that you need to understand is that vvii is a modeful edi-
- tor, i.e. you are either entering text or you are executing commands, and
- you have to be in the right mode to do one or the other. You will be in
- command mode when you first start editing a file. There are commands
- that switch you into input mode. There is only one key that takes you
- out of input mode, and that is the <escape> key. (Key names are written
- using less-than and greater-than signs, e.g. <escape> means the
- ``escape'' key, usually labeled ``esc'' on your terminal's keyboard.) If
- you're ever confused as to which mode you're in, keep entering the <es-
- cape> key until vvii beeps at you. (Generally, vvii will beep at you if you
- try and do something that's not allowed. It will also display error mes-
- sages.)
-
- To start editing a file, enter the command ``vi file_name<carriage-
- return>''. The command you should enter as soon as you start editing is
- ``:set verbose showmode<carriage-return>''. This will make the editor
- give you verbose error messages and display the current mode at the bot-
- tom of the screen.
-
- The commands to move around the file are:
- hh Move the cursor left one character.
- jj Move the cursor down one line.
- kk Move the cursor up one line.
- ll Move the cursor right one character.
- <<ccuurrssoorr--aarrrroowwss>>
- The cursor arrow keys should work, too.
- //tteexxtt<<ccaarrrriiaaggee--rreettuurrnn>>
- Search for the string ``text'' in the file, and move the cursor to
- its first character.
-
- The commands to enter new text are:
- aa Append new text, _a_f_t_e_r the cursor.
- ii Insert new text, _b_e_f_o_r_e the cursor.
- oo Open a new line below the line the cursor is on, and start entering
- text.
- OO Open a new line above the line the cursor is on, and start entering
- text.
- <<eessccaappee>>
- Once you've entered input mode using the one of the aa, ii, OO, or oo
- commands, use <<eessccaappee>> to quit entering text and return to command
- mode.
-
- The commands to copy text are:
- yyyy Copy the line the cursor is on.
- pp Append the copied line after the line the cursor is on.
-
- The commands to delete text are:
- dddd Delete the line the cursor is on.
- xx Delete the character the cursor is on.
-
- The commands to write the file are:
- ::ww<<ccaarrrriiaaggee--rreettuurrnn>>
- Write the file back to the file with the name that you originally
- used as an argument on the vvii command line.
- ::ww ffiillee__nnaammee<<ccaarrrriiaaggee--rreettuurrnn>>
- Write the file back to the file with the name ``file_name''.
-
- The commands to quit editing and exit the editor are:
- ::qq<<ccaarrrriiaaggee--rreettuurrnn>>
- Quit editing and leave vi (if you've modified the file, but not
- saved your changes, vvii will refuse to quit).
- ::qq!!<<ccaarrrriiaaggee--rreettuurrnn>>
- Quit, discarding any modifications that you may have made.
-
- One final caution. Unusual characters can take up more than one column
- on the screen, and long lines can take up more than a single screen line.
- The above commands work on ``physical'' characters and lines, i.e. they
- affect the entire line no matter how many screen lines it takes up and
- the entire character no matter how many screen columns it takes up.
-
-VVII CCOOMMMMAANNDDSS
- The following section describes the commands available in the command
- mode of the vvii editor. In each entry below, the tag line is a usage syn-
- opsis for the command character.
-
- [[ccoouunntt]] <<ccoonnttrrooll--AA>>
- Search forward count times for the current word.
- [[ccoouunntt]] <<ccoonnttrrooll--BB>>
- Page backwards count screens.
- [[ccoouunntt]] <<ccoonnttrrooll--DD>>
- Scroll forward count lines.
- [[ccoouunntt]] <<ccoonnttrrooll--EE>>
- Scroll forward count lines, leaving the current line and column as
- is, if possible.
- [[ccoouunntt]] <<ccoonnttrrooll--FF>>
- Page forward count screens.
- <<ccoonnttrrooll--GG>>
- Display the file information.
- <<ccoonnttrrooll--HH>>
- [[ccoouunntt]] hh
- Move the cursor back count characters in the current line.
- [[ccoouunntt]] <<ccoonnttrrooll--JJ>>
- [[ccoouunntt]] <<ccoonnttrrooll--NN>>
- [[ccoouunntt]] jj
- Move the cursor down count lines without changing the current col-
- umn.
- <<ccoonnttrrooll--LL>>
- <<ccoonnttrrooll--RR>>
- Repaint the screen.
- [[ccoouunntt]] <<ccoonnttrrooll--MM>>
- [[ccoouunntt]] ++
- Move the cursor down count lines to the first nonblank character of
- that line.
- [[ccoouunntt]] <<ccoonnttrrooll--PP>>
- [[ccoouunntt]] kk
- Move the cursor up count lines, without changing the current col-
-
- umn.
- <<ccoonnttrrooll--TT>>
- Return to the most recent tag context.
- <<ccoonnttrrooll--UU>>
- Scroll backwards count lines.
- <<ccoonnttrrooll--WW>>
- Switch to the next lower screen in the window, or, to the first
- screen if there are no lower screens in the window.
- <<ccoonnttrrooll--YY>>
- Scroll backwards count lines, leaving the current line and column
- as is, if possible.
- <<ccoonnttrrooll--ZZ>>
- Suspend the current editor session.
- <<eessccaappee>>
- Execute eexx commands or cancel partial commands.
- <<ccoonnttrrooll--]]>>
- Push a tag reference onto the tag stack.
- <<ccoonnttrrooll--^^>>
- Switch to the most recently edited file.
- [[ccoouunntt]] <<ssppaaccee>>
- [[ccoouunntt]] ll
- Move the cursor forward count characters without changing the cur-
- rent line.
- [[ccoouunntt]] !! mmoottiioonn sshheellll--aarrgguummeenntt((ss))
- Replace text with results from a shell command.
- [[ccoouunntt]] ## ++||--||##
- Increment or decrement the cursor number.
- [[ccoouunntt]] $$
- Move the cursor to the end of a line.
- %% Move to the matching character.
- && Repeat the previous substitution command on the current line.
- ''<<cchhaarraacctteerr>>
- ``<<cchhaarraacctteerr>>
- Return to a context marked by the character <character>.
- [[ccoouunntt]] ((
- Back up count sentences.
- [[ccoouunntt]] ))
- Move forward count sentences.
- [[ccoouunntt]] ,,
- Reverse find character count times.
- [[ccoouunntt]] --
- Move to first nonblank of the previous line, count times.
- [[ccoouunntt]] ..
- Repeat the last vvii command that modified text.
- //RREE<<ccaarrrriiaaggee--rreettuurrnn>>
- //RREE// [[ooffffsseett]]<<ccaarrrriiaaggee--rreettuurrnn>>
- ??RREE<<ccaarrrriiaaggee--rreettuurrnn>>
- ??RREE?? [[ooffffsseett]]<<ccaarrrriiaaggee--rreettuurrnn>>
- NN
- nn Search forward or backward for a regular expression.
- 00 Move to the first character in the current line.
- : Execute an ex command.
- [[ccoouunntt]] ;;
- Repeat the last character find count times.
- [[ccoouunntt]] << mmoottiioonn
- [[ccoouunntt]] >> mmoottiioonn
- Shift lines left or right.
- @@ bbuuffffeerr
- Execute a named buffer.
- [[ccoouunntt]] AA
- Enter input mode, appending the text after the end of the line.
- [[ccoouunntt]] BB
- Move backwards count bigwords.
- [[bbuuffffeerr]] [[ccoouunntt]] CC
-
-
- Change text from the current position to the end-of-line.
- [[bbuuffffeerr]] DD
- Delete text from the current position to the end-of-line.
- [[ccoouunntt]] EE
- Move forward count end-of-bigwords.
- [[ccoouunntt]] FF <<cchhaarraacctteerr>>
- Search count times backward through the current line for
- <character>.
- [[ccoouunntt]] GG
- Move to line count, or the last line of the file if count not spec-
- ified.
- [[ccoouunntt]] HH
- Move to the screen line count - 1 lines below the top of the
- screen.
- [[ccoouunntt]] II
- Enter input mode, inserting the text at the beginning of the line.
- [[ccoouunntt]] JJ
- Join lines.
- [[ccoouunntt]] LL
- Move to the screen line count - 1 lines above the bottom of the
- screen.
- MM Move to the screen line in the middle of the screen.
- [[ccoouunntt]] OO
- Enter input mode, appending text in a new line above the current
- line.
- [[bbuuffffeerr]] PP
- Insert text from a buffer.
- QQ Exit vvii (or visual) mode and switch to eexx mode.
- [[ccoouunntt]] RR
- Enter input mode, replacing the characters in the current line.
- [[bbuuffffeerr]] [[ccoouunntt]] SS
- Substitute count lines.
- [[ccoouunntt]] TT <<cchhaarraacctteerr>>
- Search backwards, count times, through the current line for the
- character _a_f_t_e_r the specified <character>.
- UU Restore the current line to its state before the cursor last moved
- to it.
- [[ccoouunntt]] WW
- Move forward count bigwords.
- [[bbuuffffeerr]] [[ccoouunntt]] XX
- Delete count characters before the cursor.
- [[bbuuffffeerr]] [[ccoouunntt]] YY
- Copy (or ``yank'') count lines into the specified buffer.
- ZZZZ Write the file and exit vvii.
- [[ccoouunntt]] [[[[
- Back up count section boundaries.
- [[ccoouunntt]] ]]]]
- Move forward count section boundaries.
- ^^ Move to first nonblank character on the current line.
- [[ccoouunntt]] __
- Move down count - 1 lines, to the first nonblank character.
- [[ccoouunntt]] aa
- Enter input mode, appending the text after the cursor.
- [[ccoouunntt]] bb
- Move backwards count words.
- [[bbuuffffeerr]] [[ccoouunntt]] cc mmoottiioonn
- Change a region of text.
- [[bbuuffffeerr]] [[ccoouunntt]] dd mmoottiioonn
- Delete a region of text.
- [[ccoouunntt]] ee
- Move forward count end-of-words.
- [[ccoouunntt]] ff<<cchhaarraacctteerr>>
- Search forward, count times, through the rest of the current line
- for <character>.
- [[ccoouunntt]] ii
-
- Enter input mode, inserting the text before the cursor.
- mm <<cchhaarraacctteerr>>
- Save the current context (line and column) as <character>.
- [[ccoouunntt]] oo
- Enter input mode, appending text in a new line under the current
- line.
- [[bbuuffffeerr]] pp
- Append text from a buffer.
- [[ccoouunntt]] rr <<cchhaarraacctteerr>>
- Replace count characters.
- [[bbuuffffeerr]] [[ccoouunntt]] ss
- Substitute count characters in the current line starting with the
- current character.
- [[ccoouunntt]] tt <<cchhaarraacctteerr>>
- Search forward, count times, through the current line for the char-
- acter immediately _b_e_f_o_r_e <character>.
- uu Undo the last change made to the file.
- [[ccoouunntt]] ww
- Move forward count words.
- [[bbuuffffeerr]] [[ccoouunntt]] xx
- Delete count characters.
- [[bbuuffffeerr]] [[ccoouunntt]] yy mmoottiioonn
- Copy (or ``yank'') a text region specified by the count and motion
- into a buffer.
- [[ccoouunntt11]] zz [[ccoouunntt22]] --||..||++||^^||<<ccaarrrriiaaggee--rreettuurrnn>>
- Redraw, optionally repositioning and resizing the screen.
- [[ccoouunntt]] {{
- Move backward count paragraphs.
- [[ccoouunntt]] ||
- Move to a specific _c_o_l_u_m_n position on the current line.
- [[ccoouunntt]] }}
- Move forward count paragraphs.
- [[ccoouunntt]] ~~
- Reverse the case of the next count character(s).
- [[ccoouunntt]] ~~ mmoottiioonn
- Reverse the case of the characters in a text region specified by
- the count and motion.
- <<iinntteerrrruupptt>>
- Interrupt the current operation.
-
-VVII TTEEXXTT IINNPPUUTT CCOOMMMMAANNDDSS
- The following section describes the commands available in the text input
- mode of the vvii editor.
-
- <<nnuull>>
- Replay the previous input.
- <<ccoonnttrrooll--DD>>
- Erase the previous autoindent character.
- ^^<<ccoonnttrrooll--DD>>
- Erase all of the autoindent characters, and reset the autoindent
- level.
- 00<<ccoonnttrrooll--DD>>
- Erase all of the autoindent characters.
- <<ccoonnttrrooll--TT>>
- Insert sufficient <tab> and <space> characters to move the cursor
- forward to a column immediately after the next column which is an
- even multiple of the sshhiiffttwwiiddtthh option.
- <<eerraassee>>
- <<ccoonnttrrooll--HH>>
- Erase the last character.
- <<lliitteerraall nneexxtt>>
- Quote the next character.
- <<eessccaappee>>
- Resolve all text input into the file, and return to command mode.
- <<lliinnee eerraassee>>
-
- Erase the current line.
- <<ccoonnttrrooll--WW>>
- <<wwoorrdd eerraassee>>
- Erase the last word. The definition of word is dependent on the
- aallttwweerraassee and ttttyywweerraassee options.
- <<ccoonnttrrooll--XX>>[[00--99AA--FFaa--ff]]**
- Insert a character with the specified hexadecimal value into the
- text.
- <<iinntteerrrruupptt>>
- Interrupt text input mode, returning to command mode.
-
-EEXX CCOOMMMMAANNDDSS
- The following section describes the commands available in the eexx editor.
- In each entry below, the tag line is a usage synopsis for the command.
-
- <<eenndd--ooff--ffiillee>>
- Scroll the screen.
- !! aarrgguummeenntt((ss))
- [[rraannggee]]!! aarrgguummeenntt((ss))
- Execute a shell command, or filter lines through a shell command.
- "" A comment.
- [[rraannggee]] nnuu[[mmbbeerr]] [[ccoouunntt]] [[ffllaaggss]]
- [[rraannggee]] ## [[ccoouunntt]] [[ffllaaggss]]
- Display the selected lines, each preceded with its line number.
- @@ bbuuffffeerr
- ** bbuuffffeerr
- Execute a buffer.
- [[rraannggee]] dd[[eelleettee]] [[bbuuffffeerr]] [[ccoouunntt]] [[ffllaaggss]]
- Delete the lines from the file.
- ddii[[ssppllaayy]] bb[[uuffffeerrss]] || ss[[ccrreeeennss]] || tt[[aaggss]]
- Display buffers, screens or tags.
- ee[[ddiitt]][[!!]] [[++ccmmdd]] [[ffiillee]]
- eexx[[!!]] [[++ccmmdd]] [[ffiillee]]
- Edit a different file.
- eexxuu[[ssaaggee]] [[ccoommmmaanndd]]
- Display usage for an eexx command.
- ff[[iillee]] [[ffiillee]]
- Display and optionally change the file name.
- ffgg [[nnaammee]]
- VVii mode only. Foreground the specified screen.
- [[rraannggee]] gg[[lloobbaall]] //ppaatttteerrnn// [[ccoommmmaannddss]]
- [[rraannggee]] vv //ppaatttteerrnn// [[ccoommmmaannddss]]
- Apply commands to lines matching (or not matching) a pattern.
- hhee[[llpp]]
- Display a help message.
- [[lliinnee]] ii[[nnsseerrtt]][[!!]]
- The input text is inserted before the specified line.
- [[rraannggee]] jj[[ooiinn]][[!!]] [[ccoouunntt]] [[ffllaaggss]]
- Join lines of text together.
- [[rraannggee]] ll[[iisstt]] [[ccoouunntt]] [[ffllaaggss]]
- Display the lines unambiguously.
- mmaapp[[!!]] [[llhhss rrhhss]]
- Define or display maps (for vvii only).
- [[lliinnee]] mmaa[[rrkk]] <<cchhaarraacctteerr>>
- [[lliinnee]] kk <<cchhaarraacctteerr>>
- Mark the line with the mark <character>.
- [[rraannggee]] mm[[oovvee]] lliinnee
- Move the specified lines after the target line.
- mmkk[[eexxrrcc]][[!!]] ffiillee
- Write the abbreviations, editor options and maps to the specified
- file.
- nn[[eexxtt]][[!!]] [[ffiillee ......]]
- Edit the next file from the argument list.
- [[lliinnee]] oo[[ppeenn]] //ppaatttteerrnn// [[ffllaaggss]]
-
-
- Enter open mode.
- pprree[[sseerrvvee]]
- Save the file in a form that can later be recovered using the eexx --rr
- option.
- pprreevv[[iioouuss]][[!!]]
- Edit the previous file from the argument list.
- [[rraannggee]] pp[[rriinntt]] [[ccoouunntt]] [[ffllaaggss]]
- Display the specified lines.
- [[lliinnee]] ppuu[[tt]] [[bbuuffffeerr]]
- Append buffer contents to the current line.
- qq[[uuiitt]][[!!]]
- End the editing session.
- [[lliinnee]] rr[[eeaadd]][[!!]] [[ffiillee]]
- Read a file.
- rreecc[[oovveerr]] ffiillee
- Recover file if it was previously saved.
- rreess[[iizzee]] [[++||--]]ssiizzee
- VVii mode only. Grow or shrink the current screen.
- rreeww[[iinndd]][[!!]]
- Rewind the argument list.
- ssee[[tt]] [[ooppttiioonn[[==[[vvaalluuee]]]] ......]] [[nnooooppttiioonn ......]] [[ooppttiioonn?? ......]] [[aallll]]
- Display or set editor options.
- sshh[[eellll]]
- Run a shell program.
- ssoo[[uurrccee]] ffiillee
- Read and execute eexx commands from a file.
- sspp[[lliitt]] [[ffiillee ......]]
- VVii mode only. Split the screen.
- [[rraannggee]] ss[[uubbssttiittuuttee]] [[//ppaatttteerrnn//rreeppllaaccee//]] [[ooppttiioonnss]] [[ccoouunntt]] [[ffllaaggss]]
- [[rraannggee]] && [[ooppttiioonnss]] [[ccoouunntt]] [[ffllaaggss]]
- [[rraannggee]] ~~ [[ooppttiioonnss]] [[ccoouunntt]] [[ffllaaggss]]
- Make substitutions.
- ssuu[[ssppeenndd]][[!!]]
- sstt[[oopp]][[!!]]
- <<ssuussppeenndd>>
- Suspend the edit session.
- ttaa[[gg]][[!!]] ttaaggssttrriinngg
- Edit the file containing the specified tag.
- ttaaggpp[[oopp]][[!!]] [[ffiillee || nnuummbbeerr]]
- Pop to the specified tag in the tags stack.
- uunnmm[[aapp]][[!!]] llhhss
- Unmap a mapped string.
- vvee[[rrssiioonn]]
- Display the version of the eexx//vvii editor.
- [[lliinnee]] vvii[[ssuuaall]] [[ttyyppee]] [[ccoouunntt]] [[ffllaaggss]]
- EExx mode only. Enter vvii.
- vvii[[ssuuaall]][[!!]] [[++ccmmdd]] [[ffiillee]]
- VVii mode only. Edit a new file.
- vviiuu[[ssaaggee]] [[ccoommmmaanndd]]
- Display usage for a vvii command.
- [[rraannggee]] ww[[rriittee]][[!!]] [[>>>>]] [[ffiillee]]
- [[rraannggee]] ww[[rriittee]] [[!!]] [[ffiillee]]
- [[rraannggee]] wwnn[[!!]] [[>>>>]] [[ffiillee]]
- [[rraannggee]] wwqq[[!!]] [[>>>>]] [[ffiillee]]
- Write the file.
- [[rraannggee]] xx[[iitt]][[!!]] [[ffiillee]]
- Write the file if it has been modified.
- [[rraannggee]] yyaa[[nnkk]] [[bbuuffffeerr]] [[ccoouunntt]]
- Copy the specified lines to a buffer.
- [[lliinnee]] zz [[ttyyppee]] [[ccoouunntt]] [[ffllaaggss]]
- Adjust the window.
-
-SSEETT OOPPTTIIOONNSS
- There are a large number of options that may be set (or unset) to change
- the editor's behavior. This section describes the options, their abbre-
- viations and their default values.
-
- In each entry below, the first part of the tag line is the full name of
- the option, followed by any equivalent abbreviations. The part in square
- brackets is the default value of the option. Most of the options are
- boolean, i.e. they are either on or off, and do not have an associated
- value.
-
- Options apply to both eexx and vvii modes, unless otherwise specified.
-
- aallttwweerraassee [[ooffff]]
- VVii only. Select an alternate word erase algorithm.
- aauuttooiinnddeenntt,, aaii [[ooffff]]
- Automatically indent new lines.
- aauuttoopprriinntt,, aapp [[ooffff]]
- EExx only. Display the current line automatically.
- aauuttoowwrriittee,, aaww [[ooffff]]
- Write modified files automatically when changing files.
- bbeeaauuttiiffyy,, bbff [[ooffff]]
- Discard control characters.
- ccddppaatthh [[eennvviirroonnmmeenntt vvaarriiaabbllee CCDDPPAATTHH,, oorr ccuurrrreenntt ddiirreeccttoorryy]]
- The directory paths used as path prefixes for the ccdd command.
- ccoolluummnnss,, ccoo [[8800]]
- Set the number of columns in the screen.
- ccoommmmeenntt [[ooffff]]
- VVii only. Skip leading comments in files.
- ddiirreeccttoorryy,, ddiirr [[eennvviirroonnmmeenntt vvaarriiaabbllee TTMMPPDDIIRR,, oorr //ttmmpp]]
- The directory where temporary files are created.
- eeddccoommppaattiibbllee,, eedd [[ooffff]]
- Remember the values of the ``c'' and ``g'' suffices to the
- ssuubbssttiittuuttee commands, instead of initializing them as unset for each
- new command.
- eerrrroorrbbeellllss,, eebb [[ooffff]]
- EExx only. Announce error messages with a bell.
- eexxrrcc,, eexx [[ooffff]]
- Never read startup files in the local directory.
- eexxtteennddeedd [[ooffff]]
- Regular expressions are extended (i.e. egrep(1) style) expres-
- sions.
- ffllaasshh [[oonn]]
- Flash the screen instead of beeping the keyboard on error.
- hhaarrddttaabbss,, hhtt [[88]]
- Set the spacing between hardware tab settings.
- iiggnnoorreeccaassee,, iicc [[ooffff]]
- Ignore case differences in regular expressions.
- kkeeyyttiimmee [[66]]
- The 10th's of a second eexx//vvii waits for a subsequent key to complete
- a key mapping.
- lleeffttrriigghhtt [[ooffff]]
- VVii only. Do left-right scrolling.
- lliinneess,, llii [[2244]]
- VVii only. Set the number of lines in the screen.
- lliisspp [[ooffff]]
- VVii only. Modify various search commands and options to work with
- Lisp.
-
- _T_h_i_s _o_p_t_i_o_n _i_s _n_o_t _y_e_t _i_m_p_l_e_m_e_n_t_e_d_.
- lliisstt [[ooffff]]
- Display lines in an unambiguous fashion.
- mmaaggiicc [[oonn]]
- Treat certain characters specially in regular expressions.
- mmaattcchhttiimmee [[77]]
- VVii only. The 10th's of a second eexx//vvii pauses on the matching char-
- acter when the sshhoowwmmaattcchh option is set.
- mmeessgg [[oonn]]
-
-
- Permit messages from other users.
- mmooddeelliinneess,, mmooddeelliinnee [[ooffff]]
- Read the first and last few lines of each file for eexx commands.
-
- _T_h_i_s _o_p_t_i_o_n _w_i_l_l _n_e_v_e_r _b_e _i_m_p_l_e_m_e_n_t_e_d_.
- nnuummbbeerr,, nnuu [[ooffff]]
- Precede each line displayed with its current line number.
- ooccttaall [[ooffff]]
- Display unknown characters as octal numbers, instead of the default
- hexadecimal.
- ooppeenn [[oonn]]
- EExx only. If this option is not set, the ooppeenn and vviissuuaall commands
- are disallowed.
- ooppttiimmiizzee,, oopptt [[oonn]]
- VVii only. Optimize text throughput to dumb terminals.
-
- _T_h_i_s _o_p_t_i_o_n _i_s _n_o_t _y_e_t _i_m_p_l_e_m_e_n_t_e_d_.
- ppaarraaggrraapphhss,, ppaarraa [[IIPPLLPPPPPPQQPPPP LLIIppppllppiippbbpp]]
- VVii only. Define additional paragraph boundaries for the {{ and }}
- commands.
- pprroommpptt [[oonn]]
- EExx only. Display a command prompt.
- rreeaaddoonnllyy,, rroo [[ooffff]]
- Mark the file as read-only.
- rreeccddiirr [[//vvaarr//ttmmpp//vvii..rreeccoovveerr]]
- The directory where recovery files are stored.
- rreeddrraaww,, rree [[ooffff]]
- VVii only. Simulate an intelligent terminal on a dumb one.
-
- _T_h_i_s _o_p_t_i_o_n _i_s _n_o_t _y_e_t _i_m_p_l_e_m_e_n_t_e_d_.
- rreemmaapp [[oonn]]
- Remap keys until resolved.
- rreeppoorrtt [[55]]
- Set the number of lines about which the editor reports changes or
- yanks.
- rruulleerr [[ooffff]]
- VVii only. Display a row/column ruler on the colon command line.
- ssccrroollll,, ssccrr [[wwiinnddooww // 22]]
- Set the number of lines scrolled.
- sseeccttiioonnss,, sseecctt [[NNHHSSHHHH HHUUnnhhsshh]]
- VVii only. Define additional section boundaries for the [[[[ and ]]]]
- commands.
- sshheellll,, sshh [[eennvviirroonnmmeenntt vvaarriiaabbllee SSHHEELLLL,, oorr //bbiinn//sshh]]
- Select the shell used by the editor.
- sshhiiffttwwiiddtthh,, ssww [[88]]
- Set the autoindent and shift command indentation width.
- sshhoowwddiirrttyy [[ooffff]]
- VVii only. Display an asterisk on the colon command line if the file
- has been modified.
- sshhoowwmmaattcchh,, ssmm [[ooffff]]
- VVii only. Note matching ``{'' and ``('' for ``}'' and ``)'' charac-
- ters.
- sshhoowwmmooddee [[ooffff]]
- VVii only. Display the current editor mode (command or input).
- ssiiddeessccrroollll [[1166]]
- VVii only. Set the amount a left-right scroll will shift.
- sslloowwooppeenn,, ssllooww [[ooffff]]
- Delay display updating during text input.
-
- _T_h_i_s _o_p_t_i_o_n _i_s _n_o_t _y_e_t _i_m_p_l_e_m_e_n_t_e_d_.
- ssoouurrcceeaannyy [[ooffff]]
- Read startup files not owned by the current user.
-
- _T_h_i_s _o_p_t_i_o_n _w_i_l_l _n_e_v_e_r _b_e _i_m_p_l_e_m_e_n_t_e_d_.
- ttaabbssttoopp,, ttss [[88]]
-
- This option sets tab widths for the editor display.
- ttaagglleennggtthh,, ttll [[00]]
- Set the number of significant characters in tag names.
- ttaaggss,, ttaagg [[ttaaggss //vvaarr//ddbb//lliibbcc..ttaaggss //ssyyss//kkeerrnn//ttaaggss]]
- Set the list of tags files.
- tteerrmm,, ttttyyttyyppee,, ttttyy [[eennvviirroonnmmeenntt vvaarriiaabbllee TTEERRMM]]
- Set the terminal type.
- tteerrssee [[ooffff]]
- This option has historically made editor messages less verbose. It
- has no effect in this implementation.
- ttiillddeeoopp
- Modify the ~~ command to take an associated motion.
- ttiimmeeoouutt,, ttoo [[oonn]]
- Time out on keys which may be mapped.
- ttttyywweerraassee [[ooffff]]
- VVii only. Select an alternate erase algorithm.
- vveerrbboossee [[ooffff]]
- only. Display an error message for every error.
- ww330000 [[nnoo ddeeffaauulltt]]
- VVii only. Set the window size if the baud rate is less than 1200
- baud.
- ww11220000 [[nnoo ddeeffaauulltt]]
- VVii only. Set the window size if the baud rate is equal to 1200
- baud.
- ww99660000 [[nnoo ddeeffaauulltt]]
- VVii only. Set the window size if the baud rate is greater than 1200
- baud.
- wwaarrnn [[oonn]]
- EExx only. This option causes a warning message to the terminal if
- the file has been modified, since it was last written, before a !!
- command.
- wwiinnddooww,, ww,, wwii [[eennvviirroonnmmeenntt vvaarriiaabbllee LLIINNEESS]]
- Set the window size for the screen.
- wwrraappmmaarrggiinn,, wwmm [[00]]
- VVii only. Break lines automatically when they reach the right-hand
- margin.
- wwrraappssccaann,, wwss [[oonn]]
- Set searches to wrap around the end or beginning of the file.
- wwrriitteeaannyy,, wwaa [[ooffff]]
- Turn off file-overwriting checks.
-
-EENNVVIIRROONNMMEENNTTAALL VVAARRIIAABBLLEESS
- COLUMNS The number of columns on the screen. This value overrides any
- system or terminal specific values. If the COLUMNS environ-
- mental variable is not set when eexx//vvii runs, or the ccoolluummnnss op-
- tion is explicitly reset by the user, eexx//vvii enters the value
- into the environment.
- EXINIT A list of eexx startup commands, read if the variable NEXINIT is
- not set.
- HOME The user's home directory, used as the initial directory path
- for the startup _$_H_O_M_E_/_._n_e_x_r_c and _$_H_O_M_E_/_._e_x_r_c files. This val-
- ue is also used as the default directory for the vvii ccdd com-
- mand.
- LINES The number of rows on the screen. This value overrides any
- system or terminal specific values. If the LINES environmen-
- tal variable is not set when eexx//vvii runs, or the lliinneess option
- is explicitly reset by the user, eexx//vvii enters the value into
- the environment.
- NEXINIT A list of eexx startup commands.
- SHELL The user's shell of choice (see also the sshheellll option).
- TERM The user's terminal type. The default is the type
- ``unknown''. If the TERM environmental variable is not set
- when eexx//vvii runs, or the tteerrmm option is explicitly reset by the
- user, eexx//vvii enters the value into the environment.
- TMPDIR The location used to stored temporary files (see also the
- ddiirreeccttoorryy option).
-
-AASSYYNNCCHHRROONNOOUUSS EEVVEENNTTSS
- SIGALRM VVii//eexx uses this signal for periodic backups of file modifica-
- tions and to display ``busy'' messages when operations are
- likely to take a long time.
- SIGHUP
- SIGTERM If the current buffer has changed since it was last written
- in its entirety, the editor attempts to save the modified
- file so it can be later recovered. See the vvii//eexx Reference
- manual section entitled ``Recovery'' for more information.
- SIGINT When an interrupt occurs, the current operation is halted,
- and the editor returns to the command level. If interrupted
- during text input, the text already input is resolved into
- the file as if the text input had been normally terminated.
- SIGWINCH The screen is resized. See the vvii//eexx Reference manual sec-
- tion entitled ``Sizing the Screen'' for more information.
- SIGCONT
- SIGQUIT
- SIGTSTP VVii//eexx ignores these signals.
-
-BBUUGGSS
- See the file _n_v_i_/_d_o_c_s_/_b_u_g_s_._c_u_r_r_e_n_t for a list of the known bugs in this
- version.
-
-FFIILLEESS
- /bin/sh The default user shell.
- /etc/vi.exrc System-wide vi startup file.
- /tmp Temporary file directory.
- /var/tmp/vi.recover The default recovery file directory.
- $HOME/.nexrc 1st choice for user's home directory startup file.
- $HOME/.exrc 2nd choice for user's home directory startup file.
- .nexrc 1st choice for local directory startup file.
- .exrc 2nd choice for local directory startup file.
-
-SSEEEE AALLSSOO
- ctags(1), more(1), curses(3), dbopen(3)
-
- The ``Vi Quick Reference'' card.
-
- ``An Introduction to Display Editing with Vi'', found in the ``UNIX
- User's Manual Supplementary Documents'' section of both the 4.3BSD and
- 4.4BSD manual sets. This document is the closest thing available to an
- introduction to the vvii screen editor.
-
- ``Ex Reference Manual (Version 3.7)'', found in the ``UNIX User's Manual
- Supplementary Documents'' section of both the 4.3BSD and 4.4BSD manual
- sets. This document is the final reference for the eexx editor, as dis-
- tributed in most historic 4BSD and System V systems.
-
- ``Edit: A tutorial'', found in the ``UNIX User's Manual Supplementary
- Documents'' section of the 4.3BSD manual set. This document is an intro-
- duction to a simple version of the eexx screen editor.
-
- ``Ex/Vi Reference Manual'', found in the ``UNIX User's Manual
- Supplementary Documents'' section of the 4.4BSD manual set. This docu-
- ment is the final reference for the nneexx//nnvvii text editors, as distributed
- in 4.4BSD and 4.4BSD-Lite.
-
- RRooffff source for all of these documents is distributed with nneexx//nnvvii in the
- _n_v_i_/_U_S_D_._d_o_c directory of the nneexx//nnvvii source code.
-
- The files ``autowrite'', ``input'', ``quoting'', and ``structures'',
- found in the _n_v_i_/_d_o_c_s_/_i_n_t_e_r_n_a_l_s directory of the nneexx//nnvvii source code.
-
-HHIISSTTOORRYY
- The nneexx//nnvvii replacements for the eexx//vvii editor first appeared in 4.4BSD.
-
-SSTTAANNDDAARRDDSS
- NNeexx//nnvvii is close to IEEE Std1003.2 (``POSIX''). That document differs
- from historical eexx//vvii practice in several places; there are changes to be
- made on both sides.
-
-4.4BSD July 15, 1994 13
diff --git a/usr.bin/vi/USD.doc/vi.man/vi.0.ps b/usr.bin/vi/USD.doc/vi.man/vi.0.ps
deleted file mode 100644
index f6cfc03ea937..000000000000
--- a/usr.bin/vi/USD.doc/vi.man/vi.0.ps
+++ /dev/null
@@ -1,1063 +0,0 @@
-%!PS-Adobe-3.0
-%%Creator: groff version 1.08
-%%DocumentNeededResources: font Times-Roman
-%%+ font Times-Bold
-%%+ font Courier-Bold
-%%+ font Courier-Oblique
-%%+ font Courier
-%%+ font Times-Italic
-%%+ font Symbol
-%%DocumentSuppliedResources: procset grops 1.08 0
-%%Pages: 14
-%%PageOrder: Ascend
-%%Orientation: Portrait
-%%EndComments
-%%BeginProlog
-%%BeginResource: procset grops 1.08 0
-/setpacking where{
-pop
-currentpacking
-true setpacking
-}if
-/grops 120 dict dup begin
-/SC 32 def
-/A/show load def
-/B{0 SC 3 -1 roll widthshow}bind def
-/C{0 exch ashow}bind def
-/D{0 exch 0 SC 5 2 roll awidthshow}bind def
-/E{0 rmoveto show}bind def
-/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
-/G{0 rmoveto 0 exch ashow}bind def
-/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
-/I{0 exch rmoveto show}bind def
-/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
-/K{0 exch rmoveto 0 exch ashow}bind def
-/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
-/M{rmoveto show}bind def
-/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
-/O{rmoveto 0 exch ashow}bind def
-/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
-/Q{moveto show}bind def
-/R{moveto 0 SC 3 -1 roll widthshow}bind def
-/S{moveto 0 exch ashow}bind def
-/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
-/SF{
-findfont exch
-[exch dup 0 exch 0 exch neg 0 0]makefont
-dup setfont
-[exch/setfont cvx]cvx bind def
-}bind def
-/MF{
-findfont
-[5 2 roll
-0 3 1 roll
-neg 0 0]makefont
-dup setfont
-[exch/setfont cvx]cvx bind def
-}bind def
-/level0 0 def
-/RES 0 def
-/PL 0 def
-/LS 0 def
-/PLG{
-gsave newpath clippath pathbbox grestore
-exch pop add exch pop
-}bind def
-/BP{
-/level0 save def
-1 setlinecap
-1 setlinejoin
-72 RES div dup scale
-LS{
-90 rotate
-}{
-0 PL translate
-}ifelse
-1 -1 scale
-}bind def
-/EP{
-level0 restore
-showpage
-}bind def
-/DA{
-newpath arcn stroke
-}bind def
-/SN{
-transform
-.25 sub exch .25 sub exch
-round .25 add exch round .25 add exch
-itransform
-}bind def
-/DL{
-SN
-moveto
-SN
-lineto stroke
-}bind def
-/DC{
-newpath 0 360 arc closepath
-}bind def
-/TM matrix def
-/DE{
-TM currentmatrix pop
-translate scale newpath 0 0 .5 0 360 arc closepath
-TM setmatrix
-}bind def
-/RC/rcurveto load def
-/RL/rlineto load def
-/ST/stroke load def
-/MT/moveto load def
-/CL/closepath load def
-/FL{
-currentgray exch setgray fill setgray
-}bind def
-/BL/fill load def
-/LW/setlinewidth load def
-/RE{
-findfont
-dup maxlength 1 index/FontName known not{1 add}if dict begin
-{
-1 index/FID ne{def}{pop pop}ifelse
-}forall
-/Encoding exch def
-dup/FontName exch def
-currentdict end definefont pop
-}bind def
-/DEFS 0 def
-/EBEGIN{
-moveto
-DEFS begin
-}bind def
-/EEND/end load def
-/CNT 0 def
-/level1 0 def
-/PBEGIN{
-/level1 save def
-translate
-div 3 1 roll div exch scale
-neg exch neg exch translate
-0 setgray
-0 setlinecap
-1 setlinewidth
-0 setlinejoin
-10 setmiterlimit
-[]0 setdash
-/setstrokeadjust where{
-pop
-false setstrokeadjust
-}if
-/setoverprint where{
-pop
-false setoverprint
-}if
-newpath
-/CNT countdictstack def
-userdict begin
-/showpage{}def
-}bind def
-/PEND{
-clear
-countdictstack CNT sub{end}repeat
-level1 restore
-}bind def
-end def
-/setpacking where{
-pop
-setpacking
-}if
-%%EndResource
-%%IncludeResource: font Times-Roman
-%%IncludeResource: font Times-Bold
-%%IncludeResource: font Courier-Bold
-%%IncludeResource: font Courier-Oblique
-%%IncludeResource: font Courier
-%%IncludeResource: font Times-Italic
-%%IncludeResource: font Symbol
-grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
-792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
-/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
-/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
-/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
-/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
-/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
-/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/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/bracketleft/backslash
-/bracketright/circumflex/underscore/quoteleft/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/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
-/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
-/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
-/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
-/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
-/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
-/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
-/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
-/onequarter/onehalf/threequarters/questiondown/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
-/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]def/Times-Italic@0 ENC0/Times-Italic RE
-/Courier@0 ENC0/Courier RE/Courier-Oblique@0 ENC0/Courier-Oblique RE
-/Courier-Bold@0 ENC0/Courier-Bold RE/Times-Bold@0 ENC0/Times-Bold RE
-/Times-Roman@0 ENC0/Times-Roman RE
-%%EndProlog
-%%Page: 1 1
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF -.834(EX/VI \( 1 \))72 48 R(BSD Reference Manual)
-258.235 48 Q -.834(EX/VI \( 1 \))496.682 48 R/F1 10/Times-Bold@0 SF -.2(NA)72
-108 S(ME).2 E/F2 10/Courier-Bold@0 SF(ex, vi, view)102 120 Q F0 2.5<ad74>2.5 G
--.15(ex)187.42 120 S 2.5(te).15 G(ditors)206.43 120 Q F1(SYNOPSIS)72 144 Q F2
-(ex)102 156 Q F0([)3.333 E F2(\255eFRrsv)2.499 E F0 3.333(][).833 G F2<ad63>
--.834 E/F3 10/Courier-Oblique@0 SF(cmd)6 E F0 3.333(][).833 G F2<ad74>-.834 E
-F3(tag)6 E F0 3.333(][).833 G F2<ad77>-.834 E F3(size)6 E F0 3.333(][).833 G F3
-(file ...)330.796 156 Q F0(]).833 E F2(vi)102 168 Q F0([)3.333 E F2(\255eFRrv)
-2.499 E F0 3.333(][).833 G F2<ad63>-.834 E F3(cmd)6 E F0 3.333(][).833 G F2
-<ad74>-.834 E F3(tag)6 E F0 3.333(][).833 G F2<ad77>-.834 E F3(size)6 E F0
-3.333(][).833 G F3(file ...)324.796 168 Q F0(]).833 E F2(view)102 180 Q F0([)
-3.333 E F2(\255eFRrv)2.499 E F0 3.333(][).833 G F2<ad63>-.834 E F3(cmd)6 E F0
-3.333(][).833 G F2<ad74>-.834 E F3(tag)6 E F0 3.333(][).833 G F2<ad77>-.834 E
-F3(size)6 E F0 3.333(][).833 G F3(file ...)336.796 180 Q F0(]).833 E F1
-(DESCRIPTION)72 204 Q F2(Vi)102 216 Q F0 .176(is a screen oriented te)2.676 F
-.176(xt editor)-.15 F(.)-.55 E F2(Ex)5.176 E F0 .176(is a line-oriented te)
-2.676 F .175(xt editor)-.15 F(.)-.55 E F2(Ex)5.175 E F0(and)2.675 E F2(vi)2.675
-E F0 .175(are dif)2.675 F .175(ferent interf)-.25 F .175(aces to the)-.1 F .56
-(same program, and it is possible to switch back and forth during an edit sess\
-ion.)102 228 R F2(View)5.561 E F0 .561(is the equi)3.061 F -.25(va)-.25 G .561
-(lent of).25 F(using the)102 240 Q F2<ad52>4.166 E F0(\(read-only\) option of)
-2.5 E F2(vi)2.5 E F0(.)A .216(This manual page is the one pro)102 258 R .215
-(vided with the)-.15 F F2(nex/nvi)2.715 E F0 -.15(ve)2.715 G .215
-(rsions of the).15 F F2(ex/vi)2.715 E F0(te)2.715 E .215(xt editors.)-.15 F F2
-(Nex/nvi)5.215 E F0(are)2.715 E 1.937(intended as b)102 270 R(ug-for)-.2 E(-b)
--.2 E 1.937(ug compatible replacements for the original F)-.2 F 1.938
-(ourth Berk)-.15 F(ele)-.1 E 4.438(yS)-.15 G(oftw)456.982 270 Q 1.938
-(are Distrib)-.1 F(ution)-.2 E(\(4BSD\))102 282 Q F2(ex)3.008 E F0(and)3.008 E
-F2(vi)3.008 E F0 3.008(programs. F)3.008 F .508
-(or the rest of this manual page,)-.15 F F2(nex/nvi)3.008 E F0 .507
-(is used only when it')3.008 F 3.007(sn)-.55 G(ecessary)506.13 282 Q
-(to distinguish it from the historic implementations of)102 294 Q F2(ex/vi)2.5
-E F0(.)A .961(This manual page is intended for users already f)102 312 R .961
-(amiliar with)-.1 F F2(ex/vi)3.461 E F0 3.462(.A)C -.15(ny)397.982 312 S .962
-(one else should almost certainly).15 F .582
-(read a good tutorial on the editor before this manual page.)102 324 R .582
-(If you')5.582 F .581(re in an unf)-.5 F .581(amiliar en)-.1 F .581
-(vironment, and you)-.4 F .799(absolutely ha)102 336 R 1.099 -.15(ve t)-.2 H
-3.299(og).15 G .799(et w)184.317 336 R .799(ork done immediately)-.1 F 3.299
-(,r)-.65 G .8(ead the section after the options description, entitled `)299.803
-336 R(`F)-.74 E(ast)-.15 E(Startup')102 348 Q('. It')-.74 E 2.5(sp)-.55 G
-(robably enough to get you going.)162.09 348 Q(The follo)102 366 Q
-(wing options are a)-.25 E -.25(va)-.2 G(ilable:).25 E F2<ad63>103.666 384 Q F0
-(Ex)137 384 Q(ecute)-.15 E F3(cmd)2.675 E F0 .175
-(immediately after starting the edit session.)2.675 F -.15(Pa)5.175 G .174
-(rticularly useful for initial positioning in).15 F .624(the \214le, ho)137 396
-R(we)-.25 E -.15(ve)-.25 G(r).15 E F3(cmd)3.124 E F0 .625
-(is not limited to positioning commands.)3.124 F .625
-(This is the POSIX 1003.2 interf)5.625 F(ace)-.1 E(for the historic `)137 408 Q
-(`+cmd')-.74 E 2.5('s)-.74 G(yntax.)239.47 408 Q F2(Nex/nvi)5 E F0
-(supports both the old and ne)2.5 E 2.5(ws)-.25 G(yntax.)440.1 408 Q F2<ad65>
-103.666 426 Q F0(Start editing in e)137 426 Q 2.5(xm)-.15 G
-(ode, as if the command name were)218.52 426 Q F2(ex)2.5 E F0(.)A F2<ad46>
-103.666 444 Q F0(Don')137 444 Q 2.677(tc)-.18 G(op)167.267 444 Q 2.677(yt)-.1 G
-.177(he entire \214le when \214rst starting to edit.)187.624 444 R .177
-(\(The def)5.177 F .177(ault is to mak)-.1 F 2.677(eac)-.1 G(op)456.532 444 Q
-2.676(yi)-.1 G 2.676(nc)476.888 444 S .176(ase someone)489.004 444 R
-(else modi\214es the \214le during your edit session.\))137 456 Q F2<ad52>
-103.666 474 Q F0 .184
-(Start editing in read-only mode, as if the command name w)137 474 R(as)-.1 E
-F2(view)2.685 E F0 2.685(,o)C 2.685(rt)421.415 474 S .185(he readonly option w)
-430.21 474 R .185(as set.)-.1 F F2<ad72>103.666 492 Q F0(Reco)137 492 Q -.15
-(ve)-.15 G 2.627(rt).15 G .127(he speci\214ed \214les, or)175.427 492 R 2.627
-(,i)-.4 G 2.627(fn)263.305 492 S 2.627<6f8c>274.262 492 S .127
-(les are speci\214ed, list the \214les that could be reco)287.449 492 R -.15
-(ve)-.15 G 2.626(red. If).15 F .126(no re-)2.626 F(co)137 504 Q -.15(ve)-.15 G
-.4(rable \214les by the speci\214ed name e).15 F .401
-(xist, the \214le is edited as if the)-.15 F F2<ad72>4.567 E F0 .401
-(option had not been speci-)2.901 F(\214ed.)137 516 Q F2<ad73>103.666 534 Q F0
-1.621(Enter batch mode; applicable only to)137 534 R F2(ex)4.121 E F0 1.621
-(edit sessions.)4.121 F 1.62(Batch mode is useful when running)6.621 F F2(ex)
-4.12 E F0 2.647(scripts. Prompts,)137 546 R(informati)2.647 E .447 -.15(ve m)
--.25 H .147(essages and other user oriented message are turned of).15 F .148
-(f, and no start-)-.25 F .067(up \214les or en)137 558 R .067(vironmental v)-.4
-F .066(ariables are read.)-.25 F .066(This is the POSIX 1003.2 interf)5.066 F
-.066(ace for the historic `)-.1 F(`\255')-.74 E(')-.74 E(ar)137 570 Q(gument.)
--.18 E F2(Nex/nvi)5 E F0(supports both the old and ne)2.5 E 2.5(ws)-.25 G
-(yntax.)353 570 Q F2<ad74>103.666 588 Q F0
-(Start editing at the speci\214ed tag.)137 588 Q(\(See)5 E/F4 10/Courier@0 SF
-(ctags)2.5 E F0(\(1\)\).)A F2<ad77>103.666 606 Q F0(Set the initial windo)137
-606 Q 2.5(ws)-.25 G(ize to the speci\214ed number of lines.)231.2 606 Q F2
-<ad76>103.666 624 Q F0(Start editing in vi mode, as if the command name w)137
-624 Q(as)-.1 E F2(vi)2.5 E F0(or)2.5 E F2(view)2.5 E F0(.)A F2<ad58>103.666 642
-Q F0(Reserv)137 642 Q(ed for X11 interf)-.15 E(aces.)-.1 E/F5 10/Times-Italic@0
-SF(No X11 support is curr)5 E(ently implemented.)-.37 E F0 .35
-(Command input for)102 660 R F2(ex/vi)2.85 E F0 .35
-(is read from the standard input.)2.85 F .35(In the)5.35 F F2(vi)2.85 E F0
-(interf)2.85 E .35(ace, it is an error if standard in-)-.1 F .343
-(put is not a terminal.)102 672 R .343(In the)5.343 F F2(ex)2.843 E F0(interf)
-2.843 E .343(ace, if standard input is not a terminal,)-.1 F F2(ex)2.843 E F0
-.342(will read commands from it)2.843 F(re)102 684 Q -.05(ga)-.15 G .137
-(rdless, ho).05 F(we)-.25 E -.15(ve)-.25 G .937 -.4(r, t).15 H .137
-(he session will be a batch mode session, e).4 F .138(xactly as if the)-.15 F
-F2<ad73>4.304 E F0 .138(option had been speci\214ed.)2.638 F 172.465
-(4.4BSD July)72 750 R(15, 1994)2.5 E(1)535 750 Q EP
-%%Page: 2 2
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF -.834(EX/VI \( 1 \))72 48 R(BSD Reference Manual)
-258.235 48 Q -.834(EX/VI \( 1 \))496.682 48 R/F1 10/Courier-Bold@0 SF(Ex/vi)102
-96 Q F0 -.15(ex)2.5 G(its 0 on success, and greater than 0 if an error occurs.)
-.15 E/F2 10/Times-Bold@0 SF -.9(FA)72 120 S 1.666(ST ST).9 F(AR)-.9 E(TUP)-.4 E
-F0 .467(This section will tell you the minimum amount that you need to do simp\
-le editing tasks using)102 132 R F1(vi)2.966 E F0 2.966(.I)C 2.966(fy)506.584
-132 S(ou')517.88 132 Q -.15(ve)-.5 G(ne)102 144 Q -.15(ve)-.25 G 3.453(ru).15 G
-.953(sed an)132.263 144 R 3.453(ys)-.15 G .953(creen editor before, you')
-170.679 144 R .953(re lik)-.5 F .953(ely to ha)-.1 F 1.253 -.15(ve p)-.2 H .953
-(roblems e).15 F -.15(ve)-.25 G 3.453(nw).15 G .953
-(ith this simple introduction.)412.286 144 R(In)5.954 E
-(that case you should \214nd someone that already kno)102 156 Q(ws)-.25 E F1
-(vi)2.5 E F0(and ha)2.5 E .3 -.15(ve t)-.2 H(hem w).15 E
-(alk you through this section.)-.1 E F1(Vi)102 174 Q F0 .294
-(is a screen editor)2.794 F 5.294(.T)-.55 G .294(his means that it tak)198.51
-174 R .293
-(es up almost the entire screen, displaying part of the \214le on each)-.1 F
-.001(screen line, e)102 186 R .001(xcept for the last line of the screen.)-.15
-F .002(The last line of the screen is used for you to gi)5.001 F .302 -.15
-(ve c)-.25 H(ommands).15 E(to)102 198 Q F1(vi)2.5 E F0 2.5(,a)C(nd for)133.72
-198 Q F1(vi)2.5 E F0(to gi)2.5 E .3 -.15(ve i)-.25 H(nformation to you.).15 E
-.585(The other f)102 216 R .585(act that you need to understand is that)-.1 F
-F1(vi)3.085 E F0 .585(is a modeful editor)3.085 F 3.085(,i)-.4 G .584
-(.e. you are either entering te)406.125 216 R .584(xt or)-.15 F .836(you are e)
-102 228 R -.15(xe)-.15 G .836(cuting commands, and you ha).15 F 1.137 -.15
-(ve t)-.2 H 3.337(ob).15 G 3.337(ei)301.062 228 S 3.337(nt)311.619 228 S .837
-(he right mode to do one or the other)322.736 228 R 5.837(.Y)-.55 G .837
-(ou will be in)487.209 228 R 1.094
-(command mode when you \214rst start editing a \214le.)102 240 R 1.093
-(There are commands that switch you into input mode.)6.094 F .084
-(There is only one k)102 252 R .384 -.15(ey t)-.1 H .085(hat tak).15 F .085
-(es you out of input mode, and that is the <escape> k)-.1 F -.15(ey)-.1 G 5.085
-(.\()-.5 G -2.15 -.25(Ke y)449.895 252 T .085(names are written)2.835 F 1.473
-(using less-than and greater)102 264 R 1.473(-than signs, e.g.)-.2 F 1.473
-(<escape> means the `)6.473 F(`escape')-.74 E 3.973('k)-.74 G -.15(ey)420.59
-264 S 3.973(,u)-.5 G 1.473(sually labeled `)440.703 264 R(`esc')-.74 E 3.972
-('o)-.74 G(n)535 264 Q .553(your terminal')102 276 R 3.053(sk)-.55 G -.15(ey)
-171.336 276 S 3.053(board.\) If).15 F(you')3.053 E .554(re e)-.5 F -.15(ve)-.25
-G 3.054(rc).15 G .554(onfused as to which mode you')277.45 276 R .554(re in, k)
--.5 F .554(eep entering the <escape>)-.1 F -.1(ke)102 288 S 2.615(yu)-.05 G
-(ntil)123.805 288 Q F1(vi)2.615 E F0 .115(beeps at you.)2.615 F(\(Generally)
-5.115 E(,)-.65 E F1(vi)2.615 E F0 .115
-(will beep at you if you try and do something that')2.615 F 2.614(sn)-.55 G
-.114(ot allo)484.472 288 R 2.614(wed. It)-.25 F
-(will also display error messages.\))102 300 Q 2.057 -.8(To s)102 318 T .457
-(tart editing a \214le, enter the command `).8 F(`)-.74 E/F3 10/Courier@0 SF
-.458(vi file_name<carriage-return>)B F0 -.74('')C 2.958(.T).74 G .458
-(he command you)470.204 318 R .333
-(should enter as soon as you start editing is `)102 330 R(`)-.74 E F3 .333
-(:set verbose showmode<carriage-return>)B F0 -.74('')C 2.833(.T).74 G(his)
-528.33 330 Q 1.441(will mak)102 342 R 3.941(et)-.1 G 1.441(he editor gi)149.782
-342 R 1.741 -.15(ve y)-.25 H 1.441(ou v).15 F 1.441
-(erbose error messages and display the current mode at the bottom of the)-.15 F
-(screen.)102 354 Q(The commands to mo)102 372 Q .3 -.15(ve a)-.15 H
-(round the \214le are:).15 E F2(h)102 384 Q F0(Mo)131 384 Q .3 -.15(ve t)-.15 H
-(he cursor left one character).15 E(.)-.55 E F2(j)102 396 Q F0(Mo)131 396 Q .3
--.15(ve t)-.15 H(he cursor do).15 E(wn one line.)-.25 E F2(k)102 408 Q F0(Mo)
-131 408 Q .3 -.15(ve t)-.15 H(he cursor up one line.).15 E F2(l)102 420 Q F0
-(Mo)131 420 Q .3 -.15(ve t)-.15 H(he cursor right one character).15 E(.)-.55 E
-F2(<cursor)102 432 Q(-arr)-.37 E -.1(ow)-.18 G(s>).1 E F0(The cursor arro)131
-444 Q 2.5(wk)-.25 G -.15(ey)207.01 444 S 2.5(ss).15 G(hould w)226.58 444 Q
-(ork, too.)-.1 E F2(/text<carriage-r)102 456 Q(etur)-.18 E(n>)-.15 E F0
-(Search for the string `)131 468 Q(`te)-.74 E(xt')-.15 E 2.5('i)-.74 G 2.5(nt)
-246.84 468 S(he \214le, and mo)257.12 468 Q .3 -.15(ve t)-.15 H
-(he cursor to its \214rst character).15 E(.)-.55 E(The commands to enter ne)102
-486 Q 2.5(wt)-.25 G -.15(ex)220.34 486 S 2.5(ta).15 G(re:)239.35 486 Q F2(a)102
-498 Q F0(Append ne)131 498 Q 2.5(wt)-.25 G -.15(ex)186.85 498 S(t,).15 E/F4 10
-/Times-Italic@0 SF(after)2.5 E F0(the cursor)2.5 E(.)-.55 E F2(i)102 510 Q F0
-(Insert ne)131 510 Q 2.5(wt)-.25 G -.15(ex)177.96 510 S(t,).15 E F4(befor)2.5 E
-(e)-.37 E F0(the cursor)2.5 E(.)-.55 E F2(o)102 522 Q F0(Open a ne)131 522 Q
-2.5(wl)-.25 G(ine belo)183.79 522 Q 2.5(wt)-.25 G
-(he line the cursor is on, and start entering te)227.98 522 Q(xt.)-.15 E F2(O)
-102 534 Q F0(Open a ne)131 534 Q 2.5(wl)-.25 G(ine abo)183.79 534 Q .3 -.15
-(ve t)-.15 H(he line the cursor is on, and start entering te).15 E(xt.)-.15 E
-F2(<escape>)102 546 Q F0 .744(Once you')131 558 R 1.044 -.15(ve e)-.5 H .744
-(ntered input mode using the one of the).15 F F2(a)3.244 E F0(,)A F2(i)3.244 E
-F0(,)A F2(O)3.244 E F0 3.244(,o)C(r)390.542 558 Q F2(o)3.243 E F0 .743
-(commands, use)3.243 F F2(<escape>)3.243 E F0 .743(to quit)3.243 F(entering te)
-131 570 Q(xt and return to command mode.)-.15 E(The commands to cop)102 588 Q
-2.5(yt)-.1 G -.15(ex)200.78 588 S 2.5(ta).15 G(re:)219.79 588 Q F2(yy)102 600 Q
-F0(Cop)131 600 Q 2.5(yt)-.1 G(he line the cursor is on.)157.85 600 Q F2(p)102
-612 Q F0(Append the copied line after the line the cursor is on.)131 612 Q
-(The commands to delete te)102 630 Q(xt are:)-.15 E F2(dd)102 642 Q F0
-(Delete the line the cursor is on.)131 642 Q F2(x)102 654 Q F0
-(Delete the character the cursor is on.)131 654 Q
-(The commands to write the \214le are:)102 672 Q F2(:w<carriage-r)102 684 Q
-(etur)-.18 E(n>)-.15 E F0 .528(Write the \214le back to the \214le with the na\
-me that you originally used as an ar)131 696 R .528(gument on the)-.18 F F1(vi)
-3.028 E F0(com-)3.028 E 172.465(4.4BSD July)72 750 R(15, 1994)2.5 E(2)535 750 Q
-EP
-%%Page: 3 3
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF -.834(EX/VI \( 1 \))72 48 R(BSD Reference Manual)
-258.235 48 Q -.834(EX/VI \( 1 \))496.682 48 R(mand line.)131 96 Q/F1 10
-/Times-Bold@0 SF(:w \214le_name<carriage-r)102 108 Q(etur)-.18 E(n>)-.15 E F0
-(Write the \214le back to the \214le with the name `)131 120 Q(`\214le_name')
--.74 E('.)-.74 E(The commands to quit editing and e)102 138 Q
-(xit the editor are:)-.15 E F1(:q<carriage-r)102 150 Q(etur)-.18 E(n>)-.15 E F0
-.848(Quit editing and lea)131 162 R 1.148 -.15(ve v)-.2 H 3.348(i\().15 G .848
-(if you')239.6 162 R 1.148 -.15(ve m)-.5 H .848(odi\214ed the \214le, b).15 F
-.848(ut not sa)-.2 F -.15(ve)-.2 G 3.348(dy).15 G .848(our changes,)415.454 162
-R/F2 10/Courier-Bold@0 SF(vi)3.347 E F0 .847(will refuse to)3.347 F(quit\).)131
-174 Q F1(:q!<carriage-r)102 186 Q(etur)-.18 E(n>)-.15 E F0(Quit, discarding an)
-131 198 Q 2.5(ym)-.15 G(odi\214cations that you may ha)222.51 198 Q .3 -.15
-(ve m)-.2 H(ade.).15 E .686(One \214nal caution.)102 216 R .686
-(Unusual characters can tak)5.686 F 3.187(eu)-.1 G 3.187(pm)302.483 216 S .687
-(ore than one column on the screen, and long lines can)318.45 216 R(tak)102 228
-Q 3.129(eu)-.1 G 3.129(pm)126.689 228 S .629(ore than a single screen line.)
-142.598 228 R .629(The abo)5.629 F .929 -.15(ve c)-.15 H .629(ommands w).15 F
-.629(ork on `)-.1 F(`ph)-.74 E(ysical')-.05 E 3.129('c)-.74 G .628
-(haracters and lines, i.e.)446.476 228 R(the)102 240 Q 2.74(ya)-.15 G -.25(ff)
-126.25 240 S .24(ect the entire line no matter ho).25 F 2.74(wm)-.25 G(an)
-273.79 240 Q 2.74(ys)-.15 G .241(creen lines it tak)294.71 240 R .241
-(es up and the entire character no matter ho)-.1 F(w)-.25 E(man)102 252 Q 2.5
-(ys)-.15 G(creen columns it tak)130.46 252 Q(es up.)-.1 E F1 1.666(VI COMMANDS)
-72 276 R F0 .186(The follo)102 288 R .186
-(wing section describes the commands a)-.25 F -.25(va)-.2 G .186
-(ilable in the command mode of the).25 F F2(vi)2.686 E F0(editor)2.686 E 5.186
-(.I)-.55 G 2.685(ne)498.54 288 S .185(ach en-)510.665 288 R(try belo)102 300 Q
-1.3 -.65(w, t)-.25 H(he tag line is a usage synopsis for the command character)
-.65 E(.)-.55 E F1([count] <contr)102 324 Q(ol-A>)-.18 E F0(Search forw)131 336
-Q(ard)-.1 E/F3 10/Courier@0 SF(count)2.5 E F0(times for the current w)2.5 E
-(ord.)-.1 E F1([count] <contr)102 348 Q(ol-B>)-.18 E F0 -.15(Pa)131 360 S
-(ge backw).15 E(ards)-.1 E F3(count)2.5 E F0(screens.)2.5 E F1([count] <contr)
-102 372 Q(ol-D>)-.18 E F0(Scroll forw)131 384 Q(ard)-.1 E F3(count)2.5 E F0
-(lines.)2.5 E F1([count] <contr)102 396 Q(ol-E>)-.18 E F0(Scroll forw)131 408 Q
-(ard)-.1 E F3(count)2.5 E F0(lines, lea)2.5 E
-(ving the current line and column as is, if possible.)-.2 E F1([count] <contr)
-102 420 Q(ol-F>)-.18 E F0 -.15(Pa)131 432 S(ge forw).15 E(ard)-.1 E F3(count)
-2.5 E F0(screens.)2.5 E F1(<contr)102 444 Q(ol-G>)-.18 E F0
-(Display the \214le information.)131 456 Q F1(<contr)102 468 Q(ol-H>)-.18 E
-([count] h)102 480 Q F0(Mo)131 492 Q .3 -.15(ve t)-.15 H(he cursor back).15 E
-F3(count)2.5 E F0(characters in the current line.)2.5 E F1([count] <contr)102
-504 Q(ol-J>)-.18 E([count] <contr)102 516 Q(ol-N>)-.18 E([count] j)102 528 Q F0
-(Mo)131 540 Q .3 -.15(ve t)-.15 H(he cursor do).15 E(wn)-.25 E F3(count)2.5 E
-F0(lines without changing the current column.)2.5 E F1(<contr)102 552 Q(ol-L>)
--.18 E(<contr)102 564 Q(ol-R>)-.18 E F0(Repaint the screen.)131 576 Q F1
-([count] <contr)102 588 Q(ol-M>)-.18 E([count] +)102 600 Q F0(Mo)131 612 Q .3
--.15(ve t)-.15 H(he cursor do).15 E(wn)-.25 E F3(count)2.5 E F0
-(lines to the \214rst nonblank character of that line.)2.5 E F1([count] <contr)
-102 624 Q(ol-P>)-.18 E([count] k)102 636 Q F0(Mo)131 648 Q .3 -.15(ve t)-.15 H
-(he cursor up).15 E F3(count)2.5 E F0
-(lines, without changing the current column.)2.5 E F1(<contr)102 660 Q(ol-T>)
--.18 E F0(Return to the most recent tag conte)131 672 Q(xt.)-.15 E F1(<contr)
-102 684 Q(ol-U>)-.18 E F0 172.465(4.4BSD July)72 750 R(15, 1994)2.5 E(3)535 750
-Q EP
-%%Page: 4 4
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF -.834(EX/VI \( 1 \))72 48 R(BSD Reference Manual)
-258.235 48 Q -.834(EX/VI \( 1 \))496.682 48 R(Scroll backw)131 96 Q(ards)-.1 E
-/F1 10/Courier@0 SF(count)2.5 E F0(lines.)2.5 E/F2 10/Times-Bold@0 SF(<contr)
-102 108 Q(ol-W>)-.18 E F0 .635(Switch to the ne)131 120 R .635(xt lo)-.15 F
-.635(wer screen in the windo)-.25 F 1.935 -.65(w, o)-.25 H 1.435 -.4(r, t).65 H
-3.135(ot).4 G .635(he \214rst screen if there are no lo)353.205 120 R .635
-(wer screens in)-.25 F(the windo)131 132 Q -.65(w.)-.25 G F2(<contr)102 144 Q
-(ol-Y>)-.18 E F0(Scroll backw)131 156 Q(ards)-.1 E F1(count)2.5 E F0
-(lines, lea)2.5 E(ving the current line and column as is, if possible.)-.2 E F2
-(<contr)102 168 Q(ol-Z>)-.18 E F0(Suspend the current editor session.)131 180 Q
-F2(<escape>)102 192 Q F0(Ex)131 204 Q(ecute)-.15 E/F3 10/Courier-Bold@0 SF(ex)
-2.5 E F0(commands or cancel partial commands.)2.5 E F2(<contr)102 216 Q(ol-]>)
--.18 E F0(Push a tag reference onto the tag stack.)131 228 Q F2(<contr)102 240
-Q(ol-^>)-.18 E F0(Switch to the most recently edited \214le.)131 252 Q F2
-([count] <space>)102 264 Q([count] l)102 276 Q F0(Mo)131 288 Q .3 -.15(ve t)
--.15 H(he cursor forw).15 E(ard)-.1 E F1(count)2.5 E F0
-(characters without changing the current line.)2.5 E F2
-([count] ! motion shell-ar)102 300 Q(gument\(s\))-.1 E F0(Replace te)131 312 Q
-(xt with results from a shell command.)-.15 E F2([count] # +|-|#)102 324 Q F0
-(Increment or decrement the cursor number)131 336 Q(.)-.55 E F2([count] $)102
-348 Q F0(Mo)131 360 Q .3 -.15(ve t)-.15 H(he cursor to the end of a line.).15 E
-F2(%)102 372 Q F0(Mo)131 372 Q .3 -.15(ve t)-.15 H 2.5(ot).15 G
-(he matching character)169.59 372 Q(.)-.55 E F2(&)102 384 Q F0(Repeat the pre)
-131 384 Q(vious substitution command on the current line.)-.25 E F2
-('<character>)102 396 Q(`<character>)102 408 Q F0(Return to a conte)131 420 Q
-(xt mark)-.15 E(ed by the character)-.1 E F1(<character>)2.5 E F0(.)A F2
-([count] \()102 432 Q F0(Back up)131 444 Q F1(count)2.5 E F0(sentences.)2.5 E
-F2([count] \))102 456 Q F0(Mo)131 468 Q .3 -.15(ve f)-.15 H(orw).15 E(ard)-.1 E
-F1(count)2.5 E F0(sentences.)2.5 E F2([count] ,)102 480 Q F0(Re)131 492 Q -.15
-(ve)-.25 G(rse \214nd character).15 E F1(count)2.5 E F0(times.)2.5 E F2
-([count] -)102 504 Q F0(Mo)131 516 Q .3 -.15(ve t)-.15 H 2.5<6f8c>.15 G
-(rst nonblank of the pre)172.37 516 Q(vious line,)-.25 E F1(count)2.5 E F0
-(times.)2.5 E F2([count] .)102 528 Q F0(Repeat the last)131 540 Q F3(vi)2.5 E
-F0(command that modi\214ed te)2.5 E(xt.)-.15 E F2(/RE<carriage-r)102 552 Q
-(etur)-.18 E(n>)-.15 E(/RE/ [offset]<carriage-r)102 564 Q(etur)-.18 E(n>)-.15 E
-(?RE<carriage-r)102 576 Q(etur)-.18 E(n>)-.15 E(?RE? [offset]<carriage-r)102
-588 Q(etur)-.18 E(n>)-.15 E(N)102 600 Q(n)102 612 Q F0(Search forw)131 612 Q
-(ard or backw)-.1 E(ard for a re)-.1 E(gular e)-.15 E(xpression.)-.15 E F2(0)
-102 624 Q F0(Mo)131 624 Q .3 -.15(ve t)-.15 H 2.5(ot).15 G
-(he \214rst character in the current line.)169.59 624 Q 26.22(:E)102 636 S -.15
-(xe)137.11 636 S(cute an e).15 E 2.5(xc)-.15 G(ommand.)193.73 636 Q F2
-([count] ;)102 648 Q F0(Repeat the last character \214nd)131 660 Q F1(count)2.5
-E F0(times.)2.5 E F2([count] < motion)102 672 Q F0 172.465(4.4BSD July)72 750 R
-(15, 1994)2.5 E(4)535 750 Q EP
-%%Page: 5 5
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF -.834(EX/VI \( 1 \))72 48 R(BSD Reference Manual)
-258.235 48 Q -.834(EX/VI \( 1 \))496.682 48 R/F1 10/Times-Bold@0 SF
-([count] > motion)102 96 Q F0(Shift lines left or right.)131 108 Q F1 2.5(@b)
-102 120 S(uffer)119.16 120 Q F0(Ex)131 132 Q(ecute a named b)-.15 E(uf)-.2 E
-(fer)-.25 E(.)-.55 E F1([count] A)102 144 Q F0
-(Enter input mode, appending the te)131 156 Q(xt after the end of the line.)
--.15 E F1([count] B)102 168 Q F0(Mo)131 180 Q .3 -.15(ve b)-.15 H(ackw).15 E
-(ards)-.1 E/F2 10/Courier@0 SF(count)2.5 E F0(bigw)2.5 E(ords.)-.1 E F1([b)102
-192 Q(uffer] [count] C)-.2 E F0(Change te)131 204 Q
-(xt from the current position to the end-of-line.)-.15 E F1([b)102 216 Q
-(uffer] D)-.2 E F0(Delete te)131 228 Q
-(xt from the current position to the end-of-line.)-.15 E F1([count] E)102 240 Q
-F0(Mo)131 252 Q .3 -.15(ve f)-.15 H(orw).15 E(ard)-.1 E F2(count)2.5 E F0
-(end-of-bigw)2.5 E(ords.)-.1 E F1([count] F <character>)102 264 Q F0(Search)131
-276 Q F2(count)2.5 E F0(times backw)2.5 E(ard through the current line for)-.1
-E F2(<character>)2.5 E F0(.)A F1([count] G)102 288 Q F0(Mo)131 300 Q .3 -.15
-(ve t)-.15 H 2.5(ol).15 G(ine)169.59 300 Q F2(count)2.5 E F0 2.5(,o)C 2.5(rt)
-224.31 300 S(he last line of the \214le if)232.92 300 Q F2(count)2.5 E F0
-(not speci\214ed.)2.5 E F1([count] H)102 312 Q F0(Mo)131 324 Q .3 -.15(ve t)
--.15 H 2.5(ot).15 G(he screen line)169.59 324 Q F2(count - 1)2.5 E F0
-(lines belo)2.5 E 2.5(wt)-.25 G(he top of the screen.)334.43 324 Q F1
-([count] I)102 336 Q F0(Enter input mode, inserting the te)131 348 Q
-(xt at the be)-.15 E(ginning of the line.)-.15 E F1([count] J)102 360 Q F0
-(Join lines.)131 372 Q F1([count] L)102 384 Q F0(Mo)131 396 Q .3 -.15(ve t)-.15
-H 2.5(ot).15 G(he screen line)169.59 396 Q F2(count - 1)2.5 E F0(lines abo)2.5
-E .3 -.15(ve t)-.15 H(he bottom of the screen.).15 E F1(M)102 408 Q F0(Mo)131
-408 Q .3 -.15(ve t)-.15 H 2.5(ot).15 G
-(he screen line in the middle of the screen.)169.59 408 Q F1([count] O)102 420
-Q F0(Enter input mode, appending te)131 432 Q(xt in a ne)-.15 E 2.5(wl)-.25 G
-(ine abo)305.86 432 Q .3 -.15(ve t)-.15 H(he current line.).15 E F1([b)102 444
-Q(uffer] P)-.2 E F0(Insert te)131 456 Q(xt from a b)-.15 E(uf)-.2 E(fer)-.25 E
-(.)-.55 E F1(Q)102 468 Q F0(Exit)131 468 Q/F3 10/Courier-Bold@0 SF(vi)2.5 E F0
-(\(or visual\) mode and switch to)2.5 E F3(ex)2.5 E F0(mode.)2.5 E F1
-([count] R)102 480 Q F0
-(Enter input mode, replacing the characters in the current line.)131 492 Q F1
-([b)102 504 Q(uffer] [count] S)-.2 E F0(Substitute)131 516 Q F2(count)2.5 E F0
-(lines.)2.5 E F1([count] T <character>)102 528 Q F0 2.78(Search backw)131 540 R
-(ards,)-.1 E F2(count)5.28 E F0 2.779
-(times, through the current line for the character)5.28 F/F4 10/Times-Italic@0
-SF(after)5.279 E F0 2.779(the speci\214ed)5.279 F F2(<character>)131 552 Q F0
-(.)A F1(U)102 564 Q F0
-(Restore the current line to its state before the cursor last mo)131 564 Q -.15
-(ve)-.15 G 2.5(dt).15 G 2.5(oi)388.99 564 S(t.)399.27 564 Q F1([count] W)102
-576 Q F0(Mo)131 588 Q .3 -.15(ve f)-.15 H(orw).15 E(ard)-.1 E F2(count)2.5 E F0
-(bigw)2.5 E(ords.)-.1 E F1([b)102 600 Q(uffer] [count] X)-.2 E F0(Delete)131
-612 Q F2(count)2.5 E F0(characters before the cursor)2.5 E(.)-.55 E F1([b)102
-624 Q(uffer] [count] Y)-.2 E F0(Cop)131 636 Q 2.5(y\()-.1 G(or `)158.4 636 Q
-(`yank')-.74 E('\))-.74 E F2(count)2.5 E F0(lines into the speci\214ed b)2.5 E
-(uf)-.2 E(fer)-.25 E(.)-.55 E F1(ZZ)102 648 Q F0(Write the \214le and e)131 648
-Q(xit)-.15 E F3(vi)2.5 E F0(.)A F1([count] [[)102 660 Q F0(Back up)131 672 Q F2
-(count)2.5 E F0(section boundaries.)2.5 E F1([count] ]])102 684 Q F0 172.465
-(4.4BSD July)72 750 R(15, 1994)2.5 E(5)535 750 Q EP
-%%Page: 6 6
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF -.834(EX/VI \( 1 \))72 48 R(BSD Reference Manual)
-258.235 48 Q -.834(EX/VI \( 1 \))496.682 48 R(Mo)131 96 Q .3 -.15(ve f)-.15 H
-(orw).15 E(ard)-.1 E/F1 10/Courier@0 SF(count)2.5 E F0(section boundaries.)2.5
-E/F2 10/Times-Bold@0 SF(^)102 108 Q F0(Mo)131 108 Q .3 -.15(ve t)-.15 H 2.5
-<6f8c>.15 G(rst nonblank character on the current line.)172.37 108 Q F2
-([count] _)102 120 Q F0(Mo)131 132 Q .3 -.15(ve d)-.15 H -.25(ow).15 G(n).25 E
-F1(count - 1)2.5 E F0(lines, to the \214rst nonblank character)2.5 E(.)-.55 E
-F2([count] a)102 144 Q F0(Enter input mode, appending the te)131 156 Q
-(xt after the cursor)-.15 E(.)-.55 E F2([count] b)102 168 Q F0(Mo)131 180 Q .3
--.15(ve b)-.15 H(ackw).15 E(ards)-.1 E F1(count)2.5 E F0 -.1(wo)2.5 G(rds.).1 E
-F2([b)102 192 Q(uffer] [count] c motion)-.2 E F0(Change a re)131 204 Q
-(gion of te)-.15 E(xt.)-.15 E F2([b)102 216 Q(uffer] [count] d motion)-.2 E F0
-(Delete a re)131 228 Q(gion of te)-.15 E(xt.)-.15 E F2([count] e)102 240 Q F0
-(Mo)131 252 Q .3 -.15(ve f)-.15 H(orw).15 E(ard)-.1 E F1(count)2.5 E F0
-(end-of-w)2.5 E(ords.)-.1 E F2([count] f<character>)102 264 Q F0(Search forw)
-131 276 Q(ard,)-.1 E F1(count)2.5 E F0
-(times, through the rest of the current line for)2.5 E F1(<character>)2.5 E F0
-(.)A F2([count] i)102 288 Q F0(Enter input mode, inserting the te)131 300 Q
-(xt before the cursor)-.15 E(.)-.55 E F2 2.5(m<)102 312 S(character>)118.53 312
-Q F0(Sa)131 324 Q .3 -.15(ve t)-.2 H(he current conte).15 E
-(xt \(line and column\) as)-.15 E F1(<character>)2.5 E F0(.)A F2([count] o)102
-336 Q F0(Enter input mode, appending te)131 348 Q(xt in a ne)-.15 E 2.5(wl)-.25
-G(ine under the current line.)305.86 348 Q F2([b)102 360 Q(uffer] p)-.2 E F0
-(Append te)131 372 Q(xt from a b)-.15 E(uf)-.2 E(fer)-.25 E(.)-.55 E F2
-([count] r <character>)102 384 Q F0(Replace)131 396 Q F1(count)2.5 E F0
-(characters.)2.5 E F2([b)102 408 Q(uffer] [count] s)-.2 E F0(Substitute)131 420
-Q F1(count)2.5 E F0
-(characters in the current line starting with the current character)2.5 E(.)
--.55 E F2([count] t <character>)102 432 Q F0 3.435(Search forw)131 444 R(ard,)
--.1 E F1(count)5.935 E F0 3.435
-(times, through the current line for the character immediately)5.935 F/F3 10
-/Times-Italic@0 SF(befor)5.935 E(e)-.37 E F1(<character>)131 456 Q F0(.)A F2(u)
-102 468 Q F0(Undo the last change made to the \214le.)131 468 Q F2([count] w)
-102 480 Q F0(Mo)131 492 Q .3 -.15(ve f)-.15 H(orw).15 E(ard)-.1 E F1(count)2.5
-E F0 -.1(wo)2.5 G(rds.).1 E F2([b)102 504 Q(uffer] [count] x)-.2 E F0(Delete)
-131 516 Q F1(count)2.5 E F0(characters.)2.5 E F2([b)102 528 Q
-(uffer] [count] y motion)-.2 E F0(Cop)131 540 Q 2.5(y\()-.1 G(or `)158.4 540 Q
-(`yank')-.74 E('\) a te)-.74 E(xt re)-.15 E(gion speci\214ed by the)-.15 E F1
-(count)2.5 E F0(and motion into a b)2.5 E(uf)-.2 E(fer)-.25 E(.)-.55 E F2
-([count1] z [count2] -|.|+|^|<carriage-r)102 552 Q(etur)-.18 E(n>)-.15 E F0
-(Redra)131 564 Q 1.3 -.65(w, o)-.15 H
-(ptionally repositioning and resizing the screen.).65 E F2([count] {)102 576 Q
-F0(Mo)131 588 Q .3 -.15(ve b)-.15 H(ackw).15 E(ard)-.1 E F1(count)2.5 E F0
-(paragraphs.)2.5 E F2([count] |)102 600 Q F0(Mo)131 612 Q .3 -.15(ve t)-.15 H
-2.5(oas).15 G(peci\214c)177.64 612 Q F3(column)2.5 E F0
-(position on the current line.)2.5 E F2([count] })102 624 Q F0(Mo)131 636 Q .3
--.15(ve f)-.15 H(orw).15 E(ard)-.1 E F1(count)2.5 E F0(paragraphs.)2.5 E F2
-([count] ~)102 648 Q F0(Re)131 660 Q -.15(ve)-.25 G(rse the case of the ne).15
-E(xt)-.15 E F1(count)2.5 E F0(character\(s\).)2.5 E F2([count] ~ motion)102 672
-Q F0 172.465(4.4BSD July)72 750 R(15, 1994)2.5 E(6)535 750 Q EP
-%%Page: 7 7
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF -.834(EX/VI \( 1 \))72 48 R(BSD Reference Manual)
-258.235 48 Q -.834(EX/VI \( 1 \))496.682 48 R(Re)131 96 Q -.15(ve)-.25 G
-(rse the case of the characters in a te).15 E(xt re)-.15 E
-(gion speci\214ed by the)-.15 E/F1 10/Courier@0 SF(count)2.5 E F0(and)2.5 E F1
-(motion)2.5 E F0(.)A/F2 10/Times-Bold@0 SF(<interrupt>)102 108 Q F0
-(Interrupt the current operation.)131 120 Q F2 1.666(VI TEXT INPUT COMMANDS)72
-144 R F0(The follo)102 156 Q(wing section describes the commands a)-.25 E -.25
-(va)-.2 G(ilable in the te).25 E(xt input mode of the)-.15 E/F3 10
-/Courier-Bold@0 SF(vi)2.5 E F0(editor)2.5 E(.)-.55 E F2(<nul>)102 174 Q F0
-(Replay the pre)131 186 Q(vious input.)-.25 E F2(<contr)102 198 Q(ol-D>)-.18 E
-F0(Erase the pre)131 210 Q(vious autoindent character)-.25 E(.)-.55 E F2
-(^<contr)102 222 Q(ol-D>)-.18 E F0
-(Erase all of the autoindent characters, and reset the autoindent le)131 234 Q
--.15(ve)-.25 G(l.).15 E F2(0<contr)102 246 Q(ol-D>)-.18 E F0
-(Erase all of the autoindent characters.)131 258 Q F2(<contr)102 270 Q(ol-T>)
--.18 E F0 .076(Insert suf)131 282 R(\214cient)-.25 E F1(<tab>)2.576 E F0(and)
-2.576 E F1(<space>)2.576 E F0 .076(characters to mo)2.576 F .376 -.15(ve t)-.15
-H .076(he cursor forw).15 F .075(ard to a column immediate-)-.1 F
-(ly after the ne)131 294 Q(xt column which is an e)-.15 E -.15(ve)-.25 G 2.5
-(nm).15 G(ultiple of the)305.7 294 Q F2(shiftwidth)2.5 E F0(option.)2.5 E F2
-(<erase>)102 306 Q(<contr)102 318 Q(ol-H>)-.18 E F0(Erase the last character)
-131 330 Q(.)-.55 E F2(<literal next>)102 342 Q F0(Quote the ne)131 354 Q
-(xt character)-.15 E(.)-.55 E F2(<escape>)102 366 Q F0(Resolv)131 378 Q 2.5(ea)
--.15 G(ll te)170.01 378 Q
-(xt input into the \214le, and return to command mode.)-.15 E F2(<line erase>)
-102 390 Q F0(Erase the current line.)131 402 Q F2(<contr)102 414 Q(ol-W>)-.18 E
-(<w)102 426 Q(ord erase>)-.1 E F0(Erase the last w)131 438 Q 2.5(ord. The)-.1 F
-(de\214nition of w)2.5 E(ord is dependent on the)-.1 E F2(altwerase)2.5 E F0
-(and)2.5 E F2(ttywerase)2.5 E F0(options.)2.5 E F2(<contr)102 450 Q
-(ol-X>[0-9A-F)-.18 E(a-f])-.25 E/F4 10/Symbol SF(*)A F0
-(Insert a character with the speci\214ed he)131 462 Q(xadecimal v)-.15 E
-(alue into the te)-.25 E(xt.)-.15 E F2(<interrupt>)102 474 Q F0(Interrupt te)
-131 486 Q(xt input mode, returning to command mode.)-.15 E F2 1.666
-(EX COMMANDS)72 510 R F0 .163(The follo)102 522 R .163
-(wing section describes the commands a)-.25 F -.25(va)-.2 G .163(ilable in the)
-.25 F F3(ex)2.663 E F0(editor)2.663 E 5.163(.I)-.55 G 2.663(ne)405.333 522 S
-.164(ach entry belo)417.436 522 R 1.464 -.65(w, t)-.25 H .164(he tag line is)
-.65 F 2.5(au)102 534 S(sage synopsis for the command.)113.94 534 Q F2
-(<end-of-\214le>)102 558 Q F0(Scroll the screen.)131 570 Q F2 2.5(!a)102 582 S
--.1(rg)112.83 582 S(ument\(s\)).1 E([range]! ar)102 594 Q(gument\(s\))-.1 E F0
-(Ex)131 606 Q
-(ecute a shell command, or \214lter lines through a shell command.)-.15 E F2(")
-102 618 Q F0 2.5(Ac)131 618 S(omment.)145.16 618 Q F2
-([range] nu[mber] [count] [\215ags])102 630 Q([range] # [count] [\215ags])102
-642 Q F0(Display the selected lines, each preceded with its line number)131 654
-Q(.)-.55 E F2 2.5(@b)102 666 S(uffer)119.16 666 Q F4(*)102 678 Q F2 -.2(bu)2.5
-G(ffer).2 E F0 172.465(4.4BSD July)72 750 R(15, 1994)2.5 E(7)535 750 Q EP
-%%Page: 8 8
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF -.834(EX/VI \( 1 \))72 48 R(BSD Reference Manual)
-258.235 48 Q -.834(EX/VI \( 1 \))496.682 48 R(Ex)131 96 Q(ecute a b)-.15 E(uf)
--.2 E(fer)-.25 E(.)-.55 E/F1 10/Times-Bold@0 SF([range] d[elete] [b)102 108 Q
-(uffer] [count] [\215ags])-.2 E F0(Delete the lines from the \214le.)131 120 Q
-F1(di[splay] b[uffers] | s[cr)102 132 Q(eens] | t[ags])-.18 E F0(Display b)131
-144 Q(uf)-.2 E(fers, screens or tags.)-.25 E F1(e[dit][!] [+cmd] [\214le])102
-156 Q(ex[!] [+cmd] [\214le])102 168 Q F0(Edit a dif)131 180 Q(ferent \214le.)
--.25 E F1(exu[sage] [command])102 192 Q F0(Display usage for an)131 204 Q/F2 10
-/Courier-Bold@0 SF(ex)2.5 E F0(command.)2.5 E F1(f[ile] [\214le])102 216 Q F0
-(Display and optionally change the \214le name.)131 228 Q F1(fg [name])102 240
-Q F2(Vi)131 252 Q F0(mode only)2.5 E 5(.F)-.65 G(ore)200.26 252 Q
-(ground the speci\214ed screen.)-.15 E F1([range] g[lobal] /patter)102 264 Q
-(n/ [commands])-.15 E([range] v /patter)102 276 Q(n/ [commands])-.15 E F0
-(Apply commands to lines matching \(or not matching\) a pattern.)131 288 Q F1
-(he[lp])102 300 Q F0(Display a help message.)131 312 Q F1([line] i[nsert][!])
-102 324 Q F0(The input te)131 336 Q
-(xt is inserted before the speci\214ed line.)-.15 E F1
-([range] j[oin][!] [count] [\215ags])102 348 Q F0(Join lines of te)131 360 Q
-(xt together)-.15 E(.)-.55 E F1([range] l[ist] [count] [\215ags])102 372 Q F0
-(Display the lines unambiguously)131 384 Q(.)-.65 E F1(map[!] [lhs rhs])102 396
-Q F0(De\214ne or display maps \(for)131 408 Q F2(vi)2.5 E F0(only\).)2.5 E F1
-([line] ma[rk] <character>)102 420 Q([line] k <character>)102 432 Q F0
-(Mark the line with the mark)131 444 Q/F3 10/Courier@0 SF(<character>)2.5 E F0
-(.)A F1([range] m[o)102 456 Q -.1(ve)-.1 G 2.5(]l).1 G(ine)170.11 456 Q F0(Mo)
-131 468 Q .3 -.15(ve t)-.15 H(he speci\214ed lines after the tar).15 E
-(get line.)-.18 E F1(mk[exr)102 480 Q(c][!] \214le)-.18 E F0(Write the abbre)
-131 492 Q(viations, editor options and maps to the speci\214ed \214le.)-.25 E
-F1(n[ext][!] [\214le ...])102 504 Q F0(Edit the ne)131 516 Q
-(xt \214le from the ar)-.15 E(gument list.)-.18 E F1([line] o[pen] /patter)102
-528 Q(n/ [\215ags])-.15 E F0(Enter open mode.)131 540 Q F1(pr)102 552 Q(e[ser)
--.18 E -.1(ve)-.1 G(]).1 E F0(Sa)131 564 Q .3 -.15(ve t)-.2 H
-(he \214le in a form that can later be reco).15 E -.15(ve)-.15 G(red using the)
-.15 E F2 -1.834(ex \255r)2.5 F F0(option.)2.5 E F1(pr)102 576 Q -.15(ev)-.18 G
-([ious][!]).15 E F0(Edit the pre)131 588 Q(vious \214le from the ar)-.25 E
-(gument list.)-.18 E F1([range] p[rint] [count] [\215ags])102 600 Q F0
-(Display the speci\214ed lines.)131 612 Q F1([line] pu[t] [b)102 624 Q(uffer])
--.2 E F0(Append b)131 636 Q(uf)-.2 E(fer contents to the current line.)-.25 E
-F1(q[uit][!])102 648 Q F0(End the editing session.)131 660 Q F1
-([line] r[ead][!] [\214le])102 672 Q F0 172.465(4.4BSD July)72 750 R(15, 1994)
-2.5 E(8)535 750 Q EP
-%%Page: 9 9
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF -.834(EX/VI \( 1 \))72 48 R(BSD Reference Manual)
-258.235 48 Q -.834(EX/VI \( 1 \))496.682 48 R(Read a \214le.)131 96 Q/F1 10
-/Times-Bold@0 SF -.18(re)102 108 S(c[o).18 E -.1(ve)-.1 G(r] \214le).1 E F0
-(Reco)131 120 Q -.15(ve)-.15 G(r).15 E/F2 10/Courier@0 SF(file)2.5 E F0
-(if it w)2.5 E(as pre)-.1 E(viously sa)-.25 E -.15(ve)-.2 G(d.).15 E F1 -.18
-(re)102 132 S(s[ize] [+|-]size).18 E/F3 10/Courier-Bold@0 SF(Vi)131 144 Q F0
-(mode only)2.5 E 5(.G)-.65 G(ro)202.07 144 Q 2.5(wo)-.25 G 2.5(rs)224.87 144 S
-(hrink the current screen.)234.59 144 Q F1 -.18(re)102 156 S(w[ind][!]).18 E F0
-(Re)131 168 Q(wind the ar)-.25 E(gument list.)-.18 E F1(se[t] [option[=[v)102
-180 Q(alue]] ...] [nooption ...] [option? ...] [all])-.1 E F0
-(Display or set editor options.)131 192 Q F1(sh[ell])102 204 Q F0
-(Run a shell program.)131 216 Q F1(so[ur)102 228 Q(ce] \214le)-.18 E F0
-(Read and e)131 240 Q -.15(xe)-.15 G(cute).15 E F3(ex)2.5 E F0
-(commands from a \214le.)2.5 E F1(sp[lit] [\214le ...])102 252 Q F3(Vi)131 264
-Q F0(mode only)2.5 E 5(.S)-.65 G(plit the screen.)200.41 264 Q F1
-([range] s[ubstitute] [/patter)102 276 Q(n/r)-.15 E
-(eplace/] [options] [count] [\215ags])-.18 E
-([range] & [options] [count] [\215ags])102 288 Q
-([range] ~ [options] [count] [\215ags])102 300 Q F0(Mak)131 312 Q 2.5(es)-.1 G
-(ubstitutions.)160.06 312 Q F1(su[spend][!])102 324 Q(st[op][!])102 336 Q
-(<suspend>)102 348 Q F0(Suspend the edit session.)131 360 Q F1
-(ta[g][!] tagstring)102 372 Q F0
-(Edit the \214le containing the speci\214ed tag.)131 384 Q F1
-(tagp[op][!] [\214le | number])102 396 Q F0
-(Pop to the speci\214ed tag in the tags stack.)131 408 Q F1(unm[ap][!] lhs)102
-420 Q F0(Unmap a mapped string.)131 432 Q F1 -.1(ve)102 444 S([rsion]).1 E F0
-(Display the v)131 456 Q(ersion of the)-.15 E F3(ex/vi)2.5 E F0(editor)2.5 E(.)
--.55 E F1([line] vi[sual] [type] [count] [\215ags])102 468 Q F3(Ex)131 480 Q F0
-(mode only)2.5 E 5(.E)-.65 G(nter)200.96 480 Q F3(vi)2.5 E F0(.)A F1
-(vi[sual][!] [+cmd] [\214le])102 492 Q F3(Vi)131 504 Q F0(mode only)2.5 E 5(.E)
--.65 G(dit a ne)200.96 504 Q 2.5<778c>-.25 G(le.)245.43 504 Q F1
-(viu[sage] [command])102 516 Q F0(Display usage for a)131 528 Q F3(vi)2.5 E F0
-(command.)2.5 E F1([range] w[rite][!] [>>] [\214le])102 540 Q
-([range] w[rite] [!] [\214le])102 552 Q([range] wn[!] [>>] [\214le])102 564 Q
-([range] wq[!] [>>] [\214le])102 576 Q F0(Write the \214le.)131 588 Q F1
-([range] x[it][!] [\214le])102 600 Q F0
-(Write the \214le if it has been modi\214ed.)131 612 Q F1([range] ya[nk] [b)102
-624 Q(uffer] [count])-.2 E F0(Cop)131 636 Q 2.5(yt)-.1 G
-(he speci\214ed lines to a b)157.85 636 Q(uf)-.2 E(fer)-.25 E(.)-.55 E F1
-([line] z [type] [count] [\215ags])102 648 Q F0(Adjust the windo)131 660 Q -.65
-(w.)-.25 G 172.465(4.4BSD July)72 750 R(15, 1994)2.5 E(9)535 750 Q EP
-%%Page: 10 10
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF -.834(EX/VI \( 1 \))72 48 R(BSD Reference Manual)
-258.235 48 Q -.834(EX/VI \( 1 \))496.682 48 R/F1 10/Times-Bold@0 SF 1.666
-(SET OPTIONS)72 96 R F0 .519(There are a lar)102 108 R .518
-(ge number of options that may be set \(or unset\) to change the editor')-.18 F
-3.018(sb)-.55 G(eha)453.614 108 Q(vior)-.2 E 5.518(.T)-.55 G .518(his section)
-496.982 108 R(describes the options, their abbre)102 120 Q
-(viations and their def)-.25 E(ault v)-.1 E(alues.)-.25 E .095
-(In each entry belo)102 138 R 1.395 -.65(w, t)-.25 H .095
-(he \214rst part of the tag line is the full name of the option, follo).65 F
-.095(wed by an)-.25 F 2.595(ye)-.15 G(qui)487.915 138 Q -.25(va)-.25 G .095
-(lent ab-).25 F(bre)102 150 Q 3.034(viations. The)-.25 F .534
-(part in square brack)3.034 F .533(ets is the def)-.1 F .533(ault v)-.1 F .533
-(alue of the option.)-.25 F .533(Most of the options are boolean,)5.533 F
-(i.e. the)102 162 Q 2.5(ya)-.15 G(re either on or of)140.73 162 Q
-(f, and do not ha)-.25 E .3 -.15(ve a)-.2 H 2.5(na).15 G(ssociated v)298.14 162
-Q(alue.)-.25 E(Options apply to both)102 180 Q/F2 10/Courier-Bold@0 SF(ex)2.5 E
-F0(and)2.5 E F2(vi)2.5 E F0(modes, unless otherwise speci\214ed.)2.5 E F1
-(altwerase [off])102 204 Q F2(Vi)131 216 Q F0(only)2.5 E 5(.S)-.65 G
-(elect an alternate w)175.69 216 Q(ord erase algorithm.)-.1 E F1
-(autoindent, ai [off])102 228 Q F0(Automatically indent ne)131 240 Q 2.5(wl)
--.25 G(ines.)239.91 240 Q F1(autoprint, ap [off])102 252 Q F2(Ex)131 264 Q F0
-(only)2.5 E 5(.D)-.65 G(isplay the current line automatically)177.35 264 Q(.)
--.65 E F1(auto)102 276 Q(write, aw [off])-.1 E F0
-(Write modi\214ed \214les automatically when changing \214les.)131 288 Q F1
-(beautify)102 300 Q 2.5(,b)-.55 G 2.5(f[)147.01 300 S(off])156.17 300 Q F0
-(Discard control characters.)131 312 Q F1(cdpath [en)102 324 Q(vir)-.4 E
-(onment v)-.18 E(ariable CDP)-.1 E -.95(AT)-.74 G(H, or curr).95 E(ent dir)-.18
-E(ectory])-.18 E F0(The directory paths used as path pre\214x)131 336 Q
-(es for the)-.15 E F1(cd)2.5 E F0(command.)2.5 E F1(columns, co [80])102 348 Q
-F0(Set the number of columns in the screen.)131 360 Q F1(comment [off])102 372
-Q F2(Vi)131 384 Q F0(only)2.5 E 5(.S)-.65 G(kip leading comments in \214les.)
-175.69 384 Q F1(dir)102 396 Q(ectory)-.18 E 2.5(,d)-.55 G(ir [en)151.26 396 Q
-(vir)-.4 E(onment v)-.18 E(ariable TMPDIR, or /tmp])-.1 E F0
-(The directory where temporary \214les are created.)131 408 Q F1
-(edcompatible, ed [off])102 420 Q F0 .279(Remember the v)131 432 R .279
-(alues of the `)-.25 F(`c')-.74 E 2.779('a)-.74 G .279(nd `)270.344 432 R(`g')
--.74 E 2.779('s)-.74 G(uf)306.632 432 Q .279(\214ces to the)-.25 F F1
-(substitute)2.78 E F0 .28(commands, instead of initializing)2.78 F
-(them as unset for each ne)131 444 Q 2.5(wc)-.25 G(ommand.)246.27 444 Q F1(err)
-102 456 Q(orbells, eb [off])-.18 E F2(Ex)131 468 Q F0(only)2.5 E 5(.A)-.65 G
-(nnounce error messages with a bell.)177.35 468 Q F1(exr)102 480 Q(c, ex [off])
--.18 E F0(Ne)131 492 Q -.15(ve)-.25 G 2.5(rr).15 G
-(ead startup \214les in the local directory)160.86 492 Q(.)-.65 E F1
-(extended [off])102 504 Q F0(Re)131 516 Q(gular e)-.15 E(xpressions are e)-.15
-E(xtended \(i.e.)-.15 E/F3 10/Courier@0 SF(egrep)5 E F0(\(1\) style\) e)A
-(xpressions.)-.15 E F1(\215ash [on])102 528 Q F0
-(Flash the screen instead of beeping the k)131 540 Q -.15(ey)-.1 G
-(board on error).15 E(.)-.55 E F1(hardtabs, ht [8])102 552 Q F0
-(Set the spacing between hardw)131 564 Q(are tab settings.)-.1 E F1(ignor)102
-576 Q(ecase, ic [off])-.18 E F0(Ignore case dif)131 588 Q(ferences in re)-.25 E
-(gular e)-.15 E(xpressions.)-.15 E F1 -.1(ke)102 600 S(ytime [6]).1 E F0
-(The 10th')131 612 Q 2.5(so)-.55 G 2.5(fas)181 612 S(econd)197.66 612 Q F2
-(ex/vi)2.5 E F0 -.1(wa)2.5 G(its for a subsequent k).1 E .3 -.15(ey t)-.1 H 2.5
-(oc).15 G(omplete a k)379.5 612 Q .3 -.15(ey m)-.1 H(apping.).15 E F1
-(leftright [off])102 624 Q F2(Vi)131 636 Q F0(only)2.5 E 5(.D)-.65 G 2.5(ol)
-177.35 636 S(eft-right scrolling.)187.63 636 Q F1(lines, li [24])102 648 Q F2
-(Vi)131 660 Q F0(only)2.5 E 5(.S)-.65 G(et the number of lines in the screen.)
-175.69 660 Q F1(lisp [off])102 672 Q F2(Vi)131 684 Q F0(only)2.5 E 5(.M)-.65 G
-(odify v)179.02 684 Q(arious search commands and options to w)-.25 E
-(ork with Lisp.)-.1 E 172.465(4.4BSD July)72 750 R(15, 1994)2.5 E(10)530 750 Q
-EP
-%%Page: 11 11
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF -.834(EX/VI \( 1 \))72 48 R(BSD Reference Manual)
-258.235 48 Q -.834(EX/VI \( 1 \))496.682 48 R/F1 10/Times-Italic@0 SF
-(This option is not yet implemented.)131 96 Q/F2 10/Times-Bold@0 SF(list [off])
-102 108 Q F0(Display lines in an unambiguous f)131 120 Q(ashion.)-.1 E F2
-(magic [on])102 132 Q F0 -.35(Tr)131 144 S
-(eat certain characters specially in re).35 E(gular e)-.15 E(xpressions.)-.15 E
-F2(matchtime [7])102 156 Q/F3 10/Courier-Bold@0 SF(Vi)131 168 Q F0(only)2.885 E
-5.385(.T)-.65 G .385(he 10th')177.01 168 R 2.885(so)-.55 G 2.885(fas)221.67 168
-S(econd)239.1 168 Q F3(ex/vi)2.884 E F0 .384
-(pauses on the matching character when the)2.884 F F2(sho)2.884 E(wmatch)-.1 E
-F0(op-)2.884 E(tion is set.)131 180 Q F2(mesg [on])102 192 Q F0
-(Permit messages from other users.)131 204 Q F2(modelines, modeline [off])102
-216 Q F0(Read the \214rst and last fe)131 228 Q 2.5(wl)-.25 G
-(ines of each \214le for)240.18 228 Q F3(ex)2.5 E F0(commands.)2.5 E F1
-(This option will ne)131 246 Q(ver be implemented.)-.15 E F2(number)102 258 Q
-2.5(,n)-.92 G 2.5(u[)145.53 258 S(off])156.92 258 Q F0
-(Precede each line displayed with its current line number)131 270 Q(.)-.55 E F2
-(octal [off])102 282 Q F0(Display unkno)131 294 Q
-(wn characters as octal numbers, instead of the def)-.25 E(ault he)-.1 E
-(xadecimal.)-.15 E F2(open [on])102 306 Q F3(Ex)131 318 Q F0(only)2.5 E 5(.I)
--.65 G 2.5(ft)173.46 318 S(his option is not set, the)182.07 318 Q F2(open)2.5
-E F0(and)2.5 E F2(visual)2.5 E F0(commands are disallo)2.5 E(wed.)-.25 E F2
-(optimize, opt [on])102 330 Q F3(Vi)131 342 Q F0(only)2.5 E 5(.O)-.65 G
-(ptimize te)177.35 342 Q(xt throughput to dumb terminals.)-.15 E F1
-(This option is not yet implemented.)131 360 Q F2
-(paragraphs, para [IPLPPPQPP LIpplpipbp])102 372 Q F3(Vi)131 384 Q F0(only)2.5
-E 5(.D)-.65 G(e\214ne additional paragraph boundaries for the)177.35 384 Q F2
-({)2.5 E F0(and)2.5 E F2(})2.5 E F0(commands.)2.5 E F2(pr)102 396 Q(ompt [on])
--.18 E F3(Ex)131 408 Q F0(only)2.5 E 5(.D)-.65 G(isplay a command prompt.)
-177.35 408 Q F2 -.18(re)102 420 S(adonly).18 E 2.5(,r)-.55 G 2.5(o[)148.31 420
-S(off])159.14 420 Q F0(Mark the \214le as read-only)131 432 Q(.)-.65 E F2 -.18
-(re)102 444 S(cdir [/v).18 E(ar/tmp/vi.r)-.1 E(eco)-.18 E -.1(ve)-.1 G(r]).1 E
-F0(The directory where reco)131 456 Q -.15(ve)-.15 G(ry \214les are stored.).15
-E F2 -.18(re)102 468 S(draw).18 E 2.5(,r)-.55 G 2.5(e[)141.63 468 S(off])151.9
-468 Q F3(Vi)131 480 Q F0(only)2.5 E 5(.S)-.65 G
-(imulate an intelligent terminal on a dumb one.)175.69 480 Q F1
-(This option is not yet implemented.)131 498 Q F2 -.18(re)102 510 S(map [on])
-.18 E F0(Remap k)131 522 Q -.15(ey)-.1 G 2.5(su).15 G(ntil resolv)187.41 522 Q
-(ed.)-.15 E F2 -.18(re)102 534 S(port [5]).18 E F0
-(Set the number of lines about which the editor reports changes or yanks.)131
-546 Q F2(ruler [off])102 558 Q F3(Vi)131 570 Q F0(only)2.5 E 5(.D)-.65 G
-(isplay a ro)177.35 570 Q(w/column ruler on the colon command line.)-.25 E F2
-(scr)102 582 Q(oll, scr [windo)-.18 E 2.5(w/2)-.1 G(])194.77 582 Q F0
-(Set the number of lines scrolled.)131 594 Q F2(sections, sect [NHSHH HUnhsh])
-102 606 Q F3(Vi)131 618 Q F0(only)2.5 E 5(.D)-.65 G
-(e\214ne additional section boundaries for the)177.35 618 Q F2([[)2.5 E F0(and)
-2.5 E F2(]])2.5 E F0(commands.)2.5 E F2(shell, sh [en)102 630 Q(vir)-.4 E
-(onment v)-.18 E(ariable SHELL, or /bin/sh])-.1 E F0
-(Select the shell used by the editor)131 642 Q(.)-.55 E F2(shiftwidth, sw [8])
-102 654 Q F0(Set the autoindent and shift command indentation width.)131 666 Q
-F2(sho)102 678 Q(wdirty [off])-.1 E F0 172.465(4.4BSD July)72 750 R(15, 1994)
-2.5 E(11)530 750 Q EP
-%%Page: 12 12
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF -.834(EX/VI \( 1 \))72 48 R(BSD Reference Manual)
-258.235 48 Q -.834(EX/VI \( 1 \))496.682 48 R/F1 10/Courier-Bold@0 SF(Vi)131 96
-Q F0(only)2.5 E 5(.D)-.65 G(isplay an asterisk on the colon command line if th\
-e \214le has been modi\214ed.)177.35 96 Q/F2 10/Times-Bold@0 SF(sho)102 108 Q
-(wmatch, sm [off])-.1 E F1(Vi)131 120 Q F0(only)2.5 E 5(.N)-.65 G
-(ote matching `)177.35 120 Q(`{')-.74 E 2.5('a)-.74 G(nd `)255.37 120 Q(`\(')
--.74 E 2.5('f)-.74 G(or `)288.87 120 Q(`}')-.74 E 2.5('a)-.74 G(nd `)323.28 120
-Q(`\)')-.74 E 2.5('c)-.74 G(haracters.)357.89 120 Q F2(sho)102 132 Q
-(wmode [off])-.1 E F1(Vi)131 144 Q F0(only)2.5 E 5(.D)-.65 G
-(isplay the current editor mode \(command or input\).)177.35 144 Q F2(sidescr)
-102 156 Q(oll [16])-.18 E F1(Vi)131 168 Q F0(only)2.5 E 5(.S)-.65 G
-(et the amount a left-right scroll will shift.)175.69 168 Q F2(slo)102 180 Q
--.1(wo)-.1 G(pen, slo).1 E 2.5(w[)-.1 G(off])170.87 180 Q F0
-(Delay display updating during te)131 192 Q(xt input.)-.15 E/F3 10
-/Times-Italic@0 SF(This option is not yet implemented.)131 210 Q F2(sour)102
-222 Q(ceany [off])-.18 E F0(Read startup \214les not o)131 234 Q
-(wned by the current user)-.25 E(.)-.55 E F3(This option will ne)131 252 Q
-(ver be implemented.)-.15 E F2(tabstop, ts [8])102 264 Q F0
-(This option sets tab widths for the editor display)131 276 Q(.)-.65 E F2
-(taglength, tl [0])102 288 Q F0
-(Set the number of signi\214cant characters in tag names.)131 300 Q F2
-(tags, tag [tags /v)102 312 Q(ar/db/libc.tags /sys/k)-.1 E(er)-.1 E(n/tags])
--.15 E F0(Set the list of tags \214les.)131 324 Q F2(term, ttytype, tty [en)102
-336 Q(vir)-.4 E(onment v)-.18 E(ariable TERM])-.1 E F0(Set the terminal type.)
-131 348 Q F2(terse [off])102 360 Q F0 .759
-(This option has historically made editor messages less v)131 372 R 3.259
-(erbose. It)-.15 F .76(has no ef)3.259 F .76(fect in this implementa-)-.25 F
-(tion.)131 384 Q F2(tildeop)102 396 Q F0(Modify the)131 408 Q F2(~)2.5 E F0
-(command to tak)2.5 E 2.5(ea)-.1 G 2.5(na)259.77 408 S(ssociated motion.)271.71
-408 Q F2(timeout, to [on])102 420 Q F0 -.35(Ti)131 432 S(me out on k).35 E -.15
-(ey)-.1 G 2.5(sw).15 G(hich may be mapped.)209.84 432 Q F2(ttywerase [off])102
-444 Q F1(Vi)131 456 Q F0(only)2.5 E 5(.S)-.65 G
-(elect an alternate erase algorithm.)175.69 456 Q F2 -.1(ve)102 468 S
-(rbose [off]).1 E F0(only)131 480 Q 5(.D)-.65 G(isplay an error message for e)
-162.85 480 Q -.15(ve)-.25 G(ry error).15 E(.)-.55 E F2(w300 [no default])102
-492 Q F1(Vi)131 504 Q F0(only)2.5 E 5(.S)-.65 G(et the windo)175.69 504 Q 2.5
-(ws)-.25 G(ize if the baud rate is less than 1200 baud.)238.49 504 Q F2
-(w1200 [no default])102 516 Q F1(Vi)131 528 Q F0(only)2.5 E 5(.S)-.65 G
-(et the windo)175.69 528 Q 2.5(ws)-.25 G
-(ize if the baud rate is equal to 1200 baud.)238.49 528 Q F2
-(w9600 [no default])102 540 Q F1(Vi)131 552 Q F0(only)2.5 E 5(.S)-.65 G
-(et the windo)175.69 552 Q 2.5(ws)-.25 G
-(ize if the baud rate is greater than 1200 baud.)238.49 552 Q F2(war)102 564 Q
-2.5(n[)-.15 G(on])129.9 564 Q F1(Ex)131 576 Q F0(only)2.979 E 5.479(.T)-.65 G
-.479(his option causes a w)177.198 576 R .479
-(arning message to the terminal if the \214le has been modi\214ed, since it)-.1
-F -.1(wa)131 588 S 2.5(sl).1 G(ast written, before a)151.73 588 Q F2(!)2.5 E F0
-(command.)2.5 E F2(windo)102 600 Q 1.1 -.55(w, w, w)-.1 H 2.5(i[).55 G(en)
-167.19 600 Q(vir)-.4 E(onment v)-.18 E(ariable LINES])-.1 E F0(Set the windo)
-131 612 Q 2.5(ws)-.25 G(ize for the screen.)199.36 612 Q F2(wrapmar)102 624 Q
-(gin, wm [0])-.1 E F1(Vi)131 636 Q F0(only)2.5 E 5(.B)-.65 G
-(reak lines automatically when the)176.8 636 Q 2.5(yr)-.15 G
-(each the right-hand mar)321.9 636 Q(gin.)-.18 E F2(wrapscan, ws [on])102 648 Q
-F0(Set searches to wrap around the end or be)131 660 Q(ginning of the \214le.)
--.15 E F2(writeany)102 672 Q 2.5(,w)-.55 G 2.5(a[)151.44 672 S(off])162.27 672
-Q F0 -.45(Tu)131 684 S(rn of).45 E 2.5<668c>-.25 G(le-o)171.96 684 Q -.15(ve)
--.15 G(rwriting checks.).15 E 172.465(4.4BSD July)72 750 R(15, 1994)2.5 E(12)
-530 750 Q EP
-%%Page: 13 13
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF -.834(EX/VI \( 1 \))72 48 R(BSD Reference Manual)
-258.235 48 Q -.834(EX/VI \( 1 \))496.682 48 R/F1 10/Times-Bold@0 SF(ENVIR)72 96
-Q(ONMENT)-.3 E 1.666(AL V)-.9 F(ARIABLES)-1.35 E/F2 10/Courier@0 SF(COLUMNS)102
-108 Q F0 .895(The number of columns on the screen.)161 108 R .896(This v)5.896
-F .896(alue o)-.25 F -.15(ve)-.15 G .896(rrides an).15 F 3.396(ys)-.15 G .896
-(ystem or terminal speci\214c)433.712 108 R -.25(va)161 120 S 5.317(lues. If)
-.25 F 2.816(the COLUMNS en)5.317 F 2.816(vironmental v)-.4 F 2.816
-(ariable is not set when)-.25 F/F3 10/Courier-Bold@0 SF(ex/vi)5.316 E F0 2.816
-(runs, or the)5.316 F F1(columns)161 132 Q F0(option is e)2.5 E
-(xplicitly reset by the user)-.15 E(,)-.4 E F3(ex/vi)2.5 E F0(enters the v)2.5
-E(alue into the en)-.25 E(vironment.)-.4 E F2(EXINIT)102 144 Q F0 2.5(Al)161
-144 S(ist of)173.5 144 Q F3(ex)2.5 E F0(startup commands, read if the v)2.5 E
-(ariable)-.25 E F2(NEXINIT)2.5 E F0(is not set.)2.5 E F2(HOME)102 156 Q F0 .677
-(The user')161 156 R 3.177(sh)-.55 G .677(ome directory)211.234 156 R 3.177(,u)
--.65 G .678(sed as the initial directory path for the startup)277.758 156 R F2
-($HOME/.nexrc)3.178 E F0(and)161 168 Q F2($HOME/.exrc)2.865 E F0 2.865
-(\214les. This)2.865 F -.25(va)2.865 G .365(lue is also used as the def).25 F
-.365(ault directory for the)-.1 F F3(vi)2.865 E F1(cd)2.865 E F0(com-)2.865 E
-(mand.)161 180 Q F2(LINES)102 192 Q F0 .629(The number of ro)161 192 R .629
-(ws on the screen.)-.25 F .629(This v)5.629 F .629(alue o)-.25 F -.15(ve)-.15 G
-.629(rrides an).15 F 3.13(ys)-.15 G .63(ystem or terminal speci\214c v)416.08
-192 R(al-)-.25 E 3.123(ues. If)161 204 R .623(the LINES en)3.123 F .623
-(vironmental v)-.4 F .623(ariable is not set when)-.25 F F3(ex/vi)3.122 E F0
-.622(runs, or the)3.122 F F1(lines)3.122 E F0 .622(option is)3.122 F -.15(ex)
-161 216 S(plicitly reset by the user).15 E(,)-.4 E F3(ex/vi)2.5 E F0
-(enters the v)2.5 E(alue into the en)-.25 E(vironment.)-.4 E F2(NEXINIT)102 228
-Q F0 2.5(Al)161 228 S(ist of)173.5 228 Q F3(ex)2.5 E F0(startup commands.)2.5 E
-F2(SHELL)102 240 Q F0(The user')161 240 Q 2.5(ss)-.55 G
-(hell of choice \(see also the)208.77 240 Q F1(shell)2.5 E F0(option\).)2.5 E
-F2(TERM)102 252 Q F0 1.338(The user')161 252 R 3.838(st)-.55 G 1.338
-(erminal type.)210.336 252 R 1.338(The def)6.338 F 1.338(ault is the type `)-.1
-F(`unkno)-.74 E(wn')-.25 E 1.339('. If the TERM en)-.74 F(vironmental)-.4 E
--.25(va)161 264 S .106(riable is not set when).25 F F3(ex/vi)2.606 E F0 .105
-(runs, or the)2.605 F F1(term)2.605 E F0 .105(option is e)2.605 F .105
-(xplicitly reset by the user)-.15 F(,)-.4 E F3(ex/vi)2.605 E F0(enters the v)
-161 276 Q(alue into the en)-.25 E(vironment.)-.4 E F2(TMPDIR)102 288 Q F0
-(The location used to stored temporary \214les \(see also the)161 288 Q F1(dir)
-2.5 E(ectory)-.18 E F0(option\).)2.5 E F1(ASYNCHR)72 312 Q 1.666(ONOUS EVENTS)
--.3 F F0(SIGALRM)102 324 Q F3(Vi/ex)167 324 Q F0 1.58(uses this signal for per\
-iodic backups of \214le modi\214cations and to display `)4.08 F(`b)-.74 E(usy')
--.2 E(')-.74 E(messages when operations are lik)167 336 Q(ely to tak)-.1 E 2.5
-(eal)-.1 G(ong time.)354.54 336 Q(SIGHUP)102 348 Q 18.61(SIGTERM If)102 360 R
-.12(the current b)2.62 F(uf)-.2 E .12(fer has changed since it w)-.25 F .12
-(as last written in its entirety)-.1 F 2.62(,t)-.65 G .12
-(he editor attempts to)457.7 360 R(sa)167 372 Q .493 -.15(ve t)-.2 H .193
-(he modi\214ed \214le so it can be later reco).15 F -.15(ve)-.15 G 2.693
-(red. See).15 F(the)2.694 E F3(vi/ex)2.694 E F0 .194(Reference manual section)
-2.694 F(entitled `)167 384 Q(`Reco)-.74 E -.15(ve)-.15 G(ry').15 E 2.5('f)-.74
-G(or more information.)255.19 384 Q 29.73(SIGINT When)102 396 R .594(an interr\
-upt occurs, the current operation is halted, and the editor returns to the com\
--)3.094 F .364(mand le)167 408 R -.15(ve)-.25 G 2.864(l. If).15 F .364
-(interrupted during te)2.864 F .364(xt input, the te)-.15 F .364
-(xt already input is resolv)-.15 F .365(ed into the \214le as)-.15 F(if the te)
-167 420 Q(xt input had been normally terminated.)-.15 E 12.51(SIGWINCH The)102
-432 R 2.772(screen is resized.)5.272 F 2.772(See the)7.772 F F3(vi/ex)5.272 E
-F0 2.771(Reference manual section entitled `)5.272 F 2.771(`Sizing the)-.74 F
-(Screen')167 444 Q 2.5('f)-.74 G(or more information.)205.96 444 Q(SIGCONT)102
-456 Q(SIGQ)102 468 Q(UIT)-.1 E(SIGTSTP)102 480 Q F3(Vi/ex)167 480 Q F0
-(ignores these signals.)2.5 E F1 -.1(BU)72 504 S(GS).1 E F0(See the \214le)102
-516 Q F2(nvi/docs/bugs.current)2.5 E F0(for a list of the kno)2.5 E(wn b)-.25 E
-(ugs in this v)-.2 E(ersion.)-.15 E F1(FILES)72 540 Q F2(/bin/sh)102 552 Q F0
-(The def)221 552 Q(ault user shell.)-.1 E F2(/etc/vi.exrc)102 564 Q F0
-(System-wide vi startup \214le.)221 564 Q F2(/tmp)102 576 Q F0 -.7(Te)221 576 S
-(mporary \214le directory).7 E(.)-.65 E F2(/var/tmp/vi.recover)102 588 Q F0
-(The def)5 E(ault reco)-.1 E -.15(ve)-.15 G(ry \214le directory).15 E(.)-.65 E
-F2($HOME/.nexrc)102 600 Q F0(1st choice for user')221 600 Q 2.5(sh)-.55 G
-(ome directory startup \214le.)308.76 600 Q F2($HOME/.exrc)102 612 Q F0
-(2nd choice for user')221 612 Q 2.5(sh)-.55 G(ome directory startup \214le.)
-312.09 612 Q F2(.nexrc)102 624 Q F0
-(1st choice for local directory startup \214le.)221 624 Q F2(.exrc)102 636 Q F0
-(2nd choice for local directory startup \214le.)221 636 Q F1 1.666(SEE ALSO)72
-660 R F2(ctags)102 672 Q F0(\(1\),)A F2(more)5 E F0(\(1\),)A F2(curses)5 E F0
-(\(3\),)A F2(dbopen)5 E F0(\(3\))A(The `)102 696 Q(`V)-.74 E 2.5(iQ)-.6 G
-(uick Reference')145.09 696 Q 2.5('c)-.74 G(ard.)218.2 696 Q 172.465
-(4.4BSD July)72 750 R(15, 1994)2.5 E(13)530 750 Q EP
-%%Page: 14 14
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF -.834(EX/VI \( 1 \))72 48 R(BSD Reference Manual)
-258.235 48 Q -.834(EX/VI \( 1 \))496.682 48 R -.74(``)102 96 S
-(An Introduction to Display Editing with V).74 E(i')-.6 E(', found in the `)
--.74 E(`UNIX User')-.74 E 2.5(sM)-.55 G(anual Supplementary)412.2 96 Q
-(Documents')102 108 Q 2.5('s)-.74 G
-(ection of both the 4.3BSD and 4.4BSD manual sets.)159.86 108 Q
-(This document is the closest thing a)5 E -.25(va)-.2 G(il-).25 E
-(able to an introduction to the)102 120 Q/F1 10/Courier-Bold@0 SF(vi)2.5 E F0
-(screen editor)2.5 E(.)-.55 E -.74(``)102 144 S(Ex Reference Manual \(V).74 E
-(ersion 3.7\)')-1.11 E(', found in the `)-.74 E(`UNIX User')-.74 E 2.5(sM)-.55
-G(anual Supplementary Documents')381.92 144 Q 2.5('s)-.74 G(ec-)526.99 144 Q
-(tion of both the 4.3BSD and 4.4BSD manual sets.)102 156 Q
-(This document is the \214nal reference for the)5 E F1(ex)2.5 E F0(editor)2.5 E
-2.5(,a)-.4 G(s)528 156 Q(distrib)102 168 Q
-(uted in most historic 4BSD and System V systems.)-.2 E -.74(``)102 192 S
-(Edit: A tutorial').74 E(', found in the `)-.74 E(`UNIX User')-.74 E 2.5(sM)
--.55 G(anual Supplementary Documents')300.58 192 Q 2.5('s)-.74 G
-(ection of the 4.3BSD)445.65 192 Q(manual set.)102 204 Q
-(This document is an introduction to a simple v)5 E(ersion of the)-.15 E F1(ex)
-2.5 E F0(screen editor)2.5 E(.)-.55 E -.74(``)102 228 S(Ex/V).74 E 2.5(iR)-.6 G
-(eference Manual')140.38 228 Q(', found in the `)-.74 E(`UNIX User')-.74 E 2.5
-(sM)-.55 G(anual Supplementary Documents')339.39 228 Q 2.5('s)-.74 G
-(ection of the)484.46 228 Q(4.4BSD manual set.)102 240 Q
-(This document is the \214nal reference for the)5 E F1(nex/nvi)2.5 E F0(te)2.5
-E(xt editors, as distrib)-.15 E(uted in)-.2 E(4.4BSD and 4.4BSD-Lite.)102 252 Q
-F1(Roff)102 270 Q F0(source for all of these documents is distrib)2.5 E
-(uted with)-.2 E F1(nex/nvi)2.5 E F0(in the)2.5 E/F2 10/Courier@0 SF
-(nvi/USD.doc)2.5 E F0(directory of the)2.5 E F1(nex/nvi)102 282 Q F0
-(source code.)2.5 E(The \214les `)102 306 Q(`auto)-.74 E(write')-.25 E(', `)
--.74 E(`input')-.74 E(', `)-.74 E(`quoting')-.74 E(', and `)-.74 E
-(`structures')-.74 E(', found in the)-.74 E F2(nvi/docs/internals)2.5 E F0
-(direc-)2.5 E(tory of the)102 318 Q F1(nex/nvi)2.5 E F0(source code.)2.5 E/F3
-10/Times-Bold@0 SF(HIST)72 342 Q(OR)-.18 E(Y)-.35 E F0(The)102 354 Q F1
-(nex/nvi)2.5 E F0(replacements for the)2.5 E F1(ex/vi)2.5 E F0
-(editor \214rst appeared in 4.4BSD.)2.5 E F3(ST)72 378 Q(AND)-.9 E(ARDS)-.35 E
-F1(Nex/nvi)102 390 Q F0 .1(is close to IEEE Std1003.2 \(`)2.6 F(`POSIX')-.74 E
-2.6('\). That)-.74 F .1(document dif)2.6 F .1(fers from historical)-.25 F F1
-(ex/vi)2.6 E F0 .1(practice in)2.6 F(se)102 402 Q -.15(ve)-.25 G
-(ral places; there are changes to be made on both sides.).15 E 172.465
-(4.4BSD July)72 750 R(15, 1994)2.5 E(14)530 750 Q EP
-%%Trailer
-end
-%%EOF
diff --git a/usr.bin/vi/USD.doc/vi.ref/Makefile b/usr.bin/vi/USD.doc/vi.ref/Makefile
deleted file mode 100644
index 2690f86edc70..000000000000
--- a/usr.bin/vi/USD.doc/vi.ref/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-# @(#)Makefile 8.16 (Berkeley) 8/15/94
-
-DIR= usd/13.viref
-SRCS= vi.ref ex.cmd.roff set.opt.roff vi.cmd.roff ref.so
-MACROS= -me
-CLEANFILES+=vi.ref.txt index index.so
-
-paper.ps: vi.ref index.so
- soelim vi.ref | ${TBL} | ${ROFF} > ${.TARGET}
-
-vi.ref.txt: vi.ref index.so
- soelim vi.ref | ${TBL} | groff ${MACROS} -Tascii > $@
-
-index.so: vi.ref
- # Build index.so, side-effect of building the paper.
- soelim vi.ref | ${TBL} | ${ROFF} > /dev/null
- sed -e 's/MINUSSIGN/\\-/' \
- -e 's/DOUBLEQUOTE/""/' \
- -e "s/SQUOTE/'/" \
- -e 's/ /__SPACE/g' < index | \
- sort -u '-t ' +0 -1 +1n | awk -f merge.awk | \
- sed -e 's/__SPACE/ /g' > index.so
- rm -f index
-
-.include <bsd.doc.mk>
diff --git a/usr.bin/vi/USD.doc/vi.ref/paper.ps b/usr.bin/vi/USD.doc/vi.ref/paper.ps
deleted file mode 100644
index e429d56ba11f..000000000000
--- a/usr.bin/vi/USD.doc/vi.ref/paper.ps
+++ /dev/null
@@ -1,30924 +0,0 @@
-%!PS-Adobe-1.0
-%%Creator: python.bostic.com:root (Charlie,458E,7750)
-%%Title: stdin (ditroff)
-%%CreationDate: Mon Aug 15 14:24:12 1994
-%%EndComments
-% @(#)psdit.pro 1.6 11/6/90
-% lib/psdit.pro -- prolog for psdit (ditroff) files
-% Copyright (c) 1984, 1985 Adobe Systems Incorporated. All Rights Reserved.
-% last edit: shore Sat Nov 23 20:28:03 1985
-% RCSID: $Header: psdit.pro,v 2.1 85/11/24 12:19:43 shore Rel $
-
-% Changed by Edward Wang (edward@ucbarpa.berkeley.edu) to handle graphics,
-% 17 Feb, 87.
-
-/$DITroff 140 dict def $DITroff begin
-/fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def
-/xi{0 72 11 mul translate 72 resolution div dup neg scale 0 0 moveto
- /fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def F}def
-/PB{save /psv exch def currentpoint translate
- resolution 72 div dup neg scale 0 0 moveto}def
-/PE{psv restore}def
-/arctoobig 90 def /arctoosmall .05 def
-/m1 matrix def /m2 matrix def /m3 matrix def /oldmat matrix def
-/tan{dup sin exch cos div}def
-/point{resolution 72 div mul}def
-/dround {transform round exch round exch itransform}def
-/xT{/devname exch def}def
-/xr{/mh exch def /my exch def /resolution exch def}def
-/xp{}def
-/xs{docsave restore end}def
-/xt{}def
-/xf{/fontname exch def /slotno exch def fontnames slotno get fontname eq not
- {fonts slotno fontname findfont put fontnames slotno fontname put}if}def
-/xH{/fontheight exch def F}def
-/xS{/fontslant exch def F}def
-/s{/fontsize exch def /fontheight fontsize def F}def
-/f{/fontnum exch def F}def
-/F{fontheight 0 le{/fontheight fontsize def}if
- fonts fontnum get fontsize point 0 0 fontheight point neg 0 0 m1 astore
- fontslant 0 ne{1 0 fontslant tan 1 0 0 m2 astore m3 concatmatrix}if
- makefont setfont .04 fontsize point mul 0 dround pop setlinewidth}def
-/X{exch currentpoint exch pop moveto show}def
-/N{3 1 roll moveto show}def
-/Y{exch currentpoint pop exch moveto show}def
-/S{show}def
-/ditpush{}def/ditpop{}def
-/AX{3 -1 roll currentpoint exch pop moveto 0 exch ashow}def
-/AN{4 2 roll moveto 0 exch ashow}def
-/AY{3 -1 roll currentpoint pop exch moveto 0 exch ashow}def
-/AS{0 exch ashow}def
-/MX{currentpoint exch pop moveto}def
-/MY{currentpoint pop exch moveto}def
-/MXY{moveto}def
-/cb{pop}def % action on unknown char -- nothing for now
-/n{}def/w{}def
-/p{pop showpage xi}def
-/Dt{/Dlinewidth exch def}def 1 Dt
-/Ds{/Ddash exch def}def -1 Ds
-/i{/Dstipple exch def}def 1 i
-/Dsetlinewidth{2 Dlinewidth mul setlinewidth}def
-/Dsetdash{Ddash 4 eq{[8 12]}{Ddash 16 eq{[32 36]}
- {Ddash 20 eq{[32 12 8 12]}{[]}ifelse}ifelse}ifelse 0 setdash}def
-/Dstroke{gsave Dsetlinewidth Dsetdash 1 setlinecap stroke grestore
- currentpoint newpath moveto}def
-/Dl{rlineto Dstroke}def
-/arcellipse{/diamv exch def /diamh exch def oldmat currentmatrix pop
- currentpoint translate 1 diamv diamh div scale /rad diamh 2 div def
- currentpoint exch rad add exch rad -180 180 arc oldmat setmatrix}def
-/Dc{dup arcellipse Dstroke}def
-/De{arcellipse Dstroke}def
-/Da{/endv exch def /endh exch def /centerv exch def /centerh exch def
- /cradius centerv centerv mul centerh centerh mul add sqrt def
- /eradius endv endv mul endh endh mul add sqrt def
- /endang endv endh atan def
- /startang centerv neg centerh neg atan def
- /sweep startang endang sub dup 0 lt{360 add}if def
- sweep arctoobig gt
- {/midang startang sweep 2 div sub def /midrad cradius eradius add 2 div def
- /midh midang cos midrad mul def /midv midang sin midrad mul def
- midh neg midv neg endh endv centerh centerv midh midv Da
- Da}
- {sweep arctoosmall ge
- {/controldelt 1 sweep 2 div cos sub 3 sweep 2 div sin mul div 4 mul def
- centerv neg controldelt mul centerh controldelt mul
- endv neg controldelt mul centerh add endh add
- endh controldelt mul centerv add endv add
- centerh endh add centerv endv add rcurveto Dstroke}
- {centerh endh add centerv endv add rlineto Dstroke}
- ifelse}
- ifelse}def
-/Dpatterns[
-[%cf[widthbits]
-[8<0000000000000010>]
-[8<0411040040114000>]
-[8<0204081020408001>]
-[8<0000103810000000>]
-[8<6699996666999966>]
-[8<0000800100001008>]
-[8<81c36666c3810000>]
-[8<0f0e0c0800000000>]
-[8<0000000000000010>]
-[8<0411040040114000>]
-[8<0204081020408001>]
-[8<0000001038100000>]
-[8<6699996666999966>]
-[8<0000800100001008>]
-[8<81c36666c3810000>]
-[8<0f0e0c0800000000>]
-[8<0042660000246600>]
-[8<0000990000990000>]
-[8<0804020180402010>]
-[8<2418814242811824>]
-[8<6699996666999966>]
-[8<8000000008000000>]
-[8<00001c3e363e1c00>]
-[8<0000000000000000>]
-[32<00000040000000c00000004000000040000000e0000000000000000000000000>]
-[32<00000000000060000000900000002000000040000000f0000000000000000000>]
-[32<000000000000000000e0000000100000006000000010000000e0000000000000>]
-[32<00000000000000002000000060000000a0000000f00000002000000000000000>]
-[32<0000000e0000000000000000000000000000000f000000080000000e00000001>]
-[32<0000090000000600000000000000000000000000000007000000080000000e00>]
-[32<00010000000200000004000000040000000000000000000000000000000f0000>]
-[32<0900000006000000090000000600000000000000000000000000000006000000>]]
-[%ug
-[8<0000020000000000>]
-[8<0000020000002000>]
-[8<0004020000002000>]
-[8<0004020000402000>]
-[8<0004060000402000>]
-[8<0004060000406000>]
-[8<0006060000406000>]
-[8<0006060000606000>]
-[8<00060e0000606000>]
-[8<00060e000060e000>]
-[8<00070e000060e000>]
-[8<00070e000070e000>]
-[8<00070e020070e000>]
-[8<00070e020070e020>]
-[8<04070e020070e020>]
-[8<04070e024070e020>]
-[8<04070e064070e020>]
-[8<04070e064070e060>]
-[8<06070e064070e060>]
-[8<06070e066070e060>]
-[8<06070f066070e060>]
-[8<06070f066070f060>]
-[8<060f0f066070f060>]
-[8<060f0f0660f0f060>]
-[8<060f0f0760f0f060>]
-[8<060f0f0760f0f070>]
-[8<0e0f0f0760f0f070>]
-[8<0e0f0f07e0f0f070>]
-[8<0e0f0f0fe0f0f070>]
-[8<0e0f0f0fe0f0f0f0>]
-[8<0f0f0f0fe0f0f0f0>]
-[8<0f0f0f0ff0f0f0f0>]
-[8<1f0f0f0ff0f0f0f0>]
-[8<1f0f0f0ff1f0f0f0>]
-[8<1f0f0f8ff1f0f0f0>]
-[8<1f0f0f8ff1f0f0f8>]
-[8<9f0f0f8ff1f0f0f8>]
-[8<9f0f0f8ff9f0f0f8>]
-[8<9f0f0f9ff9f0f0f8>]
-[8<9f0f0f9ff9f0f0f9>]
-[8<9f8f0f9ff9f0f0f9>]
-[8<9f8f0f9ff9f8f0f9>]
-[8<9f8f1f9ff9f8f0f9>]
-[8<9f8f1f9ff9f8f1f9>]
-[8<bf8f1f9ff9f8f1f9>]
-[8<bf8f1f9ffbf8f1f9>]
-[8<bf8f1fdffbf8f1f9>]
-[8<bf8f1fdffbf8f1fd>]
-[8<ff8f1fdffbf8f1fd>]
-[8<ff8f1fdffff8f1fd>]
-[8<ff8f1ffffff8f1fd>]
-[8<ff8f1ffffff8f1ff>]
-[8<ff9f1ffffff8f1ff>]
-[8<ff9f1ffffff9f1ff>]
-[8<ff9f9ffffff9f1ff>]
-[8<ff9f9ffffff9f9ff>]
-[8<ffbf9ffffff9f9ff>]
-[8<ffbf9ffffffbf9ff>]
-[8<ffbfdffffffbf9ff>]
-[8<ffbfdffffffbfdff>]
-[8<ffffdffffffbfdff>]
-[8<ffffdffffffffdff>]
-[8<fffffffffffffdff>]
-[8<ffffffffffffffff>]]
-[%mg
-[8<8000000000000000>]
-[8<0822080080228000>]
-[8<0204081020408001>]
-[8<40e0400000000000>]
-[8<66999966>]
-[8<8001000010080000>]
-[8<81c36666c3810000>]
-[8<f0e0c08000000000>]
-[16<07c00f801f003e007c00f800f001e003c007800f001f003e007c00f801f003e0>]
-[16<1f000f8007c003e001f000f8007c003e001f800fc007e003f001f8007c003e00>]
-[8<c3c300000000c3c3>]
-[16<0040008001000200040008001000200040008000000100020004000800100020>]
-[16<0040002000100008000400020001800040002000100008000400020001000080>]
-[16<1fc03fe07df0f8f8f07de03fc01f800fc01fe03ff07df8f87df03fe01fc00f80>]
-[8<80>]
-[8<8040201000000000>]
-[8<84cc000048cc0000>]
-[8<9900009900000000>]
-[8<08040201804020100800020180002010>]
-[8<2418814242811824>]
-[8<66999966>]
-[8<8000000008000000>]
-[8<70f8d8f870000000>]
-[8<0814224180402010>]
-[8<aa00440a11a04400>]
-[8<018245aa45820100>]
-[8<221c224180808041>]
-[8<88000000>]
-[8<0855800080550800>]
-[8<2844004482440044>]
-[8<0810204080412214>]
-[8<00>]]]def
-/Dfill{
- save 6 1 roll
- transform /maxy exch def /maxx exch def
- transform /miny exch def /minx exch def
- minx maxx gt{/minx maxx /maxx minx def def}if
- miny maxy gt{/miny maxy /maxy miny def def}if
- Dpatterns Dstipple 1 sub get exch 1 sub get
- aload pop /stip exch def /stipw exch def /stiph 128 def
- /imatrix[stipw 0 0 stiph 0 0]def
- /tmatrix[stipw 0 0 stiph 0 0]def
- /minx minx cvi stiph idiv stiph mul def
- /miny miny cvi stipw idiv stipw mul def
- eoclip 0 setgray
- miny stiph maxy{
- tmatrix exch 5 exch put
- minx stipw maxx{
- tmatrix exch 4 exch put tmatrix setmatrix
- stipw stiph true imatrix {stip} imagemask
- }for
- }for
- restore
-}def
-/Dp{Dfill Dstroke}def
-/DP{Dfill currentpoint newpath moveto}def
-end
-
-/ditstart{$DITroff begin
- /nfonts 60 def % NFONTS makedev/ditroff dependent!
- /fonts[nfonts{0}repeat]def
- /fontnames[nfonts{()}repeat]def
-/docsave save def
-}def
-
-% character outcalls
-/oc{
- /pswid exch def /cc exch def /name exch def
- /ditwid pswid fontsize mul resolution mul 72000 div def
- /ditsiz fontsize resolution mul 72 div def
- ocprocs name known{ocprocs name get exec}{name cb}ifelse
-}def
-/fractm [.65 0 0 .6 0 0] def
-/fraction{
- /fden exch def /fnum exch def gsave /cf currentfont def
- cf fractm makefont setfont 0 .3 dm 2 copy neg rmoveto
- fnum show rmoveto currentfont cf setfont(\244)show setfont fden show
- grestore ditwid 0 rmoveto
-}def
-/oce{grestore ditwid 0 rmoveto}def
-/dm{ditsiz mul}def
-/ocprocs 50 dict def ocprocs begin
-(14){(1)(4)fraction}def
-(12){(1)(2)fraction}def
-(34){(3)(4)fraction}def
-(13){(1)(3)fraction}def
-(23){(2)(3)fraction}def
-(18){(1)(8)fraction}def
-(38){(3)(8)fraction}def
-(58){(5)(8)fraction}def
-(78){(7)(8)fraction}def
-(sr){gsave 0 .06 dm rmoveto(\326)show oce}def
-(is){gsave 0 .15 dm rmoveto(\362)show oce}def
-(->){gsave 0 .02 dm rmoveto(\256)show oce}def
-(<-){gsave 0 .02 dm rmoveto(\254)show oce}def
-(==){gsave 0 .05 dm rmoveto(\272)show oce}def
-(uc){gsave currentpoint 400 .009 dm mul add translate
- 8 -8 scale ucseal oce}def
-end
-
-% an attempt at a PostScript FONT to implement ditroff special chars
-% this will enable us to
-% cache the little buggers
-% generate faster, more compact PS out of psdit
-% confuse everyone (including myself)!
-50 dict dup begin
-/FontType 3 def
-/FontName /DIThacks def
-/FontMatrix [.001 0 0 .001 0 0] def
-/FontBBox [-260 -260 900 900] def% a lie but ...
-/Encoding 256 array def
-0 1 255{Encoding exch /.notdef put}for
-Encoding
- dup 8#040/space put %space
- dup 8#110/rc put %right ceil
- dup 8#111/lt put %left top curl
- dup 8#112/bv put %bold vert
- dup 8#113/lk put %left mid curl
- dup 8#114/lb put %left bot curl
- dup 8#115/rt put %right top curl
- dup 8#116/rk put %right mid curl
- dup 8#117/rb put %right bot curl
- dup 8#120/rf put %right floor
- dup 8#121/lf put %left floor
- dup 8#122/lc put %left ceil
- dup 8#140/sq put %square
- dup 8#141/bx put %box
- dup 8#142/ci put %circle
- dup 8#143/br put %box rule
- dup 8#144/rn put %root extender
- dup 8#145/vr put %vertical rule
- dup 8#146/ob put %outline bullet
- dup 8#147/bu put %bullet
- dup 8#150/ru put %rule
- dup 8#151/ul put %underline
- pop
-/DITfd 100 dict def
-/BuildChar{0 begin
- /cc exch def /fd exch def
- /charname fd /Encoding get cc get def
- /charwid fd /Metrics get charname get def
- /charproc fd /CharProcs get charname get def
- charwid 0 fd /FontBBox get aload pop setcachedevice
- 2 setlinejoin 40 setlinewidth
- newpath 0 0 moveto gsave charproc grestore
- end}def
-/BuildChar load 0 DITfd put
-/CharProcs 50 dict def
-CharProcs begin
-/space{}def
-/.notdef{}def
-/ru{500 0 rls}def
-/rn{0 840 moveto 500 0 rls}def
-/vr{0 800 moveto 0 -770 rls}def
-/bv{0 800 moveto 0 -1000 rls}def
-/br{0 840 moveto 0 -1000 rls}def
-/ul{0 -140 moveto 500 0 rls}def
-/ob{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath stroke}def
-/bu{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath fill}def
-/sq{80 0 rmoveto currentpoint dround newpath moveto
- 640 0 rlineto 0 640 rlineto -640 0 rlineto closepath stroke}def
-/bx{80 0 rmoveto currentpoint dround newpath moveto
- 640 0 rlineto 0 640 rlineto -640 0 rlineto closepath fill}def
-/ci{500 360 rmoveto currentpoint newpath 333 0 360 arc
- 50 setlinewidth stroke}def
-
-/lt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 add exch s4 a4p stroke}def
-/lb{0 800 moveto 0 -550 rlineto currx -200 2cx s4 add exch s4 a4p stroke}def
-/rt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 sub exch s4 a4p stroke}def
-/rb{0 800 moveto 0 -500 rlineto currx -200 2cx s4 sub exch s4 a4p stroke}def
-/lk{0 800 moveto 0 300 -300 300 s4 arcto pop pop 1000 sub
- 0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
-/rk{0 800 moveto 0 300 s2 300 s4 arcto pop pop 1000 sub
- 0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
-/lf{0 800 moveto 0 -1000 rlineto s4 0 rls}def
-/rf{0 800 moveto 0 -1000 rlineto s4 neg 0 rls}def
-/lc{0 -200 moveto 0 1000 rlineto s4 0 rls}def
-/rc{0 -200 moveto 0 1000 rlineto s4 neg 0 rls}def
-end
-
-/Metrics 50 dict def Metrics begin
-/.notdef 0 def
-/space 500 def
-/ru 500 def
-/br 0 def
-/lt 416 def
-/lb 416 def
-/rt 416 def
-/rb 416 def
-/lk 416 def
-/rk 416 def
-/rc 416 def
-/lc 416 def
-/rf 416 def
-/lf 416 def
-/bv 416 def
-/ob 350 def
-/bu 350 def
-/ci 750 def
-/bx 750 def
-/sq 750 def
-/rn 500 def
-/ul 500 def
-/vr 0 def
-end
-
-DITfd begin
-/s2 500 def /s4 250 def /s3 333 def
-/a4p{arcto pop pop pop pop}def
-/2cx{2 copy exch}def
-/rls{rlineto stroke}def
-/currx{currentpoint pop}def
-/dround{transform round exch round exch itransform} def
-end
-end
-/DIThacks exch definefont pop
-ditstart
-(psc)xT
-576 1 1 xr
-1(Times-Roman)xf 1 f
-2(Times-Italic)xf 2 f
-3(Times-Bold)xf 3 f
-4(Times-BoldItalic)xf 4 f
-5(Helvetica)xf 5 f
-6(Helvetica-Bold)xf 6 f
-7(Courier)xf 7 f
-8(Courier-Bold)xf 8 f
-9(Symbol)xf 9 f
-10(DIThacks)xf 10 f
-10 s
-1 f
-xi
-%%EndProlog
-
-%%Page: 1 1
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-12 s
-1796 795(Ex/Vi)N
-2055(Reference)X
-2491(Manual)X
-2 f
-10 s
-2107 975(Keith)N
-2300(Bostic)X
-1 f
-1861 1155(Computer)N
-2201(Science)X
-2471(Division)X
-1328 1245(Department)N
-1727(of)X
-1814(Electrical)X
-2142(Engineering)X
-2554(and)X
-2690(Computer)X
-3030(Science)X
-1754 1335(University)N
-2112(of)X
-2199(California,)X
-2564(Berkeley)X
-1856 1425(Berkeley,)N
-2186(California)X
-2551(94720)X
-2038 1605(August)N
-2289(15,)X
-2409(1994)X
-2 f
-2168 1965(Abstract)N
-1 f
-776 2244(This)N
-948(document)X
-1294(is)X
-1377(the)X
-1505 0.4531(reference)AX
-1836(guide)X
-2045(for)X
-2170(the)X
-2299(4.4BSD)X
-2585(implementations)X
-3149(of)X
-3 f
-3247(nex)X
-1 f
-(/)S
-3 f
-3389(nvi)X
-1 f
-3495(,)X
-3546(which)X
-3773(are)X
-576 2334(reimplementations)N
-1192(of)X
-1279(the)X
-1397(historic)X
-1657(Berkeley)X
-3 f
-1967(ex)X
-1 f
-2043(/)X
-3 f
-2065(vi)X
-1 f
-2147(editors.)X
-2 f
-1996 2778(Acknowledgements)N
-1 f
-776 3063(Bruce)N
-1005(Englar)X
-1256(encouraged)X
-1664(the)X
-1799(early)X
-1997(development)X
-2448(of)X
-2552(the)X
-2687(historic)X
-3 f
-2965(ex)X
-1 f
-3041(/)X
-3 f
-3063(vi)X
-1 f
-3163(editor.)X
-3428(Peter)X
-3631(Kessler)X
-576 3153(helped)N
-811(bring)X
-1001(sanity)X
-1213(to)X
-1296(version)X
-1553(2's)X
-1672(command)X
-2009(layout.)X
-2270(Bill)X
-2410(Joy)X
-2541(wrote)X
-2744(versions)X
-3031(1)X
-3091(and)X
-3227(2.0)X
-3347(through)X
-3616(2.7,)X
-3756(and)X
-576 3243(created)N
-842(the)X
-973(framework)X
-1359(that)X
-1512(users)X
-1710(see)X
-1846(in)X
-1941(the)X
-2072(present)X
-2337(editor.)X
-2597(Mark)X
-2804(Horton)X
-3065(added)X
-3291(macros)X
-3557(and)X
-3707(other)X
-576 3333(features)N
-851(and)X
-987(made)X
-3 f
-1181(ex)X
-1 f
-1257(/)X
-3 f
-1279(vi)X
-1 f
-1361(work)X
-1546(on)X
-1646(a)X
-1702(large)X
-1883(number)X
-2148(of)X
-2235(terminals)X
-2553(and)X
-2689(Unix)X
-2869(systems.)X
-3 f
-776 3456(Nvi)N
-1 f
-918(is)X
-993(originally)X
-1326(derived)X
-1589(from)X
-1767(software)X
-2066(contributed)X
-2454(to)X
-2539(the)X
-2660(University)X
-3021(of)X
-3111(California,)X
-3479(Berkeley)X
-3792(by)X
-576 3546(Steve)N
-774(Kirkendall,)X
-1157(the)X
-1275(author)X
-1500(of)X
-1587(the)X
-3 f
-1705(vi)X
-1 f
-1787(clone)X
-3 f
-1981(elvis)X
-1 f
-2132(.)X
-776 3669(IEEE)N
-992(Standard)X
-1319(Portable)X
-1628(Operating)X
-1991(System)X
-2268(Interface)X
-2597(for)X
-2733(Computer)X
-3095(Environments)X
-3587(\(POSIX\))X
-576 3759(1003.2)N
-816(style)X
-987(Regular)X
-1261(Expression)X
-1637(support)X
-1897(was)X
-2042(done)X
-2218(by)X
-2318(Henry)X
-2539(Spencer.)X
-776 3882(The)N
-930(curses)X
-1161(library)X
-1405(was)X
-1560(originally)X
-1901(done)X
-2087(by)X
-2197(Ken)X
-2361(Arnold.)X
-2658(Scrolling)X
-2981(and)X
-3127(reworking)X
-3487(for)X
-3 f
-3611(nvi)X
-1 f
-3747(was)X
-576 3972(done)N
-752(by)X
-852(Elan)X
-1019(Amir.)X
-776 4095(The)N
-923(Institute)X
-1207(of)X
-1296(Electrical)X
-1626(and)X
-1764(Electronics)X
-2147(Engineers)X
-2490(has)X
-2619(given)X
-2820(us)X
-2914(permission)X
-3288(to)X
-3373(reprint)X
-3610(portions)X
-576 4185(of)N
-682(their)X
-868(documentation.)X
-1423(Portions)X
-1728(of)X
-1834(this)X
-1987(document)X
-2341(are)X
-2478(reprinted)X
-2806(and)X
-2960(reproduced)X
-3360(from)X
-3554(IEEE)X
-3766(Std)X
-576 4275(1003.2-1992,)N
-1031(IEEE)X
-1233(Standard)X
-1546(Portable)X
-1841(Operating)X
-2190(System)X
-2453(Interface)X
-2768(for)X
-2890(Computer)X
-3238(Environments)X
-3716(\(PO-)X
-576 4365(SIX\),)N
-772(copyright)X
-1099(1992)X
-1279(by)X
-1379(the)X
-1497(Institute)X
-1779(of)X
-1866(Electrical)X
-2194(and)X
-2330(Electronics)X
-2711(Engineers,)X
-3072(Inc.)X
-776 4488(The)N
-921(\256nancial)X
-1217(support)X
-1477(of)X
-1564(UUNET)X
-1856(Communications)X
-2422(Services)X
-2714(is)X
-2787(gratefully)X
-3119(acknowledged.)X
-
-3 p
-%%Page: 3 2
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-3698(USD:13-3)X
-576 762(1.)N
-676(Description)X
-1 f
-3 f
-776 885(Vi)N
-1 f
-876(is)X
-949(a)X
-1005(screen)X
-1231(oriented)X
-1514(text)X
-1654(editor.)X
-3 f
-1902(Ex)X
-1 f
-2016(is)X
-2090(a)X
-2147(line-oriented)X
-2578(text)X
-2719(editor.)X
-3 f
-2967(Ex)X
-1 f
-3081(and)X
-3 f
-3218(vi)X
-1 f
-3301(are)X
-3421(different)X
-3719(interfaces)X
-576 975(to)N
-674(the)X
-808(same)X
-1009(program,)X
-1336(and)X
-1487(it)X
-1566(is)X
-1654(possible)X
-1951(to)X
-2048(switch)X
-2292(back)X
-2479(and)X
-2630(forth)X
-2821(during)X
-3065(an)X
-3176(edit)X
-3331(session.)X
-3 f
-3637(View)X
-1 f
-3846(is)X
-3934(the)X
-576 1065(equivalent)N
-930(of)X
-1017(using)X
-1210(the)X
-3 f
-9 f
-1328(-)X
-1330(-)X
-3 f
-1374(R)X
-1 f
-1452(\(read-only\))X
-1834(option)X
-2058(of)X
-3 f
-2145(vi)X
-1 f
-2207(.)X
-776 1188(This)N
-957 0.4531(reference)AX
-1297(manual)X
-1572(is)X
-1664(the)X
-1801(one)X
-1956(provided)X
-2280(with)X
-2461(the)X
-3 f
-2598(nex)X
-1 f
-(/)S
-3 f
-2740(nvi)X
-1 f
-2885(versions)X
-3191(of)X
-3297(the)X
-3 f
-3434(ex)X
-1 f
-3510(/)X
-3 f
-3532(vi)X
-1 f
-3634(text)X
-3794(editors.)X
-3 f
-576 1278(Nex)N
-1 f
-710(/)X
-3 f
-732(nvi)X
-1 f
-868(are)X
-997(intended)X
-1302(as)X
-1398(bug-for-bug)X
-1815(compatible)X
-2200(replacements)X
-2653(for)X
-2776(the)X
-2903(original)X
-3181(Fourth)X
-3423(Berkeley)X
-3742(Software)X
-576 1368(Distribution)N
-987(\(4BSD\))X
-3 f
-1261(ex)X
-1 f
-1337(/)X
-3 f
-1359(vi)X
-1 f
-1446(programs.)X
-1814(This)X
-1981 0.4531(reference)AX
-2307(manual)X
-2568(is)X
-2646(accompanied)X
-3095(by)X
-3201(a)X
-3263(traditional-style)X
-3796(manual)X
-576 1458(page.)N
-798(That)X
-975(manual)X
-1241(page)X
-1423(describes)X
-1752(the)X
-1880(functionality)X
-2319(found)X
-2536(in)X
-3 f
-2627(ex)X
-1 f
-2703(/)X
-3 f
-2725(vi)X
-1 f
-2816(in)X
-2907(far)X
-3026(less)X
-3175(detail)X
-3382(than)X
-3549(the)X
-3676(description)X
-576 1548(here.)N
-781(In)X
-874(addition,)X
-1182(it)X
-1252(describes)X
-1578(the)X
-1703(system)X
-1952(interface)X
-2261(to)X
-3 f
-2350(ex)X
-1 f
-2426(/)X
-3 f
-2448(vi)X
-1 f
-2510(,)X
-2557(e.g.)X
-2700(command)X
-3043(line)X
-3190(options,)X
-3472(session)X
-3730(recovery,)X
-576 1638(signals,)N
-838(environmental)X
-1321(variables,)X
-1651(and)X
-1787(similar)X
-2029(things.)X
-776 1761(This)N
-939 0.4531(reference)AX
-1261(is)X
-1336(intended)X
-1634(for)X
-1750(users)X
-1937(already)X
-2196(familiar)X
-2472(with)X
-3 f
-2636(ex)X
-1 f
-2712(/)X
-3 f
-2734(vi)X
-1 f
-2796(.)X
-2858(Anyone)X
-3134(else)X
-3281(should)X
-3516(almost)X
-3751(certainly)X
-576 1851(read)N
-737(a)X
-795(good)X
-977(tutorial)X
-1230(on)X
-1332(the)X
-1452(editor)X
-1661(\256rst.)X
-1847(If)X
-1923(you)X
-2065(are)X
-2186(in)X
-2270(an)X
-2368(unfamiliar)X
-2723(environment,)X
-3169(and)X
-3306(you)X
-3447(absolutely)X
-3797(have)X
-3970(to)X
-576 1941(get)N
-702(work)X
-895(done)X
-1079(immediately,)X
-1527(see)X
-1658(the)X
-1784(section)X
-2039(entitled)X
-2308(``)X
-3 f
-2362(Fast)X
-2538(Startup)X
-1 f
-2800('')X
-2883(in)X
-2974(the)X
-3101(manual)X
-3366(page.)X
-3587(It)X
-3665(is)X
-3747(probably)X
-576 2031(enough)N
-832(to)X
-914(get)X
-1032(you)X
-1172(started.)X
-776 2154(There)N
-984(are)X
-1103(a)X
-1159(few)X
-1300(features)X
-1575(in)X
-3 f
-1657(nex)X
-1 f
-(/)S
-3 f
-1799(nvi)X
-1 f
-1925(that)X
-2065(are)X
-2185(not)X
-2308(found)X
-2516(in)X
-2599(historic)X
-2860(versions)X
-3148(of)X
-3 f
-3236(ex)X
-1 f
-3312(/)X
-3 f
-3334(vi)X
-1 f
-3396(.)X
-3457(Some)X
-3660(of)X
-3748(the)X
-3867(more)X
-576 2244(interesting)N
-941(of)X
-1035(those)X
-1231(features)X
-1513(are)X
-1639(brie\257y)X
-1875(described)X
-2210(in)X
-2299(the)X
-2424(section)X
-2678(entitled)X
-2945(``)X
-3 f
-2999(Additional)X
-3389(Features)X
-1 f
-3688('')X
-3769(near)X
-3934(the)X
-576 2334(end)N
-719(of)X
-813(this)X
-955(document.)X
-1338(For)X
-1476(the)X
-1601(rest)X
-1744(of)X
-1838(this)X
-1980(document,)X
-3 f
-2343(nex)X
-1 f
-(/)S
-3 f
-2485(nvi)X
-1 f
-2618(is)X
-2698(used)X
-2872(only)X
-3042(when)X
-3244(it)X
-3316(is)X
-3397(necessary)X
-3738(to)X
-3828(distin-)X
-576 2424(guish)N
-769(it)X
-833(from)X
-1009(the)X
-1127(historic)X
-1387(implementations)X
-1940(of)X
-3 f
-2027(ex)X
-1 f
-2103(/)X
-3 f
-2125(vi)X
-1 f
-2187(.)X
-776 2547(Future)N
-1012(versions)X
-1306(of)X
-1400(this)X
-1542(software)X
-1846(will)X
-1997(be)X
-2100(periodically)X
-2510(made)X
-2712(available)X
-3030(by)X
-3138(anonymous)X
-3535(ftp,)X
-3672(and)X
-3816(can)X
-3956(be)X
-576 2637(retrieved)N
-882(from)X
-7 f
-1058(ftp.cs.berkeley.edu)X
-1 f
-(,)S
-2010(in)X
-2092(the)X
-2210(directory)X
-7 f
-2520(ucb/4bsd)X
-1 f
-(.)S
-3 f
-576 2823(2.)N
-676(Startup)X
-958(Information)X
-1 f
-3 f
-776 2946(Ex)N
-1 f
-869(/)X
-3 f
-891(vi)X
-1 f
-981(interprets)X
-1312(one)X
-1456(of)X
-1551(two)X
-1699(possible)X
-1989(environmental)X
-2480(variables)X
-2798(and)X
-2942(reads)X
-3140(up)X
-3248(to)X
-3338(three)X
-3527(of)X
-3622(\256ve)X
-3770(possible)X
-576 3036(\256les)N
-737(during)X
-974(startup.)X
-1260(The)X
-1413(variables)X
-1731(and)X
-1875(\256les)X
-2036(are)X
-2163(expected)X
-2477(to)X
-2567(contain)X
-3 f
-2831(ex)X
-1 f
-2935(commands,)X
-3330(not)X
-3 f
-3460(vi)X
-1 f
-3550(commands.)X
-3965(In)X
-576 3126(addition,)N
-879(they)X
-1038(are)X
-1158(interpreted)X
-2 f
-1527(before)X
-1 f
-1753(the)X
-1872(\256le)X
-1996(to)X
-2080(be)X
-2178(edited)X
-2396(is)X
-2471(read,)X
-2652(and)X
-2790(therefore)X
-3103(many)X
-3 f
-3303(ex)X
-1 f
-3401(commands)X
-3770(may)X
-3930(not)X
-576 3216(be)N
-683(used.)X
-901(Generally,)X
-1269(any)X
-1416(command)X
-1763(that)X
-1914(requires)X
-2204(output)X
-2439(to)X
-2532(the)X
-2660(screen)X
-2896(or)X
-2993(that)X
-3143(needs)X
-3356(a)X
-3422(\256le)X
-3554(upon)X
-3744(which)X
-3970(to)X
-576 3306(operate,)N
-853(will)X
-997(cause)X
-1196(an)X
-1292(error)X
-1469(if)X
-1538(included)X
-1834(in)X
-1916(a)X
-1972(startup)X
-2210(\256le)X
-2332(or)X
-2419(environmental)X
-2902(variable.)X
-776 3429(Because)N
-1071(the)X
-3 f
-1197(ex)X
-1 f
-1301(command)X
-1645(set)X
-1762(supported)X
-2106(by)X
-3 f
-2214(nex)X
-1 f
-(/)S
-3 f
-2356(nvi)X
-1 f
-2490(is)X
-2571(a)X
-2635(superset)X
-2926(of)X
-3021(the)X
-3147(command)X
-3491(set)X
-3608(supported)X
-3952(by)X
-576 3519(most)N
-753(historical)X
-1073(implementations)X
-1628(of)X
-3 f
-1717(ex)X
-1 f
-1793(,)X
-3 f
-1835(nex)X
-1 f
-(/)S
-3 f
-1977(nvi)X
-1 f
-2105(can)X
-2238(use)X
-2366(the)X
-2485(startup)X
-2724(\256les)X
-2878(created)X
-3132(for)X
-3247(the)X
-3366(historical)X
-3685(implemen-)X
-576 3609(tations,)N
-829(but)X
-951(the)X
-1069(converse)X
-1375(may)X
-1533(not)X
-1655(be)X
-1751(true.)X
-776 3732(If)N
-852(the)X
-3 f
-9 f
-973(-)X
-975(-)X
-3 f
-1019(s)X
-1 f
-1073(\(the)X
-1221(historic)X
-9 f
-1484(-)X
-1 f
-1551(option\))X
-1805(is)X
-1881(speci\256ed,)X
-2209(or)X
-2299(if)X
-2371(standard)X
-2666(input)X
-2853(is)X
-2929(redirected)X
-3274(from)X
-3453(a)X
-3512(\256le,)X
-3657(all)X
-3760(environ-)X
-576 3822(mental)N
-814(variables)X
-1124(and)X
-1260(startup)X
-1498(\256les)X
-1651(are)X
-1770(ignored.)X
-776 3945(Otherwise,)N
-1146(startup)X
-1384(\256les)X
-1537(and)X
-1673(environmental)X
-2156(variables)X
-2466(are)X
-2585(handled)X
-2859(in)X
-2941(the)X
-3059(following)X
-3390(order:)X
-616 4068(\(1\))N
-830(The)X
-975(\256le)X
-7 f
-1097(/etc/vi.exrc)X
-1 f
-1693(is)X
-1766(read,)X
-1945(as)X
-2032(long)X
-2194(as)X
-2281(it)X
-2345(is)X
-2418(owned)X
-2652(by)X
-2752(root)X
-2901(or)X
-2988(the)X
-3106(effective)X
-3408(user)X
-3562(ID)X
-3667(of)X
-3754(the)X
-3872(user.)X
-616 4191(\(2\))N
-830(The)X
-981(environmental)X
-1471(variable)X
-7 f
-1757(NEXINIT)X
-1 f
-2120(\(or)X
-2241(the)X
-2366(variable)X
-7 f
-2652(EXINIT)X
-1 f
-(,)S
-2987(if)X
-7 f
-3063(NEXINIT)X
-1 f
-3426(is)X
-3506(not)X
-3635(set\))X
-3778(is)X
-3858(inter-)X
-830 4281(preted.)N
-616 4404(\(3\))N
-830(If)X
-918(neither)X
-7 f
-1175(NEXINIT)X
-1 f
-1545(or)X
-7 f
-1646(EXINIT)X
-1 f
-1968(was)X
-2127(set,)X
-2270(and)X
-2420(the)X
-7 f
-2552(HOME)X
-1 f
-2778(environmental)X
-3275(variable)X
-3568(is)X
-3655(set,)X
-3798(the)X
-3930(\256le)X
-7 f
-830 4494($HOME/.nexrc)N
-1 f
-1430(\(or)X
-1548(the)X
-1670(\256le)X
-7 f
-1796($HOME/.exrc)X
-1 f
-(,)S
-2368(if)X
-7 f
-2441($HOME/.nexrc)X
-1 f
-3041(does)X
-3212(not)X
-3338(exist\))X
-3540(is)X
-3617(read,)X
-3800(as)X
-3890(long)X
-830 4584(as)N
-917(the)X
-1035(effective)X
-1337(user)X
-1491(ID)X
-1596(of)X
-1683(the)X
-1801(user)X
-1955(is)X
-2028(root)X
-2177(or)X
-2264(is)X
-2337(the)X
-2455(same)X
-2640(as)X
-2727(the)X
-2845(owner)X
-3066(of)X
-3153(the)X
-3271(\256le.)X
-616 4707(\(4\))N
-830(If)X
-921(the)X
-3 f
-1056(exrc)X
-1 f
-1241(option)X
-1482(was)X
-1644(turned)X
-1886(on)X
-2003(by)X
-2120(one)X
-2273(of)X
-2377(the)X
-2512(previous)X
-2825(startup)X
-3080(information)X
-3495(sources,)X
-3794(the)X
-3930(\256le)X
-7 f
-830 4797(.nexrc)N
-1 f
-1142(\(or)X
-1260(the)X
-1382(\256le)X
-7 f
-1508(.exrc)X
-1 f
-(,)S
-1792(if)X
-7 f
-1864(.nexrc)X
-1 f
-2175(does)X
-2345(not)X
-2470(exist\))X
-2671(is)X
-2747(read,)X
-2929(as)X
-3019(long)X
-3184(as)X
-3274(the)X
-3395(effective)X
-3700(user)X
-3857(ID)X
-3965(of)X
-830 4887(the)N
-948(user)X
-1102(is)X
-1175(the)X
-1293(same)X
-1478(as)X
-1565(the)X
-1683(owner)X
-1904(of)X
-1991(the)X
-2109(\256le.)X
-776 5010(No)N
-894(startup)X
-1132(\256le)X
-1254(is)X
-1327(read)X
-1486(if)X
-1555(it)X
-1619(is)X
-1692(writable)X
-1975(by)X
-2075(anyone)X
-2327(other)X
-2512(than)X
-2670(its)X
-2765(owner.)X
-776 5133(It)N
-845(is)X
-918(not)X
-1040(an)X
-1136(error)X
-1313(for)X
-1427(any)X
-1563(of)X
-1650(the)X
-1768(startup)X
-2006(environmental)X
-2489(variables)X
-2799(or)X
-2886(\256les)X
-3039(not)X
-3161(to)X
-3243(exist.)X
-776 5256(Once)N
-978(all)X
-1090(environmental)X
-1585(variables)X
-1907(are)X
-2038(interpreted,)X
-2438(and)X
-2586(all)X
-2698(startup)X
-2948(\256les)X
-3114(are)X
-3246(read,)X
-3438(the)X
-3569(\256rst)X
-3726(\256le)X
-3861(to)X
-3956(be)X
-576 5346(edited)N
-800(is)X
-881(read)X
-1048(in)X
-1138(\(or)X
-1260(a)X
-1324(temporary)X
-1682(\256le)X
-1812(is)X
-1893(created\).)X
-2221(Then,)X
-2434(any)X
-2578(commands)X
-2953(speci\256ed)X
-3266(using)X
-3467(the)X
-3 f
-9 f
-3593(-)X
-3595(-)X
-3 f
-3639(c)X
-1 f
-3702(option)X
-3933(are)X
-576 5436(executed,)N
-902(in)X
-984(the)X
-1102(context)X
-1358(of)X
-1445(that)X
-1585(\256le.)X
-
-4 p
-%%Page: 4 3
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-4)N
-3391(Nvi/Nex)X
-3687 0.3906(Reference)AX
-576 762(3.)N
-676(Recovery)X
-1 f
-776 885(There)N
-991(is)X
-1071(no)X
-1178(recovery)X
-1487(program)X
-1786(for)X
-3 f
-1907(nex)X
-1 f
-(/)S
-3 f
-2049(nvi)X
-1 f
-2155(,)X
-2202(nor)X
-2336(does)X
-3 f
-2510(nex)X
-1 f
-(/)S
-3 f
-2652(nvi)X
-1 f
-2785(run)X
-2919(setuid.)X
-3177(Recovery)X
-3512(\256les)X
-3672(are)X
-3799(created)X
-576 975(readable)N
-887(and)X
-1041(writable)X
-1342(by)X
-1460(the)X
-1596(owner)X
-1835(only.)X
-2055(Users)X
-2276(may)X
-2452(recover)X
-2732(any)X
-2886(\256le)X
-3026(which)X
-3260(they)X
-3436(can)X
-3585(read,)X
-3781(and)X
-3934(the)X
-576 1065(superuser)N
-904(may)X
-1062(recover)X
-1324(any)X
-1460(edit)X
-1600(session.)X
-776 1188(Edit)N
-952(sessions)X
-1257(are)X
-1399(backed)X
-1670(by)X
-1793(\256les)X
-1969(in)X
-2074(the)X
-2215(directory)X
-2548(named)X
-2805(by)X
-2929(the)X
-3 f
-3071(recdir)X
-1 f
-3325(option)X
-3573(\(the)X
-3742(directory)X
-7 f
-576 1278(/var/tmp/vi.recover)N
-1 f
-1508(by)X
-1608(default\),)X
-1898(and)X
-2034(are)X
-2153(named)X
-2387(``)X
-3 f
-2441(vi.XXXXXX)X
-1 f
-2871('',)X
-2965(where)X
-3182(``)X
-3 f
-3236(XXXXXX)X
-1 f
-3584('')X
-3658(is)X
-3731(a)X
-3787(number)X
-576 1368(related)N
-816(to)X
-899(the)X
-1018(process)X
-1281(ID.)X
-1428(When)X
-1642(a)X
-1700(\256le)X
-1824(is)X
-1899(\256rst)X
-2045(modi\256ed,)X
-2371(a)X
-2429(second)X
-2674(recovery)X
-2978(\256le)X
-3102(containing)X
-3462(an)X
-3560(email)X
-3760(message)X
-576 1458(for)N
-691(the)X
-810(user)X
-965(is)X
-1039(created,)X
-1313(and)X
-1450(is)X
-1524(named)X
-1759(``)X
-3 f
-1813 0.3077(recover.XXXXXX)AX
-1 f
-2441('',)X
-2536(where,)X
-2774(again,)X
-2989(``)X
-3 f
-3043(XXXXXX)X
-1 f
-3391('')X
-3466(is)X
-3540(associated)X
-3890(with)X
-576 1548(the)N
-698(process)X
-963(ID.)X
-1112(Both)X
-1291(\256les)X
-1448(are)X
-1571(removed)X
-1876(at)X
-1958(the)X
-2080(end)X
-2220(of)X
-2311(a)X
-2371(normal)X
-2622(edit)X
-2766(session,)X
-3041(but)X
-3168(will)X
-3317(remain)X
-3565(if)X
-3639(the)X
-3762(edit)X
-3907(ses-)X
-576 1638(sion)N
-729(is)X
-802(abnormally)X
-1187(terminated)X
-1550(or)X
-1637(the)X
-1755(user)X
-1909(runs)X
-2067(the)X
-3 f
-2185(ex)X
-2281(preserve)X
-1 f
-2596(command.)X
-776 1761(The)N
-3 f
-935(recdir)X
-1 f
-1180(option)X
-1419(may)X
-1592(be)X
-1703(set)X
-1827(in)X
-1924(either)X
-2142(the)X
-2275(user's)X
-2502(or)X
-2604(system's)X
-2919(startup)X
-3172(information,)X
-3605(changing)X
-3934(the)X
-576 1851(recovery)N
-887(directory.)X
-1246(\(Note,)X
-1478(however,)X
-1804(that)X
-1953(if)X
-2031(a)X
-2096(memory)X
-2392(based)X
-2604(\256le)X
-2735(system)X
-2985(is)X
-3066(used)X
-3241(as)X
-3336(the)X
-3462(backup)X
-3722(directory,)X
-576 1941(each)N
-752(system)X
-1002(reboot)X
-1235(will)X
-1388(delete)X
-1609(all)X
-1718(of)X
-1814(the)X
-1941(recovery)X
-2252(\256les!)X
-2461(The)X
-2615(same)X
-2809(caution)X
-3074(applies)X
-3330(to)X
-3421(directories)X
-3789(such)X
-3965(as)X
-7 f
-576 2031(/tmp)N
-1 f
-792(which)X
-1012(are)X
-1135(cleared)X
-1392(of)X
-1483(their)X
-1654(contents)X
-1945(by)X
-2049(a)X
-2108(system)X
-2353(reboot,)X
-2601(or)X
-7 f
-2691(/usr/tmp)X
-1 f
-3098(which)X
-3317(is)X
-3393(periodically)X
-3799(cleared)X
-576 2121(of)N
-663(old)X
-785(\256les)X
-938(on)X
-1038(many)X
-1236(systems.\))X
-776 2244(The)N
-926(recovery)X
-1233(directory)X
-1548(should)X
-1786(be)X
-1887(owned)X
-2126(by)X
-2231(root,)X
-2405(or)X
-2497(at)X
-2580(least)X
-2752(by)X
-2857(a)X
-2918(pseudo-user.)X
-3371(In)X
-3463(addition,)X
-3770(if)X
-3844(direc-)X
-576 2334(tory)N
-727(``sticky-bit'')X
-1159(semantics)X
-1497(are)X
-1618(available,)X
-1950(the)X
-2070(directory)X
-2382(should)X
-2617(have)X
-2791(the)X
-2911(sticky-bit)X
-3234(set)X
-3344(so)X
-3436(that)X
-3577(\256les)X
-3731(may)X
-3890(only)X
-576 2424(be)N
-676(removed)X
-981(by)X
-1085(their)X
-1256(owners.)X
-1552(The)X
-1702(recovery)X
-2009(directory)X
-2324(must)X
-2504(be)X
-2605(read,)X
-2789(write,)X
-2999(and)X
-3140(executable)X
-3509(by)X
-3614(any)X
-3755(user,)X
-3934(i.e.)X
-576 2514(mode)N
-774(1777.)X
-776 2637(If)N
-850(the)X
-968(recovery)X
-1270(directory)X
-1581(does)X
-1749(not)X
-1872(exist,)X
-3 f
-2064(ex)X
-1 f
-2140(/)X
-3 f
-2162(vi)X
-1 f
-2245(will)X
-2390(attempt)X
-2651(to)X
-2734(create)X
-2948(it.)X
-3053(This)X
-3216(can)X
-3349(result)X
-3548(in)X
-3631(the)X
-3750(recovery)X
-576 2727(directory)N
-895(being)X
-1102(owned)X
-1345(by)X
-1454(a)X
-1518(normal)X
-1773(user,)X
-1955(which)X
-2179(means)X
-2412(that)X
-2560(that)X
-2708(user)X
-2870(will)X
-3022(be)X
-3126(able)X
-3288(to)X
-3378(remove)X
-3647(other)X
-3840(user's)X
-576 2817(recovery)N
-880(and)X
-1018(backup)X
-1272(\256les.)X
-1467(This)X
-1631(is)X
-1706(annoying,)X
-2046(but)X
-2170(is)X
-2245(not)X
-2369(a)X
-2427(security)X
-2703(issue)X
-2886(as)X
-2976(the)X
-3097(user)X
-3254(cannot)X
-3491(otherwise)X
-3826(access)X
-576 2907(or)N
-663(modify)X
-914(the)X
-1032(\256les.)X
-776 3030(The)N
-924(recovery)X
-1229(\256le)X
-1354(has)X
-1484(all)X
-1587(of)X
-1677(the)X
-1798(necessary)X
-2134(information)X
-2535(in)X
-2621(it)X
-2689(to)X
-2775(enable)X
-3009(the)X
-3131(user)X
-3289(to)X
-3375(recover)X
-3641(the)X
-3763(edit)X
-3907(ses-)X
-576 3120(sion.)N
-774(In)X
-866(addition,)X
-1173(it)X
-1242(has)X
-1374(all)X
-1479(of)X
-1571(the)X
-1694(necessary)X
-2032(email)X
-2235(headers)X
-2505(for)X
-2 f
-2623(sendmail)X
-1 f
-2912(\(8\).)X
-3070(When)X
-3286(the)X
-3408(system)X
-3654(is)X
-3731(rebooted,)X
-576 3210(all)N
-677(of)X
-765(the)X
-884(\256les)X
-1038(in)X
-7 f
-1121(/var/tmp/vi.recover)X
-1 f
-2054(named)X
-2289(``)X
-3 f
-2343 0.3077(recover.XXXXXX)AX
-1 f
-2971('')X
-3046(should)X
-3280(be)X
-3377(sent)X
-3527(to)X
-3611(their)X
-3780(owners,)X
-576 3300(by)N
-684(email,)X
-910(using)X
-1111(the)X
-3 f
-9 f
-1237(-)X
-1239(-)X
-3 f
-1283(t)X
-1 f
-1338(option)X
-1570(of)X
-3 f
-1665(sendmail)X
-1 f
-1999(\(or)X
-2121(a)X
-2185(similar)X
-2434(mechanism)X
-2826(in)X
-2915(other)X
-3107(mailers\).)X
-3437(If)X
-3 f
-3518(ex)X
-1 f
-3594(/)X
-3 f
-3616(vi)X
-1 f
-3705(receives)X
-3996(a)X
-576 3390(hangup)N
-839(\(SIGHUP\))X
-1209(signal,)X
-1447(or)X
-1541(the)X
-1666(user)X
-1828(executes)X
-2133(the)X
-3 f
-2259(ex)X
-2363(preserve)X
-1 f
-2686(command,)X
-3 f
-3050(ex)X
-1 f
-3126(/)X
-3 f
-3148(vi)X
-1 f
-3238(will)X
-3390(automatically)X
-3854(email)X
-576 3480(the)N
-694(recovery)X
-996(information)X
-1394(to)X
-1476(the)X
-1594(user.)X
-776 3603(If)N
-853(your)X
-1023(system)X
-1268(does)X
-1438(not)X
-1564(have)X
-1740(the)X
-3 f
-1862(sendmail)X
-1 f
-2192(utility)X
-2406(\(or)X
-2524(a)X
-2584(mailer)X
-2813(program)X
-3109(which)X
-3329(supports)X
-3624(its)X
-3723(interface\))X
-576 3693(the)N
-700(source)X
-936(\256le)X
-7 f
-1063(nvi/common/recover.c)X
-1 f
-2048(will)X
-2197(have)X
-2374(to)X
-2461(be)X
-2562(modi\256ed)X
-2871(to)X
-2958(use)X
-3090(your)X
-3262(local)X
-3443(mail)X
-3610(delivery)X
-3898(pro-)X
-576 3783(grams.)N
-833(Note,)X
-1030(if)X
-3 f
-1100(nex)X
-1 f
-(/)S
-3 f
-1242(nvi)X
-1 f
-1369(is)X
-1443(changed)X
-1732(to)X
-1815(use)X
-1944(another)X
-2207(mailer,)X
-2454(it)X
-2520(is)X
-2595(important)X
-2928(to)X
-3012(remember)X
-3360(that)X
-3502(the)X
-3622(owner)X
-3845(of)X
-3934(the)X
-576 3873(\256le)N
-708(given)X
-916(to)X
-1008(the)X
-1136(mailer)X
-1371(is)X
-1454(the)X
-3 f
-1582(nex)X
-1 f
-(/)S
-3 f
-1724(nvi)X
-1 f
-1860(user,)X
-2044(so)X
-2145(nothing)X
-2419(in)X
-2511(the)X
-2638(\256le)X
-2769(should)X
-3011(be)X
-3116(trusted)X
-3363(as)X
-3459(it)X
-3532(may)X
-3699(have)X
-3880(been)X
-576 3963(modi\256ed)N
-880(in)X
-962(an)X
-1058(effort)X
-1257(to)X
-1339(compromise)X
-1755(the)X
-1873(system.)X
-776 4086(Finally,)N
-1046(the)X
-1168(owner)X
-1393(execute)X
-1663(bit)X
-1771(is)X
-1848(set)X
-1961(on)X
-2065(backup)X
-2321(\256les)X
-2478(when)X
-2676(they)X
-2838(are)X
-2961(created,)X
-3238(and)X
-3378(unset)X
-3571(when)X
-3770(they)X
-3933(are)X
-576 4176(\256rst)N
-724(modi\256ed,)X
-1052(e.g.)X
-1192(backup)X
-1448(\256les)X
-1605(that)X
-1749(have)X
-1925(no)X
-2029(associated)X
-2383(email)X
-2585(recovery)X
-2891(\256le)X
-3017(will)X
-3165(have)X
-3341(this)X
-3480(bit)X
-3588(set.)X
-3741(\(There)X
-3979(is)X
-576 4266(also)N
-735(a)X
-801(small)X
-1004(window)X
-1292(where)X
-1519(empty)X
-1749(\256les)X
-1912(can)X
-2054(be)X
-2160(created)X
-2424(and)X
-2571(not)X
-2704(yet)X
-2833(have)X
-3016(this)X
-3162(bit)X
-3277(set.)X
-3437(This)X
-3610(is)X
-3694(due)X
-3841(to)X
-3934(the)X
-576 4356(method)N
-836(in)X
-918(which)X
-1134(the)X
-1252(\256les)X
-1405(are)X
-1524(created.\))X
-1844(Such)X
-2024(\256les)X
-2177(should)X
-2410(be)X
-2506(deleted)X
-2758(when)X
-2952(the)X
-3070(system)X
-3312(reboots.)X
-776 4479(A)N
-884(simple)X
-1147(way)X
-1331(to)X
-1443(do)X
-1573(this)X
-1738(cleanup)X
-2038(is)X
-2141(to)X
-2253(insert)X
-2481(the)X
-2630(following)X
-2992(Bourne)X
-3279(shell)X
-3481(script)X
-3710(into)X
-3885(your)X
-7 f
-576 4569(/etc/rc.local)N
-1 f
-1224(\(or)X
-1342(other)X
-1531(startup\))X
-1800(\256le.)X
-1966(The)X
-2115(script)X
-2316(should)X
-2552(work)X
-2740(with)X
-2905(the)X
-3026(historic)X
-3289(Bourne)X
-3548(shell,)X
-3742(a)X
-3801(POSIX)X
-576 4659(1003.2)N
-818(shell)X
-991(or)X
-1080(the)X
-1201(Korn)X
-1389(shell.)X
-1603(\(A)X
-1711(copy)X
-1890(of)X
-1980(this)X
-2118(script)X
-2319(is)X
-2395(included)X
-2694(as)X
-7 f
-2784(nvi/install/recover.script)X
-1 f
-576 4749(in)N
-658(the)X
-3 f
-776(nex)X
-1 f
-(/)S
-3 f
-918(nvi)X
-1 f
-1044(distribution.\))X
-
-5 p
-%%Page: 5 4
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-3698(USD:13-5)X
-7 f
-896 762(#)N
-1184(@\(#\)recover.script)X
-2336(8.4)X
-2528(\(Berkeley\))X
-3056(8/13/94)X
-896 852(#)N
-896 942(#)N
-992(Recover)X
-1376(nvi)X
-1568(editor)X
-1904(files:)X
-896 1032(RECDIR=/var/tmp/vi.recover)N
-896 1122(SENDMAIL=/usr/lib/sendmail)N
-896 1212(echo)N
-1136('Recovering)X
-1712(nvi)X
-1904(editor)X
-2240(sessions.')X
-896 1392(#)N
-992(Unmodified)X
-1520(nvi)X
-1712(editor)X
-2048(backup)X
-2384(files)X
-2672(are)X
-2864(either)X
-3200(zero)X
-3440(length)X
-3776(or)X
-896 1482(#)N
-992(have)X
-1232(the)X
-1424(execute)X
-1808(bit)X
-2000(set.)X
-2288(Delete)X
-2624(both)X
-2864(cases.)X
-896 1572(vibackup=`echo)N
-1616($RECDIR/vi.*`)X
-896 1662(if)N
-1040([)X
-1136("$vibackup")X
-1712(!=)X
-1856("$RECDIR/vi.*")X
-2576(];)X
-2720(then)X
-1184 1752(for)N
-1376(i)X
-1472(in)X
-1616($vibackup;)X
-2144(do)X
-1472 1842(if)N
-1616(test)X
-1856(-x)X
-2000($i)X
-2144(-o)X
-2288(!)X
-2384(-s)X
-2528($i;)X
-2720(then)X
-1760 1932(rm)N
-1904($i)X
-1472 2022(fi)N
-1184 2112(done)N
-896 2202(fi)N
-896 2382(#)N
-992(It)X
-1136(is)X
-1280(possible)X
-1712(to)X
-1856(get)X
-2048(incomplete)X
-2576(recovery)X
-3008(files,)X
-3344(if)X
-3488(the)X
-3680(editor)X
-896 2472(#)N
-992(crashes)X
-1376(at)X
-1520(the)X
-1712(right)X
-2000(time.)X
-2336(Delete)X
-2672(any)X
-2864(recovery)X
-3296(files)X
-3584(without)X
-896 2562(#)N
-992(corresponding)X
-1664(backup)X
-2000(files,)X
-2336(otherwise)X
-2816(send)X
-3056(mail)X
-3296(to)X
-3440(the)X
-3632(user.)X
-896 2652(virecovery=`echo)N
-1712($RECDIR/recover.*`)X
-896 2742(if)N
-1040([)X
-1136("$virecovery")X
-1808(!=)X
-1952("$RECDIR/recover.*")X
-2912(];)X
-3056(then)X
-1184 2832(for)N
-1376(i)X
-1472(in)X
-1616($virecovery;)X
-2240(do)X
-1472 2922(recfile=`awk)N
-2096('/\303X-vi-recover-path:/{print)X
-3488($2}')X
-3728(<)X
-3824($i`)X
-1472 3012(if)N
-1616(test)X
-1856(!)X
-1952(-n)X
-2096($recfile)X
-2528(-a)X
-2672(-s)X
-2816($recfile;)X
-3296(then)X
-1760 3102($SENDMAIL)N
-2240(-t)X
-2384(<)X
-2480($i)X
-1472 3192(else)N
-1760 3282(rm)N
-1904($i)X
-1472 3372(fi)N
-1184 3462(done)N
-896 3552(fi)N
-1 f
-776 3798(If)N
-859(you)X
-1008(are)X
-1136(not)X
-1267(using)X
-1469(the)X
-1596(default)X
-1848(value)X
-2051(for)X
-2174(the)X
-3 f
-2301(recdir)X
-1 f
-2540(option,)X
-2793(be)X
-2898(sure)X
-3062(to)X
-3154(substitute)X
-3490(the)X
-3618(value)X
-3822(you're)X
-576 3888(using)N
-769(for)X
-883(the)X
-7 f
-1001(RECDIR)X
-1 f
-1309(value)X
-1503(in)X
-1585(the)X
-1703(recovery)X
-2005(script.)X
-776 4011(If)N
-882(the)X
-1032(path)X
-1222(of)X
-1341(your)X
-1540(system's)X
-3 f
-1872(sendmail)X
-1 f
-2230(program)X
-2555(\(or)X
-2702(whatever)X
-3050(mailer)X
-3308(you're)X
-3571(using\))X
-3824(is)X
-3930(not)X
-7 f
-576 4101(/usr/lib/sendmail)N
-1 f
-(,)S
-1451(be)X
-1566(sure)X
-1739(to)X
-1840(substitute)X
-2184(the)X
-2320(correct)X
-2582(pathname)X
-2932(for)X
-3064(the)X
-7 f
-3200(SENDMAIL)X
-1 f
-3622(value)X
-3834(in)X
-3934(the)X
-576 4191(recovery)N
-878(script.)X
-1116(Consult)X
-1384(the)X
-1502(manual)X
-1758(page)X
-1930(for)X
-2044(details)X
-2273(on)X
-2373(recovering)X
-2737(preserved)X
-3070(or)X
-3157(aborted)X
-3418(editing)X
-3660(sessions.)X
-3 f
-576 4377(4.)N
-676(Sizing)X
-904(the)X
-1031(Screen)X
-1 f
-776 4500(The)N
-926(size)X
-1076(of)X
-1168(the)X
-1291(screen)X
-1522(can)X
-1659(be)X
-1760(set)X
-1874(in)X
-1961(a)X
-2022(number)X
-2292(of)X
-2384(ways.)X
-3 f
-2614(Ex)X
-1 f
-2707(/)X
-3 f
-2729(vi)X
-1 f
-2817(takes)X
-3008(the)X
-3132(following)X
-3469(steps)X
-3655(until)X
-3827(values)X
-576 4590(are)N
-695(obtained)X
-991(for)X
-1105(both)X
-1267(the)X
-1385(number)X
-1650(of)X
-1737(rows)X
-1913(and)X
-2049(number)X
-2314(of)X
-2401(columns)X
-2692(in)X
-2774(the)X
-2892(screen.)X
-616 4713(\(1\))N
-830(If)X
-904(the)X
-1022(environmental)X
-1505(variable)X
-7 f
-1784(LINES)X
-1 f
-2044(exists,)X
-2266(it)X
-2330(is)X
-2403(used)X
-2570(to)X
-2652(specify)X
-2904(the)X
-3022(number)X
-3287(of)X
-3374(rows)X
-3550(in)X
-3632(the)X
-3750(screen.)X
-616 4836(\(2\))N
-830(If)X
-909(the)X
-1032(environmental)X
-1520(variable)X
-7 f
-1804(COLUMNS)X
-1 f
-2165(exists,)X
-2393(it)X
-2463(is)X
-2542(used)X
-2715(to)X
-2803(specify)X
-3061(the)X
-3185(number)X
-3456(of)X
-3549(columns)X
-3846(in)X
-3934(the)X
-830 4926(screen.)N
-616 5049(\(3\))N
-830(The)X
-975(TIOCGWINSZ)X
-2 f
-1494(ioctl)X
-1 f
-1636(\(2\))X
-1750(is)X
-1823(attempted)X
-2159(on)X
-2259(the)X
-2377(standard)X
-2669(error)X
-2846(\256le)X
-2968(descriptor.)X
-616 5172(\(4\))N
-830(The)X
-978(termcap)X
-1260(entry)X
-1448(\(or)X
-1565(terminfo)X
-1864(entry)X
-2053(on)X
-2157(System)X
-2416(V)X
-2498(machines\))X
-2852(is)X
-2929(checked)X
-3217(for)X
-3335(the)X
-3457(``li'')X
-3633(entry)X
-3822(\(rows\))X
-830 5262(and)N
-966(the)X
-1084(``co'')X
-1288(entry)X
-1473(\(columns\).)X
-616 5385(\(5\))N
-830(The)X
-975(number)X
-1240(of)X
-1327(rows)X
-1503(is)X
-1576(set)X
-1685(to)X
-1767(24,)X
-1887(and)X
-2023(the)X
-2141(number)X
-2406(of)X
-2493(columns)X
-2784(is)X
-2857(set)X
-2966(to)X
-3048(80.)X
-776 5508(If)N
-851(a)X
-908(window)X
-1187(change)X
-1436(size)X
-1582(signal)X
-1794(\(SIGWINCH\))X
-2270(is)X
-2344(received,)X
-2658(the)X
-2777(new)X
-2932(window)X
-3211(size)X
-3357(is)X
-3431(retrieved)X
-3739(using)X
-3934(the)X
-576 5598(TIOCGWINSZ)N
-2 f
-1095(ioctl)X
-1 f
-1237(\(2\))X
-1351(call,)X
-1507(and)X
-1643(all)X
-1743(other)X
-1928(information)X
-2326(is)X
-2399(ignored.)X
-
-6 p
-%%Page: 6 5
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-6)N
-3391(Nvi/Nex)X
-3687 0.3906(Reference)AX
-576 762(5.)N
-676(Character)X
-1049(Display)X
-1 f
-776 885(In)N
-865(both)X
-3 f
-1030(ex)X
-1 f
-1129(and)X
-3 f
-1268(vi)X
-1 f
-1353(printable)X
-1661(characters)X
-2011(as)X
-2101(de\256ned)X
-2360(by)X
-2 f
-2463(isprint)X
-1 f
-2671(\(3\))X
-2788(are)X
-2910(displayed)X
-3240(using)X
-3436(the)X
-3557(local)X
-3736(character)X
-576 975(set.)N
-776 1098(Non-printable)N
-1255(characters,)X
-1631(for)X
-1754(which)X
-2 f
-1980(iscntrl)X
-1 f
-2184(\(3\))X
-2308(returns)X
-2561(true,)X
-2736(and)X
-2882(which)X
-3108(are)X
-3237(less)X
-3387(than)X
-3555(octal)X
-3741(\\076,)X
-3933(are)X
-576 1188(displayed)N
-915(as)X
-1014(the)X
-1144(string)X
-1357(``)X
-7 f
-1411(\303<character>)X
-1 f
-('',)S
-2092(where)X
-7 f
-2320(<character>)X
-1 f
-2879(is)X
-2963(the)X
-3092(character)X
-3419(that)X
-3570(is)X
-3654(the)X
-3783(original)X
-576 1278 0.3250(character's)AN
-961(value)X
-1166(offset)X
-1380(from)X
-1568(the)X
-1698(``)X
-7 f
-1752(@)X
-1 f
-('')S
-1886(character.)X
-2254(For)X
-2397(example,)X
-2721(the)X
-2851(octal)X
-3039(character)X
-3367(\\001)X
-3541(is)X
-3626(displayed)X
-3965(as)X
-576 1368(``)N
-7 f
-630(\303A)X
-1 f
-(''.)S
-845(If)X
-2 f
-924(iscntrl)X
-1 f
-1128(\(3\))X
-1247(returns)X
-1495(true)X
-1645(for)X
-1764(the)X
-1887(octal)X
-2068(character)X
-2389(\\177,)X
-2576(it)X
-2645(is)X
-2723(displayed)X
-3054(as)X
-3145(the)X
-3267(string)X
-3473(``)X
-7 f
-3527(\303?)X
-1 f
-(''.)S
-3741(All)X
-3867(other)X
-576 1458(characters)N
-947(are)X
-1090(displayed)X
-1441(as)X
-1552(either)X
-1779(hexadecimal)X
-2229(values,)X
-2498(in)X
-2604(the)X
-2746(form)X
-2946(``)X
-7 f
-3000(0x<high-halfbyte>)X
-3888(...)X
-576 1548(0x<low-halfbyte>)N
-1 f
-('',)S
-1469(or)X
-1587(as)X
-1705(octal)X
-1911(values,)X
-2186(in)X
-2298(the)X
-2446(form)X
-2652(``)X
-7 f
-2706(\\<high-one-or-two-bits>)X
-3888(...)X
-576 1638(\\<low-three-bits>)N
-1 f
-(''.)S
-1506(The)X
-1651(display)X
-1902(of)X
-1989(unknown)X
-2307(characters)X
-2654(is)X
-2727(based)X
-2930(on)X
-3030(the)X
-3148(value)X
-3342(of)X
-3429(the)X
-3 f
-3547(octal)X
-1 f
-3732(option.)X
-776 1761(In)N
-3 f
-864(vi)X
-1 f
-947(command)X
-1285(mode,)X
-1505(the)X
-1625(cursor)X
-1848(is)X
-1923(always)X
-2168(positioned)X
-2523(on)X
-2625(the)X
-2745(last)X
-2878(column)X
-3140(of)X
-3229(characters)X
-3578(which)X
-3796(take)X
-3952(up)X
-576 1851(more)N
-765(than)X
-927(one)X
-1067(column)X
-1331(on)X
-1435(the)X
-1557(screen.)X
-1827(In)X
-3 f
-1918(vi)X
-1 f
-2003(text)X
-2146(input)X
-2333(mode,)X
-2554(the)X
-2675(cursor)X
-2899(is)X
-2975(positioned)X
-3331(on)X
-3434(the)X
-3555(\256rst)X
-3702(column)X
-3965(of)X
-576 1941(characters)N
-923(which)X
-1139(take)X
-1293(up)X
-1393(more)X
-1578(than)X
-1736(one)X
-1872(column)X
-2132(on)X
-2232(the)X
-2350(screen.)X
-3 f
-576 2127(6.)N
-676(Multiple)X
-989(Screens)X
-1 f
-3 f
-776 2250(Nvi)N
-1 f
-916(supports)X
-1207(multiple)X
-1493(screens)X
-1750(by)X
-1851(dividing)X
-2138(the)X
-2257(window)X
-2536(into)X
-2681(regions.)X
-2978(It)X
-3048(also)X
-3198(supports)X
-3490(stacks)X
-3707(of)X
-3795(screens)X
-576 2340(by)N
-676(permitting)X
-1029(the)X
-1147(user)X
-1301(to)X
-1383(change)X
-1631(the)X
-1749(set)X
-1858(of)X
-1945(screens)X
-2202(that)X
-2342(are)X
-2461(currently)X
-2771(displayed.)X
-776 2463(The)N
-924(command)X
-3 f
-1263(split)X
-1 f
-1432(divides)X
-1686(the)X
-1807(current)X
-2058(screen)X
-2287(into)X
-2434(two)X
-2577(regions)X
-2836(of)X
-2926(approximately)X
-3412(equal)X
-3609(size.)X
-3797(If)X
-3875(a)X
-3935(list)X
-576 2553(of)N
-668(\256les)X
-826(are)X
-950(speci\256ed)X
-1260(as)X
-1352(arguments)X
-1711(to)X
-1798(the)X
-3 f
-1921(split)X
-1 f
-2092(command,)X
-2452(the)X
-2574(list)X
-2695(of)X
-2786(\256les)X
-2943(to)X
-3029(be)X
-3129(edited)X
-3349(is)X
-3426(initialized)X
-3770(as)X
-3861(if)X
-3934(the)X
-3 f
-576 2643(next)N
-1 f
-747(command)X
-1087(had)X
-1227(been)X
-1403(used.)X
-1614(If)X
-1692(no)X
-1796(\256les)X
-1953(are)X
-2076(speci\256ed,)X
-2405(the)X
-2527(new)X
-2685(screen)X
-2915(will)X
-3063(begin)X
-3265(by)X
-3370(editing)X
-3617(the)X
-3740(same)X
-3930(\256le)X
-576 2733(as)N
-663(the)X
-781(previous)X
-1077(screen.)X
-776 2856(When)N
-992(more)X
-1181(than)X
-1343(one)X
-1483(screen)X
-1713(is)X
-1790(editing)X
-2036(a)X
-2097(\256le,)X
-2244(changes)X
-2528(in)X
-2615(any)X
-2756(screen)X
-2987(are)X
-3111(re\257ected)X
-3413(in)X
-3500(all)X
-3605(other)X
-3795(screens)X
-576 2946(editing)N
-820(the)X
-940(same)X
-1127(\256le.)X
-1291(Exiting)X
-1548(any)X
-1686(screen)X
-1914(without)X
-2180(saving)X
-2410(any)X
-2547(changes)X
-2827(\(or)X
-2942(explicitly)X
-3265(discarding)X
-3620(them\))X
-3828(is)X
-3902(per-)X
-576 3036(mitted)N
-800(until)X
-966(the)X
-1084(last)X
-1215(screen)X
-1441(editing)X
-1683(the)X
-1801(\256le)X
-1923(is)X
-1996(exited.)X
-776 3159(The)N
-3 f
-923(resize)X
-1 f
-1142(command)X
-1480(permits)X
-1742(resizing)X
-2018(of)X
-2107(individual)X
-2453(screens.)X
-2752(Screens)X
-3024(may)X
-3184(be)X
-3282(grown,)X
-3529(shrunk)X
-3769(or)X
-3858(set)X
-3970(to)X
-576 3249(an)N
-672(absolute)X
-959(number)X
-1224(of)X
-1311(rows.)X
-776 3372(The)N
-3 f
-921(\303W)X
-1 f
-1048(command)X
-1384(is)X
-1457(used)X
-1624(to)X
-1706(switch)X
-1935(between)X
-2223(screens.)X
-2520(Each)X
-3 f
-2701(\303W)X
-1 f
-2829(moves)X
-3059(to)X
-3142(the)X
-3261(next)X
-3420(lower)X
-3624(screen)X
-3851(in)X
-3934(the)X
-576 3462(window,)N
-874(or)X
-961(to)X
-1043(the)X
-1161(\256rst)X
-1305(screen)X
-1531(in)X
-1613(the)X
-1731(window)X
-2009(if)X
-2078(there)X
-2259(are)X
-2378(no)X
-2478(lower)X
-2681(screens.)X
-776 3585(The)N
-3 f
-925(bg)X
-1 f
-1033(command)X
-1374(``backgrounds'')X
-1917(the)X
-2040(current)X
-2293(screen.)X
-2564(The)X
-2714(screen)X
-2945(disappears)X
-3309(from)X
-3490(the)X
-3613(window,)X
-3916(and)X
-576 3675(the)N
-702(rows)X
-886(it)X
-958(occupied)X
-1276(are)X
-1403(taken)X
-1605(over)X
-1776(by)X
-1884(a)X
-1948(neighboring)X
-2363(screen.)X
-2637(It)X
-2714(is)X
-2795(an)X
-2899(error)X
-3083(to)X
-3172(attempt)X
-3439(to)X
-3528(background)X
-3934(the)X
-576 3765(only)N
-738(screen)X
-964(in)X
-1046(the)X
-1164(window.)X
-776 3888(The)N
-3 f
-935(display)X
-1212(screens)X
-1 f
-1496(command)X
-1846(displays)X
-2142(the)X
-2274(names)X
-2513(of)X
-2614(the)X
-2747(\256les)X
-2915(associated)X
-3280(with)X
-3457(the)X
-3590(current)X
-3853(back-)X
-576 3978(grounded)N
-899(screens)X
-1156(in)X
-1238(the)X
-1356(window.)X
-776 4101(The)N
-3 f
-932(fg)X
-1031([\256le])X
-1 f
-1219(command)X
-1567(``foregrounds'')X
-2095(the)X
-2225(\256rst)X
-2381(screen)X
-2619(in)X
-2713(the)X
-2843(list)X
-2972(of)X
-3071(backgrounded)X
-3558(screens)X
-3827(that)X
-3979(is)X
-576 4191(associated)N
-934(with)X
-1103(its)X
-1205(argument.)X
-1575(If)X
-1656(no)X
-1763(\256le)X
-1892(argument)X
-2222(is)X
-2302(speci\256ed,)X
-2634(the)X
-2759(\256rst)X
-2910(screen)X
-3143(on)X
-3250(the)X
-3375(list)X
-3499(is)X
-3579(foregrounded.)X
-576 4281(Foregrounding)N
-1072(consists)X
-1345(of)X
-1432(backgrounding)X
-1933(the)X
-2051(current)X
-2299(screen,)X
-2545(and)X
-2681(replacing)X
-3000(its)X
-3095(space)X
-3294(in)X
-3376(the)X
-3494(window)X
-3772(with)X
-3934(the)X
-576 4371(foregrounded)N
-1029(screen.)X
-776 4494(If)N
-852(the)X
-972(last)X
-1105(screen)X
-1333(in)X
-1417(the)X
-1537(window)X
-1817(is)X
-1892(exited,)X
-2131(and)X
-2270(there)X
-2454(are)X
-2576(backgrounded)X
-3054(screens,)X
-3334(the)X
-3455(\256rst)X
-3602(screen)X
-3831(on)X
-3934(the)X
-576 4584(list)N
-693(of)X
-780(backgrounded)X
-1255(screens)X
-1512(takes)X
-1697(over)X
-1860(the)X
-1978(window.)X
-3 f
-576 4770(7.)N
-676(Regular)X
-972(Expressions)X
-1400(and)X
-1548(Replacement)X
-2014(Strings)X
-1 f
-776 4893(Regular)N
-1050(expressions)X
-1444(are)X
-1563(used)X
-1730(in)X
-1812(line)X
-1952(addresses,)X
-2301(as)X
-2389(the)X
-2508(\256rst)X
-2653(part)X
-2799(of)X
-2887(the)X
-3 f
-3006(ex)X
-3103(substitute)X
-1 f
-3436(,)X
-3 f
-3477(global)X
-1 f
-3685(,)X
-3726(and)X
-3 f
-3863(vglo-)X
-576 4983(bal)N
-1 f
-702(commands,)X
-1089(and)X
-1225(in)X
-1307(search)X
-1533(patterns.)X
-776 5106(The)N
-927(regular)X
-1181(expressions)X
-1581(supported)X
-1923(by)X
-3 f
-2030(ex)X
-1 f
-2106(/)X
-3 f
-2128(vi)X
-1 f
-2217(are,)X
-2363(by)X
-2470(default,)X
-2740(the)X
-2865(Basic)X
-3070(Regular)X
-3351(Expressions)X
-3765(\(BRE's\))X
-576 5196(described)N
-909(in)X
-996(the)X
-1119(IEEE)X
-1318(POSIX)X
-1574(Standard)X
-1884(1003.2.)X
-2169(The)X
-3 f
-2319(extended)X
-1 f
-2651(option)X
-2880(causes)X
-3115(all)X
-3220(regular)X
-3472(expressions)X
-3870(to)X
-3956(be)X
-576 5286(interpreted)N
-976(as)X
-1095(the)X
-1245(Extended)X
-1600(Regular)X
-1906(Expressions)X
-2345(\(ERE's\))X
-2661(described)X
-3022(by)X
-3155(the)X
-3306(same)X
-3524(standard.)X
-3889(\(See)X
-2 f
-576 5376(re_format)N
-1 f
-(\(7\))S
-1025(for)X
-1154(more)X
-1354(information.\))X
-1834(Generally)X
-2186(speaking,)X
-2526(BRE's)X
-2774(are)X
-2908(the)X
-3040(Regular)X
-3328(Expressions)X
-3749(found)X
-3970(in)X
-2 f
-576 5466(ed)N
-1 f
-652(\(1\))X
-766(and)X
-2 f
-902(grep)X
-1 f
-1049(\(1\),)X
-1183(and)X
-1319(ERE's)X
-1548(are)X
-1667(the)X
-1785(Regular)X
-2059(Expressions)X
-2466(found)X
-2673(in)X
-2 f
-2755(egrep)X
-1 f
-2938(\(1\).)X
-776 5589(The)N
-922(following)X
-1254(is)X
-1328(not)X
-1451(intended)X
-1748(to)X
-1831(provide)X
-2097(a)X
-2154(description)X
-2532(of)X
-2621(Regular)X
-2897(Expressions.)X
-3346(The)X
-3493(information)X
-3893(here)X
-576 5679(only)N
-742(describes)X
-1065(strings)X
-1302(and)X
-1442(characters)X
-1793(which)X
-2013(have)X
-2189(special)X
-2436(meanings)X
-2766(in)X
-2851(the)X
-3 f
-2972(ex)X
-1 f
-3048(/)X
-3 f
-3070(vi)X
-1 f
-3155(version)X
-3414(of)X
-3504(RE's,)X
-3707(or)X
-3797(options)X
-576 5769(which)N
-792(change)X
-1040(the)X
-1158(meanings)X
-1485(of)X
-1572(characters)X
-1919(that)X
-2059(normally)X
-2368(have)X
-2540(special)X
-2783(meanings)X
-3110(in)X
-3192(RE's.)X
-
-7 p
-%%Page: 7 6
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-3698(USD:13-7)X
-1 f
-616 762(\(1\))N
-830(An)X
-948(empty)X
-1168(RE)X
-1290(\(e.g.)X
-1473(``)X
-7 f
-1527(//)X
-1 f
-('')S
-1697(or)X
-1784(``)X
-7 f
-1838(??)X
-1 f
-('')S
-2028(is)X
-2101(equivalent)X
-2455(to)X
-2537(the)X
-2655(last)X
-2786(RE)X
-2908(used.)X
-616 885(\(2\))N
-830(The)X
-975(construct)X
-1289(``)X
-7 f
-1343(\\<)X
-1 f
-('')S
-1513(matches)X
-1796(the)X
-1914(beginning)X
-2254(of)X
-2341(a)X
-2397(word.)X
-616 1008(\(3\))N
-830(The)X
-975(construct)X
-1289(``)X
-7 f
-1343(\\>)X
-1 f
-('')S
-1513(matches)X
-1796(the)X
-1914(end)X
-2050(of)X
-2137(a)X
-2193(word.)X
-616 1131(\(4\))N
-830(The)X
-975(character)X
-1291(``)X
-7 f
-1345(\304)X
-1 f
-('')S
-1467(matches)X
-1750(the)X
-1868(replacement)X
-2281(part)X
-2426(of)X
-2513(the)X
-2631(last)X
-3 f
-2762(substitute)X
-1 f
-3115(command.)X
-776 1254(When)N
-992(the)X
-3 f
-1114(magic)X
-1 f
-1343(option)X
-1571(is)X
-2 f
-1648(not)X
-1 f
-1774(set,)X
-1907(the)X
-2029(only)X
-2195(characters)X
-2546(with)X
-2712(special)X
-2959(meanings)X
-3290(are)X
-3413(a)X
-3473(``)X
-7 f
-3527(\303)X
-1 f
-('')S
-3653(character)X
-3974(at)X
-576 1344(the)N
-698(beginning)X
-1042(of)X
-1133(an)X
-1233(RE,)X
-1379(a)X
-1439(``)X
-7 f
-1493($)X
-1 f
-('')S
-1619(character)X
-1939(at)X
-2021(the)X
-2143(end)X
-2282(of)X
-2372(an)X
-2471(RE,)X
-2616(and)X
-2755(the)X
-2876(escaping)X
-3180(character)X
-3499(``)X
-7 f
-3553(\\)X
-1 f
-(''.)S
-3718(The)X
-3866(char-)X
-576 1434(acters)N
-788(``)X
-7 f
-842(.)X
-1 f
-('',)S
-988(``)X
-7 f
-1042(*)X
-1 f
-('',)S
-1188(``)X
-7 f
-1242([)X
-1 f
-('')S
-1368(and)X
-1508(``)X
-7 f
-1562(\304)X
-1 f
-('')S
-1688(are)X
-1811(treated)X
-2054(as)X
-2145(ordinary)X
-2441(characters)X
-2793(unless)X
-3018(preceded)X
-3334(by)X
-3439(a)X
-3500(``)X
-7 f
-3554(\\)X
-1 f
-('';)S
-3703(when)X
-3902(pre-)X
-576 1524(ceded)N
-784(by)X
-884(a)X
-940(``)X
-7 f
-994(\\)X
-1 f
-('')S
-1116(they)X
-1274(regain)X
-1495(their)X
-1662(special)X
-1905(meaning.)X
-776 1647(Replacement)N
-1215(strings)X
-1448(are)X
-1567(the)X
-1685(second)X
-1928(part)X
-2073(of)X
-2160(a)X
-3 f
-2216(substitute)X
-1 f
-2569(command.)X
-776 1770(The)N
-924(character)X
-1243(``)X
-7 f
-1297(&)X
-1 f
-('')S
-1422(\(or)X
-1539(``)X
-7 f
-1593(\\&)X
-1 f
-('')S
-1766(if)X
-1839(the)X
-3 f
-1961(magic)X
-1 f
-2190(option)X
-2418(is)X
-2 f
-2495(not)X
-1 f
-2621(set\))X
-2761(in)X
-2847(the)X
-2969(replacement)X
-3386(string)X
-3592(stands)X
-3816(for)X
-3934(the)X
-576 1860(text)N
-717(matched)X
-1010(by)X
-1111(the)X
-1230(RE)X
-1353(that)X
-1494(is)X
-1568(being)X
-1767(replaced.)X
-2101(The)X
-2247(character)X
-2564(``)X
-7 f
-2618(\304)X
-1 f
-('')S
-2741(\(or)X
-2856(``)X
-7 f
-2910(\\\304)X
-1 f
-('')S
-3081(if)X
-3151(the)X
-3 f
-3270(magic)X
-1 f
-3496(option)X
-3721(is)X
-2 f
-3794(not)X
-1 f
-3916(set\))X
-576 1950(stands)N
-806(for)X
-931(the)X
-1060(replacement)X
-1484(part)X
-1640(of)X
-1738(the)X
-1867(previous)X
-3 f
-2174(substitute)X
-1 f
-2538(command.)X
-2925(It)X
-3005(is)X
-3089(only)X
-3262(valid)X
-3453(after)X
-3632(a)X
-3 f
-3699(substitute)X
-1 f
-576 2040(command)N
-912(has)X
-1039(been)X
-1211(performed.)X
-776 2163(The)N
-922(string)X
-1125(``)X
-7 f
-1179(\\#)X
-1 f
-('',)S
-1370(where)X
-1588(``)X
-7 f
-1642(#)X
-1 f
-('')S
-1765(is)X
-1839(an)X
-1936(integer)X
-2180(value)X
-2376(from)X
-2554(1)X
-2616(to)X
-2700(9,)X
-2782(stands)X
-3004(for)X
-3120(the)X
-3240(text)X
-3382(matched)X
-3676(by)X
-3778(the)X
-3898(por-)X
-576 2253(tion)N
-728(of)X
-823(the)X
-949(RE)X
-1079(enclosed)X
-1388(in)X
-1478(the)X
-1604(``)X
-7 f
-1658(#)X
-1 f
-('''th)S
-1877(set)X
-1994(of)X
-2089(escaped)X
-2372(parentheses,)X
-2794(e.g.)X
-2957(``)X
-7 f
-3011(\\\()X
-1 f
-('')S
-3188(and)X
-3331(``)X
-7 f
-3385(\\\))X
-1 f
-(''.)S
-3602(For)X
-3740(example,)X
-576 2343(``)N
-7 f
-630(s/abc\\\(.*\\\)def/\\1/)X
-1 f
-('')S
-1568(deletes)X
-1811(the)X
-1929(strings)X
-2162(``)X
-7 f
-2216(abc)X
-1 f
-('')S
-2434(and)X
-2570(``)X
-7 f
-2624(def)X
-1 f
-('')S
-2842(from)X
-3018(the)X
-3136(matched)X
-3428(pattern.)X
-776 2466(The)N
-934(strings)X
-1180(``)X
-7 f
-1234(\\l)X
-1 f
-('',)S
-1437(``)X
-7 f
-1491(\\u)X
-1 f
-('',)S
-1694(``)X
-7 f
-1748(\\L)X
-1 f
-('')S
-1931(and)X
-2080(``)X
-7 f
-2134(\\U)X
-1 f
-('')S
-2317(can)X
-2462(be)X
-2571(used)X
-2752(to)X
-2848(modify)X
-3113(the)X
-3245(case)X
-3418(of)X
-3519(elements)X
-3838(in)X
-3934(the)X
-576 2556(replacement)N
-999(string.)X
-1251(The)X
-1406(string)X
-1618(``)X
-7 f
-1672(\\l)X
-1 f
-('')S
-1852(causes)X
-2092(the)X
-2220(next)X
-2388(character)X
-2714(to)X
-2806(be)X
-2912(converted)X
-3259(to)X
-3350(lowercase;)X
-3723(the)X
-3850(string)X
-576 2646(``)N
-7 f
-630(\\u)X
-1 f
-('')S
-815(behaves)X
-1109(similarly,)X
-1448(but)X
-1585(converts)X
-1892(to)X
-1989(uppercase)X
-2346(\(e.g.)X
-7 f
-2544(s/abc/\\U&/)X
-1 f
-3059(replaces)X
-3358(the)X
-3492(string)X
-7 f
-3710(abc)X
-1 f
-3890(with)X
-7 f
-576 2736(ABC)N
-1 f
-(\).)S
-810(The)X
-958(strings)X
-1194(``)X
-7 f
-1248(\\L)X
-1 f
-('')S
-1421(causes)X
-1654(characters)X
-2004(up)X
-2107(to)X
-2192(the)X
-2313(end)X
-2452(of)X
-2541(the)X
-2661(string)X
-2865(or)X
-2954(the)X
-3074(next)X
-3234 0.3611(occurrence)AX
-3610(of)X
-3699(the)X
-3819(strings)X
-576 2826(``)N
-7 f
-630(\\e)X
-1 f
-('')S
-806(or)X
-899(``)X
-7 f
-953(\\E)X
-1 f
-('')S
-1129(to)X
-1217(be)X
-1319(converted)X
-1663(to)X
-1752(lowercase;)X
-2123(the)X
-2248(string)X
-2457(``)X
-7 f
-2511(\\U)X
-1 f
-('')S
-2688(behaves)X
-2974(similarly,)X
-3305(but)X
-3434(converts)X
-3733(to)X
-3822(upper-)X
-576 2916(case.)N
-776 3039(If)N
-850(the)X
-968(entire)X
-1171(replacement)X
-1584(pattern)X
-1827(is)X
-1900(``)X
-7 f
-1954(%)X
-1 f
-('',)S
-2096(then)X
-2254(the)X
-2372(last)X
-2503(replacement)X
-2916(pattern)X
-3159(is)X
-3232(used)X
-3399(again.)X
-776 3162(In)N
-3 f
-867(vi)X
-1 f
-929(,)X
-973(inserting)X
-1278(a)X
-7 f
-1339(<control-M>)X
-1 f
-1892(into)X
-2041(the)X
-2164(replacement)X
-2582(string)X
-2789(will)X
-2938(cause)X
-3142(the)X
-3265(matched)X
-3562(line)X
-3707(to)X
-3794(be)X
-3895(split)X
-576 3252(into)N
-720(two)X
-860(lines)X
-1031(at)X
-1109(that)X
-1249(point.)X
-1473(\(The)X
-7 f
-1645(<control-M>)X
-1 f
-2193(will)X
-2337(be)X
-2433(discarded.\))X
-3 f
-576 3438(8.)N
-676(General)X
-972(Editor)X
-1214(Description)X
-1 f
-776 3561(When)N
-3 f
-989(ex)X
-1 f
-1086(or)X
-3 f
-1174(vi)X
-1 f
-1257(are)X
-1377(executed,)X
-1704(the)X
-1823(text)X
-1964(of)X
-2052(a)X
-2109(\256le)X
-2232(is)X
-2306(read)X
-2466(\(or)X
-2581(a)X
-2638(temporary)X
-2989(\256le)X
-3112(is)X
-3186(created\),)X
-3487(and)X
-3624(then)X
-3783(all)X
-3885(edit-)X
-576 3651(ing)N
-700(changes)X
-981(happen)X
-1235(within)X
-1461(the)X
-1581(context)X
-1838(of)X
-1926(the)X
-2045(copy)X
-2222(of)X
-2310(the)X
-2429(\256le.)X
-2 f
-2592(No)X
-2706(changes)X
-2990(affect)X
-3189(the)X
-3308(actual)X
-3529(\256le)X
-3648(until)X
-3815(the)X
-3934(\256le)X
-576 3741(is)N
-662(written)X
-921(out)X
-1 f
-1023(,)X
-1076(either)X
-1293(using)X
-1500(a)X
-1570(write)X
-1769(command)X
-2119(or)X
-2220(another)X
-2495(command)X
-2845(which)X
-3075(is)X
-3162(affected)X
-3456(by)X
-3570(the)X
-3 f
-3702(autowrite)X
-1 f
-576 3831(option.)N
-776 3954(All)N
-898(\256les)X
-1052(are)X
-1172(locked)X
-1407(\(using)X
-1628(the)X
-2 f
-1747(\257ock)X
-1 f
-1899(\(2\))X
-2014(or)X
-2 f
-2102(fcntl)X
-1 f
-2244(\(2\))X
-2359(interfaces\))X
-2720(during)X
-2950(the)X
-3069(edit)X
-3210(session,)X
-3482(to)X
-3565(avoid)X
-3764(inadver-)X
-576 4044(tently)N
-781(making)X
-1044(modi\256cations)X
-1502(to)X
-1587(multiple)X
-1876(copies)X
-2104(of)X
-2194(the)X
-2315(\256le.)X
-2480(If)X
-2557(a)X
-2616(lock)X
-2777(cannot)X
-3014(be)X
-3113(obtained)X
-3412(for)X
-3529(a)X
-3587(\256le)X
-3711(because)X
-3988(it)X
-576 4134(is)N
-657(locked)X
-899(by)X
-1007(another)X
-1276(process,)X
-1565(the)X
-1691(edit)X
-1840(session)X
-2100(is)X
-2182(read-only)X
-2519(\(as)X
-2642(if)X
-2720(the)X
-3 f
-2847(readonly)X
-1 f
-3178(option)X
-3411(or)X
-3507(the)X
-3 f
-9 f
-3634(-)X
-3636(-)X
-3 f
-3680(R)X
-1 f
-3767(\257ag)X
-3916(had)X
-576 4224(been)N
-754(speci\256ed\).)X
-1132(If)X
-1212(a)X
-1274(lock)X
-1438(cannot)X
-1678(be)X
-1780(obtained)X
-2082(for)X
-2202(other)X
-2393(reasons,)X
-2680(the)X
-2804(edit)X
-2950(session)X
-3207(will)X
-3357(continue,)X
-3679(but)X
-3807(the)X
-3930(\256le)X
-576 4314(status)N
-778(information)X
-1176(\(see)X
-1326(the)X
-3 f
-1444(<control-G>)X
-1 f
-1890(command\))X
-2253(will)X
-2397(re\257ect)X
-2618(this)X
-2753(fact.)X
-776 4437(Both)N
-3 f
-955(ex)X
-1 f
-1055(and)X
-3 f
-1195(vi)X
-1 f
-1281(are)X
-1405(modeful)X
-1697(editors,)X
-1960(i.e.)X
-2083(they)X
-2246(have)X
-2423(two)X
-2568(modes,)X
-2822(``command'')X
-3271(mode)X
-3474(and)X
-3615(``text)X
-3814(input'')X
-576 4527(mode.)N
-817(The)X
-965(former)X
-1207(is)X
-1283(intended)X
-1582(to)X
-1667(permit)X
-1898(you)X
-2040(to)X
-2124(enter)X
-2307(commands)X
-2676(which)X
-2894(modi\256es)X
-3191(already)X
-3450(existing)X
-3725(text.)X
-3907(The)X
-576 4617(latter)N
-762(is)X
-836(intended)X
-1133(to)X
-1216(permit)X
-1446(you)X
-1588(to)X
-1672(enter)X
-1855(new)X
-2011(text.)X
-2193(When)X
-3 f
-2407(ex)X
-1 f
-2505(\256rst)X
-2651(starts)X
-2842(running,)X
-3133(it)X
-3199(is)X
-3274(in)X
-3358(command)X
-3696(mode,)X
-3916(and)X
-576 4707(usually)N
-838(displays)X
-1131(a)X
-1198(prompt)X
-1460(\(see)X
-1621(the)X
-3 f
-1750(prompt)X
-1 f
-2039(option)X
-2274(for)X
-2398(more)X
-2593(information\).)X
-3068(The)X
-3223(prompt)X
-3484(is)X
-3567(a)X
-3633(single)X
-3854(colon)X
-576 4797(\(``)N
-7 f
-657(:)X
-1 f
-(''\))S
-817(character.)X
-1184(There)X
-1403(are)X
-1533(three)X
-1725(commands)X
-2103(that)X
-2255(switch)X
-3 f
-2496(ex)X
-1 f
-2604(into)X
-2760(text)X
-2912(input)X
-3108(mode:)X
-3 f
-3340(append)X
-1 f
-3592(,)X
-3 f
-3644(change)X
-1 f
-3916(and)X
-3 f
-576 4887(insert)N
-1 f
-772(.)X
-840(Once)X
-1038(in)X
-1128(input)X
-1320(mode,)X
-1546(entering)X
-1837(a)X
-1901(line)X
-2049(containing)X
-2415(only)X
-2585(a)X
-2649(single)X
-2868(period)X
-3101(\(``)X
-7 f
-3182(.)X
-1 f
-(''\))S
-3359(terminates)X
-3721(text)X
-3868(input)X
-576 4977(mode)N
-774(and)X
-910(returns)X
-1153(to)X
-1235(command)X
-1571(mode,)X
-1789(where)X
-2006(the)X
-2124(prompt)X
-2375(is)X
-2448(redisplayed.)X
-776 5100(When)N
-3 f
-989(vi)X
-1 f
-1072(\256rst)X
-1217(starts)X
-1407(running,)X
-1697(it)X
-1763(is)X
-1838(in)X
-1922(command)X
-2260(mode)X
-2460(as)X
-2549(well.)X
-2749(There)X
-2959(are)X
-3080(eleven)X
-3312(commands)X
-3681(that)X
-3823(switch)X
-3 f
-576 5190(vi)N
-1 f
-659(into)X
-804(text)X
-945(input)X
-1130(mode:)X
-3 f
-1351(A)X
-1 f
-1409(,)X
-3 f
-1450(a)X
-1 f
-(,)S
-3 f
-1531(C)X
-1 f
-1589(,)X
-3 f
-1629(c)X
-1 f
-1665(,)X
-3 f
-1705(I)X
-1 f
-1736(,)X
-3 f
-1776(i)X
-1 f
-1798(,)X
-3 f
-1838(O)X
-1 f
-1900(,)X
-3 f
-1940(o)X
-1 f
-(,)S
-3 f
-2020(R)X
-1 f
-2078(,)X
-3 f
-2118(S)X
-1 f
-2182(and)X
-3 f
-2318(s)X
-1 f
-2349(.)X
-2409(Once)X
-2599(in)X
-2681(input)X
-2865(mode,)X
-3083(entering)X
-3366(an)X
-7 f
-3462(<escape>)X
-1 f
-3866(char-)X
-576 5280(acter)N
-753(terminates)X
-1107(text)X
-1247(input)X
-1431(mode)X
-1629(and)X
-1765(returns)X
-2008(to)X
-2090(command)X
-2426(mode.)X
-776 5403(The)N
-921(following)X
-1252(words)X
-1468(have)X
-1640(special)X
-1883(meanings)X
-2210(in)X
-2292(both)X
-2454(the)X
-3 f
-2572(ex)X
-1 f
-2668(and)X
-3 f
-2804(vi)X
-1 f
-2886(command)X
-3222(descriptions:)X
-3 f
-576 5583(<interrupt>)N
-1 f
-776 5673(The)N
-927(interrupt)X
-1229(character)X
-1551(is)X
-1630(used)X
-1803(to)X
-1891(interrupt)X
-2193(the)X
-2317(current)X
-2571(operation.)X
-2940(Normally)X
-7 f
-3274(<control-C>)X
-1 f
-(,)S
-3849(what-)X
-776 5763(ever)N
-935(character)X
-1251(is)X
-1324(set)X
-1433(for)X
-1547(the)X
-1665(current)X
-1913(terminal)X
-2200(is)X
-2273(used.)X
-
-8 p
-%%Page: 8 7
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-8)N
-3391(Nvi/Nex)X
-3687 0.3906(Reference)AX
-576 762(<literal)N
-847(next>)X
-1 f
-776 852(The)N
-923(literal)X
-1132(next)X
-1292(character)X
-1610(is)X
-1685(used)X
-1854(to)X
-1938(escape)X
-2175(the)X
-2295(subsequent)X
-2673(character)X
-2991(from)X
-3169(any)X
-3307(special)X
-3552(meaning.)X
-3890(This)X
-776 942(character)N
-1102(is)X
-1185(always)X
-7 f
-1438(<control-V>)X
-1 f
-(.)S
-2036(If)X
-2120(the)X
-2248(terminal)X
-2545(is)X
-2627(not)X
-2758(set)X
-2876(up)X
-2985(to)X
-3076(do)X
-3185(XON/XOFF)X
-3614(\257ow)X
-3785(control,)X
-776 1032(then)N
-7 f
-934(<control-Q>)X
-1 f
-1482(is)X
-1555(used)X
-1722(to)X
-1804(mean)X
-1998(literal)X
-2205(next)X
-2363(as)X
-2450(well.)X
-3 f
-576 1212(current)N
-855(pathname)X
-1 f
-776 1302(The)N
-923(pathname)X
-1257(of)X
-1346(the)X
-1467(\256le)X
-1592(currently)X
-1905(being)X
-2106(edited)X
-2325(by)X
-2428(vi.)X
-2553(When)X
-2768(the)X
-2889(percent)X
-3149(character)X
-3468(\(``)X
-7 f
-3549(%)X
-1 f
-(''\))S
-3701(appears)X
-3970(in)X
-776 1392(a)N
-833(\256le)X
-956(name)X
-1151(entered)X
-1409(as)X
-1497(part)X
-1643(of)X
-1731(an)X
-3 f
-1828(ex)X
-1 f
-1925(command)X
-2262(argument,)X
-2606(it)X
-2671(is)X
-2745(replaced)X
-3039(by)X
-3140(the)X
-3259(current)X
-3508(pathname.)X
-3880(\(The)X
-776 1482(``)N
-7 f
-830(%)X
-1 f
-('')S
-952(character)X
-1268(can)X
-1400(be)X
-1496(escaped)X
-1771(by)X
-1871(preceding)X
-2208(it)X
-2272(with)X
-2434(a)X
-2490(backslash.\))X
-3 f
-576 1662(alternate)N
-904(pathname)X
-1 f
-776 1752(The)N
-921(name)X
-1115(of)X
-1202(the)X
-1320(last)X
-1451(\256le)X
-1573(name)X
-1767(mentioned)X
-2125(in)X
-2207(an)X
-3 f
-2304(ex)X
-1 f
-2401(command,)X
-2758(or,)X
-2866(the)X
-2985(previous)X
-3282(current)X
-3531(pathname)X
-3864(if)X
-3934(the)X
-776 1842(last)N
-913(\256le)X
-1041(mentioned)X
-1404(becomes)X
-1710(the)X
-1833(current)X
-2086(\256le.)X
-2253(When)X
-2470(the)X
-2593(hash)X
-2765(mark)X
-2955(character)X
-3276(\(``)X
-7 f
-3357(#)X
-1 f
-(''\))S
-3511(appears)X
-3782(in)X
-3869(a)X
-3930(\256le)X
-776 1932(name)N
-979(entered)X
-1245(as)X
-1341(part)X
-1495(of)X
-1591(an)X
-3 f
-1696(ex)X
-1 f
-1801(command)X
-2146(argument,)X
-2498(it)X
-2571(is)X
-2653(replaced)X
-2955(by)X
-3064(the)X
-3191(alternate)X
-3498(pathname.)X
-3880(\(The)X
-776 2022(``)N
-7 f
-830(#)X
-1 f
-('')S
-952(character)X
-1268(can)X
-1400(be)X
-1496(escaped)X
-1771(by)X
-1871(preceding)X
-2208(it)X
-2272(with)X
-2434(a)X
-2490(backslash.\))X
-3 f
-576 2202(buffer)N
-1 f
-776 2292(One)N
-931(of)X
-1019(a)X
-1076(number)X
-1342(of)X
-1430(named)X
-1665(areas)X
-1852(for)X
-1968(saving)X
-2199(copies)X
-2426(of)X
-2515(text.)X
-2697(Commands)X
-3083(that)X
-3225(change)X
-3475(or)X
-3564(delete)X
-3778(text)X
-3920(can)X
-776 2382(save)N
-941(the)X
-1061(changed)X
-1351(or)X
-1440(deleted)X
-1693(text)X
-1834(into)X
-1979(a)X
-2036(speci\256c)X
-2302(buffer,)X
-2540(for)X
-2655(later)X
-2819(use,)X
-2967(if)X
-3037(the)X
-3156(command)X
-3493(allows)X
-3723(it)X
-3788(\(i.e.)X
-3934(the)X
-3 f
-776 2472(ex)N
-872(change)X
-1 f
-1132(command)X
-1468(cannot)X
-1702(save)X
-1866(the)X
-1985(changed)X
-2274(text)X
-2415(in)X
-2498(a)X
-2555(named)X
-2790(buffer\).)X
-3075(Buffers)X
-3337(are)X
-3457(named)X
-3692(with)X
-3855(a)X
-3912(sin-)X
-776 2562(gle)N
-895(character,)X
-1232(preceded)X
-1544(by)X
-1645(a)X
-1702(double)X
-1941(quote,)X
-2160(e.g.)X
-7 f
-2317("<character>)X
-1 f
-(.)S
-2954(Historic)X
-3232(implementations)X
-3785(of)X
-3 f
-3872(ex)X
-1 f
-3948(/)X
-3 f
-3970(vi)X
-1 f
-776 2652(limited)N
-7 f
-1022(<character>)X
-1 f
-1570(to)X
-1652(the)X
-1770(alphanumeric)X
-2227(characters;)X
-3 f
-2596(nex)X
-1 f
-(/)S
-3 f
-2738(nvi)X
-1 f
-2864(permits)X
-3124(the)X
-3242(use)X
-3369(of)X
-3456(any)X
-3592(character.)X
-776 2832(Buffers)N
-1041(named)X
-1279(by)X
-1383(uppercase)X
-1729(characters)X
-2080(are)X
-2203(the)X
-2325(same)X
-2514(as)X
-2605(buffers)X
-2857(named)X
-3095(by)X
-3199(lowercase)X
-3545(characters,)X
-3916(e.g.)X
-776 2922(the)N
-904(buffer)X
-1131(named)X
-1375(by)X
-1485(the)X
-1613(English)X
-1887(character)X
-2213(``)X
-7 f
-2267(A)X
-1 f
-('')S
-2399(is)X
-2482(the)X
-2610(same)X
-2805(as)X
-2902(the)X
-3030(buffer)X
-3257(named)X
-3500(by)X
-3609(the)X
-3736(character)X
-776 3012(``)N
-7 f
-830(a)X
-1 f
-('',)S
-977(with)X
-1144(the)X
-1267(exception)X
-1604(that,)X
-1769(if)X
-1843(the)X
-1966(buffer)X
-2188(contents)X
-2480(are)X
-2604(being)X
-2807(changed)X
-3100(\(as)X
-3219(with)X
-3386(a)X
-3447(text)X
-3593(deletion)X
-3877(or)X
-3 f
-3970(vi)X
-776 3102(change)N
-1 f
-1036(command\),)X
-1419(the)X
-1537(text)X
-1677(is)X
-2 f
-1750(appended)X
-1 f
-2082(to)X
-2164(the)X
-2282(buffer,)X
-2519(instead)X
-2766(of)X
-2853(replacing)X
-3172(the)X
-3290(current)X
-3538(contents.)X
-776 3282(The)N
-925(buffers)X
-1177(named)X
-1415(by)X
-1519(the)X
-1641(numeric)X
-1928(characters)X
-2279(\(in)X
-2392(English,)X
-2680(``)X
-7 f
-2734(1)X
-1 f
-('')S
-2860(through)X
-3133(``)X
-7 f
-3187(9)X
-1 f
-(''\),)S
-3360(are)X
-3483(special,)X
-3751(in)X
-3838(that)X
-3983(if)X
-776 3372(at)N
-864(least)X
-1041(one)X
-1187(line)X
-1337(is)X
-1420(changed)X
-1718(or)X
-1814(deleted)X
-2075(in)X
-2166(the)X
-2293(\256le,)X
-2444(\(or)X
-2567(a)X
-2632(command)X
-2977(changes)X
-3265(or)X
-3361(deletes)X
-3613(a)X
-3678(region)X
-3912(that)X
-776 3462(crosses)N
-1032(a)X
-1093(line)X
-1238(boundary\))X
-1593(a)X
-1654(copy)X
-1835(of)X
-1927(the)X
-2050(text)X
-2195(is)X
-2273(placed)X
-2508(into)X
-2657(the)X
-2780(numeric)X
-3068(buffer)X
-3290(``)X
-7 f
-3344(1)X
-1 f
-('',)S
-3491(regardless)X
-3842(of)X
-3934(the)X
-776 3552(user)N
-933(specifying)X
-1290(another)X
-1553(buffer)X
-1772(in)X
-1856(which)X
-2074(to)X
-2158(save)X
-2323(it.)X
-2429(Before)X
-2670(this)X
-2807(copy)X
-2985(is)X
-3060(done,)X
-3258(the)X
-3378(previous)X
-3676(contents)X
-3965(of)X
-776 3642(buffer)N
-1000(``)X
-7 f
-1054(1)X
-1 f
-('')S
-1183(are)X
-1309(moved)X
-1555(into)X
-1707(buffer)X
-1932(``)X
-7 f
-1986(2)X
-1 f
-('',)S
-2136(``)X
-7 f
-2190(2)X
-1 f
-('')S
-2320(into)X
-2472(buffer)X
-2697(``)X
-7 f
-2751(3)X
-1 f
-('',)S
-2901(and)X
-3045(so)X
-3144(on.)X
-3292(The)X
-3445(contents)X
-3740(of)X
-3835(buffer)X
-776 3732(``)N
-7 f
-830(9)X
-1 f
-('')S
-961(are)X
-1089(discarded.)X
-1466(In)X
-3 f
-1562(vi)X
-1 f
-1624(,)X
-1672(text)X
-1820(may)X
-1986(be)X
-2090(explicitly)X
-2420(stored)X
-2644(into)X
-2796(the)X
-2922(numeric)X
-3213(buffers.)X
-3509(In)X
-3604(this)X
-3747(case,)X
-3934(the)X
-776 3822(buffer)N
-995(rotation)X
-1266(described)X
-1596(above)X
-1810(occurs)X
-2042(before)X
-2270(the)X
-2390(replacement)X
-2805(of)X
-2894(the)X
-3014(buffer's)X
-3291(contents.)X
-3621(\(Text)X
-3818(cannot)X
-776 3912(be)N
-874(explicitly)X
-1198(stored)X
-1416(into)X
-1562(the)X
-1682(numeric)X
-1966(buffers)X
-2215(in)X
-3 f
-2298(ex)X
-1 f
-2395(because)X
-2671(of)X
-2759(ambiguities)X
-3153(that)X
-3294(this)X
-3430(would)X
-3651(cause)X
-3851(in)X
-3934(the)X
-3 f
-776 4002(ex)N
-1 f
-872(command)X
-1208(syntax.\))X
-776 4182(When)N
-991(a)X
-3 f
-1051(vi)X
-1 f
-1137(command)X
-1477(synopsis)X
-1776(shows)X
-2000(both)X
-2166(a)X
-7 f
-2226([buffer])X
-1 f
-2634(and)X
-2774(a)X
-7 f
-2834([count])X
-1 f
-(,)S
-3214(they)X
-3376(may)X
-3538(be)X
-3638(presented)X
-3970(in)X
-776 4272(any)N
-912(order.)X
-776 4452(Finally,)N
-1052(all)X
-1162(buffers)X
-1420(are)X
-1549(either)X
-1762(``line'')X
-2020(or)X
-2117 0.3750(``character'')AX
-2551(oriented.)X
-2884(All)X
-3 f
-3016(ex)X
-1 f
-3122(commands)X
-3499(which)X
-3725(store)X
-3912(text)X
-776 4542(into)N
-922(buffers)X
-1172(are)X
-1293(line)X
-1435(oriented.)X
-1760(Some)X
-3 f
-1964(vi)X
-1 f
-2048(commands)X
-2417(which)X
-2635(store)X
-2813(text)X
-2955(into)X
-3101(buffers)X
-3351(are)X
-3471(line)X
-3612(oriented,)X
-3916(and)X
-776 4632(some)N
-980(are)X
-1114(character)X
-1445(oriented;)X
-1765(the)X
-1898(description)X
-2289(for)X
-2418(each)X
-2601(applicable)X
-3 f
-2966(vi)X
-1 f
-3063(command)X
-3414(notes)X
-3618(whether)X
-3912(text)X
-776 4722(copied)N
-1020(into)X
-1174(buffers)X
-1432(using)X
-1635(the)X
-1762(command)X
-2107(is)X
-2189(line)X
-2338(or)X
-2434(character)X
-2759(oriented.)X
-3091(In)X
-3187(addition,)X
-3498(the)X
-3 f
-3625(vi)X
-1 f
-3716(command)X
-3 f
-776 4812(display)N
-1053(buffers)X
-1 f
-1332(displays)X
-1628(the)X
-1760(current)X
-2023(orientation)X
-2405(for)X
-2534(each)X
-2717(buffer.)X
-2989(Generally,)X
-3361(the)X
-3494(only)X
-3671(importance)X
-776 4902(attached)N
-1074(to)X
-1166(this)X
-1311(orientation)X
-1688(is)X
-1771(that)X
-1921(if)X
-2000(the)X
-2128(buffer)X
-2355(is)X
-2438(subsequently)X
-2886(inserted)X
-3170(into)X
-3324(the)X
-3451(text,)X
-3620(line)X
-3769(oriented)X
-776 4992(buffers)N
-1027(create)X
-1243(new)X
-1400(lines)X
-1574(for)X
-1691(each)X
-1862(of)X
-1952(the)X
-2073(lines)X
-2247(they)X
-2408(contain,)X
-2687(and)X
-2826(character)X
-3145(oriented)X
-3431(buffers)X
-3682(create)X
-3898(new)X
-776 5082(lines)N
-951(for)X
-1069(any)X
-1209(lines)X
-2 f
-1384(other)X
-1 f
-1577(than)X
-1739(the)X
-1860(\256rst)X
-2007(and)X
-2146(last)X
-2280(lines)X
-2454(they)X
-2615(contain.)X
-2914(The)X
-3062(\256rst)X
-3209(and)X
-3348(last)X
-3482(lines)X
-3656(are)X
-3778(inserted)X
-776 5172(into)N
-927(the)X
-1052(text)X
-1199(at)X
-1284(the)X
-1409(current)X
-1664(cursor)X
-1892(position,)X
-2196(becoming)X
-2539(part)X
-2691(of)X
-2785(the)X
-2910(current)X
-3165(line.)X
-3352(If)X
-3433(there)X
-3621(is)X
-3701(more)X
-3894(than)X
-776 5262(one)N
-912(line)X
-1052(in)X
-1134(the)X
-1252(buffer,)X
-1489(however,)X
-1806(the)X
-1924(current)X
-2172(line)X
-2312(itself)X
-2492(will)X
-2636(be)X
-2732(split.)X
-3 f
-576 5442(unnamed)N
-915(buffer)X
-1 f
-776 5532(The)N
-924(unnamed)X
-1241(buffer)X
-1461(is)X
-1537(a)X
-1596(text)X
-1739(storage)X
-1994(area)X
-2152(which)X
-2371(is)X
-2447(used)X
-2617(by)X
-2720(commands)X
-3090(that)X
-3233(take)X
-3390(a)X
-3450(buffer)X
-3671(as)X
-3762(an)X
-3862(argu-)X
-776 5622(ment,)N
-976(when)X
-1170(no)X
-1270(buffer)X
-1487(is)X
-1560(speci\256ed)X
-1865(by)X
-1965(the)X
-2083(user.)X
-2277(There)X
-2485(is)X
-2558(no)X
-2658(way)X
-2812(to)X
-2894(explicitly)X
-3216 0.4531(reference)AX
-3537(this)X
-3672(buffer.)X
-
-9 p
-%%Page: 9 8
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Vi)X
-1364(Commands\))X
-3698(USD:13-9)X
-576 762(9.)N
-676(Vi)X
-776(Description)X
-1 f
-3 f
-776 885(Vi)N
-1 f
-879(takes)X
-1067(up)X
-1170(the)X
-1291(entire)X
-1497(screen)X
-1727(to)X
-1813(display)X
-2068(the)X
-2190(edited)X
-2410(\256le,)X
-2556(except)X
-2790(for)X
-2908(the)X
-3030(bottom)X
-3280(line)X
-3424(of)X
-3515(the)X
-3637(screen.)X
-3907(The)X
-576 975(bottom)N
-824(line)X
-966(of)X
-1055(the)X
-1175(screen)X
-1403(is)X
-1478(used)X
-1647(to)X
-1731(enter)X
-3 f
-1914(ex)X
-1 f
-2012(commands,)X
-2401(and)X
-2539(for)X
-3 f
-2655(vi)X
-1 f
-2739(error)X
-2918(and)X
-3056(informational)X
-3513(messages.)X
-3877(If)X
-3952(no)X
-576 1065(other)N
-777(information)X
-1191(is)X
-1281(being)X
-1496(displayed,)X
-1860(the)X
-1995(default)X
-2255(display)X
-2523(can)X
-2672(show)X
-2878(the)X
-3013(current)X
-3278(cursor)X
-3516(row)X
-3678(and)X
-3831(cursor)X
-576 1155(column,)N
-863(an)X
-966(indication)X
-1313(of)X
-1407(whether)X
-1693(the)X
-1818(\256le)X
-1947(has)X
-2081(been)X
-2260(modi\256ed,)X
-2591(and)X
-2734(the)X
-2859(current)X
-3114(mode)X
-3319(of)X
-3413(the)X
-3538(editor.)X
-3792(See)X
-3934(the)X
-3 f
-576 1245(ruler)N
-1 f
-750(,)X
-3 f
-790(showdirty)X
-1 f
-1152(and)X
-3 f
-1288(showmode)X
-1 f
-1668(options)X
-1923(for)X
-2037(more)X
-2222(information.)X
-776 1368(Empty)N
-1012(lines)X
-1186(do)X
-1289(not)X
-1414(have)X
-1589(any)X
-1729(special)X
-1976(representation)X
-2455(on)X
-2559(the)X
-2681(screen,)X
-2931(but)X
-3057(lines)X
-3232(on)X
-3336(the)X
-3458(screen)X
-3688(that)X
-3832(would)X
-576 1458(logically)N
-886(come)X
-1090(after)X
-1268(the)X
-1396(end)X
-1542(of)X
-1639(the)X
-1767(\256le)X
-1899(are)X
-2028(displayed)X
-2365(as)X
-2461(a)X
-2526(single)X
-2746(tilde)X
-2917(\(``)X
-7 f
-2998(\304)X
-1 f
-(''\))S
-3156(character.)X
-3521(To)X
-3639(differentiate)X
-576 1548(between)N
-871(empty)X
-1098(lines)X
-1276(and)X
-1419(lines)X
-1597(consisting)X
-1948(of)X
-2042(only)X
-2211(whitespace)X
-2596(characters,)X
-2971(use)X
-3106(the)X
-3 f
-3232(list)X
-1 f
-3362(option.)X
-3634(Historically,)X
-576 1638(implementations)N
-1130(of)X
-3 f
-1218(vi)X
-1 f
-1301(have)X
-1474(also)X
-1624(displayed)X
-1952(some)X
-2141(lines)X
-2312(as)X
-2399(single)X
-2610(asterisk)X
-2875(\(``)X
-7 f
-2956(@)X
-1 f
-(''\))S
-3105(characters.)X
-3492(These)X
-3704(were)X
-3881(lines)X
-576 1728(that)N
-717(were)X
-895(not)X
-1018(correctly)X
-1326(displayed,)X
-1675(i.e.)X
-1795(lines)X
-1968(on)X
-2070(the)X
-2190(screen)X
-2418(that)X
-2560(did)X
-2684(not)X
-2808(correspond)X
-3187(to)X
-3271(lines)X
-3444(in)X
-3528(the)X
-3648(\256le,)X
-3792(or)X
-3881(lines)X
-576 1818(that)N
-716(did)X
-838(not)X
-960(\256t)X
-1046(on)X
-1146(the)X
-1264(current)X
-1512(screen.)X
-3 f
-1778(Nvi)X
-1 f
-1918(never)X
-2117(displays)X
-2399(lines)X
-2570(in)X
-2652(this)X
-2787(fashion.)X
-3 f
-776 1941(Vi)N
-1 f
-881(is)X
-959(a)X
-1020(modeful)X
-1312(editor,)X
-1544(i.e.)X
-1667(it)X
-1736(has)X
-1868(two)X
-2013(modes,)X
-2268(``command'')X
-2718(mode)X
-2922(and)X
-3064(``text)X
-3264(input'')X
-3508(mode.)X
-3752(When)X
-3 f
-3970(vi)X
-1 f
-576 2031(\256rst)N
-724(starts,)X
-937(it)X
-1005(is)X
-1082(in)X
-1168(command)X
-1508(mode.)X
-1750(There)X
-1962(are)X
-2085(several)X
-2337(commands)X
-2708(that)X
-2852(change)X
-3 f
-3104(vi)X
-1 f
-3189(into)X
-3336(text)X
-3479(input)X
-3666(mode.)X
-3907(The)X
-7 f
-576 2121(<escape>)N
-1 f
-980(character)X
-1296(is)X
-1369(used)X
-1536(to)X
-1618(resolve)X
-1870(the)X
-1988(text)X
-2128(input)X
-2312(into)X
-2456(the)X
-2574(\256le,)X
-2716(and)X
-2852(exit)X
-2992(back)X
-3164(into)X
-3308(command)X
-3644(mode.)X
-3882(In)X
-3 f
-3970(vi)X
-1 f
-576 2211(command)N
-916(mode,)X
-1138(the)X
-1260(cursor)X
-1485(is)X
-1562(always)X
-1809(positioned)X
-2166(on)X
-2269(the)X
-2390(last)X
-2524(column)X
-2787(of)X
-2877(characters)X
-3227(which)X
-3446(take)X
-3603(up)X
-3706(more)X
-3894(than)X
-576 2301(one)N
-714(column)X
-976(on)X
-1078(the)X
-1198(screen.)X
-1466(In)X
-3 f
-1555(vi)X
-1 f
-1639(text)X
-1782(insert)X
-1983(mode,)X
-2204(the)X
-2325(cursor)X
-2549(is)X
-2625(positioned)X
-2981(on)X
-3084(the)X
-3205(\256rst)X
-3352(column)X
-3615(of)X
-3705(characters)X
-576 2391(which)N
-792(take)X
-946(up)X
-1046(more)X
-1231(than)X
-1389(one)X
-1525(column)X
-1785(on)X
-1885(the)X
-2003(screen.)X
-776 2514(Generally,)N
-1138(if)X
-1212(the)X
-1335(cursor)X
-1561(line)X
-1707(and)X
-1849(cursor)X
-2076(column)X
-2342(are)X
-2467(not)X
-2595(on)X
-2701(the)X
-2825(screen,)X
-3077(then)X
-3241(the)X
-3365(screen)X
-3597(is)X
-3676(scrolled)X
-3956(\(if)X
-576 2604(the)N
-695(target)X
-899(cursor)X
-1121(is)X
-1195(close\))X
-1407(or)X
-1494(repainted)X
-1813(\(if)X
-1909(the)X
-2027(target)X
-2230(cursor)X
-2451(is)X
-2524(far)X
-2634(away\))X
-2851(so)X
-2942(that)X
-3082(the)X
-3200(cursor)X
-3421(is)X
-3494(on)X
-3594(the)X
-3712(screen.)X
-3978(If)X
-576 2694(the)N
-699(screen)X
-930(is)X
-1009(scrolled,)X
-1309(it)X
-1379(is)X
-1458(moved)X
-1702(a)X
-1764(minimal)X
-2056(amount,)X
-2342(and)X
-2484(the)X
-2608(cursor)X
-2835(line)X
-2981(will)X
-3131(usually)X
-3388(appear)X
-3629(at)X
-3713(the)X
-3837(top)X
-3965(or)X
-576 2784(bottom)N
-832(of)X
-929(the)X
-1057(screen.)X
-1333(In)X
-1430(the)X
-1558(screen)X
-1794(is)X
-1877(repainted,)X
-2226(the)X
-2354(cursor)X
-2585(line)X
-2735(will)X
-2889(appear)X
-3134(in)X
-3226(the)X
-3354(center)X
-3581(of)X
-3678(the)X
-3806(screen,)X
-576 2874(unless)N
-799(the)X
-920(cursor)X
-1144(is)X
-1220(suf\256ciently)X
-1603(close)X
-1791(to)X
-1876(the)X
-1997(beginning)X
-2340(or)X
-2430(end)X
-2569(of)X
-2660(the)X
-2782(\256le)X
-2908(that)X
-3052(this)X
-3191(is)X
-3268(not)X
-3394(possible.)X
-3720(If)X
-3798(the)X
-3 f
-3920(lef-)X
-576 2964(tright)N
-1 f
-794(option)X
-1020(is)X
-1095(set,)X
-1226(the)X
-1346(screen)X
-1574(may)X
-1734(be)X
-1832(scrolled)X
-2108(or)X
-2197(repainted)X
-2518(in)X
-2602(a)X
-2660(horizontal)X
-3007(direction)X
-3314(as)X
-3403(well)X
-3563(as)X
-3651(in)X
-3734(a)X
-3791(vertical)X
-576 3054(one.)N
-776 3177(A)N
-869(major)X
-1091(difference)X
-1453(between)X
-1756(the)X
-1889(historical)X
-3 f
-2222(vi)X
-1 f
-2319(presentation)X
-2746(and)X
-3 f
-2897(nvi)X
-1 f
-3038(is)X
-3126(in)X
-3224(the)X
-3358(scrolling)X
-3674(and)X
-3826(screen)X
-576 3267(oriented)N
-893(position)X
-1204(commands,)X
-3 f
-1625(<control-B>)X
-1 f
-2042(,)X
-3 f
-2116(<control-D>)X
-1 f
-2538(,)X
-3 f
-2612(<control-E>)X
-1 f
-3029(,)X
-3 f
-3103(<control-F>)X
-1 f
-3516(,)X
-3 f
-3590(<control-U>)X
-1 f
-4012(,)X
-3 f
-576 3357(<control-Y>)N
-1 f
-998(,)X
-3 f
-1049(H)X
-1 f
-1111(,)X
-3 f
-1162(L)X
-1 f
-1246(and)X
-3 f
-1394(M)X
-1 f
-1470(.)X
-1542(In)X
-1641(historical)X
-1971(implementations)X
-2536(of)X
-3 f
-2635(vi)X
-1 f
-2697(,)X
-2749(these)X
-2946(commands)X
-3325(acted)X
-3527(on)X
-3639(physical)X
-3938(\(as)X
-576 3447(opposed)N
-877(to)X
-973(logical,)X
-1245(or)X
-1346(screen\))X
-1613(lines.)X
-1838(For)X
-1982(lines)X
-2166(that)X
-2319(were)X
-2509(suf\256ciently)X
-2902(long)X
-3077(in)X
-3172(relation)X
-3450(to)X
-3545(the)X
-3676(size)X
-3834(of)X
-3934(the)X
-576 3537(screen,)N
-822(this)X
-957(meant)X
-1174(that)X
-1315(single)X
-1527(line)X
-1668(scroll)X
-1867(commands)X
-2235(might)X
-2442(repaint)X
-2686(the)X
-2805(entire)X
-3009(screen,)X
-3256(scrolling)X
-3557(or)X
-3645(screen)X
-3872(posi-)X
-576 3627(tioning)N
-823(command)X
-1160(might)X
-1367(not)X
-1489(change)X
-1737(the)X
-1855(screen)X
-2081(or)X
-2168(move)X
-2366(the)X
-2484(cursor)X
-2705(at)X
-2783(all,)X
-2903(and)X
-3039(some)X
-3228(lines)X
-3399(simply)X
-3636(could)X
-3834(not)X
-3956(be)X
-576 3717(displayed,)N
-927(even)X
-1104(though)X
-3 f
-1351(vi)X
-1 f
-1438(would)X
-1663(edit)X
-1808(the)X
-1931(\256le)X
-2058(that)X
-2203(contained)X
-2540(them.)X
-2765(In)X
-3 f
-2857(nvi)X
-1 f
-2963(,)X
-3008(these)X
-3198(commands)X
-3570(act)X
-3689(on)X
-3794(logical,)X
-576 3807(i.e.)N
-718(screen)X
-968(lines.)X
-1203(You)X
-1385(are)X
-1528(unlikely)X
-1834(to)X
-1939(notice)X
-2178(any)X
-2337(difference)X
-2707(unless)X
-2950(you)X
-3113(are)X
-3255(editing)X
-3520(\256les)X
-3696(with)X
-3881(lines)X
-576 3897(signi\256cantly)N
-991(longer)X
-1216(than)X
-1374(a)X
-1430(screen)X
-1656(width.)X
-3 f
-776 4020(Vi)N
-1 f
-883(keeps)X
-1094(track)X
-1283(of)X
-1378(the)X
-1504(currently)X
-1822(``most)X
-2059(attractive'')X
-2440(cursor)X
-2669(position.)X
-2994(Each)X
-3183(command)X
-3527(description)X
-3911(\(for)X
-576 4110(commands)N
-945(that)X
-1087(can)X
-1221(change)X
-1471(the)X
-1591(current)X
-1841(cursor)X
-2064(position\),)X
-2390(speci\256es)X
-2688(if)X
-2759(the)X
-2879(cursor)X
-3101(is)X
-3175(set)X
-3285(to)X
-3368(a)X
-3425(speci\256c)X
-3691(location)X
-3970(in)X
-576 4200(the)N
-705(line,)X
-876(or)X
-974(if)X
-1054(it)X
-1129(is)X
-1213(moved)X
-1462(to)X
-1555(the)X
-1685(``most)X
-1926(attractive)X
-2257(cursor)X
-2490(position''.)X
-2873(The)X
-3030(latter)X
-3227(means)X
-3464(that)X
-3616(the)X
-3746(cursor)X
-3979(is)X
-576 4290(moved)N
-825(to)X
-918(the)X
-1047(cursor)X
-1279(position)X
-1567(that)X
-1717(is)X
-1800(vertically)X
-2133(as)X
-2230(close)X
-2425(as)X
-2522(possible)X
-2814(to)X
-2906(the)X
-3034(current)X
-3292(cursor)X
-3523(position.)X
-3850(If)X
-3934(the)X
-576 4380(current)N
-826(line)X
-968(is)X
-1043(shorter)X
-1288(than)X
-1448(the)X
-1568(cursor)X
-1791(position)X
-3 f
-2070(vi)X
-1 f
-2154(would)X
-2376(select,)X
-2601(the)X
-2722(cursor)X
-2946(is)X
-3022(positioned)X
-3378(on)X
-3481(the)X
-3602(last)X
-3736(character)X
-576 4470(in)N
-666(the)X
-792(line.)X
-980(\(If)X
-1089(the)X
-1215(line)X
-1363(is)X
-1444(empty,)X
-1692(the)X
-1818(cursor)X
-2047(is)X
-2128(positioned)X
-2489(on)X
-2596(the)X
-2721(\256rst)X
-2872(column)X
-3139(of)X
-3233(the)X
-3358(line.\))X
-3572(If)X
-3653(a)X
-3716(command)X
-576 4560(moves)N
-810(the)X
-933(cursor)X
-1159(to)X
-1246(the)X
-1369(most)X
-1549(attractive)X
-1873(position,)X
-2175(it)X
-2245(does)X
-2418(not)X
-2546(alter)X
-2715(the)X
-2839(current)X
-3093(cursor)X
-3320(position,)X
-3623(and)X
-3765(a)X
-3827(subse-)X
-576 4650(quent)N
-775(movement)X
-1134(will)X
-1279(again)X
-1474(attempt)X
-1735(to)X
-1818(move)X
-2017(the)X
-2136(cursor)X
-2358(to)X
-2441(that)X
-2581(position.)X
-2898(Therefore,)X
-3256(although)X
-3556(a)X
-3612(movement)X
-3970(to)X
-576 4740(a)N
-640(line)X
-788(shorter)X
-1039(than)X
-1205(the)X
-1331(currently)X
-1649(most)X
-1832(attractive)X
-2159(position)X
-2444(will)X
-2596(cause)X
-2803(the)X
-2929(cursor)X
-3158(to)X
-3248(move)X
-3454(to)X
-3544(the)X
-3671(end)X
-3816(of)X
-3912(that)X
-576 4830(line,)N
-737(a)X
-794(subsequent)X
-1171(movement)X
-1530(to)X
-1613(a)X
-1670(longer)X
-1896(line)X
-2037(will)X
-2182(cause)X
-2382(the)X
-2501(cursor)X
-2723(to)X
-2806(move)X
-3005(back)X
-3178(to)X
-3260(the)X
-3378(most)X
-3553(attractive)X
-3872(posi-)X
-576 4920(tion.)N
-776 5043(In)N
-864(addition,)X
-1167(the)X
-3 f
-1286($)X
-1 f
-1347(command)X
-1684(makes)X
-1910(the)X
-2029(end)X
-2166(of)X
-2254(each)X
-2423(line)X
-2564(the)X
-2684(most)X
-2861(attractive)X
-3182(cursor)X
-3405(position)X
-3684(rather)X
-3894(than)X
-576 5133(a)N
-632(speci\256c)X
-897(column.)X
-776 5256(Each)N
-3 f
-958(vi)X
-1 f
-1042(command)X
-1380(described)X
-1710(below)X
-1928(notes)X
-2119(where)X
-2338(the)X
-2458(cursor)X
-2681(ends)X
-2850(up)X
-2952(after)X
-3122(it)X
-3188(is)X
-3263(executed.)X
-3611(This)X
-3775(position)X
-576 5346(is)N
-653(described)X
-985(in)X
-1071(terms)X
-1273(of)X
-1364(characters)X
-1715(on)X
-1819(the)X
-1940(line,)X
-2103(i.e.)X
-2244(``the)X
-2419(previous)X
-2718 0.3409(character'',)AX
-3111(or,)X
-3221(``the)X
-3396(last)X
-3530(character)X
-3849(in)X
-3934(the)X
-576 5436(line''.)N
-810(This)X
-972(is)X
-1045(to)X
-1127(avoid)X
-1325(needing)X
-1599(to)X
-1681(continually)X
-2061(refer)X
-2234(to)X
-2316(on)X
-2416(what)X
-2592(part)X
-2737(of)X
-2824(the)X
-2942(character)X
-3258(the)X
-3376(cursor)X
-3597(rests.)X
-776 5559(The)N
-921(following)X
-1252(words)X
-1468(have)X
-1640(special)X
-1883(meaning)X
-2179(for)X
-3 f
-2293(vi)X
-1 f
-2375(commands.)X
-
-10 p
-%%Page: 10 9
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-10)N
-2826(Nvi/Nex)X
-3122 0.3906(Reference)AX
-3487(\(Vi)X
-3614(Commands\))X
-576 762(previous)N
-889(context)X
-1 f
-776 852(The)N
-927(position)X
-1210(of)X
-1303(the)X
-1427(cursor)X
-1654(before)X
-1886(the)X
-2010(command)X
-2352(which)X
-2574(caused)X
-2819(the)X
-2944(last)X
-3082(absolute)X
-3376(movement)X
-3741(was)X
-3893(exe-)X
-776 942(cuted.)N
-1012(Each)X
-3 f
-1195(vi)X
-1 f
-1279(command)X
-1617(described)X
-1947(in)X
-2031(the)X
-2151(next)X
-2311(section)X
-2559(that)X
-2700(is)X
-2774(considered)X
-3143(an)X
-3240(absolute)X
-3528(movement)X
-3887(is)X
-3961(so)X
-776 1032(noted.)N
-1014(In)X
-1101(addition,)X
-1403(specifying)X
-2 f
-1757(any)X
-1 f
-1893(address)X
-2154(to)X
-2236(an)X
-3 f
-2332(ex)X
-1 f
-2428(command)X
-2764(is)X
-2837(considered)X
-3205(an)X
-3301(absolute)X
-3588(movement.)X
-3 f
-576 1212(motion)N
-1 f
-776 1302(A)N
-863(second)X
-3 f
-1115(vi)X
-1 f
-1206(command)X
-1551(can)X
-1693(be)X
-1799(used)X
-1976(as)X
-2073(an)X
-2179(optional)X
-2471(trailing)X
-2732(argument)X
-3065(to)X
-3157(the)X
-3 f
-3285(vi)X
-3377(!)X
-1 f
-3404(,)X
-3 f
-3454(<)X
-1 f
-3500(,)X
-3 f
-3550(>)X
-1 f
-3596(,)X
-3 f
-3646(c)X
-1 f
-3682(,)X
-3 f
-3732(d)X
-1 f
-3776(,)X
-3 f
-3826(y)X
-1 f
-(,)S
-3916(and)X
-776 1392(\(depending)N
-1158(on)X
-1259(the)X
-3 f
-1378(tildeop)X
-1 f
-1633(option\))X
-3 f
-1884(\304)X
-1 f
-1931(commands.)X
-2338(This)X
-2500(command)X
-2836(indicates)X
-3141(the)X
-3259(end)X
-3395(of)X
-3482(the)X
-3600(region)X
-3825(of)X
-3912(text)X
-776 1482(that's)N
-993(affected)X
-1292(by)X
-1411(the)X
-1548(command.)X
-1943(The)X
-2107(motion)X
-2372(command)X
-2727(may)X
-2904(be)X
-3019(either)X
-3242(the)X
-3380(command)X
-3736(character)X
-776 1572(repeated)N
-1070(\(in)X
-1180(which)X
-1397(case)X
-1557(it)X
-1622(means)X
-1848(the)X
-1967(current)X
-2216(line\))X
-2384(or)X
-2472(a)X
-2528(cursor)X
-2749(movement)X
-3107(command.)X
-3483(In)X
-3570(the)X
-3688(latter)X
-3873(case,)X
-776 1662(the)N
-894(region)X
-1119(affected)X
-1399(by)X
-1499(the)X
-1617(command)X
-1953(is)X
-2026(from)X
-2202(the)X
-2320(starting)X
-2581(or)X
-2669(stopping)X
-2965(cursor)X
-3187(position)X
-3465(which)X
-3682(comes)X
-3908(\256rst)X
-776 1752(in)N
-859(the)X
-978(\256le,)X
-1120(to)X
-1202(immediately)X
-1622(before)X
-1848(the)X
-1966(starting)X
-2226(or)X
-2313(stopping)X
-2608(cursor)X
-2829(position)X
-3106(which)X
-3322(comes)X
-3547(later)X
-3710(in)X
-3792(the)X
-3910(\256le.)X
-776 1842(Commands)N
-1166(that)X
-1313(operate)X
-1577(on)X
-1684(lines)X
-1862(instead)X
-2116(of)X
-2210(using)X
-2410(beginning)X
-2757(and)X
-2900(ending)X
-3145(cursor)X
-3373(positions)X
-3688(operate)X
-3952(on)X
-776 1932(all)N
-880(of)X
-971(the)X
-1093(lines)X
-1268(that)X
-1412(are)X
-1535(wholly)X
-1781(or)X
-1872(partially)X
-2163(in)X
-2248(the)X
-2369(region.)X
-2637(In)X
-2727(addition,)X
-3032(some)X
-3224(other)X
-3412(commands)X
-3782(become)X
-776 2022(line)N
-922(oriented)X
-1211(depending)X
-1571(on)X
-1677(where)X
-1900(in)X
-1988(the)X
-2112(text)X
-2258(they)X
-2422(are)X
-2548(used.)X
-2762(The)X
-2914(command)X
-3257(descriptions)X
-3671(below)X
-3894(note)X
-776 2112(these)N
-961(special)X
-1204(cases.)X
-776 2292(The)N
-921(following)X
-1252(commands)X
-1619(may)X
-1777(all)X
-1877(be)X
-1973(used)X
-2140(as)X
-2227(motion)X
-2473(components)X
-2880(for)X
-3 f
-2994(vi)X
-1 f
-3076(commands:)X
-7 f
-776 2505(<control-A>)N
-1472(<control-H>)X
-2120(<control-J>)X
-2768(<control-M>)X
-776 2595(<control-N>)N
-1472(<control-P>)X
-2312(<space>)X
-3248($)X
-1256 2685(%)N
-1424('<character>)X
-2600(\()X
-3248(\))X
-1256 2775(+)N
-1952(,)X
-2600(-)X
-3248(/)X
-1256 2865(0)N
-1952(;)X
-2600(?)X
-3248(B)X
-1256 2955(E)N
-1952(F)X
-2600(G)X
-3248(H)X
-1256 3045(L)N
-1952(M)X
-2600(N)X
-3248(T)X
-1256 3135(W)N
-1904([[)X
-2552(]])X
-3248(\303)X
-1256 3225(_)N
-1424(`<character>)X
-2600(b)X
-3248(e)X
-1256 3315(f)N
-1952(h)X
-2600(j)X
-3248(k)X
-1256 3405(l)N
-1952(n)X
-2600(t)X
-3248(w)X
-1256 3495({)N
-1952(|)X
-2600(})X
-1 f
-776 3708(The)N
-923(optional)X
-1207(count)X
-1407(pre\256x)X
-1617(available)X
-1930(for)X
-2047(some)X
-2239(of)X
-2329(the)X
-3 f
-2450(vi)X
-1 f
-2535(commands)X
-2905(that)X
-3048(take)X
-3205(motion)X
-3454(commands,)X
-3844(or)X
-3934(the)X
-776 3798(count)N
-975(pre\256x)X
-1183(available)X
-1494(for)X
-1609(the)X
-3 f
-1728(vi)X
-1 f
-1811(commands)X
-2179(that)X
-2320(are)X
-2439(used)X
-2606(as)X
-2693(motion)X
-2939(components,)X
-3366(may)X
-3524(be)X
-3620(included)X
-3916(and)X
-776 3888(is)N
-2 f
-850(always)X
-1 f
-1093(considered)X
-1463(part)X
-1610(of)X
-1699(the)X
-1819(motion)X
-2067(argument.)X
-2432(For)X
-2565(example,)X
-2879(the)X
-2999(commands)X
-3368(``)X
-7 f
-3422(c2w)X
-1 f
-('')S
-3642(and)X
-3780(``)X
-7 f
-3834(2cw)X
-1 f
-('')S
-776 3978(are)N
-903(equivalent,)X
-1285(and)X
-1429(the)X
-1555(region)X
-1788(affected)X
-2076(by)X
-2184(the)X
-3 f
-2310(c)X
-1 f
-2374(command)X
-2718(is)X
-2799(two)X
-2947(words)X
-3171(of)X
-3266(text.)X
-3454(In)X
-3549(addition,)X
-3858(if)X
-3934(the)X
-776 4068(optional)N
-1066(count)X
-1272(pre\256x)X
-1487(is)X
-1568(speci\256ed)X
-1881(for)X
-2003(both)X
-2173(the)X
-3 f
-2299(vi)X
-1 f
-2389(command)X
-2733(and)X
-2877(its)X
-2980(motion)X
-3234(component,)X
-3639(the)X
-3766(effect)X
-3979(is)X
-776 4158(multiplicative)N
-1246(and)X
-1388(is)X
-1467(considered)X
-1841(part)X
-1992(of)X
-2085(the)X
-2209(motion)X
-2461(argument.)X
-2830(For)X
-2967(example,)X
-3285(the)X
-3408(commands)X
-3780(``)X
-7 f
-3834(4cw)X
-1 f
-('')S
-776 4248(and)N
-912(``)X
-7 f
-966(2c2w)X
-1 f
-('')S
-1232(are)X
-1351(equivalent,)X
-1725(and)X
-1861(the)X
-1979(region)X
-2204(affected)X
-2484(by)X
-2584(the)X
-3 f
-2702(c)X
-1 f
-2758(command)X
-3094(is)X
-3167(four)X
-3321(words)X
-3537(of)X
-3624(text.)X
-3 f
-576 4428(count)N
-1 f
-776 4518(A)N
-859(positive)X
-1137(number)X
-1407(used)X
-1579(as)X
-1671(an)X
-1772(optional)X
-2059(argument)X
-2387(to)X
-2474(most)X
-2654(commands,)X
-3046(either)X
-3254(to)X
-3341(give)X
-3504(a)X
-3566(size)X
-3717(or)X
-3810(a)X
-3872(posi-)X
-776 4608(tion)N
-930(\(for)X
-1081(display)X
-1342(or)X
-1439(movement)X
-1807(commands\),)X
-2231(or)X
-2328(as)X
-2425(a)X
-2491(repeat)X
-2718(count)X
-2926(\(for)X
-3077(commands)X
-3454(that)X
-3604(modify)X
-3865(text\).)X
-776 4698(The)N
-932(count)X
-1141(argument)X
-1475(is)X
-1559(always)X
-1813(optional)X
-2106(and)X
-2254(defaults)X
-2540(to)X
-2634(1)X
-2706(unless)X
-2938(otherwise)X
-3282(noted)X
-3492(in)X
-3586(the)X
-3716(command)X
-776 4788(description.)N
-776 4968(When)N
-995(a)X
-3 f
-1059(vi)X
-1 f
-1149(command)X
-1493(synopsis)X
-1796(shows)X
-2024(both)X
-2194(a)X
-7 f
-2258([buffer])X
-1 f
-2670(and)X
-7 f
-2814([count])X
-1 f
-(,)S
-3198(they)X
-3364(may)X
-3530(be)X
-3634(presented)X
-3970(in)X
-776 5058(any)N
-912(order.)X
-3 f
-576 5238(bigword)N
-1 f
-776 5328(A)N
-854(set)X
-963(of)X
-1050(non-whitespace)X
-1575(characters)X
-1923(preceded)X
-2235(and)X
-2372(followed)X
-2678(by)X
-2779(whitespace)X
-3157(characters)X
-3505(or)X
-3593(the)X
-3712(beginning)X
-776 5418(or)N
-863(end)X
-999(of)X
-1086(the)X
-1204(\256le)X
-1326(or)X
-1413(line.)X
-776 5598(Groups)N
-1040(of)X
-1135(empty)X
-1363(lines)X
-1542(\(or)X
-1664(lines)X
-1843(containing)X
-2209(only)X
-2379(whitespace)X
-2764 0.3250(characters\))AX
-3146(are)X
-3274(treated)X
-3522(as)X
-3618(a)X
-3683(single)X
-3903(big-)X
-776 5688(word.)N
-
-11 p
-%%Page: 11 10
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Vi)X
-1364(Commands\))X
-3658(USD:13-11)X
-576 762(word)N
-1 f
-776 852(Generally,)N
-1133(in)X
-1215(languages)X
-1556(where)X
-1773(it)X
-1837(is)X
-1910(applicable,)X
-3 f
-2280(vi)X
-1 f
-2362(recognizes)X
-2726(two)X
-2866(kinds)X
-3060(of)X
-3148(words.)X
-3405(First,)X
-3592(a)X
-3649(sequence)X
-3965(of)X
-776 942(letters,)N
-1027(digits)X
-1239(and)X
-1390(underscores,)X
-1829(delimited)X
-2166(at)X
-2259(both)X
-2435(ends)X
-2616(by:)X
-2752(characters)X
-3113(other)X
-3312(than)X
-3484(letters,)X
-3734(digits,)X
-3965(or)X
-776 1032(underscores;)N
-1206(the)X
-1328(beginning)X
-1672(or)X
-1763(end)X
-1903(of)X
-1994(a)X
-2054(line;)X
-2220(the)X
-2343(beginning)X
-2688(or)X
-2780(end)X
-2921(of)X
-3013(the)X
-3136(\256le.)X
-3303(Second,)X
-3584(a)X
-3645(sequence)X
-3965(of)X
-776 1122(characters)N
-1126(other)X
-1313(than)X
-1473(letters,)X
-1711(digits,)X
-1930(underscores,)X
-2356(or)X
-2445(whitespace)X
-2824(characters,)X
-3193(delimited)X
-3517(at)X
-3597(both)X
-3761(ends)X
-3930(by:)X
-776 1212(a)N
-838(letter,)X
-1049(digit,)X
-1241(underscore,)X
-1640(or)X
-1733(whitespace)X
-2116(character;)X
-2460(the)X
-2584(beginning)X
-2930(or)X
-3024(end)X
-3167(of)X
-3261(a)X
-3324(line;)X
-3493(the)X
-3618(beginning)X
-3965(or)X
-776 1302(end)N
-912(of)X
-999(the)X
-1117(\256le.)X
-776 1482(Groups)N
-1032(of)X
-1119(empty)X
-1339(lines)X
-1510(\(or)X
-1624(lines)X
-1795(containing)X
-2153(only)X
-2315(whitespace)X
-2692 0.3250(characters\))AX
-3066(are)X
-3185(treated)X
-3424(as)X
-3511(a)X
-3567(single)X
-3778(word.)X
-3 f
-576 1662(paragraph)N
-1 f
-776 1752(An)N
-898(area)X
-1057(of)X
-1148(text)X
-1292(that)X
-1436(begins)X
-1670(with)X
-1837(either)X
-2045(the)X
-2168(beginning)X
-2513(of)X
-2605(a)X
-2666(\256le,)X
-2813(an)X
-2914(empty)X
-3139(line,)X
-3304(or)X
-3396(a)X
-3457(section)X
-3709(boundary,)X
-776 1842(and)N
-912(continues)X
-1239(until)X
-1405(either)X
-1608(an)X
-1704(empty)X
-1924(line,)X
-2084(section)X
-2331(boundary,)X
-2674(or)X
-2761(the)X
-2879(end)X
-3015(of)X
-3102(the)X
-3220(\256le.)X
-776 2022(Groups)N
-1037(of)X
-1129(empty)X
-1355(lines)X
-1532(\(or)X
-1652(lines)X
-1829(containing)X
-2193(only)X
-2361(whitespace)X
-2744 0.3250(characters\))AX
-3124(are)X
-3249(treated)X
-3494(as)X
-3587(a)X
-3649(single)X
-3866(para-)X
-776 2112(graph.)N
-776 2292(Additional)N
-1138(paragraph)X
-1480(boundaries)X
-1852(can)X
-1984(be)X
-2080(de\256ned)X
-2336(using)X
-2529(the)X
-3 f
-2647(paragraph)X
-1 f
-3031(option.)X
-3 f
-576 2472(section)N
-1 f
-776 2562(An)N
-903(area)X
-1067(of)X
-1163(text)X
-1312(that)X
-1461(starts)X
-1659(with)X
-1830(the)X
-1957(beginning)X
-2306(of)X
-2402(the)X
-2529(\256le)X
-2660(or)X
-2756(a)X
-2822(line)X
-2972(whose)X
-3207(\256rst)X
-3361(character)X
-3687(is)X
-3770(an)X
-3876(open)X
-776 2652(brace)N
-971(\(``)X
-7 f
-1052({)X
-1 f
-(''\))S
-1201(and)X
-1337(continues)X
-1664(until)X
-1830(the)X
-1948(next)X
-2106(section)X
-2353(or)X
-2440(the)X
-2558(end)X
-2694(of)X
-2781(the)X
-2899(\256le.)X
-776 2832(Additional)N
-1138(section)X
-1385(boundaries)X
-1757(can)X
-1889(be)X
-1985(de\256ned)X
-2241(using)X
-2434(the)X
-3 f
-2552(sections)X
-1 f
-2839(option.)X
-3 f
-576 3012(sentence)N
-1 f
-776 3102(An)N
-895(area)X
-1051(of)X
-1139(text)X
-1280(that)X
-1421(begins)X
-1651(with)X
-1814(either)X
-2018(the)X
-2137(beginning)X
-2478(of)X
-2566(the)X
-2685(\256le)X
-2808(or)X
-2896(the)X
-3015(\256rst)X
-3160(nonblank)X
-3479(character)X
-3796(follow-)X
-776 3192(ing)N
-901(the)X
-1022(previous)X
-1321(sentence,)X
-1641(paragraph,)X
-2006(or)X
-2096(section)X
-2346(boundary)X
-2672(and)X
-2811(continues)X
-3141(until)X
-3310(the)X
-3431(end)X
-3570(of)X
-3660(the)X
-3781(\256le)X
-3906(or)X
-3996(a)X
-776 3282(or)N
-866(a)X
-926(period)X
-1155(\(``)X
-7 f
-1236(.)X
-1 f
-(''\))S
-1409(exclamation)X
-1825(point)X
-2013(\(``)X
-7 f
-2094(!)X
-1 f
-(''\))S
-2267(or)X
-2358(question)X
-2653(mark)X
-2842(\(``)X
-7 f
-2923(?)X
-1 f
-(''\))S
-3096(character,)X
-3436(followed)X
-3745(by)X
-3849(either)X
-776 3372(an)N
-882(end-of-line)X
-1269(or)X
-1366(two)X
-1516(whitespace)X
-1903(characters.)X
-2300(Any)X
-2468(number)X
-2743(of)X
-2840(closing)X
-3101(parentheses)X
-3505(\(``)X
-7 f
-3586(\))X
-1 f
-(''\),)S
-3764(brackets)X
-776 3462(\(``)N
-7 f
-857(])X
-1 f
-(''\))S
-1007(or)X
-1095(double-quote)X
-1540(\(``)X
-7 f
-1621(")X
-1 f
-(''\))S
-1772(characters)X
-2121(can)X
-2255(appear)X
-2492(between)X
-2782(the)X
-2902(period,)X
-3149(exclamation)X
-3563(point,)X
-3769(or)X
-3858(ques-)X
-776 3552(tion)N
-920(mark)X
-1105(and)X
-1241(the)X
-1359(whitespace)X
-1736(characters)X
-2083(or)X
-2170(end-of-line.)X
-776 3732(Groups)N
-1040(of)X
-1135(empty)X
-1363(lines)X
-1542(\(or)X
-1664(lines)X
-1843(containing)X
-2209(only)X
-2379(whitespace)X
-2764 0.3250(characters\))AX
-3146(are)X
-3273(treated)X
-3520(as)X
-3615(a)X
-3679(single)X
-3898(sen-)X
-776 3822(tence.)N
-3 f
-576 4008(10.)N
-716(Vi)X
-816(Commands)X
-1 f
-776 4131(The)N
-926(following)X
-1262(section)X
-1514(describes)X
-1838(the)X
-1961(commands)X
-2333(available)X
-2649(in)X
-2737(the)X
-2861(command)X
-3203(mode)X
-3407(of)X
-3500(the)X
-3 f
-3624(vi)X
-1 f
-3712(editor.)X
-3965(In)X
-576 4221(each)N
-745(entry)X
-931(below,)X
-1168(the)X
-1287(tag)X
-1406(line)X
-1547(is)X
-1621(a)X
-1678(usage)X
-1882(synopsis)X
-2178(for)X
-2293(the)X
-2412(command)X
-2749(character.)X
-3106(In)X
-3194(addition,)X
-3496(the)X
-3614(\256nal)X
-3776(line)X
-3916(and)X
-576 4311(column)N
-836(the)X
-954(cursor)X
-1175(rests)X
-1342(upon,)X
-1542(and)X
-1678(any)X
-1814(options)X
-2069(which)X
-2285(affect)X
-2489(the)X
-2607(command)X
-2943(are)X
-3062(noted.)X
-3 f
-576 4491([count])N
-841(<control-A>)X
-1 f
-776 4581(Search)N
-1034(forward)X
-7 f
-1328(count)X
-1 f
-1607(times)X
-1819(for)X
-1952(the)X
-2089(current)X
-2356(word.)X
-2600(The)X
-2764(current)X
-3031(word)X
-3236(begins)X
-3485(at)X
-3583(the)X
-3721(\256rst)X
-3885(non-)X
-776 4671(whitespace)N
-1164(character)X
-1491(on)X
-1602(or)X
-1699(after)X
-1877(the)X
-2005(current)X
-2263(cursor)X
-2494(position,)X
-2801(and)X
-2947(extends)X
-3222(up)X
-3332(to)X
-3424(the)X
-3552(next)X
-3720(non-word)X
-776 4761(character)N
-1095(or)X
-1185(the)X
-1306(end)X
-1445(of)X
-1535(the)X
-1656(line.)X
-1839(The)X
-1987(search)X
-2216(is)X
-2292(literal,)X
-2522(i.e.)X
-2643(no)X
-2746(characters)X
-3096(in)X
-3182(the)X
-3304(word)X
-3493(have)X
-3669(any)X
-3809(special)X
-776 4851(meaning)N
-1076(in)X
-1162(terms)X
-1364(of)X
-1455(Regular)X
-1733(Expressions.)X
-2184(It)X
-2257(is)X
-2334(an)X
-2434(error)X
-2615(if)X
-2687(no)X
-2790(matching)X
-3111(pattern)X
-3357(is)X
-3433(found)X
-3643(between)X
-3934(the)X
-776 4941(starting)N
-1036(position)X
-1313(and)X
-1449(the)X
-1567(end)X
-1703(of)X
-1790(the)X
-1908(\256le.)X
-776 5121(The)N
-3 f
-926(<control-A>)X
-1 f
-1373(command)X
-1714(is)X
-1792(an)X
-1893(absolute)X
-2185(movement.)X
-2588(The)X
-3 f
-2738(<control-A>)X
-1 f
-3185(command)X
-3526(may)X
-3690(be)X
-3792(used)X
-3965(as)X
-776 5211(the)N
-896(motion)X
-1144(component)X
-1522(of)X
-1611(other)X
-3 f
-1798(vi)X
-1 f
-1881(commands,)X
-2269(in)X
-2352(which)X
-2569(case)X
-2729(any)X
-2866(text)X
-3007(copied)X
-3242(into)X
-3387(a)X
-3444(buffer)X
-3662(is)X
-3736(character)X
-776 5301(oriented.)N
-776 5481(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(where)X
-1815(the)X
-1933(word)X
-2118(is)X
-2191(found.)X
-776 5571(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(character)X
-1918(of)X
-2005(the)X
-2123(word.)X
-776 5661(Options:)N
-1136(Affected)X
-1438(by)X
-1538(the)X
-3 f
-1656(extended)X
-1 f
-1963(,)X
-3 f
-2003(ignorecase)X
-1 f
-2384(and)X
-3 f
-2520(wrapscan)X
-1 f
-2869(options.)X
-
-12 p
-%%Page: 12 11
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-12)N
-2826(Nvi/Nex)X
-3122 0.3906(Reference)AX
-3487(\(Vi)X
-3614(Commands\))X
-576 762([count])N
-841(<control-B>)X
-1 f
-776 852(Page)N
-965(backward)X
-7 f
-1311(count)X
-1 f
-1585(screens.)X
-1896(Two)X
-2077(lines)X
-2262(of)X
-2363(overlap)X
-2638(are)X
-2771(maintained)X
-3161(by)X
-3275(displaying)X
-3642(the)X
-3774(window)X
-776 942(starting)N
-1042(at)X
-1126(line)X
-7 f
-1272(\(top_line)X
-1758(-)X
-1860(count)X
-2154(*)X
-2256(window_size\))X
-2886(+)X
-2988(2)X
-1 f
-(,)S
-3081(where)X
-7 f
-3303(window_size)X
-1 f
-3856(is)X
-3934(the)X
-776 1032(value)N
-973(of)X
-1063(the)X
-3 f
-1184(window)X
-1 f
-1473(option.)X
-1741(\(In)X
-1859(the)X
-1981(case)X
-2144(of)X
-2235(split)X
-2396(screens,)X
-2677(this)X
-2816(size)X
-2965(is)X
-3042(corrected)X
-3366(to)X
-3452(the)X
-3574(current)X
-3826(screen)X
-776 1122(size.\))N
-988(This)X
-1150(is)X
-1223(an)X
-1319(error)X
-1496(if)X
-1565(the)X
-1683(movement)X
-2041(is)X
-2114(past)X
-2263(the)X
-2381(beginning)X
-2721(of)X
-2808(the)X
-2926(\256le.)X
-776 1302(The)N
-3 f
-921(<control-B>)X
-1 f
-1358(command)X
-1694(is)X
-1767(an)X
-1863(absolute)X
-2150(movement.)X
-776 1482(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(line)X
-1729(of)X
-1816(text)X
-1956(displayed)X
-2283(on)X
-2383(the)X
-2501(screen.)X
-776 1572(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(of)X
-2323(the)X
-2441(line.)X
-776 1662(Options:)N
-1136(None.)X
-3 f
-576 1842([count])N
-841(<control-D>)X
-1 f
-776 1932(Scroll)N
-990(forward)X
-7 f
-1268(count)X
-1 f
-1531(lines.)X
-1745(If)X
-7 f
-1822(count)X
-1 f
-2085(is)X
-2161(not)X
-2286(speci\256ed,)X
-2614(scroll)X
-2815(forward)X
-3093(the)X
-3214(number)X
-3482(of)X
-3572(lines)X
-3747(speci\256ed)X
-776 2022(by)N
-881(the)X
-1004(last)X
-3 f
-1140(<control-D>)X
-1 f
-1587(or)X
-3 f
-1679(<control-U>)X
-1 f
-2126(command.)X
-2507(If)X
-2586(this)X
-2726(is)X
-2803(the)X
-2925(\256rst)X
-3 f
-3073(<control-D>)X
-1 f
-3519(or)X
-3 f
-3610(<control-U>)X
-1 f
-776 2112(command,)N
-1141(scroll)X
-1348(forward)X
-1632(half)X
-1786(the)X
-1913(number)X
-2188(of)X
-2285(lines)X
-2466(in)X
-2558(the)X
-2686(screen.)X
-2962(\(In)X
-3086(the)X
-3214(case)X
-3383(of)X
-3480(split)X
-3647(screens,)X
-3934(the)X
-776 2202(default)N
-1026(scrolling)X
-1333(distance)X
-1623(is)X
-1703(corrected)X
-2029(to)X
-2117(half)X
-2268(the)X
-2392(current)X
-2646(screen)X
-2878(size.\))X
-3096(This)X
-3264(is)X
-3343(an)X
-3445(error)X
-3628(if)X
-3703(the)X
-3827(move-)X
-776 2292(ment)N
-956(is)X
-1029(past)X
-1178(the)X
-1296(end)X
-1432(of)X
-1519(the)X
-1637(\256le.)X
-776 2472(The)N
-3 f
-921(<control-D>)X
-1 f
-1363(command)X
-1699(is)X
-1772(an)X
-1868(absolute)X
-2155(movement.)X
-776 2652(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(current)X
-1706(line)X
-1846(plus)X
-1999(the)X
-2117(number)X
-2382(of)X
-2469(lines)X
-2640(scrolled.)X
-776 2742(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(of)X
-2323(the)X
-2441(line.)X
-776 2832(Options:)N
-1136(None.)X
-3 f
-576 3012([count])N
-841(<control-E>)X
-1 f
-776 3102(Scroll)N
-987(forward)X
-7 f
-1262(count)X
-1 f
-1522(lines,)X
-1713(leaving)X
-1969(the)X
-2087(cursor)X
-2308(on)X
-2408(the)X
-2526(current)X
-2774(line)X
-2914(and)X
-3050(column,)X
-3330(if)X
-3399(possible.)X
-3721(This)X
-3883(is)X
-3956(an)X
-776 3192(error)N
-953(if)X
-1022(the)X
-1140(movement)X
-1498(is)X
-1571(past)X
-1720(the)X
-1838(end)X
-1974(of)X
-2061(the)X
-2179(\256le.)X
-776 3372(Line:)N
-1136(Unchanged)X
-1524(unless)X
-1747(the)X
-1868(current)X
-2119(line)X
-2262(scrolls)X
-2494(off)X
-2611(the)X
-2732(screen,)X
-2981(in)X
-3066(which)X
-3285(case)X
-3447(it)X
-3514(is)X
-3590(set)X
-3702(to)X
-3787(the)X
-3908(\256rst)X
-1136 3462(line)N
-1276(on)X
-1376(the)X
-1494(screen.)X
-776 3552(Column:)N
-1136(Unchanged)X
-1523(unless)X
-1744(the)X
-1863(current)X
-2112(line)X
-2253(scrolls)X
-2483(off)X
-2598(the)X
-2717(screen,)X
-2964(in)X
-3047(which)X
-3264(case)X
-3424(it)X
-3489(is)X
-3563(set)X
-3673(to)X
-3757(the)X
-3877(most)X
-1136 3642(attractive)N
-1455(cursor)X
-1676(position.)X
-776 3732(Options:)N
-1136(None.)X
-3 f
-576 3912([count])N
-841(<control-F>)X
-1 f
-776 4002(Page)N
-955(forward)X
-7 f
-1233(count)X
-1 f
-1496(screens.)X
-1797(Two)X
-1968(lines)X
-2143(of)X
-2234(overlap)X
-2499(are)X
-2622(maintained)X
-3002(by)X
-3106(displaying)X
-3463(the)X
-3585(window)X
-3867(start-)X
-776 4092(ing)N
-900(at)X
-980(line)X
-7 f
-1122(top_line)X
-1556(+)X
-1654(count)X
-1944(*)X
-2042(window_size)X
-2620(-)X
-2718(2)X
-1 f
-(,)S
-2808(where)X
-7 f
-3027(window_size)X
-1 f
-3577(is)X
-3651(the)X
-3770(value)X
-3965(of)X
-776 4182(the)N
-3 f
-903(window)X
-1 f
-1198(option.)X
-1471(\(In)X
-1594(the)X
-1721(case)X
-1889(of)X
-1985(split)X
-2151(screens,)X
-2437(this)X
-2581(size)X
-2735(is)X
-2817(corrected)X
-3146(to)X
-3238(the)X
-3366(current)X
-3624(screen)X
-3860(size.\))X
-776 4272(This)N
-938(is)X
-1011(an)X
-1107(error)X
-1284(if)X
-1353(the)X
-1471(movement)X
-1829(is)X
-1902(past)X
-2051(the)X
-2169(end)X
-2305(of)X
-2392(the)X
-2510(\256le.)X
-776 4452(The)N
-3 f
-921(<control-F>)X
-1 f
-1354(command)X
-1690(is)X
-1763(an)X
-1859(absolute)X
-2146(movement.)X
-776 4632(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(line)X
-1742(on)X
-1842(the)X
-1960(screen.)X
-776 4722(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(of)X
-2323(the)X
-2441(current)X
-2689(line.)X
-776 4812(Options:)N
-1136(None.)X
-3 f
-576 4992(<control-G>)N
-1 f
-776 5082(Display)N
-1055(the)X
-1183(\256le)X
-1315(information.)X
-1763(The)X
-1918(information)X
-2326(includes)X
-2624(the)X
-2753(current)X
-3012(pathname,)X
-3375(the)X
-3504(current)X
-3763(line,)X
-3934(the)X
-776 5172(number)N
-1043(of)X
-1132(total)X
-1296(lines)X
-1469(in)X
-1553(the)X
-1673(\256le,)X
-1817(the)X
-1937(current)X
-2187(line)X
-2329(as)X
-2418(a)X
-2476(percentage)X
-2847(of)X
-2936(the)X
-3056(total)X
-3220(lines)X
-3393(in)X
-3477(the)X
-3597(\256le,)X
-3741(if)X
-3811(the)X
-3930(\256le)X
-776 5262(has)N
-905(been)X
-1079(modi\256ed,)X
-1405(was)X
-1552(able)X
-1708(to)X
-1792(be)X
-1890(locked,)X
-2146(if)X
-2217(the)X
-2337(\256le's)X
-2519(name)X
-2715(has)X
-2844(been)X
-3018(changed,)X
-3328(and)X
-3466(if)X
-3537(the)X
-3658(edit)X
-3801(session)X
-776 5352(is)N
-849(read-only.)X
-776 5532(Line:)N
-1136(Unchanged.)X
-776 5622(Column:)N
-1136(Unchanged.)X
-776 5712(Options:)N
-1136(None.)X
-
-13 p
-%%Page: 13 12
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Vi)X
-1364(Commands\))X
-3658(USD:13-13)X
-576 762(<control-H>)N
-576 852([count])N
-841(h)X
-1 f
-776 942(Move)N
-989(the)X
-1113(cursor)X
-1340(back)X
-7 f
-1518(count)X
-1 f
-1784(characters)X
-2137(in)X
-2225(the)X
-2349(current)X
-2603(line.)X
-2789(This)X
-2957(is)X
-3036(an)X
-3138(error)X
-3321(if)X
-3396(the)X
-3520(cursor)X
-3747(is)X
-3827(on)X
-3934(the)X
-776 1032(\256rst)N
-920(character)X
-1236(in)X
-1318(the)X
-1436(line.)X
-776 1212(The)N
-3 f
-923(<control-H>)X
-1 f
-1372(and)X
-3 f
-1511(h)X
-1 f
-1578(commands)X
-1948(may)X
-2109(be)X
-2208(used)X
-2378(as)X
-2468(the)X
-2589(motion)X
-2838(component)X
-3217(of)X
-3307(other)X
-3 f
-3495(vi)X
-1 f
-3580(commands,)X
-3970(in)X
-776 1302(which)N
-992(case)X
-1151(any)X
-1287(text)X
-1427(copied)X
-1661(into)X
-1805(a)X
-1861(buffer)X
-2078(is)X
-2151(character)X
-2467(oriented.)X
-776 1482(Line:)N
-1136(Unchanged.)X
-776 1572(Column:)N
-1136(Set)X
-1263(to)X
-1350(the)X
-7 f
-1473(current)X
-1862(-)X
-1963(count)X
-1 f
-2229(character,)X
-2571(or,)X
-2684(the)X
-2808(\256rst)X
-2958(character)X
-3280(in)X
-3368(the)X
-3492(line)X
-3638(if)X
-7 f
-3713(count)X
-1 f
-3979(is)X
-1136 1662(greater)N
-1380(than)X
-1538(or)X
-1625(equal)X
-1819(to)X
-1901(the)X
-2019(number)X
-2284(of)X
-2371(characters)X
-2718(in)X
-2800(the)X
-2918(line)X
-3058(before)X
-3284(the)X
-3402(cursor.)X
-776 1752(Options:)N
-1136(None.)X
-3 f
-576 1932([count])N
-841(<control-J>)X
-576 2022([count])N
-841(<control-N>)X
-576 2112([count])N
-841(j)X
-1 f
-776 2202(Move)N
-993(the)X
-1121(cursor)X
-1352(down)X
-7 f
-1560(count)X
-1 f
-1830(lines)X
-2011(without)X
-2285(changing)X
-2609(the)X
-2737(current)X
-2995(column.)X
-3305(This)X
-3477(is)X
-3560(an)X
-3666(error)X
-3854(if)X
-3934(the)X
-776 2292(movement)N
-1134(is)X
-1207(past)X
-1356(the)X
-1474(end)X
-1610(of)X
-1697(the)X
-1815(\256le.)X
-776 2472(The)N
-3 f
-927(<control-J>)X
-1 f
-1331(,)X
-3 f
-1377(<control-N>)X
-1 f
-1825(and)X
-3 f
-1967(j)X
-1 f
-2020(commands)X
-2393(may)X
-2557(be)X
-2659(used)X
-2832(as)X
-2925(the)X
-3049(motion)X
-3301(component)X
-3684(of)X
-3778(other)X
-3 f
-3970(vi)X
-1 f
-776 2562(commands,)N
-1163(in)X
-1245(which)X
-1461(case)X
-1620(any)X
-1756(text)X
-1896(copied)X
-2130(into)X
-2274(a)X
-2330(buffer)X
-2547(is)X
-2620(line)X
-2760(oriented.)X
-776 2742(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(current)X
-1706(line)X
-1846(plus)X
-7 f
-1999(count)X
-1 f
-(.)S
-776 2832(Column:)N
-1136(The)X
-1281(most)X
-1456(attractive)X
-1775(cursor)X
-1996(position.)X
-776 2922(Options:)N
-1136(None.)X
-3 f
-576 3102(<control-L>)N
-576 3192(<control-R>)N
-1 f
-776 3282(Repaint)N
-1045(the)X
-1163(screen.)X
-776 3462(Line:)N
-1136(Unchanged.)X
-776 3552(Column:)N
-1136(Unchanged.)X
-776 3642(Options:)N
-1136(None.)X
-3 f
-576 3822([count])N
-841(<control-M>)X
-576 3912([count])N
-841(+)X
-1 f
-776 4002(Move)N
-984(the)X
-1103(cursor)X
-1325(down)X
-7 f
-1524(count)X
-1 f
-1785(lines)X
-1957(to)X
-2040(the)X
-2159(\256rst)X
-2304(nonblank)X
-2623(character)X
-2940(of)X
-3028(that)X
-3169(line.)X
-3350(This)X
-3513(is)X
-3587(an)X
-3684(error)X
-3863(if)X
-3934(the)X
-776 4092(movement)N
-1134(is)X
-1207(past)X
-1356(the)X
-1474(end)X
-1610(of)X
-1697(the)X
-1815(\256le.)X
-776 4272(The)N
-3 f
-922(<control-M>)X
-1 f
-1384(and)X
-3 f
-1522(+)X
-1 f
-1590(commands)X
-1959(may)X
-2119(be)X
-2217(used)X
-2386(as)X
-2475(the)X
-2595(motion)X
-2843(component)X
-3221(of)X
-3310(other)X
-3 f
-3497(vi)X
-1 f
-3581(commands,)X
-3970(in)X
-776 4362(which)N
-992(case)X
-1151(any)X
-1287(text)X
-1427(copied)X
-1661(into)X
-1805(a)X
-1861(buffer)X
-2078(is)X
-2151(line)X
-2291(oriented.)X
-776 4542(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(current)X
-1706(line)X
-1846(plus)X
-7 f
-1999(count)X
-1 f
-(.)S
-776 4632(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(in)X
-2318(the)X
-2436(line.)X
-776 4722(Options:)N
-1136(None.)X
-3 f
-576 4902([count])N
-841(<control-P>)X
-576 4992([count])N
-841(k)X
-1 f
-776 5082(Move)N
-983(the)X
-1101(cursor)X
-1323(up)X
-7 f
-1424(count)X
-1 f
-1685(lines,)X
-1877(without)X
-2142(changing)X
-2457(the)X
-2576(current)X
-2825(column.)X
-3126(This)X
-3289(is)X
-3363(an)X
-3460(error)X
-3638(if)X
-3708(the)X
-3827(move-)X
-776 5172(ment)N
-956(is)X
-1029(past)X
-1178(the)X
-1296(beginning)X
-1636(of)X
-1723(the)X
-1841(\256le.)X
-776 5352(The)N
-3 f
-924(<control-P>)X
-1 f
-1360(and)X
-3 f
-1499(k)X
-1 f
-1566(commands)X
-1937(may)X
-2099(be)X
-2199(used)X
-2370(as)X
-2461(the)X
-2583(motion)X
-2833(component)X
-3213(of)X
-3304(other)X
-3 f
-3493(vi)X
-1 f
-3579(commands,)X
-3970(in)X
-776 5442(which)N
-992(case)X
-1151(any)X
-1287(text)X
-1427(copied)X
-1661(into)X
-1805(a)X
-1861(buffer)X
-2078(is)X
-2151(line)X
-2291(oriented.)X
-776 5622(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(current)X
-1706(line)X
-1846(minus)X
-2061(count.)X
-776 5712(Column:)N
-1136(The)X
-1281(most)X
-1456(attractive)X
-1775(cursor)X
-1996(position.)X
-
-14 p
-%%Page: 14 13
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-14)N
-2826(Nvi/Nex)X
-3122 0.3906(Reference)AX
-3487(\(Vi)X
-3614(Commands\))X
-1 f
-776 762(Options:)N
-1136(None.)X
-3 f
-576 942(<control-T>)N
-1 f
-776 1032(Return)N
-1014(to)X
-1096(the)X
-1214(most)X
-1389(recent)X
-1606(tag)X
-1724(context.)X
-2020(The)X
-3 f
-2165(<control-T>)X
-1 f
-2602(command)X
-2938(is)X
-3011(an)X
-3107(absolute)X
-3394(movement.)X
-776 1212(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(context)X
-1714(of)X
-1801(the)X
-1919(previous)X
-2215(tag)X
-2333(command.)X
-776 1302(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(context)X
-1714(of)X
-1801(the)X
-1919(previous)X
-2215(tag)X
-2333(command.)X
-776 1392(Options:)N
-1136(None.)X
-3 f
-576 1572(<control-U>)N
-1 f
-776 1662(Scroll)N
-1003(backward)X
-7 f
-1352(count)X
-1 f
-1628(lines.)X
-1856(If)X
-7 f
-1947(count)X
-1 f
-2224(is)X
-2314(not)X
-2453(speci\256ed,)X
-2795(scroll)X
-3010(backward)X
-3360(the)X
-3495(number)X
-3777(of)X
-3881(lines)X
-776 1752(speci\256ed)N
-1096(by)X
-1211(the)X
-1344(last)X
-3 f
-1490(<control-D>)X
-1 f
-1947(or)X
-3 f
-2049(<control-U>)X
-1 f
-2505(command.)X
-2895(If)X
-2983(this)X
-3132(is)X
-3219(the)X
-3351(\256rst)X
-3 f
-3509(<control-D>)X
-1 f
-3965(or)X
-3 f
-776 1842(<control-U>)N
-1 f
-1221(command,)X
-1580(scroll)X
-1781(backward)X
-2117(half)X
-2266(the)X
-2388(number)X
-2657(of)X
-2748(lines)X
-2923(in)X
-3009(the)X
-3131(screen.)X
-3401(\(In)X
-3519(the)X
-3641(case)X
-3804(of)X
-3895(split)X
-776 1932(screens,)N
-1057(the)X
-1179(default)X
-1426(scrolling)X
-1729(distance)X
-2015(is)X
-2091(corrected)X
-2414(to)X
-2499(half)X
-2647(the)X
-2768(current)X
-3019(screen)X
-3248(size.\))X
-3463(This)X
-3628(is)X
-3704(an)X
-3803(error)X
-3983(if)X
-776 2022(the)N
-894(movement)X
-1252(is)X
-1325(past)X
-1474(the)X
-1592(beginning)X
-1932(of)X
-2019(the)X
-2137(\256le.)X
-776 2202(The)N
-3 f
-921(<control-U>)X
-1 f
-1363(command)X
-1699(is)X
-1772(an)X
-1868(absolute)X
-2155(movement.)X
-776 2382(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(current)X
-1706(line)X
-1846(minus)X
-2061(the)X
-2179(amount)X
-2439(scrolled.)X
-776 2472(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(in)X
-2318(the)X
-2436(line.)X
-776 2562(Options:)N
-1136(None.)X
-3 f
-576 2742(<control-W>)N
-1 f
-776 2832(Switch)N
-1021(to)X
-1106(the)X
-1227(next)X
-1388(lower)X
-1594(screen)X
-1823(in)X
-1908(the)X
-2029(window,)X
-2330(or,)X
-2440(to)X
-2525(the)X
-2646(\256rst)X
-2793(screen)X
-3022(if)X
-3094(there)X
-3278(are)X
-3400(no)X
-3503(lower)X
-3709(screens)X
-3970(in)X
-776 2922(the)N
-894(window.)X
-776 3102(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(previous)X
-1754(cursor)X
-1975(position)X
-2252(in)X
-2334(the)X
-2452(window.)X
-776 3192(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(previous)X
-1754(cursor)X
-1975(position)X
-2252(in)X
-2334(the)X
-2452(window.)X
-776 3282(Options:)N
-1136(None.)X
-3 f
-576 3462(<control-Y>)N
-1 f
-776 3552(Scroll)N
-989(backward)X
-7 f
-1324(count)X
-1 f
-1586(lines,)X
-1779(leaving)X
-2037(the)X
-2157(current)X
-2407(line)X
-2550(and)X
-2689(column)X
-2952(as)X
-3042(is,)X
-3138(if)X
-3210(possible.)X
-3535(This)X
-3700(is)X
-3776(an)X
-3875(error)X
-776 3642(if)N
-845(the)X
-963(movement)X
-1321(is)X
-1394(past)X
-1543(the)X
-1661(beginning)X
-2001(of)X
-2088(the)X
-2206(\256le.)X
-776 3822(Line:)N
-1136(Unchanged)X
-1525(unless)X
-1748(the)X
-1869(current)X
-2120(line)X
-2263(scrolls)X
-2496(off)X
-2614(the)X
-2736(screen,)X
-2986(in)X
-3072(which)X
-3292(case)X
-3455(it)X
-3523(is)X
-3600(set)X
-3713(to)X
-3799(the)X
-3921(last)X
-1136 3912(line)N
-1276(of)X
-1363(text)X
-1503(displayed)X
-1830(on)X
-1930(the)X
-2048(screen.)X
-776 4002(Column:)N
-1136(Unchanged)X
-1536(unless)X
-1770(the)X
-1902(current)X
-2164(line)X
-2318(scrolls)X
-2561(off)X
-2689(the)X
-2821(screen,)X
-3081(in)X
-3177(which)X
-3407(case)X
-3580(it)X
-3658(is)X
-3745(the)X
-3877(most)X
-1136 4092(attractive)N
-1455(cursor)X
-1676(position.)X
-776 4182(Options:)N
-1136(None.)X
-3 f
-576 4362(<control-Z>)N
-1 f
-776 4452(Suspend)N
-1069(the)X
-1189(current)X
-1439(editor)X
-1648(session.)X
-1941(If)X
-2017(the)X
-2137(\256le)X
-2261(has)X
-2390(been)X
-2564(modi\256ed)X
-2870(since)X
-3057(it)X
-3124(was)X
-3272(last)X
-3406(completely)X
-3785(written,)X
-776 4542(and)N
-914(the)X
-3 f
-1034(autowrite)X
-1 f
-1386(option)X
-1612(is)X
-1687(set,)X
-1817(the)X
-1936(\256le)X
-2059(is)X
-2133(written)X
-2381(before)X
-2608(the)X
-2727(editor)X
-2935(session)X
-3187(is)X
-3261(suspended.)X
-3656(If)X
-3731(this)X
-3867(write)X
-776 4632(fails,)N
-954(the)X
-1072(editor)X
-1279(session)X
-1530(is)X
-1603(not)X
-1725(suspended.)X
-776 4812(Line:)N
-1136(Unchanged.)X
-776 4902(Column:)N
-1136(Unchanged.)X
-776 4992(Options:)N
-1136(Affected)X
-1438(by)X
-1538(the)X
-3 f
-1656(autowrite)X
-1 f
-2006(option.)X
-3 f
-576 5172(<escape>)N
-1 f
-776 5262(Execute)N
-3 f
-1055(ex)X
-1 f
-1151(commands)X
-1518(or)X
-1605(cancel)X
-1831(partial)X
-2056(commands.)X
-2463(If)X
-2537(an)X
-3 f
-2633(ex)X
-1 f
-2729(command)X
-3065(is)X
-3138(being)X
-3336(entered)X
-3593(\(e.g.)X
-3 f
-3776(/)X
-1 f
-3798(,)X
-3 f
-3838(?)X
-1 f
-(,)S
-3 f
-3918(:)X
-1 f
-3965(or)X
-3 f
-776 5352(!)N
-1 f
-803(\),)X
-877(the)X
-1002(command)X
-1345(is)X
-1425(executed.)X
-1778(If)X
-1859(a)X
-1922(partial)X
-2154(command)X
-2497(has)X
-2631(been)X
-2810(entered,)X
-3093(e.g.)X
-3255(or)X
-3348(the)X
-3472(command)X
-3814(is)X
-3893(can-)X
-776 5442(celled.)N
-1028(Otherwise,)X
-1398(it)X
-1462(is)X
-1535(an)X
-1631(error.)X
-776 5622(Line:)N
-1136(When)X
-1350(an)X
-3 f
-1448(ex)X
-1 f
-1546(command)X
-1884(is)X
-1959(being)X
-2159(executed,)X
-2487(the)X
-2607(current)X
-2857(line)X
-2999(is)X
-3074(set)X
-3186(as)X
-3276(described)X
-3607(for)X
-3724(that)X
-3867(com-)X
-1136 5712(mand.)N
-1374(Otherwise,)X
-1744(unchanged.)X
-
-15 p
-%%Page: 15 14
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Vi)X
-1364(Commands\))X
-3658(USD:13-15)X
-1 f
-776 762(Column:)N
-1136(When)X
-1354(an)X
-3 f
-1456(ex)X
-1 f
-1558(command)X
-1901(is)X
-1981(being)X
-2186(executed,)X
-2519(the)X
-2644(current)X
-2899(column)X
-3166(is)X
-3246(set)X
-3362(as)X
-3456(described)X
-3791(for)X
-3912(that)X
-1136 852(command.)N
-1512(Otherwise,)X
-1882(unchanged.)X
-776 942(Options:)N
-1136(None.)X
-3 f
-576 1122(<control-]>)N
-1 f
-776 1212(Push)N
-953(a)X
-1011(tag)X
-1131 0.4531(reference)AX
-1454(onto)X
-1618(the)X
-1738(tag)X
-1858(stack.)X
-2085(The)X
-2232(tags)X
-2383(\256les)X
-2538(\(see)X
-2691(the)X
-3 f
-2812(tags)X
-1 f
-2973(option)X
-3200(for)X
-3317(more)X
-3505(information\))X
-3933(are)X
-776 1302(searched)N
-1086(for)X
-1207(a)X
-1270(tag)X
-1395(matching)X
-1720(the)X
-1845(current)X
-2100(word.)X
-2332(The)X
-2484(current)X
-2739(word)X
-2931(begins)X
-3167(at)X
-3252(the)X
-3377(\256rst)X
-3528(non-whitespace)X
-776 1392(character)N
-1092(on)X
-1192(or)X
-1279(after)X
-1447(the)X
-1565(current)X
-1813(cursor)X
-2034(position,)X
-2331(and)X
-2468(extends)X
-2734(up)X
-2835(to)X
-2918(the)X
-3037(next)X
-3196(non-word)X
-3529(character)X
-3846(or)X
-3934(the)X
-776 1482(end)N
-914(of)X
-1003(the)X
-1123(line.)X
-1305(If)X
-1381(a)X
-1439(matching)X
-1759(tag)X
-1879(is)X
-1954(found,)X
-2183(the)X
-2302(current)X
-2551(\256le)X
-2674(is)X
-2748(discarded)X
-3077(and)X
-3214(the)X
-3333(\256le)X
-3456(containing)X
-3815(the)X
-3934(tag)X
-776 1572 0.4531(reference)AN
-1097(is)X
-1170(edited.)X
-776 1752(If)N
-851(the)X
-971(current)X
-1221(\256le)X
-1345(has)X
-1474(been)X
-1648(modi\256ed)X
-1954(since)X
-2141(it)X
-2207(was)X
-2354(last)X
-2487(completely)X
-2865(written,)X
-3134(the)X
-3254(command)X
-3592(will)X
-3738(fail.)X
-3907(The)X
-3 f
-776 1842(<control-]>)N
-1 f
-1187(command)X
-1523(is)X
-1596(an)X
-1692(absolute)X
-1979(movement.)X
-776 2022(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(containing)X
-1956(the)X
-2074(matching)X
-2392(tag)X
-2510(string.)X
-776 2112(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(start)X
-1616(of)X
-1703(the)X
-1821(matching)X
-2139(tag)X
-2257(string.)X
-776 2202(Options:)N
-1136(Affected)X
-1438(by)X
-1538(the)X
-3 f
-1656(tags)X
-1 f
-1814(and)X
-3 f
-1950(taglength)X
-1 f
-2290(options.)X
-3 f
-576 2382(<control-\303>)N
-1 f
-776 2472(Switch)N
-1018(to)X
-1100(the)X
-1218(most)X
-1393(recently)X
-1672(edited)X
-1888(\256le.)X
-776 2652(If)N
-852(the)X
-972(\256le)X
-1096(has)X
-1225(been)X
-1399(modi\256ed)X
-1705(since)X
-1892(it)X
-1958(was)X
-2105(last)X
-2238(completely)X
-2616(written,)X
-2886(and)X
-3025(the)X
-3 f
-3146(autowrite)X
-1 f
-3499(option)X
-3726(is)X
-3802(set,)X
-3934(the)X
-776 2742(\256le)N
-905(is)X
-984(written)X
-1237(out.)X
-1405(If)X
-1485(this)X
-1626(write)X
-1817(fails,)X
-2001(the)X
-2125(command)X
-2467(will)X
-2617(fail.)X
-2790(Otherwise,)X
-3166(if)X
-3241(the)X
-3365(current)X
-3619(\256le)X
-3747(has)X
-3880(been)X
-776 2832(modi\256ed)N
-1080(since)X
-1265(it)X
-1329(was)X
-1474(last)X
-1605(completely)X
-1981(written,)X
-2248(the)X
-2366(command)X
-2702(will)X
-2846(fail.)X
-776 3012(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(the)X
-1716(cursor)X
-1937(was)X
-2082(on)X
-2182(when)X
-2376(the)X
-2494(\256le)X
-2616(was)X
-2761(last)X
-2892(edited.)X
-776 3102(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(column)X
-1718(the)X
-1836(cursor)X
-2057(was)X
-2202(on)X
-2302(when)X
-2496(the)X
-2614(\256le)X
-2736(was)X
-2881(last)X
-3012(edited.)X
-776 3192(Options:)N
-1136(Affected)X
-1438(by)X
-1538(the)X
-3 f
-1656(autowrite)X
-1 f
-2006(option.)X
-3 f
-576 3372([count])N
-841(<space>)X
-576 3462([count])N
-841(l)X
-1 f
-776 3552(Move)N
-984(the)X
-1103(cursor)X
-1325(forward)X
-7 f
-1602(count)X
-1 f
-1864(characters)X
-2213(without)X
-2479(changing)X
-2795(the)X
-2915(current)X
-3165(line.)X
-3347(This)X
-3511(is)X
-3586(an)X
-3684(error)X
-3863(if)X
-3934(the)X
-776 3642(cursor)N
-997(is)X
-1070(on)X
-1170(the)X
-1288(last)X
-1419(character)X
-1735(in)X
-1817(the)X
-1935(line.)X
-776 3822(The)N
-3 f
-921(<space>)X
-1 f
-1220(and)X
-3 f
-1356(l)X
-1 f
-1398(commands)X
-1765(may)X
-1923(be)X
-2019(used)X
-2186(as)X
-2273(the)X
-2391(motion)X
-2637(component)X
-3013(of)X
-3100(other)X
-3 f
-3285(vi)X
-1 f
-3367(commands,)X
-3754(in)X
-3836(which)X
-776 3912(case)N
-937(any)X
-1075(text)X
-1217(copied)X
-1453(into)X
-1599(a)X
-1657(buffer)X
-1876(is)X
-1951(character)X
-2269(oriented.)X
-2594(In)X
-2683(addition,)X
-2987(these)X
-3173(commands)X
-3541(may)X
-3700(be)X
-3797(used)X
-3965(as)X
-776 4002(the)N
-908(motion)X
-1168(components)X
-1589(of)X
-1690(other)X
-1889(commands)X
-2271(when)X
-2480(the)X
-2613(cursor)X
-2849(is)X
-2937(on)X
-3052(the)X
-3185(last)X
-3331(character)X
-3662(in)X
-3759(the)X
-3892(line,)X
-776 4092(without)N
-1040(error.)X
-776 4272(Line:)N
-1136(Unchanged.)X
-776 4362(Column:)N
-1136(Set)X
-1259(to)X
-1342(the)X
-1461(current)X
-1710(character)X
-2027(plus)X
-2181(the)X
-2300(next)X
-7 f
-2459(count)X
-1 f
-2720(characters,)X
-3088(or)X
-3177(to)X
-3261(the)X
-3381(last)X
-3514(character)X
-3832(on)X
-3934(the)X
-1136 4452(line)N
-1278(if)X
-7 f
-1349(count)X
-1 f
-1611(is)X
-1686(greater)X
-1932(than)X
-2092(the)X
-2212(number)X
-2478(of)X
-2566(characters)X
-2914(in)X
-2997(the)X
-3116(line)X
-3257(after)X
-3426(the)X
-3545(current)X
-3794(charac-)X
-1136 4542(ter.)N
-776 4632(Options:)N
-1136(None.)X
-3 f
-576 4812([count])N
-841(!)X
-888(motion)X
-1148(shell-argument\(s\))X
-1 f
-776 4902(Replace)N
-1055(text)X
-1195(with)X
-1357(results)X
-1586(from)X
-1762(a)X
-1818(shell)X
-1989(command.)X
-2366(Pass)X
-2529(the)X
-2648(lines)X
-2820(speci\256ed)X
-3126(by)X
-3227(the)X
-7 f
-3346(count)X
-1 f
-3607(and)X
-7 f
-3744(motion)X
-1 f
-776 4992(arguments)N
-1136(as)X
-1229(standard)X
-1527(input)X
-1717(to)X
-1805(the)X
-1928(program)X
-2225(named)X
-2464(by)X
-2569(the)X
-3 f
-2692(shell)X
-1 f
-2872(option,)X
-3121(and)X
-3262(replace)X
-3520(those)X
-3714(lines)X
-3890(with)X
-776 5082(the)N
-894(output)X
-1118(\(both)X
-1307(standard)X
-1599(error)X
-1776(and)X
-1912(standard)X
-2204(output\))X
-2455(of)X
-2542(that)X
-2682(command.)X
-776 5262(After)N
-966(the)X
-1084(motion)X
-1330(is)X
-1403(entered,)X
-3 f
-1680(vi)X
-1 f
-1762(prompts)X
-2044(for)X
-2158(arguments)X
-2512(to)X
-2594(the)X
-2712(shell)X
-2883(command.)X
-776 5442(Within)N
-1026(those)X
-1223(arguments,)X
-1605(``)X
-7 f
-1659(%)X
-1 f
-('')S
-1790(and)X
-1935(``)X
-7 f
-1989(#)X
-1 f
-('')S
-2120(characters)X
-2476(are)X
-2604(expanded)X
-2941(to)X
-3032(the)X
-3159(current)X
-3416(and)X
-3561(alternate)X
-3867(path-)X
-776 5532(names,)N
-1024(respectively.)X
-1475(The)X
-1623(``)X
-7 f
-1677(!)X
-1 f
-('')S
-1822(character)X
-2141(is)X
-2217(expanded)X
-2548(with)X
-2713(the)X
-2833(command)X
-3171(text)X
-3313(of)X
-3402(the)X
-3522(previous)X
-3 f
-3820(!)X
-1 f
-3889(or)X
-3 f
-3978(:!)X
-1 f
-776 5622(commands.)N
-1183 0.3125(\(Therefore,)AX
-1568(the)X
-1686(command)X
-3 f
-2022(!!)X
-1 f
-2116(repeats)X
-2364(the)X
-2482(previous)X
-3 f
-2778(!)X
-1 f
-2845(command.\))X
-3248(The)X
-3393(special)X
-3637(meanings)X
-3965(of)X
-776 5712(``)N
-7 f
-830(%)X
-1 f
-('',)S
-975(``)X
-7 f
-1029(#)X
-1 f
-('')S
-1154(and)X
-1293(``)X
-7 f
-1347(!)X
-1 f
-('')S
-1492(can)X
-1627(be)X
-1726(overridden)X
-2097(by)X
-2200(escaping)X
-2504(them)X
-2687(with)X
-2852(a)X
-2910(backslash.)X
-3284(If)X
-3360(no)X
-3 f
-3462(!)X
-1 f
-3531(or)X
-3 f
-3620(:!)X
-1 f
-3716(command)X
-776 5802(has)N
-907(yet)X
-1029(been)X
-1205(executed,)X
-1535(it)X
-1603(is)X
-1680(an)X
-1780(error)X
-1961(to)X
-2047(use)X
-2178(an)X
-2278(unescaped)X
-2637(``)X
-7 f
-2691(!)X
-1 f
-('')S
-2837(character.)X
-3197(The)X
-3 f
-3346(!)X
-1 f
-3417(command)X
-3758(does)X
-2 f
-3930(not)X
-
-16 p
-%%Page: 16 15
-10 s 10 xH 0 xS 2 f 1 i
-3 f
-576 474(USD:13-16)N
-2826(Nvi/Nex)X
-3122 0.3906(Reference)AX
-3487(\(Vi)X
-3614(Commands\))X
-1 f
-776 762(do)N
-880(shell)X
-1055(expansion)X
-1404(on)X
-1508(the)X
-1630(strings)X
-1867(provided)X
-2175(as)X
-2265(arguments.)X
-2662(If)X
-2739(any)X
-2878(of)X
-2968(the)X
-3089(above)X
-3304(expansions)X
-3683(change)X
-3934(the)X
-776 852(arguments)N
-1130(the)X
-1248(user)X
-1402(entered,)X
-1679(the)X
-1797(command)X
-2133(is)X
-2206(redisplayed)X
-2596(at)X
-2674(the)X
-2792(bottom)X
-3038(of)X
-3125(the)X
-3243(screen.)X
-3 f
-776 1032(Vi)N
-1 f
-882(then)X
-1046(executes)X
-1349(the)X
-1473(program)X
-1771(named)X
-2011(by)X
-2117(the)X
-3 f
-2241(shell)X
-1 f
-2422(option,)X
-2672(with)X
-2840(a)X
-3 f
-9 f
-2902(-)X
-2904(-)X
-3 f
-2948(c)X
-1 f
-3010(\257ag)X
-3156(followed)X
-3467(by)X
-3573(the)X
-3698(arguments)X
-776 1122(\(which)N
-1019(are)X
-1138(bundled)X
-1416(into)X
-1560(a)X
-1616(single)X
-1827(argument\).)X
-776 1302(The)N
-3 f
-921(!)X
-1 f
-988(command)X
-1324(is)X
-1397(permitted)X
-1724(in)X
-1806(an)X
-1902(empty)X
-2122(\256le.)X
-776 1482(If)N
-850(the)X
-968(\256le)X
-1090(has)X
-1217(been)X
-1389(modi\256ed)X
-1693(since)X
-1878(it)X
-1942(was)X
-2087(last)X
-2218(completely)X
-2594(written,)X
-2861(the)X
-3 f
-2979(!)X
-1 f
-3046(command)X
-3382(will)X
-3526(warn)X
-3707(you.)X
-776 1662(Line:)N
-1136(The)X
-1281(\256rst)X
-1425(line)X
-1565(of)X
-1652(the)X
-1770(replaced)X
-2063(text.)X
-776 1752(Column:)N
-1136(The)X
-1281(\256rst)X
-1425(column)X
-1685(of)X
-1772(the)X
-1890(replaced)X
-2183(text.)X
-776 1842(Options:)N
-1136(Affected)X
-1438(by)X
-1538(the)X
-3 f
-1656(shell)X
-1 f
-1831(option.)X
-3 f
-576 2022([count])N
-841(#)X
-901(+|-|#)X
-1 f
-776 2112(Increment)N
-1135(or)X
-1235(decrement)X
-1603(the)X
-1734(current)X
-1996(number.)X
-2315(The)X
-2474(current)X
-2736(number)X
-3015(begins)X
-3258(at)X
-3350(the)X
-3482(\256rst)X
-3640(non-number)X
-776 2202(character)N
-1095(on)X
-1198(or)X
-1288(before)X
-1517(the)X
-1638(current)X
-1889(cursor)X
-2113(position,)X
-2413(or)X
-2503(the)X
-2624(beginning)X
-2967(of)X
-3057(the)X
-3178(line,)X
-3341(and)X
-3480(extends)X
-3748(up)X
-3850(to)X
-3934(the)X
-776 2292(\256rst)N
-920(non-number)X
-1332(character)X
-1649(on)X
-1750(or)X
-1838(after)X
-2007(the)X
-2126(current)X
-2375(cursor)X
-2597(position)X
-2875(or)X
-2963(the)X
-3082(end)X
-3219(of)X
-3307(the)X
-3426(line.)X
-3607(If)X
-3682(the)X
-3801(trailing)X
-776 2382(character)N
-1094(is)X
-1169(a)X
-7 f
-1227(+)X
-1 f
-(,)S
-1317(the)X
-1437(number)X
-1704(is)X
-1779(incremented)X
-2198(by)X
-7 f
-2300(count)X
-1 f
-(.)S
-2602(If)X
-2678(the)X
-2798(trailing)X
-3051(character)X
-3369(is)X
-3444(a)X
-7 f
-3502(-)X
-1 f
-(,)S
-3592(the)X
-3712(number)X
-3979(is)X
-776 2472(decremented)N
-1220(by)X
-7 f
-1333(count)X
-1 f
-(.)S
-1646(If)X
-1733(the)X
-1864(trailing)X
-2128(character)X
-2457(is)X
-2543(a)X
-7 f
-2612(#)X
-1 f
-(,)S
-2713(the)X
-2844(previous)X
-3154(increment)X
-3509(or)X
-3610(decrement)X
-3979(is)X
-776 2562(repeated.)N
-776 2742(The)N
-927(format)X
-1167(of)X
-1260(the)X
-1384(number)X
-1656(\(decimal,)X
-1984(hexadecimal,)X
-2437(and)X
-2580(octal,)X
-2783(and)X
-2926(leading)X
-3189(0's\))X
-3341(is)X
-3421(retained)X
-3707(unless)X
-3934(the)X
-776 2832(new)N
-930(value)X
-1124(cannot)X
-1358(be)X
-1454(represented)X
-1845(in)X
-1927(the)X
-2045(previous)X
-2341(format.)X
-776 3012(Line:)N
-1136(Unchanged.)X
-776 3102(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(character)X
-1918(in)X
-2000(the)X
-2118(cursor)X
-2339(word.)X
-776 3192(Options:)N
-1136(None.)X
-3 f
-576 3372([count])N
-841($)X
-1 f
-776 3462(Move)N
-989(the)X
-1113(cursor)X
-1340(to)X
-1428(the)X
-1552(end)X
-1694(of)X
-1787(a)X
-1849(line.)X
-2035(If)X
-7 f
-2115(count)X
-1 f
-2381(is)X
-2460(speci\256ed,)X
-2792(the)X
-2917(cursor)X
-3145(moves)X
-3381(down)X
-7 f
-3586(count)X
-3881(-)X
-3984(1)X
-1 f
-776 3552(lines.)N
-776 3732(It)N
-845(is)X
-918(not)X
-1040(an)X
-1136(error)X
-1313(to)X
-1395(use)X
-1522(the)X
-3 f
-1640($)X
-1 f
-1700(command)X
-2036(when)X
-2230(the)X
-2348(cursor)X
-2569(is)X
-2642(on)X
-2742(the)X
-2860(last)X
-2991(character)X
-3308(in)X
-3391(the)X
-3510(line)X
-3651(or)X
-3739(when)X
-3934(the)X
-776 3822(line)N
-916(is)X
-989(empty.)X
-776 4002(The)N
-3 f
-921($)X
-1 f
-981(command)X
-1317(may)X
-1475(be)X
-1571(used)X
-1739(as)X
-1827(the)X
-1946(motion)X
-2193(component)X
-2570(of)X
-2658(other)X
-3 f
-2844(vi)X
-1 f
-2927(commands,)X
-3315(in)X
-3398(which)X
-3615(case)X
-3775(any)X
-3912(text)X
-776 4092(copied)N
-1014(into)X
-1161(a)X
-1220(buffer)X
-1440(is)X
-1516(character)X
-1835(oriented,)X
-2141(unless)X
-2364(the)X
-2485(cursor)X
-2709(is)X
-2785(at,)X
-2886(or)X
-2976(before)X
-3205(the)X
-3326(\256rst)X
-3473(nonblank)X
-3794(charac-)X
-776 4182(ter)N
-885(in)X
-971(the)X
-1093(line,)X
-1257(in)X
-1343(which)X
-1563(case)X
-1726(it)X
-1794(is)X
-1871(line)X
-2015(oriented.)X
-2343(It)X
-2417(is)X
-2495(not)X
-2622(an)X
-2723(error)X
-2905(to)X
-2992(use)X
-3124(the)X
-3 f
-3247($)X
-1 f
-3312(command)X
-3653(as)X
-3745(a)X
-3806(motion)X
-776 4272(component)N
-1154(when)X
-1350(the)X
-1470(cursor)X
-1693(is)X
-1768(on)X
-1870(the)X
-1990(last)X
-2123(character)X
-2441(in)X
-2525(the)X
-2645(line,)X
-2807(although)X
-3109(it)X
-3175(is)X
-3249(an)X
-3346(error)X
-3524(when)X
-3719(the)X
-3838(line)X
-3979(is)X
-776 4362(empty.)N
-776 4542(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(current)X
-1706(line)X
-1846(plus)X
-7 f
-1999(count)X
-1 f
-2259(minus)X
-2474(1.)X
-776 4632(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(character)X
-1905(in)X
-1987(the)X
-2105(line.)X
-776 4722(Options:)N
-1136(None.)X
-3 f
-576 4902(%)N
-1 f
-776 4992(Move)N
-986(to)X
-1071(the)X
-1192(matching)X
-1513(character.)X
-1872(The)X
-2020(cursor)X
-2244(moves)X
-2477(to)X
-2563(the)X
-2685(parenthesis)X
-3070(or)X
-3161(curly)X
-3350(brace)X
-3549(which)X
-2 f
-3769(matches)X
-1 f
-776 5082(the)N
-900(parenthesis)X
-1287(or)X
-1380(curly)X
-1570(brace)X
-1770(found)X
-1982(at)X
-2065(the)X
-2188(current)X
-2441(cursor)X
-2667(position)X
-2949(or)X
-3041(which)X
-3262(is)X
-3340(the)X
-3463(closest)X
-3706(one)X
-3847(to)X
-3934(the)X
-776 5172(right)N
-964(of)X
-1068(the)X
-1203(cursor)X
-1441(on)X
-1558(the)X
-1693(line.)X
-1890(It)X
-1976(is)X
-2066(an)X
-2179(error)X
-2373(to)X
-2472(execute)X
-2756(the)X
-3 f
-2892(%)X
-1 f
-3010(command)X
-3364(on)X
-3482(a)X
-3556(line)X
-3714(without)X
-3996(a)X
-776 5262(parenthesis)N
-1157(or)X
-1244(curly)X
-1429(brace.)X
-1664(Historically,)X
-2082(any)X
-7 f
-2218(count)X
-1 f
-2478(speci\256ed)X
-2783(to)X
-2865(the)X
-3 f
-2983(%)X
-1 f
-3083(command)X
-3419(was)X
-3564(ignored.)X
-776 5442(The)N
-3 f
-921(%)X
-1 f
-1021(command)X
-1357(is)X
-1430(an)X
-1527(absolute)X
-1815(movement.)X
-2214(The)X
-3 f
-2360(%)X
-1 f
-2461(command)X
-2798(may)X
-2957(be)X
-3054(used)X
-3222(as)X
-3310(the)X
-3429(motion)X
-3676(component)X
-776 5532(of)N
-871(other)X
-3 f
-1064(vi)X
-1 f
-1153(commands,)X
-1547(in)X
-1636(which)X
-1859(case)X
-2025(any)X
-2168(text)X
-2315(copied)X
-2556(into)X
-2707(a)X
-2770(buffer)X
-2994(is)X
-3074(character)X
-3397(oriented,)X
-3707(unless)X
-3934(the)X
-776 5622(starting)N
-1036(point)X
-1220(of)X
-1307(the)X
-1425(region)X
-1650(is)X
-1723(at)X
-1801(or)X
-1888(before)X
-2115(the)X
-2234(\256rst)X
-2379(nonblank)X
-2698(character)X
-3015(on)X
-3116(its)X
-3212(line,)X
-3373(and)X
-3510(the)X
-3629(ending)X
-3868(point)X
-776 5712(is)N
-849(at)X
-927(or)X
-1014(after)X
-1182(the)X
-1300(last)X
-1431(nonblank)X
-1749(character)X
-2065(on)X
-2165(its)X
-2260(line,)X
-2420(in)X
-2502(which)X
-2718(case)X
-2877(it)X
-2941(is)X
-3014(line)X
-3154(oriented.)X
-
-17 p
-%%Page: 17 16
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Vi)X
-1364(Commands\))X
-3658(USD:13-17)X
-1 f
-776 762(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(containing)X
-1956(the)X
-2074(matching)X
-2392(character.)X
-776 852(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(matching)X
-1776(character.)X
-776 942(Options:)N
-1136(None.)X
-3 f
-576 1122(&)N
-1 f
-776 1212(Repeat)N
-1019(the)X
-1137(previous)X
-1433(substitution)X
-1825(command)X
-2161(on)X
-2261(the)X
-2379(current)X
-2627(line.)X
-776 1392(Historically,)N
-1194(any)X
-7 f
-1330(count)X
-1 f
-1590(speci\256ed)X
-1895(to)X
-1977(the)X
-3 f
-2095(&)X
-1 f
-2182(command)X
-2518(was)X
-2663(ignored.)X
-776 1572(Line:)N
-1136(Unchanged.)X
-776 1662(Column:)N
-1136(Unchanged)X
-1531(if)X
-1609(the)X
-1736(cursor)X
-1966(was)X
-2120(on)X
-2229(the)X
-2356(last)X
-2496(character)X
-2821(in)X
-2912(the)X
-3039(line,)X
-3208(otherwise,)X
-3569(set)X
-3688(to)X
-3780(the)X
-3908(\256rst)X
-1136 1752(nonblank)N
-1454(character)X
-1770(in)X
-1852(the)X
-1970(line.)X
-776 1842(Options:)N
-1136(Affected)X
-1438(by)X
-1538(the)X
-3 f
-1656(edcompatible)X
-1 f
-2114(,)X
-3 f
-2154(extended)X
-1 f
-2461(,)X
-3 f
-2501(ignorecase)X
-1 f
-2882(and)X
-3 f
-3018(magic)X
-1 f
-3243(options.)X
-3 f
-576 2022 0.3182(\302<character>)AN
-576 2112 0.3182(`<character>)AN
-1 f
-776 2202(Return)N
-1014(to)X
-1096(a)X
-1152(context)X
-1408(marked)X
-1669(by)X
-1769(the)X
-1888(character)X
-7 f
-2205(<character>)X
-1 f
-(.)S
-2794(If)X
-7 f
-2869(<character>)X
-1 f
-3418(is)X
-3492(the)X
-3611(``)X
-7 f
-3665(')X
-1 f
-('')S
-3788(or)X
-3876(``)X
-7 f
-3930(`)X
-1 f
-('')S
-776 2292(character,)N
-1113(return)X
-1326(to)X
-1409(the)X
-1528(previous)X
-1825(context.)X
-2122(If)X
-7 f
-2197(<character>)X
-1 f
-2746(is)X
-2820(any)X
-2956(other)X
-3141(character,)X
-3477(return)X
-3689(to)X
-3771(the)X
-3889(con-)X
-776 2382(text)N
-921(marked)X
-1187(by)X
-1292(that)X
-1437(character)X
-1759(\(see)X
-1915(the)X
-3 f
-2039(m)X
-1 f
-2132(command)X
-2474(for)X
-2594(more)X
-2785(information\).)X
-3256(If)X
-3336(the)X
-3460(command)X
-3802(is)X
-3881(the)X
-3 f
-4005(\302)X
-1 f
-776 2472(command,)N
-1137(only)X
-1304(the)X
-1427(line)X
-1572(value)X
-1771(is)X
-1848(restored,)X
-2151(and)X
-2291(the)X
-2413(cursor)X
-2638(is)X
-2715(placed)X
-2949(on)X
-3053(the)X
-3175(\256rst)X
-3323(nonblank)X
-3645(character)X
-3965(of)X
-776 2562(that)N
-916(line.)X
-1096(If)X
-1170(the)X
-1288(command)X
-1624(is)X
-1697(the)X
-3 f
-1815(`)X
-1 f
-1862(command,)X
-2218(both)X
-2380(the)X
-2498(line)X
-2638(and)X
-2774(column)X
-3034(values)X
-3259(are)X
-3378(restored.)X
-776 2742(It)N
-849(is)X
-926(an)X
-1026(error)X
-1207(if)X
-1280(the)X
-1402(context)X
-1662(no)X
-1766(longer)X
-1995(exists)X
-2202(because)X
-2482(of)X
-2574(line)X
-2719(deletion.)X
-3042(\(Contexts)X
-3378(follow)X
-3612(lines)X
-3788(that)X
-3933(are)X
-776 2832(moved,)N
-1034(or)X
-1121(which)X
-1337(are)X
-1456(deleted)X
-1708(and)X
-1844(then)X
-2002(restored.\))X
-776 3012(The)N
-3 f
-924(\302)X
-1 f
-974(and)X
-3 f
-1113(`)X
-1 f
-1163(commands)X
-1533(are)X
-1655(both)X
-1820(absolute)X
-2110(movements.)X
-2542(They)X
-2730(may)X
-2891(be)X
-2990(used)X
-3160(as)X
-3250(a)X
-3309(motion)X
-3558(component)X
-3938(for)X
-776 3102(other)N
-3 f
-962(vi)X
-1 f
-1045(commands.)X
-1453(For)X
-1585(the)X
-3 f
-1704(\302)X
-1 f
-1752(command,)X
-2108(any)X
-2244(text)X
-2384(copied)X
-2618(into)X
-2762(a)X
-2818(buffer)X
-3035(is)X
-3108(line)X
-3248(oriented.)X
-3571(For)X
-3702(the)X
-3 f
-3820(`)X
-1 f
-3867(com-)X
-776 3192(mand,)N
-1002(any)X
-1146(text)X
-1294(copied)X
-1536(into)X
-1688(a)X
-1752(buffer)X
-1977(is)X
-2058(character)X
-2382(oriented,)X
-2693(unless)X
-2921(it)X
-2993(both)X
-3163(starts)X
-3360(and)X
-3504(stops)X
-3696(at)X
-3782(the)X
-3908(\256rst)X
-776 3282(character)N
-1099(in)X
-1188(the)X
-1313(line,)X
-1480(in)X
-1569(which)X
-1792(case)X
-1958(it)X
-2029(is)X
-2109(line)X
-2255(oriented.)X
-2584(In)X
-2677(addition,)X
-2985(when)X
-3185(using)X
-3384(the)X
-3 f
-3508(`)X
-1 f
-3561(command)X
-3903(as)X
-3996(a)X
-776 3372(motion)N
-1025(component,)X
-1424(commands)X
-1794(which)X
-2013(move)X
-2214(backward)X
-2550(and)X
-2689(started)X
-2926(at)X
-3007(the)X
-3128(\256rst)X
-3275(character)X
-3594(in)X
-3679(the)X
-3801(line,)X
-3965(or)X
-776 3462(move)N
-983(forward)X
-1267(and)X
-1412(ended)X
-1633(at)X
-1719(the)X
-1845(\256rst)X
-1997(character)X
-2321(in)X
-2411(the)X
-2537(line,)X
-2705(are)X
-2832(corrected)X
-3160(to)X
-3250(the)X
-3376(last)X
-3515(character)X
-3839(of)X
-3934(the)X
-776 3552(starting)N
-1036(and)X
-1172(ending)X
-1410(lines,)X
-1601(respectively.)X
-776 3732(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(from)X
-1774(the)X
-1892(context.)X
-776 3822(Column:)N
-1136(Set)X
-1261(to)X
-1346(the)X
-1467(\256rst)X
-1614(nonblank)X
-1935(character)X
-2254(in)X
-2340(the)X
-2462(line,)X
-2626(for)X
-2744(the)X
-3 f
-2866(\302)X
-1 f
-2917(command,)X
-3277(and)X
-3417(set)X
-3530(to)X
-3616(the)X
-3738(context's)X
-1136 3912(column)N
-1396(for)X
-1510(the)X
-3 f
-1628(`)X
-1 f
-1675(command.)X
-776 4002(Options:)N
-1136(None.)X
-3 f
-576 4182([count])N
-841(\()X
-1 f
-776 4272(Back)N
-961(up)X
-7 f
-1061(count)X
-1 f
-1321(sentences.)X
-776 4452(The)N
-3 f
-922(\()X
-1 f
-970(command)X
-1307(is)X
-1382(an)X
-1480(absolute)X
-1769(movement.)X
-2169(The)X
-3 f
-2316(\()X
-1 f
-2365(command)X
-2703(may)X
-2863(be)X
-2961(used)X
-3130(as)X
-3219(the)X
-3339(motion)X
-3587(component)X
-3965(of)X
-776 4542(other)N
-3 f
-963(vi)X
-1 f
-1047(commands,)X
-1436(in)X
-1520(which)X
-1738(case)X
-1899(any)X
-2036(text)X
-2177(copied)X
-2412(into)X
-2557(a)X
-2614(buffer)X
-2832(is)X
-2906(character)X
-3223(oriented,)X
-3527(unless)X
-3748(the)X
-3867(start-)X
-776 4632(ing)N
-913(and)X
-1064(stopping)X
-1374(points)X
-1604(of)X
-1706(the)X
-1839(region)X
-2079(are)X
-2213(the)X
-2346(\256rst)X
-2505(character)X
-2836(in)X
-2933(the)X
-3066(line,)X
-3241(in)X
-3338(which)X
-3569(case)X
-3743(it)X
-3823(is)X
-3912(line)X
-776 4722(oriented.)N
-1111(In)X
-1210(the)X
-1340(latter)X
-1537(case,)X
-1728(the)X
-1858(stopping)X
-2165(point)X
-2361(of)X
-2460(the)X
-2590(region)X
-2827(is)X
-2911(adjusted)X
-3209(to)X
-3302(be)X
-3409(the)X
-3538(end)X
-3685(of)X
-3783(the)X
-3912(line)X
-776 4812(immediately)N
-1196(before)X
-1422(it,)X
-1506(and)X
-1642(not)X
-1764(the)X
-1882(original)X
-2151(cursor)X
-2372(position.)X
-776 4992(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(containing)X
-1956(the)X
-2074(beginning)X
-2414(of)X
-2501(the)X
-2619(sentence.)X
-776 5082(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(of)X
-2323(the)X
-2441(sentence.)X
-776 5172(Options:)N
-1136(None.)X
-3 f
-576 5352([count])N
-841(\))X
-1 f
-776 5442(Move)N
-983(forward)X
-7 f
-1258(count)X
-1 f
-1518(sentences.)X
-776 5622(The)N
-3 f
-922(\))X
-1 f
-970(command)X
-1307(is)X
-1382(an)X
-1480(absolute)X
-1769(movement.)X
-2169(The)X
-3 f
-2316(\))X
-1 f
-2365(command)X
-2703(may)X
-2863(be)X
-2961(used)X
-3130(as)X
-3219(the)X
-3339(motion)X
-3587(component)X
-3965(of)X
-776 5712(other)N
-3 f
-963(vi)X
-1 f
-1047(commands,)X
-1436(in)X
-1520(which)X
-1738(case)X
-1899(any)X
-2036(text)X
-2177(copied)X
-2412(into)X
-2557(a)X
-2614(buffer)X
-2832(is)X
-2906(character)X
-3223(oriented,)X
-3527(unless)X
-3748(the)X
-3867(start-)X
-776 5802(ing)N
-901(point)X
-1088(of)X
-1179(the)X
-1301(region)X
-1530(is)X
-1607(the)X
-1729(\256rst)X
-1877(character)X
-2197(in)X
-2283(the)X
-2405(line,)X
-2569(in)X
-2655(which)X
-2875(case)X
-3038(it)X
-3106(is)X
-3183(line)X
-3327(oriented.)X
-3654(In)X
-3745(the)X
-3867(latter)X
-
-18 p
-%%Page: 18 17
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-18)N
-2826(Nvi/Nex)X
-3122 0.3906(Reference)AX
-3487(\(Vi)X
-3614(Commands\))X
-1 f
-776 762(case,)N
-961(if)X
-1036(the)X
-1160(stopping)X
-1461(point)X
-1651(of)X
-1744(the)X
-1868(region)X
-2099(is)X
-2178(also)X
-2333(the)X
-2457(\256rst)X
-2607(character)X
-2929(in)X
-3017(the)X
-3141(line,)X
-3307(it)X
-3376(is)X
-3454(adjusted)X
-3746(to)X
-3833(be)X
-3934(the)X
-776 852(end)N
-912(of)X
-999(the)X
-1117(line)X
-1257(immediately)X
-1677(before)X
-1903(it.)X
-776 1032(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(containing)X
-1956(the)X
-2074(beginning)X
-2414(of)X
-2501(the)X
-2619(sentence.)X
-776 1122(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(of)X
-2323(the)X
-2441(sentence.)X
-776 1212(Options:)N
-1136(None.)X
-3 f
-576 1392([count])N
-841(,)X
-1 f
-776 1482(Reverse)N
-1055(\256nd)X
-1199(character)X
-7 f
-1515(count)X
-1 f
-1775(times.)X
-2008(Reverse)X
-2288(the)X
-2407(last)X
-3 f
-2539(F)X
-1 f
-2588(,)X
-3 f
-2629(f)X
-1 f
-2656(,)X
-3 f
-2697(T)X
-1 f
-2771(or)X
-3 f
-2859(t)X
-1 f
-2907(command,)X
-3264(searching)X
-3593(the)X
-3712(other)X
-3898(way)X
-776 1572(in)N
-858(the)X
-976(line,)X
-7 f
-1136(count)X
-1 f
-1396(times.)X
-776 1752(The)N
-3 f
-922(,)X
-1 f
-963(command)X
-1300(may)X
-1460(be)X
-1558(used)X
-1727(as)X
-1816(the)X
-1936(motion)X
-2184(component)X
-2562(of)X
-2651(other)X
-3 f
-2838(vi)X
-1 f
-2922(commands,)X
-3311(in)X
-3395(which)X
-3613(case)X
-3774(any)X
-3912(text)X
-776 1842(copied)N
-1010(into)X
-1154(a)X
-1210(buffer)X
-1427(is)X
-1500(character)X
-1816(oriented.)X
-776 2022(Line:)N
-1136(Unchanged.)X
-776 2112(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458 0.3068(searched-for)AX
-1881(character.)X
-776 2202(Options:)N
-1136(None.)X
-3 f
-576 2382([count])N
-9 f
-841(-)X
-843(-)X
-1 f
-776 2472(Move)N
-983(to)X
-1065(\256rst)X
-1209(nonblank)X
-1527(of)X
-1614(the)X
-1732(previous)X
-2028(line,)X
-7 f
-2188(count)X
-1 f
-2448(times.)X
-776 2652(This)N
-938(is)X
-1011(an)X
-1107(error)X
-1284(if)X
-1353(the)X
-1471(movement)X
-1829(is)X
-1902(past)X
-2051(the)X
-2169(beginning)X
-2509(of)X
-2596(the)X
-2714(\256le.)X
-776 2832(The)N
-3 f
-922(-)X
-1 f
-970(command)X
-1307(may)X
-1466(be)X
-1563(used)X
-1731(as)X
-1819(the)X
-1938(motion)X
-2185(component)X
-2562(of)X
-2651(other)X
-3 f
-2838(vi)X
-1 f
-2922(commands,)X
-3311(in)X
-3395(which)X
-3613(case)X
-3774(any)X
-3912(text)X
-776 2922(copied)N
-1010(into)X
-1154(a)X
-1210(buffer)X
-1427(is)X
-1500(line)X
-1640(oriented.)X
-776 3102(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(current)X
-1706(line)X
-1846(minus)X
-7 f
-2061(count)X
-1 f
-(.)S
-776 3192(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(in)X
-2318(the)X
-2436(line.)X
-776 3282(Options:)N
-1136(None.)X
-3 f
-576 3462([count])N
-841(.)X
-1 f
-776 3552(Repeat)N
-1031(the)X
-1161(last)X
-3 f
-1304(vi)X
-1 f
-1398(command)X
-1746(that)X
-1898(modi\256ed)X
-2214(text.)X
-2406(The)X
-2563(repeated)X
-2869(command)X
-3218(may)X
-3389(be)X
-3498(a)X
-3567(command)X
-3916(and)X
-776 3642(motion)N
-1030(component)X
-1413(combination.)X
-1880(If)X
-7 f
-1961(count)X
-1 f
-2228(is)X
-2308(speci\256ed,)X
-2640(it)X
-2711(replaces)X
-2 f
-3002(both)X
-1 f
-3171(the)X
-3296(count)X
-3501(speci\256ed)X
-3813(for)X
-3934(the)X
-776 3732(repeated)N
-1093(command,)X
-1473(and,)X
-1653(if)X
-1746(applicable,)X
-2140(for)X
-2278(the)X
-2420(repeated)X
-2737(motion)X
-3007(component.)X
-3448(If)X
-7 f
-3547(count)X
-1 f
-3832(is)X
-3930(not)X
-776 3822(speci\256ed,)N
-1101(the)X
-1219(counts)X
-1448(originally)X
-1779(speci\256ed)X
-2084(to)X
-2166(the)X
-2284(command)X
-2620(being)X
-2818(repeated)X
-3111(are)X
-3230(used)X
-3397(again.)X
-776 4002(As)N
-887(a)X
-945(special)X
-1190(case,)X
-1371(if)X
-1442(the)X
-3 f
-1562(.)X
-1 f
-1624(command)X
-1962(is)X
-2037(executed)X
-2345(immediately)X
-2767(after)X
-2937(the)X
-3 f
-3057(u)X
-1 f
-3123(command,)X
-3482(the)X
-3603(change)X
-3854(log)X
-3979(is)X
-776 4092(rolled)N
-983(forward)X
-1258(or)X
-1345(backward,)X
-1698(depending)X
-2052(on)X
-2152(the)X
-2270(action)X
-2486(of)X
-2573(the)X
-3 f
-2691(u)X
-1 f
-2755(command.)X
-776 4272(Line:)N
-1136(Set)X
-1258(as)X
-1345(described)X
-1673(for)X
-1787(the)X
-1905(repeated)X
-2198(command.)X
-776 4362(Column:)N
-1136(Set)X
-1258(as)X
-1345(described)X
-1673(for)X
-1787(the)X
-1905(repeated)X
-2198(command.)X
-776 4452(Options:)N
-1136(None.)X
-3 f
-576 4632 0.1776(/RE<carriage-return>)AN
-576 4722(/RE/)N
-751 0.2500([offset]<carriage-return>)AX
-576 4812 0.1908(?RE<carriage-return>)AN
-576 4902(?RE?)N
-787 0.2500([offset]<carriage-return>)AX
-576 4992(N)N
-576 5082(n)N
-1 f
-776 5172(Search)N
-1017(forward)X
-1295(or)X
-1385(backward)X
-1721(for)X
-1838(a)X
-1897(regular)X
-2148(expression.)X
-2554(The)X
-2702(commands)X
-3072(beginning)X
-3415(with)X
-3580(a)X
-3639(slash)X
-3822(\(``)X
-7 f
-3903(/)X
-1 f
-(''\))S
-776 5262(character)N
-1095(are)X
-1217(forward)X
-1495(searches,)X
-1811(the)X
-1932(commands)X
-2302(beginning)X
-2644(with)X
-2808(a)X
-2866(question)X
-3159(mark)X
-3346(\(``)X
-7 f
-3427(?)X
-1 f
-(''\))S
-3598(are)X
-3719(backward)X
-776 5352(searches.)N
-3 f
-1117(Vi)X
-1 f
-1225(prompts)X
-1515(with)X
-1685(the)X
-1811(leading)X
-2075(character)X
-2399(on)X
-2507(the)X
-2633(last)X
-2772(line)X
-2920(of)X
-3015(the)X
-3142(screen)X
-3377(for)X
-3500(a)X
-3565(string.)X
-3816(It)X
-3894(then)X
-776 5442(searches)N
-1071(forward)X
-1348(or)X
-1437(backward)X
-1772(in)X
-1856(the)X
-1976(\256le)X
-2100(for)X
-2216(the)X
-2336(next)X
-2496 0.3611(occurrence)AX
-2872(of)X
-2961(the)X
-3081(string,)X
-3305(which)X
-3522(is)X
-3596(interpreted)X
-3965(as)X
-776 5532(a)N
-832(Basic)X
-1030(Regular)X
-1304(Expression.)X
-776 5712(The)N
-3 f
-928(/)X
-1 f
-977(and)X
-3 f
-1120(?)X
-1 f
-1207(commands)X
-1581(are)X
-1707(absolute)X
-2001(movements.)X
-2437(They)X
-2630(may)X
-2796(be)X
-2900(used)X
-3075(as)X
-3170(the)X
-3296(motion)X
-3550(components)X
-3965(of)X
-776 5802(other)N
-3 f
-974(vi)X
-1 f
-1069(commands,)X
-1469(in)X
-1564(which)X
-1793(case)X
-1965(any)X
-2114(text)X
-2267(copied)X
-2514(into)X
-2671(a)X
-2740(buffer)X
-2970(is)X
-3056(character)X
-3385(oriented,)X
-3701(unless)X
-3934(the)X
-
-19 p
-%%Page: 19 18
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Vi)X
-1364(Commands\))X
-3658(USD:13-19)X
-1 f
-776 762(search)N
-1007(started)X
-1246(and)X
-1387(ended)X
-1604(on)X
-1709(the)X
-1832(\256rst)X
-1981(column)X
-2246(of)X
-2338(a)X
-2399(line,)X
-2564(in)X
-2651(which)X
-2872(case)X
-3036(it)X
-3105(is)X
-3183(line)X
-3328(oriented.)X
-3657(In)X
-3750(addition,)X
-776 852(forward)N
-1056(searches)X
-1354(ending)X
-1597(at)X
-1680(the)X
-1803(\256rst)X
-1951(character)X
-2271(of)X
-2362(a)X
-2422(line,)X
-2586(and)X
-2726(backward)X
-3063(searches)X
-3360(beginning)X
-3704(at)X
-3786(the)X
-3908(\256rst)X
-776 942(character)N
-1098(in)X
-1186(the)X
-1310(line,)X
-1476(are)X
-1601(corrected)X
-1927(to)X
-2015(begin)X
-2219(or)X
-2312(end)X
-2454(at)X
-2538(the)X
-2662(last)X
-2799(character)X
-3121(of)X
-3214(the)X
-3339(previous)X
-3642(line.)X
-3829(\(Note,)X
-776 1032(forward)N
-1061(and)X
-1207(backward)X
-1550(searches)X
-1853(can)X
-1995(occur)X
-2204(for)X
-2328(both)X
-3 f
-2500(/)X
-1 f
-2552(and)X
-3 f
-2698(?)X
-1 f
-2787(commands,)X
-3183(if)X
-3261(the)X
-3 f
-3388(wrapscan)X
-1 f
-3746(option)X
-3979(is)X
-776 1122(set.\))N
-776 1302(If)N
-852(an)X
-950(offset)X
-1155(from)X
-1333(the)X
-1453(matched)X
-1747(line)X
-1889(is)X
-1964(speci\256ed)X
-2271(\(i.e.)X
-2418(a)X
-2476(trailing)X
-2729(``)X
-7 f
-2783(/)X
-1 f
-('')S
-2907(or)X
-2996(``)X
-7 f
-3050(?)X
-1 f
-('')S
-3194(character)X
-3512(is)X
-3587(followed)X
-3894(by)X
-3996(a)X
-776 1392(signed)N
-1009(offset\),)X
-1263(the)X
-1385(buffer)X
-1606(will)X
-1754(always)X
-2001(be)X
-2100(line)X
-2243(oriented)X
-2529(\(e.g.)X
-2715(``)X
-7 f
-2769(/string/+0)X
-1 f
-('')S
-3326(will)X
-3473(always)X
-3719(guarantee)X
-776 1482(a)N
-832(line)X
-972(orientation\).)X
-776 1662(The)N
-3 f
-921(n)X
-1 f
-985(command)X
-1321(repeats)X
-1569(the)X
-1687(previous)X
-1983(search.)X
-776 1842(The)N
-3 f
-921(N)X
-1 f
-999(command)X
-1335(repeats)X
-1583(the)X
-1701(previous)X
-1997(search,)X
-2243(but)X
-2365(in)X
-2447(the)X
-2565(reverse)X
-2818(direction.)X
-776 2022(Missing)N
-1194(RE's)X
-1515(\(e.g.)X
-1839(``)X
-7 f
-1893(//<carriage-return>)X
-1 f
-('',)S
-3040(``)X
-7 f
-3094(/<carriage-return>)X
-1 f
-('',)S
-776 2112(``)N
-7 f
-830(??<carriage-return>)X
-1 f
-('',)S
-1847(or)X
-1945(``)X
-7 f
-1999(?<carriage-return>)X
-1 f
-('')S
-2948(search)X
-3185(for)X
-3310(the)X
-3439(last)X
-3581(search)X
-3818(RE,)X
-3970(in)X
-776 2202(the)N
-894(indicated)X
-1208(direction.)X
-776 2382(Searches)N
-1082(may)X
-1240(be)X
-1336(interrupted)X
-1708(using)X
-1901(the)X
-7 f
-2019(<interrupt>)X
-1 f
-2567(character.)X
-776 2562(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(in)X
-1680(which)X
-1896(the)X
-2014(match)X
-2230(occurred.)X
-776 2652(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(character)X
-1918(of)X
-2005(the)X
-2123(matched)X
-2415(string.)X
-776 2742(Options:)N
-1136(Affected)X
-1438(by)X
-1538(the)X
-3 f
-1656(edcompatible)X
-1 f
-2114(,)X
-3 f
-2154(extended)X
-1 f
-2461(,)X
-3 f
-2501(ignorecase)X
-1 f
-2862(,)X
-3 f
-2902(magic)X
-1 f
-3107(,)X
-3147(and)X
-3 f
-3283(wrapscan)X
-1 f
-3632(options.)X
-3 f
-576 2922(0)N
-1 f
-776 3012(Move)N
-985(to)X
-1069(the)X
-1189(\256rst)X
-1335(character)X
-1654(in)X
-1739(the)X
-1860(current)X
-2111(line.)X
-2294(It)X
-2366(is)X
-2442(not)X
-2567(an)X
-2666(error)X
-2846(to)X
-2931(use)X
-3061(the)X
-3 f
-3182(0)X
-1 f
-3245(command)X
-3584(when)X
-3781(the)X
-3902(cur-)X
-776 3102(sor)N
-894(is)X
-967(on)X
-1067(the)X
-1185(\256rst)X
-1329(character)X
-1645(in)X
-1727(the)X
-1845(line,)X
-776 3282(The)N
-3 f
-923(0)X
-1 f
-986(command)X
-1325(may)X
-1486(be)X
-1585(used)X
-1755(as)X
-1845(the)X
-1966(motion)X
-2215(component)X
-2594(of)X
-2684(other)X
-3 f
-2872(vi)X
-1 f
-2957(commands,)X
-3347(in)X
-3432(which)X
-3651(case)X
-3813(it)X
-3880(is)X
-3956(an)X
-776 3372(error)N
-953(if)X
-1022(the)X
-1140(cursor)X
-1361(is)X
-1434(on)X
-1534(the)X
-1652(\256rst)X
-1796(character)X
-2112(in)X
-2194(the)X
-2312(line.)X
-776 3552(Line:)N
-1136(Unchanged.)X
-776 3642(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(character)X
-1918(in)X
-2000(the)X
-2118(line.)X
-776 3732(Options:)N
-1136(None.)X
-3 f
-576 3912(:)N
-1 f
-776 4002(Execute)N
-1055(an)X
-1152(ex)X
-1249(command.)X
-3 f
-1626(Vi)X
-1 f
-1727(prompts)X
-2010(for)X
-2125(an)X
-3 f
-2222(ex)X
-1 f
-2319(command)X
-2656(on)X
-2757(the)X
-2876(last)X
-3008(line)X
-3149(of)X
-3237(the)X
-3356(screen,)X
-3603(using)X
-3797(a)X
-3854(colon)X
-776 4092(\(``)N
-7 f
-857(:)X
-1 f
-(''\))S
-1029(character.)X
-1408(The)X
-1575(command)X
-1933(is)X
-2028(terminated)X
-2413(by)X
-2535(a)X
-7 f
-2613(<carriage-return>)X
-1 f
-(,)S
-7 f
-3491(<newline>)X
-1 f
-3965(or)X
-7 f
-776 4182(<escape>)N
-1 f
-1184(character;)X
-1526(all)X
-1630(of)X
-1721(these)X
-1910(characters)X
-2261(may)X
-2423(be)X
-2523(escaped)X
-2802(by)X
-2906(using)X
-3103(a)X
-7 f
-3164(<literal)X
-3601(next>)X
-1 f
-3866(char-)X
-776 4272(acter.)N
-993(The)X
-1138(command)X
-1474(is)X
-1547(then)X
-1705(executed.)X
-776 4452(If)N
-850(the)X
-3 f
-968(ex)X
-1 f
-1064(command)X
-1400(writes)X
-1616(to)X
-1698(the)X
-1816(screen,)X
-3 f
-2063(vi)X
-1 f
-2146(will)X
-2291(prompt)X
-2543(the)X
-2662(user)X
-2817(for)X
-2932(a)X
-7 f
-2989(<carriage-return>)X
-1 f
-3826(before)X
-776 4542(continuing)N
-1144(when)X
-1344(the)X
-3 f
-1468(ex)X
-1 f
-1570(command)X
-1912(\256nishes.)X
-2222(Large)X
-2436(amounts)X
-2733(of)X
-2826(output)X
-3056(from)X
-3238(the)X
-3 f
-3362(ex)X
-1 f
-3464(command)X
-3806(will)X
-3956(be)X
-776 4632(paged)N
-994(for)X
-1114(the)X
-1238(user,)X
-1418(and)X
-1560(the)X
-1684(user)X
-1844(prompted)X
-2177(for)X
-2297(a)X
-7 f
-2359(<carriage-return>)X
-1 f
-3201(or)X
-7 f
-3294(<space>)X
-1 f
-3657(key)X
-3800(to)X
-3889(con-)X
-776 4722(tinue.)N
-999(In)X
-1089(some)X
-1281(cases,)X
-1494(a)X
-1553(quit)X
-1700(\(normally)X
-2039(a)X
-2098(``q'')X
-2269 0.3750(character\))AX
-2615(or)X
-7 f
-2705(<interrupt>)X
-1 f
-3256(may)X
-3417(be)X
-3515(entered)X
-3774(to)X
-3858(inter-)X
-776 4812(rupt)N
-925(the)X
-3 f
-1043(ex)X
-1 f
-1139(command.)X
-776 4992(When)N
-988(the)X
-3 f
-1106(ex)X
-1 f
-1202(command)X
-1538(\256nishes,)X
-1822(and)X
-1958(the)X
-2076(user)X
-2230(is)X
-2303(prompted)X
-2631(to)X
-2714(resume)X
-2967(visual)X
-3179(mode,)X
-3398(it)X
-3463(is)X
-3537(also)X
-3687(possible)X
-3970(to)X
-776 5082(enter)N
-957(another)X
-1218(``)X
-7 f
-1272(:)X
-1 f
-('')S
-1394(character)X
-1710(followed)X
-2015(by)X
-2115(another)X
-3 f
-2376(ex)X
-1 f
-2472(command.)X
-776 5262(Line:)N
-1136(The)X
-1281(current)X
-1529(line)X
-1669(is)X
-1742(set)X
-1851(as)X
-1938(described)X
-2266(for)X
-2380(the)X
-3 f
-2498(ex)X
-1 f
-2594(command.)X
-776 5352(Column:)N
-1136(The)X
-1281(current)X
-1529(column)X
-1789(is)X
-1862(set)X
-1971(as)X
-2058(described)X
-2386(for)X
-2500(the)X
-3 f
-2618(ex)X
-1 f
-2714(command.)X
-776 5442(Options:)N
-1136(None.)X
-3 f
-576 5622([count])N
-841(;)X
-1 f
-776 5712(Repeat)N
-1025(the)X
-1149(last)X
-1286(character)X
-1608(\256nd)X
-7 f
-1758(count)X
-1 f
-2024(times.)X
-2263(The)X
-2415(last)X
-2553(character)X
-2876(\256nd)X
-3027(is)X
-3107(one)X
-3250(of)X
-3344(the)X
-3 f
-3469(F)X
-1 f
-3518(,)X
-3 f
-3565(f)X
-1 f
-3592(,)X
-3 f
-3639(T)X
-1 f
-3719(or)X
-3 f
-3813(t)X
-1 f
-3867(com-)X
-776 5802(mands.)N
-
-20 p
-%%Page: 20 19
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-20)N
-2826(Nvi/Nex)X
-3122 0.3906(Reference)AX
-3487(\(Vi)X
-3614(Commands\))X
-1 f
-776 762(The)N
-3 f
-922(;)X
-1 f
-970(command)X
-1307(may)X
-1466(be)X
-1563(used)X
-1731(as)X
-1819(the)X
-1938(motion)X
-2185(component)X
-2562(of)X
-2651(other)X
-3 f
-2838(vi)X
-1 f
-2922(commands,)X
-3311(in)X
-3395(which)X
-3613(case)X
-3774(any)X
-3912(text)X
-776 852(copied)N
-1010(into)X
-1154(a)X
-1210(buffer)X
-1427(is)X
-1500(character)X
-1816(oriented.)X
-776 1032(Line:)N
-1136(Unchanged.)X
-776 1122(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458 0.3068(searched-for)AX
-1881(character.)X
-776 1212(Options:)N
-1136(None.)X
-3 f
-576 1392([count])N
-841(<)X
-907(motion)X
-576 1482([count])N
-841(>)X
-907(motion)X
-1 f
-776 1572(Shift)N
-956(lines)X
-1132(left)X
-1264(or)X
-1357(right.)X
-1574(Shift)X
-1755(the)X
-1879(number)X
-2150(of)X
-2243(lines)X
-2420(in)X
-2508(the)X
-2632(region)X
-2863(speci\256ed)X
-3174(by)X
-3280(the)X
-3404(motion)X
-3656(component,)X
-776 1662(times)N
-7 f
-980(count)X
-1 f
-(,)S
-1271(left)X
-1409(\(for)X
-1561(the)X
-3 f
-1690(<)X
-1 f
-1767(command\))X
-2141(or)X
-2239(right)X
-2421(\(for)X
-2573(the)X
-3 f
-2702(>)X
-1 f
-2778(command\))X
-3151(by)X
-3261(the)X
-3389(number)X
-3664(of)X
-3761(columns)X
-776 1752(speci\256ed)N
-1086(by)X
-1191(the)X
-3 f
-1314(shiftwidth)X
-1 f
-1685(option.)X
-1954(Only)X
-2139(whitespace)X
-2521(characters)X
-2873(are)X
-2997(deleted)X
-3255(when)X
-3455(shifting)X
-3725(left;)X
-3880(once)X
-776 1842(the)N
-901(\256rst)X
-1052(character)X
-1375(in)X
-1464(the)X
-1589(line)X
-1736(contains)X
-2030(a)X
-2092(nonblank)X
-2416(character,)X
-2758(the)X
-3 f
-2882(shift)X
-1 f
-3059(will)X
-3209(succeed,)X
-3510(but)X
-3638(the)X
-3762(line)X
-3908(will)X
-776 1932(not)N
-898(be)X
-994(modi\256ed.)X
-776 2112(Line:)N
-1136(Unchanged.)X
-776 2202(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(in)X
-2318(the)X
-2436(line.)X
-776 2292(Options:)N
-1136(Affected)X
-1438(by)X
-1538(the)X
-3 f
-1656(shiftwidth)X
-1 f
-2022(option.)X
-3 f
-576 2472(@)N
-670(buffer)X
-1 f
-776 2562(Execute)N
-1065(a)X
-1131(named)X
-1375(buffer.)X
-1642(Execute)X
-1931(the)X
-2059(named)X
-2303(buffer)X
-2530(as)X
-3 f
-2627(vi)X
-1 f
-2719(commands.)X
-3136(The)X
-3292(buffer)X
-3520(may)X
-3689(include)X
-3 f
-3956(ex)X
-1 f
-776 2652(commands,)N
-1170(too,)X
-1319(but)X
-1448(they)X
-1613(must)X
-1795(be)X
-1898(expressed)X
-2241(as)X
-2334(a)X
-3 f
-2396(:)X
-1 f
-2449(command.)X
-2831(If)X
-2911(the)X
-3035(buffer)X
-3258(is)X
-3337(line)X
-3483(oriented,)X
-7 f
-3792(<new-)X
-776 2742(line>)N
-1 f
-1054(characters)X
-1419(are)X
-1556(logically)X
-1874(appended)X
-2220(to)X
-2320(each)X
-2506(line)X
-2664(of)X
-2769(the)X
-2905(buffer.)X
-3180(If)X
-3272(the)X
-3408(buffer)X
-3644(is)X
-3736(character)X
-776 2832(oriented,)N
-7 f
-1079(<newline>)X
-1 f
-1531(characters)X
-1878(are)X
-1997(logically)X
-2297(appended)X
-2625(to)X
-2707(all)X
-2807(but)X
-2929(the)X
-3047(last)X
-3178(line)X
-3318(in)X
-3400(the)X
-3518(buffer.)X
-776 3012(If)N
-861(the)X
-990(buffer)X
-1218(name)X
-1423(is)X
-1507(``)X
-7 f
-1561(@)X
-1 f
-('',)S
-1714(or)X
-1812(``)X
-7 f
-1866(*)X
-1 f
-('',)S
-2019(then)X
-2188(the)X
-2317(last)X
-2459(buffer)X
-2687(executed)X
-3004(shall)X
-3186(be)X
-3293(used.)X
-3511(It)X
-3591(is)X
-3675(an)X
-3782(error)X
-3970(to)X
-776 3102(specify)N
-1033(``)X
-7 f
-1087(@@)X
-1 f
-('')S
-1262(or)X
-1354(``)X
-7 f
-1408(**)X
-1 f
-('')S
-1583(if)X
-1657(there)X
-1843(were)X
-2025(no)X
-2130(buffer)X
-2351(previous)X
-2651(executions.)X
-3058(The)X
-3207(text)X
-3351(of)X
-3442(a)X
-3502(macro)X
-3727(may)X
-3889(con-)X
-776 3192(tain)N
-919(an)X
-3 f
-1019(@)X
-1 f
-1117(command,)X
-1477(and)X
-1617(it)X
-1685(is)X
-1762(possible)X
-2048(to)X
-2134(create)X
-2351(in\256nite)X
-2601(loops)X
-2798(in)X
-2884(this)X
-3023(manner.)X
-3328(\(The)X
-7 f
-3504(<interrupt>)X
-1 f
-776 3282(character)N
-1092(may)X
-1250(be)X
-1346(used)X
-1513(to)X
-1595(interrupt)X
-1891(the)X
-2009(loop.\))X
-776 3462(Line:)N
-1136(The)X
-1281(current)X
-1529(line)X
-1669(is)X
-1742(set)X
-1851(as)X
-1938(described)X
-2266(for)X
-2380(the)X
-2498(command\(s\).)X
-776 3552(Column:)N
-1136(The)X
-1281(current)X
-1529(column)X
-1789(is)X
-1862(set)X
-1971(as)X
-2058(described)X
-2386(for)X
-2500(the)X
-2618(command\(s\).)X
-776 3642(Options:)N
-1136(None.)X
-3 f
-576 3822([count])N
-841(A)X
-1 f
-776 3912(Enter)N
-981(input)X
-1176(mode,)X
-1405(appending)X
-1770(the)X
-1899(text)X
-2050(after)X
-2229(the)X
-2358(end)X
-2505(of)X
-2603(the)X
-2732(line.)X
-2923(If)X
-7 f
-3008(count)X
-1 f
-3279(is)X
-3363(speci\256ed,)X
-3699(the)X
-3828(text)X
-3979(is)X
-776 4002(repeatedly)N
-1131(input)X
-7 f
-1315(count)X
-1603(-)X
-1699(1)X
-1 f
-1767(more)X
-1952(times)X
-2145(after)X
-2313(input)X
-2497(mode)X
-2695(is)X
-2768(exited.)X
-776 4182(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(line)X
-1729(upon)X
-1909(which)X
-2125(characters)X
-2472(were)X
-2649(entered.)X
-776 4272(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(character)X
-1905(entered.)X
-776 4362(Options:)N
-1136(Affected)X
-1440(by)X
-1542(the)X
-3 f
-1662(altwerase)X
-1 f
-1988(,)X
-3 f
-2030(autoindent)X
-1 f
-2398(,)X
-3 f
-2440(beautify)X
-1 f
-(,)S
-3 f
-2762(showmatch)X
-1 f
-3149(,)X
-3 f
-3191(ttywerase)X
-1 f
-3545(and)X
-3 f
-3684(wrapmar-)X
-1136 4452(gin)N
-1 f
-1262(options.)X
-3 f
-576 4632([count])N
-841(B)X
-1 f
-776 4722(Move)N
-995(backward)X
-7 f
-1340(count)X
-1 f
-1612(bigwords.)X
-1982(Move)X
-2201(the)X
-2331(cursor)X
-2564(backward)X
-2909(to)X
-3003(the)X
-3133(beginning)X
-3485(of)X
-3584(a)X
-3652(bigword)X
-3952(by)X
-776 4812(repeating)N
-1096(the)X
-1215(following)X
-1547(algorithm:)X
-1901(if)X
-1971(the)X
-2090(current)X
-2339(position)X
-2617(is)X
-2691(at)X
-2770(the)X
-2889(beginning)X
-3230(of)X
-3318(a)X
-3374(bigword)X
-3661(or)X
-3748(the)X
-3866(char-)X
-776 4902(acter)N
-955(at)X
-1036(the)X
-1157(current)X
-1408(position)X
-1688(cannot)X
-1925(be)X
-2024(part)X
-2172(of)X
-2262(a)X
-2321(bigword,)X
-2631(move)X
-2832(to)X
-2917(the)X
-3038(\256rst)X
-3185(character)X
-3504(of)X
-3594(the)X
-3715(preceding)X
-776 4992(bigword.)N
-1105(Otherwise,)X
-1477(move)X
-1677(to)X
-1761(the)X
-1881(\256rst)X
-2027(character)X
-2345(of)X
-2434(the)X
-2554(bigword)X
-2843(at)X
-2923(the)X
-3043(current)X
-3293(position.)X
-3612(If)X
-3688(no)X
-3790(preced-)X
-776 5082(ing)N
-908(bigword)X
-1205(exists)X
-1418(on)X
-1529(the)X
-1658(current)X
-1917(line,)X
-2088(move)X
-2297(to)X
-2390(the)X
-2519(\256rst)X
-2674(character)X
-3001(of)X
-3099(the)X
-3228(last)X
-3370(bigword)X
-3668(on)X
-3779(the)X
-3908(\256rst)X
-776 5172(preceding)N
-1113(line)X
-1253(that)X
-1393(contains)X
-1680(a)X
-1736(bigword.)X
-776 5352(The)N
-3 f
-921(B)X
-1 f
-994(command)X
-1330(may)X
-1488(be)X
-1584(used)X
-1751(as)X
-1838(the)X
-1956(motion)X
-2202(component)X
-2578(of)X
-2665(other)X
-3 f
-2850(vi)X
-1 f
-2932(commands,)X
-3319(in)X
-3401(which)X
-3617(case)X
-3776(any)X
-3912(text)X
-776 5442(copied)N
-1010(into)X
-1154(a)X
-1210(buffer)X
-1427(is)X
-1500(character)X
-1816(oriented.)X
-776 5622(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(containing)X
-1956(the)X
-2074(word)X
-2259(selected.)X
-776 5712(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(character)X
-1918(of)X
-2005(the)X
-2123(word)X
-2308(selected.)X
-
-21 p
-%%Page: 21 20
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Vi)X
-1364(Commands\))X
-3658(USD:13-21)X
-1 f
-776 762(Options:)N
-1136(None.)X
-3 f
-576 942([buffer])N
-864([count])X
-1129(C)X
-1 f
-776 1032(Change)N
-1058(text)X
-1215(from)X
-1408(the)X
-1543(current)X
-1808(position)X
-2102(to)X
-2201(the)X
-2336(end-of-line.)X
-2770(If)X
-7 f
-2862(count)X
-1 f
-3140(is)X
-3231(speci\256ed,)X
-3574(the)X
-3710(input)X
-3912(text)X
-776 1122(replaces)N
-1060(from)X
-1236(the)X
-1354(current)X
-1602(position)X
-1879(to)X
-1961(the)X
-2079(end-of-line,)X
-2476(plus)X
-7 f
-2629(count)X
-2917(-)X
-3013(1)X
-1 f
-3081(subsequent)X
-3457(lines.)X
-776 1302(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(line)X
-1729(upon)X
-1909(which)X
-2125(characters)X
-2472(were)X
-2649(entered.)X
-776 1392(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(character)X
-1905(entered.)X
-776 1482(Options:)N
-1136(Affected)X
-1440(by)X
-1542(the)X
-3 f
-1662(altwerase)X
-1 f
-1988(,)X
-3 f
-2030(autoindent)X
-1 f
-2398(,)X
-3 f
-2440(beautify)X
-1 f
-(,)S
-3 f
-2762(showmatch)X
-1 f
-3149(,)X
-3 f
-3191(ttywerase)X
-1 f
-3545(and)X
-3 f
-3684(wrapmar-)X
-1136 1572(gin)N
-1 f
-1262(options.)X
-3 f
-576 1752([buffer])N
-864(D)X
-1 f
-776 1842(Delete)N
-1006(text)X
-1146(from)X
-1322(the)X
-1440(current)X
-1688(position)X
-1965(to)X
-2047(the)X
-2165(end-of-line.)X
-776 2022(It)N
-845(is)X
-918(not)X
-1040(an)X
-1136(error)X
-1313(to)X
-1395(execute)X
-1661(the)X
-3 f
-1779(D)X
-1 f
-1857(command)X
-2193(on)X
-2293(an)X
-2389(empty)X
-2609(line.)X
-776 2202(Line:)N
-1136(Unchanged.)X
-776 2292(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(character)X
-1774(before)X
-2000(the)X
-2118(current)X
-2367(character,)X
-2704(or,)X
-2812(column)X
-3073(1)X
-3134(if)X
-3204(the)X
-3323(cursor)X
-3545(was)X
-3691(on)X
-3792(column)X
-1136 2382(1.)N
-776 2472(Options:)N
-1136(None.)X
-3 f
-576 2652([count])N
-841(E)X
-1 f
-776 2742(Move)N
-983(forward)X
-7 f
-1258(count)X
-1 f
-1518(end-of-bigwords.)X
-2113(Move)X
-2320(the)X
-2438(cursor)X
-2659(forward)X
-2935(to)X
-3018(the)X
-3137(end)X
-3274(of)X
-3362(a)X
-3419(bigword)X
-3707(by)X
-3808(repeat-)X
-776 2832(ing)N
-906(the)X
-1032(following)X
-1371(algorithm:)X
-1732(if)X
-1809(the)X
-1935(current)X
-2191(position)X
-2476(is)X
-2557(the)X
-2683(end)X
-2827(of)X
-2922(a)X
-2986(bigword)X
-3281(or)X
-3376(the)X
-3502(character)X
-3826(at)X
-3912(that)X
-776 2922(position)N
-1061(cannot)X
-1303(be)X
-1407(part)X
-1560(of)X
-1655(a)X
-1719(bigword,)X
-2034(move)X
-2240(to)X
-2331(the)X
-2458(last)X
-2598(character)X
-2923(of)X
-3019(the)X
-3146(following)X
-3486(bigword.)X
-3822(Other-)X
-776 3012(wise,)N
-973(move)X
-1181(to)X
-1273(the)X
-1401(last)X
-1542(character)X
-1868(of)X
-1965(the)X
-2093(bigword)X
-2390(at)X
-2477(the)X
-2604(current)X
-2861(position.)X
-3187(If)X
-3270(no)X
-3379(succeeding)X
-3765(bigword)X
-776 3102(exists)N
-984(on)X
-1090(the)X
-1214(current)X
-1468(line,)X
-1634(move)X
-1838(to)X
-1927(the)X
-2052(last)X
-2190(character)X
-2513(of)X
-2607(the)X
-2732(\256rst)X
-2883(bigword)X
-3177(on)X
-3284(the)X
-3409(next)X
-3574(following)X
-3912(line)X
-776 3192(that)N
-916(contains)X
-1203(a)X
-1259(bigword.)X
-776 3372(The)N
-3 f
-921(E)X
-1 f
-994(command)X
-1330(may)X
-1488(be)X
-1584(used)X
-1751(as)X
-1838(the)X
-1956(motion)X
-2202(component)X
-2578(of)X
-2665(other)X
-3 f
-2850(vi)X
-1 f
-2932(commands,)X
-3319(in)X
-3401(which)X
-3617(case)X
-3776(any)X
-3912(text)X
-776 3462(copied)N
-1010(into)X
-1154(a)X
-1210(buffer)X
-1427(is)X
-1500(character)X
-1816(oriented.)X
-776 3642(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(containing)X
-1956(the)X
-2074(word)X
-2259(selected.)X
-776 3732(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(character)X
-1905(of)X
-1992(the)X
-2110(word)X
-2295(selected.)X
-776 3822(Options:)N
-1136(None.)X
-3 f
-576 4002([count])N
-841(F)X
-910 0.3125(<character>)AX
-1 f
-776 4092(Search)N
-7 f
-1015(count)X
-1 f
-1275(times)X
-1468(backward)X
-1801(through)X
-2070(the)X
-2188(current)X
-2436(line)X
-2576(for)X
-7 f
-2690(<character>)X
-1 f
-(.)S
-776 4272(The)N
-3 f
-921(F)X
-1 f
-990(command)X
-1326(may)X
-1484(be)X
-1580(used)X
-1747(as)X
-1834(the)X
-1952(motion)X
-2198(component)X
-2574(of)X
-2661(other)X
-3 f
-2846(vi)X
-1 f
-2928(commands,)X
-3315(in)X
-3398(which)X
-3615(case)X
-3775(any)X
-3912(text)X
-776 4362(copied)N
-1010(into)X
-1154(a)X
-1210(buffer)X
-1427(is)X
-1500(character)X
-1816(oriented.)X
-776 4542(Line:)N
-1136(Unchanged.)X
-776 4632(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458 0.3068(searched-for)AX
-1881(character.)X
-776 4722(Options:)N
-1136(None.)X
-3 f
-576 4902([count])N
-841(G)X
-1 f
-776 4992(Move)N
-983(to)X
-1065(line)X
-7 f
-1205(count)X
-1 f
-(,)S
-1485(or)X
-1572(the)X
-1690(last)X
-1821(line)X
-1961(of)X
-2048(the)X
-2166(\256le)X
-2288(if)X
-7 f
-2357(count)X
-1 f
-2617(not)X
-2739(speci\256ed.)X
-776 5172(The)N
-3 f
-924(G)X
-1 f
-1009(command)X
-1348(is)X
-1424(an)X
-1523(absolute)X
-1813(movement.)X
-2214(The)X
-3 f
-2362(G)X
-1 f
-2447(command)X
-2786(may)X
-2947(be)X
-3046(used)X
-3216(as)X
-3306(the)X
-3427(motion)X
-3676(component)X
-776 5262(of)N
-863(other)X
-3 f
-1048(vi)X
-1 f
-1130(commands,)X
-1517(in)X
-1599(which)X
-1815(case)X
-1974(any)X
-2110(text)X
-2250(copied)X
-2484(into)X
-2628(a)X
-2684(buffer)X
-2901(is)X
-2974(line)X
-3114(oriented.)X
-776 5442(Line:)N
-1136(Set)X
-1258(to)X
-7 f
-1340(count)X
-1 f
-(,)S
-1620(if)X
-1689(speci\256ed,)X
-2014(otherwise,)X
-2366(the)X
-2484(last)X
-2615(line.)X
-776 5532(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(in)X
-2318(the)X
-2436(line.)X
-776 5622(Options:)N
-1136(None.)X
-
-22 p
-%%Page: 22 21
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-22)N
-2826(Nvi/Nex)X
-3122 0.3906(Reference)AX
-3487(\(Vi)X
-3614(Commands\))X
-576 762([count])N
-841(H)X
-1 f
-776 852(Move)N
-983(to)X
-1065(the)X
-1183(screen)X
-1409(line)X
-7 f
-1549(count)X
-1837(-)X
-1933(1)X
-1 f
-2001(lines)X
-2172(below)X
-2388(the)X
-2506(top)X
-2628(of)X
-2715(the)X
-2833(screen.)X
-776 1032(The)N
-3 f
-924(H)X
-1 f
-1009(command)X
-1348(is)X
-1424(an)X
-1523(absolute)X
-1813(movement.)X
-2214(The)X
-3 f
-2362(H)X
-1 f
-2447(command)X
-2786(may)X
-2947(be)X
-3046(used)X
-3216(as)X
-3306(the)X
-3427(motion)X
-3676(component)X
-776 1122(of)N
-863(other)X
-3 f
-1048(vi)X
-1 f
-1130(commands,)X
-1517(in)X
-1599(which)X
-1815(case)X
-1974(any)X
-2110(text)X
-2250(copied)X
-2484(into)X
-2628(a)X
-2684(buffer)X
-2901(is)X
-2974(line)X
-3114(oriented.)X
-776 1302(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-7 f
-1598(count)X
-1886(-)X
-1982(1)X
-1 f
-2050(lines)X
-2221(below)X
-2437(the)X
-2555(top)X
-2677(of)X
-2764(the)X
-2882(screen.)X
-776 1392(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(of)X
-2323(the)X
-2 f
-2441(screen)X
-1 f
-2671(line.)X
-776 1482(Options:)N
-1136(None.)X
-3 f
-576 1662([count])N
-841(I)X
-1 f
-776 1752(Enter)N
-971(input)X
-1156(mode,)X
-1375(inserting)X
-1676(the)X
-1795(text)X
-1936(at)X
-2015(the)X
-2134(beginning)X
-2475(of)X
-2564(the)X
-2684(line.)X
-2866(If)X
-7 f
-2942(count)X
-1 f
-3204(is)X
-3279(speci\256ed,)X
-3606(the)X
-3726(text)X
-3868(input)X
-776 1842(is)N
-849(repeatedly)X
-1204(input)X
-7 f
-1388(count)X
-1676(-)X
-1772(1)X
-1 f
-1840(more)X
-2025(times.)X
-776 2022(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(line)X
-1729(upon)X
-1909(which)X
-2125(characters)X
-2472(were)X
-2649(entered.)X
-776 2112(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(character)X
-1905(entered.)X
-776 2202(Options:)N
-1136(None.)X
-3 f
-576 2382([count])N
-841(J)X
-1 f
-776 2472(Join)N
-929(lines.)X
-1140(If)X
-7 f
-1214(count)X
-1 f
-1474(is)X
-1547(speci\256ed,)X
-7 f
-1872(count)X
-1 f
-2132(lines)X
-2303(are)X
-2422(joined;)X
-2664(a)X
-2720(minimum)X
-3050(of)X
-3137(two)X
-3277(lines)X
-3448(are)X
-3568(always)X
-3812(joined,)X
-776 2562(regardless)N
-1122(of)X
-1209(the)X
-1327(value)X
-1521(of)X
-7 f
-1608(count)X
-1 f
-(.)S
-776 2742(If)N
-859(the)X
-986(current)X
-1244(line)X
-1394(ends)X
-1571(with)X
-1743(a)X
-1809(whitespace)X
-2196(character,)X
-2542(all)X
-2652(whitespace)X
-3039(is)X
-3122(stripped)X
-3410(from)X
-3596(the)X
-3724(next)X
-3892(line.)X
-776 2832(Otherwise,)N
-1148(if)X
-1219(the)X
-1338(next)X
-1497(line)X
-1638(starts)X
-1828(with)X
-1991(a)X
-2048(open)X
-2225(parenthesis)X
-2607(\(``)X
-7 f
-2688(\()X
-1 f
-(''\))S
-2838(do)X
-2939(nothing.)X
-3244(Otherwise,)X
-3615(if)X
-3685(the)X
-3804(current)X
-776 2922(line)N
-917(ends)X
-1086(with)X
-1250(a)X
-1308(question)X
-1601(mark)X
-1788(\(``)X
-7 f
-1869(?)X
-1 f
-(''\),)S
-2040(period)X
-2267(\(``)X
-7 f
-2348(.)X
-1 f
-(''\))S
-2519(or)X
-2608(exclamation)X
-3022(point)X
-3208(\(``)X
-7 f
-3289(!)X
-1 f
-(''\),)S
-3460(insert)X
-3660(two)X
-3802(spaces.)X
-776 3012(Otherwise,)N
-1146(insert)X
-1344(a)X
-1400(single)X
-1611(space.)X
-776 3192(It)N
-845(is)X
-918(not)X
-1040(an)X
-1136(error)X
-1313(to)X
-1395(join)X
-1539(lines)X
-1710(past)X
-1859(the)X
-1977(end)X
-2113(of)X
-2200(the)X
-2318(\256le,)X
-2460(i.e.)X
-2578(lines)X
-2749(that)X
-2889(do)X
-2989(not)X
-3111(exist.)X
-776 3372(Line:)N
-1136(Unchanged.)X
-776 3462(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(character)X
-1774(after)X
-1942(the)X
-2060(last)X
-2191(character)X
-2507(of)X
-2594(the)X
-2712(next-to-last)X
-3097(joined)X
-3317(line.)X
-776 3552(Options:)N
-1136(None.)X
-3 f
-576 3732([count])N
-841(L)X
-1 f
-776 3822(Move)N
-983(to)X
-1065(the)X
-1183(screen)X
-1409(line)X
-7 f
-1549(count)X
-1837(-)X
-1933(1)X
-1 f
-2001(lines)X
-2172(above)X
-2384(the)X
-2502(bottom)X
-2748(of)X
-2835(the)X
-2953(screen.)X
-776 4002(The)N
-3 f
-925(L)X
-1 f
-1002(command)X
-1342(is)X
-1419(an)X
-1519(absolute)X
-1810(movement.)X
-2212(The)X
-3 f
-2361(L)X
-1 f
-2438(command)X
-2778(may)X
-2940(be)X
-3040(used)X
-3211(as)X
-3302(the)X
-3425(motion)X
-3676(component)X
-776 4092(of)N
-863(other)X
-3 f
-1048(vi)X
-1 f
-1130(commands,)X
-1517(in)X
-1599(which)X
-1815(case)X
-1974(any)X
-2110(text)X
-2250(copied)X
-2484(into)X
-2628(a)X
-2684(buffer)X
-2901(is)X
-2974(line)X
-3114(oriented.)X
-776 4272(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-7 f
-1598(count)X
-1886(-)X
-1982(1)X
-1 f
-2050(lines)X
-2221(above)X
-2433(the)X
-2551(bottom)X
-2797(of)X
-2884(the)X
-3002(screen.)X
-776 4362(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(of)X
-2323(the)X
-2 f
-2441(screen)X
-1 f
-2671(line.)X
-776 4452(Options:)N
-1136(None.)X
-3 f
-596 4632(M)N
-1 f
-776 4722(Move)N
-983(to)X
-1065(the)X
-1183(screen)X
-1409(line)X
-1549(in)X
-1631(the)X
-1749(middle)X
-1991(of)X
-2078(the)X
-2196(screen.)X
-776 4902(The)N
-3 f
-922(M)X
-1 f
-1019(command)X
-1356(is)X
-1430(an)X
-1527(absolute)X
-1815(movement.)X
-2214(The)X
-3 f
-2360(M)X
-1 f
-2457(command)X
-2794(may)X
-2953(be)X
-3050(used)X
-3219(as)X
-3308(the)X
-3428(motion)X
-3676(component)X
-776 4992(of)N
-863(other)X
-3 f
-1048(vi)X
-1 f
-1130(commands,)X
-1517(in)X
-1599(which)X
-1815(case)X
-1974(any)X
-2110(text)X
-2250(copied)X
-2484(into)X
-2628(a)X
-2684(buffer)X
-2901(is)X
-2974(line)X
-3114(oriented.)X
-776 5172(Historically,)N
-1194(any)X
-7 f
-1330(count)X
-1 f
-1590(speci\256ed)X
-1895(to)X
-1977(the)X
-3 f
-2095(M)X
-1 f
-2191(command)X
-2527(was)X
-2672(ignored.)X
-776 5352(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(in)X
-1680(the)X
-1798(middle)X
-2040(of)X
-2127(the)X
-2245(screen.)X
-776 5442(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(of)X
-2323(the)X
-2 f
-2441(screen)X
-1 f
-2671(line.)X
-776 5532(Options:)N
-1136(None.)X
-3 f
-576 5712([count])N
-841(O)X
-1 f
-776 5802(Enter)N
-970(input)X
-1154(mode,)X
-1372(appending)X
-1726(text)X
-1866(in)X
-1948(a)X
-2004(new)X
-2158(line)X
-2298(above)X
-2510(the)X
-2628(current)X
-2876(line.)X
-3057(If)X
-7 f
-3132(count)X
-1 f
-3393(is)X
-3467(speci\256ed,)X
-3793(the)X
-3912(text)X
-
-23 p
-%%Page: 23 22
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Vi)X
-1364(Commands\))X
-3658(USD:13-23)X
-1 f
-776 762(input)N
-960(is)X
-1033(repeatedly)X
-1388(input)X
-7 f
-1572(count)X
-1860(-)X
-1956(1)X
-1 f
-2024(more)X
-2209(times.)X
-776 942(Historically,)N
-1194(any)X
-7 f
-1330(count)X
-1 f
-1590(speci\256ed)X
-1895(to)X
-1977(the)X
-3 f
-2095(O)X
-1 f
-2177(command)X
-2513(was)X
-2658(ignored.)X
-776 1122(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(line)X
-1729(upon)X
-1909(which)X
-2125(characters)X
-2472(were)X
-2649(entered.)X
-776 1212(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(character)X
-1905(entered.)X
-776 1302(Options:)N
-1136(Affected)X
-1440(by)X
-1542(the)X
-3 f
-1662(altwerase)X
-1 f
-1988(,)X
-3 f
-2030(autoindent)X
-1 f
-2398(,)X
-3 f
-2440(beautify)X
-1 f
-(,)S
-3 f
-2762(showmatch)X
-1 f
-3149(,)X
-3 f
-3191(ttywerase)X
-1 f
-3545(and)X
-3 f
-3684(wrapmar-)X
-1136 1392(gin)N
-1 f
-1262(options.)X
-3 f
-576 1572([buffer])N
-864(P)X
-1 f
-776 1662(Insert)N
-980(text)X
-1121(from)X
-1298(a)X
-1355(buffer.)X
-1613(Text)X
-1782(from)X
-1960(the)X
-2080(buffer)X
-2299(\(the)X
-2446(unnamed)X
-2762(buffer)X
-2981(by)X
-3083(default\))X
-3355(is)X
-3430(inserted)X
-3706(before)X
-3934(the)X
-776 1752(current)N
-1024(column)X
-1284(or,)X
-1391(if)X
-1460(the)X
-1578(buffer)X
-1795(is)X
-1868(line)X
-2008(oriented,)X
-2311(before)X
-2537(the)X
-2655(current)X
-2903(line.)X
-776 1932(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(lowest)X
-1687(numbered)X
-2028(line)X
-2168(insert,)X
-2386(if)X
-2455(the)X
-2573(buffer)X
-2790(is)X
-2863(line)X
-3003(oriented,)X
-3306(otherwise)X
-3638(unchanged.)X
-776 2022(Column:)N
-1136(Set)X
-1261(to)X
-1346(the)X
-1467(\256rst)X
-1614(nonblank)X
-1935(character)X
-2254(of)X
-2344(the)X
-2465(appended)X
-2796(text,)X
-2959(if)X
-3032(the)X
-3154(buffer)X
-3375(is)X
-3452(line)X
-3596(oriented,)X
-3903(oth-)X
-1136 2112(erwise,)N
-1386(the)X
-1504(last)X
-1635(character)X
-1951(of)X
-2038(the)X
-2156(appended)X
-2484(text.)X
-776 2202(Options:)N
-1136(None.)X
-3 f
-576 2382(Q)N
-1 f
-776 2472(Exit)N
-3 f
-929(vi)X
-1 f
-1011(\(or)X
-1125(visual\))X
-1363(mode)X
-1561(and)X
-1697(switch)X
-1926(to)X
-3 f
-2008(ex)X
-1 f
-2104(mode.)X
-776 2652(Line:)N
-1136(Unchanged.)X
-776 2742(Column:)N
-1136(No)X
-1254(longer)X
-1479(relevant.)X
-776 2832(Options:)N
-1136(None.)X
-3 f
-576 3012([count])N
-841(R)X
-1 f
-776 3102(Enter)N
-971(input)X
-1156(mode,)X
-1375(replacing)X
-1695(the)X
-1814(characters)X
-2162(in)X
-2245(the)X
-2364(current)X
-2613(line.)X
-2794(If)X
-7 f
-2869(count)X
-1 f
-3130(is)X
-3204(speci\256ed,)X
-3531(the)X
-3651(text)X
-3793(input)X
-3979(is)X
-776 3192(repeatedly)N
-1131(input)X
-7 f
-1315(count)X
-1603(-)X
-1699(1)X
-1 f
-1767(more)X
-1952(times.)X
-776 3372(If)N
-855(the)X
-978(end)X
-1119(of)X
-1211(the)X
-1334(current)X
-1587(line)X
-1732(is)X
-1810(reached,)X
-2106(no)X
-2211(more)X
-2401(characters)X
-2753(are)X
-2877(replaced)X
-3176(and)X
-3318(any)X
-3460(further)X
-3705(characters)X
-776 3462(input)N
-960(are)X
-1079(appended)X
-1407(to)X
-1489(the)X
-1607(line.)X
-776 3642(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(line)X
-1729(upon)X
-1909(which)X
-2125(characters)X
-2472(were)X
-2649(entered.)X
-776 3732(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(character)X
-1905(entered.)X
-776 3822(Options:)N
-1136(Affected)X
-1440(by)X
-1542(the)X
-3 f
-1662(altwerase)X
-1 f
-1988(,)X
-3 f
-2030(autoindent)X
-1 f
-2398(,)X
-3 f
-2440(beautify)X
-1 f
-(,)S
-3 f
-2762(showmatch)X
-1 f
-3149(,)X
-3 f
-3191(ttywerase)X
-1 f
-3545(and)X
-3 f
-3684(wrapmar-)X
-1136 3912(gin)N
-1 f
-1262(options.)X
-3 f
-576 4092([buffer])N
-864([count])X
-1129(S)X
-1 f
-776 4182(Substitute)N
-7 f
-1115(count)X
-1 f
-1375(lines.)X
-776 4362(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(line)X
-1729(upon)X
-1909(which)X
-2125(characters)X
-2472(were)X
-2649(entered.)X
-776 4452(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(character)X
-1905(entered.)X
-776 4542(Options:)N
-1136(Affected)X
-1440(by)X
-1542(the)X
-3 f
-1662(altwerase)X
-1 f
-1988(,)X
-3 f
-2030(autoindent)X
-1 f
-2398(,)X
-3 f
-2440(beautify)X
-1 f
-(,)S
-3 f
-2762(showmatch)X
-1 f
-3149(,)X
-3 f
-3191(ttywerase)X
-1 f
-3545(and)X
-3 f
-3684(wrapmar-)X
-1136 4632(gin)N
-1 f
-1262(options.)X
-3 f
-576 4812([count])N
-841(T)X
-914 0.3125(<character>)AX
-1 f
-776 4902(Search)N
-1014(backward,)X
-7 f
-1366(count)X
-1 f
-1625(times,)X
-1837(through)X
-2105(the)X
-2222(current)X
-2469(line)X
-2608(for)X
-2721(the)X
-2838(character)X
-2 f
-3153(after)X
-1 f
-3323(the)X
-3440(speci\256ed)X
-7 f
-3744(<char-)X
-776 4992(acter>)N
-1 f
-(.)S
-776 5172(The)N
-3 f
-921(T)X
-1 f
-994(command)X
-1330(may)X
-1488(be)X
-1584(used)X
-1751(as)X
-1838(the)X
-1956(motion)X
-2202(component)X
-2578(of)X
-2665(other)X
-3 f
-2850(vi)X
-1 f
-2932(commands,)X
-3319(in)X
-3401(which)X
-3617(case)X
-3776(any)X
-3912(text)X
-776 5262(copied)N
-1010(into)X
-1154(a)X
-1210(buffer)X
-1427(is)X
-1500(character)X
-1816(oriented.)X
-776 5442(Line:)N
-1136(Unchanged.)X
-776 5532(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(character)X
-2 f
-1774(after)X
-1 f
-1945(the)X
-2063 0.3068(searched-for)AX
-2486(character.)X
-776 5622(Options:)N
-1136(None.)X
-
-24 p
-%%Page: 24 23
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-24)N
-2826(Nvi/Nex)X
-3122 0.3906(Reference)AX
-3487(\(Vi)X
-3614(Commands\))X
-576 762(U)N
-1 f
-776 852(Restore)N
-1041(the)X
-1159(current)X
-1407(line)X
-1547(to)X
-1629(its)X
-1724(state)X
-1891(before)X
-2117(the)X
-2235(cursor)X
-2456(last)X
-2587(moved)X
-2825(to)X
-2907(it.)X
-776 1032(Line:)N
-1136(Unchanged.)X
-776 1122(Column:)N
-1136(The)X
-1281(\256rst)X
-1425(character)X
-1741(in)X
-1823(the)X
-1941(line.)X
-776 1212(Options:)N
-1136(None.)X
-3 f
-576 1392([count])N
-841(W)X
-1 f
-776 1482(Move)N
-985(forward)X
-7 f
-1262(count)X
-1 f
-1524(bigwords.)X
-1884(Move)X
-2094(the)X
-2215(cursor)X
-2439(forward)X
-2717(to)X
-2802(the)X
-2923(beginning)X
-3266(of)X
-3356(a)X
-3415(bigword)X
-3705(by)X
-3808(repeat-)X
-776 1572(ing)N
-903(the)X
-1026(following)X
-1362(algorithm:)X
-1720(if)X
-1794(the)X
-1917(current)X
-2170(position)X
-2452(is)X
-2530(within)X
-2759(a)X
-2820(bigword)X
-3112(or)X
-3204(the)X
-3326(character)X
-3646(at)X
-3728(that)X
-3872(posi-)X
-776 1662(tion)N
-926(cannot)X
-1166(be)X
-1268(part)X
-1419(of)X
-1512(a)X
-1574(bigword,)X
-1887(move)X
-2091(to)X
-2179(the)X
-2303(\256rst)X
-2453(character)X
-2775(of)X
-2868(the)X
-2992(next)X
-3156(bigword.)X
-3489(If)X
-3569(no)X
-3676(subsequent)X
-776 1752(bigword)N
-1066(exists)X
-1271(on)X
-1374(the)X
-1495(current)X
-1746(line,)X
-1909(move)X
-2110(to)X
-2195(the)X
-2316(\256rst)X
-2463(character)X
-2782(of)X
-2872(the)X
-2993(\256rst)X
-3139(bigword)X
-3428(on)X
-3530(the)X
-3650(\256rst)X
-3796(follow-)X
-776 1842(ing)N
-898(line)X
-1038(that)X
-1178(contains)X
-1465(a)X
-1521(bigword.)X
-776 2022(The)N
-3 f
-927(W)X
-1 f
-1033(command)X
-1375(may)X
-1539(be)X
-1641(used)X
-1814(as)X
-1908(the)X
-2033(motion)X
-2286(component)X
-2669(of)X
-2763(other)X
-3 f
-2955(vi)X
-1 f
-3044(commands,)X
-3438(in)X
-3527(which)X
-3750(case)X
-3916(any)X
-776 2112(text)N
-916(copied)X
-1150(into)X
-1294(a)X
-1350(buffer)X
-1567(is)X
-1640(character)X
-1956(oriented.)X
-776 2292(Line:)N
-1136(The)X
-1281(line)X
-1421(containing)X
-1779(the)X
-1897(word)X
-2082(selected.)X
-776 2382(Column:)N
-1136(The)X
-1281(\256rst)X
-1425(character)X
-1741(of)X
-1828(the)X
-1946(word)X
-2131(selected.)X
-776 2472(Options:)N
-1136(None.)X
-3 f
-576 2652([buffer])N
-864([count])X
-1129(X)X
-1 f
-776 2742(Delete)N
-7 f
-1008(count)X
-1 f
-1270(characters)X
-1619(before)X
-1847(the)X
-1967(cursor.)X
-2230(If)X
-2306(the)X
-2426(number)X
-2693(of)X
-2782(characters)X
-3132(to)X
-3217(be)X
-3316(deleted)X
-3571(is)X
-3647(greater)X
-3894(than)X
-776 2832(or)N
-874(equal)X
-1079(to)X
-1172(the)X
-1301(number)X
-1577(of)X
-1675(characters)X
-2033(to)X
-2126(the)X
-2255(beginning)X
-2606(of)X
-2704(the)X
-2833(line,)X
-3004(all)X
-3115(of)X
-3213(the)X
-3341(characters)X
-3698(before)X
-3934(the)X
-776 2922(current)N
-1024(cursor)X
-1245(position,)X
-1542(to)X
-1624(the)X
-1742(beginning)X
-2082(of)X
-2169(the)X
-2287(line,)X
-2447(are)X
-2566(deleted.)X
-776 3102(Line:)N
-1136(Unchanged.)X
-776 3192(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(current)X
-1706(character)X
-2022(minus)X
-7 f
-2237(count)X
-1 f
-(,)S
-2518(or)X
-2606(the)X
-2725(\256rst)X
-2870(character)X
-3187(if)X
-3257(count)X
-3456(is)X
-3530(greater)X
-3775(than)X
-3934(the)X
-1136 3282(number)N
-1401(of)X
-1488(characters)X
-1835(in)X
-1917(the)X
-2035(line)X
-2175(before)X
-2401(the)X
-2519(cursor.)X
-776 3372(Options:)N
-1136(None.)X
-3 f
-576 3552([buffer])N
-864([count])X
-1129(Y)X
-1 f
-776 3642(Copy)N
-969(\(or)X
-1083(``yank''\))X
-7 f
-1394(count)X
-1 f
-1654(lines)X
-1825(into)X
-1969(the)X
-2087(speci\256ed)X
-2392(buffer.)X
-776 3822(Line:)N
-1136(Unchanged.)X
-776 3912(Column:)N
-1136(Unchanged.)X
-776 4002(Options:)N
-1136(None.)X
-3 f
-576 4182(ZZ)N
-1 f
-776 4272(Write)N
-979(the)X
-1097(\256le)X
-1219(and)X
-1356(exit)X
-3 f
-1497(vi)X
-1 f
-1559(.)X
-1620(The)X
-1766(\256le)X
-1889(is)X
-1963(only)X
-2126(written)X
-2374(if)X
-2444(it)X
-2509(has)X
-2637(been)X
-2810(modi\256ed)X
-3115(since)X
-3301(the)X
-3420(last)X
-3552(complete)X
-3867(write)X
-776 4362(of)N
-863(the)X
-981(\256le)X
-1103(to)X
-1185(any)X
-1321(\256le.)X
-776 4542(The)N
-3 f
-922(ZZ)X
-1 f
-1050(command)X
-1388(will)X
-1534(exit)X
-1676(the)X
-1796(editor)X
-2005(after)X
-2175(writing)X
-2428(the)X
-2548(\256le,)X
-2692(if)X
-2763(there)X
-2946(are)X
-3067(no)X
-3169(further)X
-3410(\256les)X
-3565(to)X
-3649(edit.)X
-3831(Enter-)X
-776 4632(ing)N
-901(two)X
-1044(``quit'')X
-1299(commands)X
-1669(\(i.e.)X
-3 f
-1837(wq)X
-1 f
-1939(,)X
-3 f
-1981(quit)X
-1 f
-2118(,)X
-3 f
-2160(xit)X
-1 f
-2271(or)X
-3 f
-2360(ZZ)X
-1 f
-2466(\))X
-2515(in)X
-2599(a)X
-2657(row)X
-2804(will)X
-2950(override)X
-3240(this)X
-3377(check)X
-3587(and)X
-3725(the)X
-3845(editor)X
-776 4722(will)N
-920(exit,)X
-1080(ignoring)X
-1371(any)X
-1507(\256les)X
-1660(that)X
-1800(have)X
-1972(not)X
-2094(yet)X
-2212(been)X
-2384(edited.)X
-776 4902(Line:)N
-1136(Unchanged.)X
-776 4992(Column:)N
-1136(Unchanged.)X
-776 5082(Options:)N
-1136(None.)X
-3 f
-576 5262([count])N
-841([[)X
-1 f
-776 5352(Back)N
-961(up)X
-7 f
-1061(count)X
-1 f
-1321(section)X
-1568(boundaries.)X
-776 5532(The)N
-3 f
-925([[)X
-1 f
-1003(command)X
-1343(is)X
-1420(an)X
-1520(absolute)X
-1811(movement.)X
-2213(The)X
-3 f
-2362([[)X
-1 f
-2440(command)X
-2780(may)X
-2942(be)X
-3042(used)X
-3213(as)X
-3304(the)X
-3426(motion)X
-3676(component)X
-776 5622(of)N
-871(other)X
-3 f
-1064(vi)X
-1 f
-1153(commands,)X
-1547(in)X
-1636(which)X
-1859(case)X
-2025(any)X
-2168(text)X
-2315(copied)X
-2556(into)X
-2707(a)X
-2770(buffer)X
-2994(is)X
-3074(character)X
-3397(oriented,)X
-3707(unless)X
-3934(the)X
-776 5712(starting)N
-1036(position)X
-1313(is)X
-1386(column)X
-1646(0,)X
-1726(in)X
-1808(which)X
-2024(case)X
-2183(it)X
-2247(is)X
-2320(line)X
-2460(oriented.)X
-
-25 p
-%%Page: 25 24
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Vi)X
-1364(Commands\))X
-3658(USD:13-25)X
-1 f
-776 762(This)N
-938(is)X
-1011(an)X
-1107(error)X
-1284(if)X
-1353(the)X
-1471(movement)X
-1829(is)X
-1902(past)X
-2051(the)X
-2169(beginning)X
-2509(of)X
-2596(the)X
-2714(\256le.)X
-776 942(Line:)N
-1136(Set)X
-1261(to)X
-1346(the)X
-1467(previous)X
-1766(line)X
-1909(that)X
-2052(is)X
-7 f
-2128(count)X
-1 f
-2391(section)X
-2641(boundaries)X
-3016(back,)X
-3212(or)X
-3303(the)X
-3425(\256rst)X
-3573(line)X
-3717(of)X
-3808(the)X
-3930(\256le)X
-1136 1032(if)N
-1205(no)X
-1305(more)X
-1490(section)X
-1737(boundaries)X
-2109(exist)X
-2280(preceding)X
-2617(the)X
-2735(current)X
-2983(line.)X
-776 1122(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(in)X
-2318(the)X
-2436(line.)X
-776 1212(Options:)N
-1136(Affected)X
-1438(by)X
-1538(the)X
-3 f
-1656(sections)X
-1 f
-1943(option.)X
-3 f
-576 1392([count])N
-841(]])X
-1 f
-776 1482(Move)N
-983(forward)X
-7 f
-1258(count)X
-1 f
-1518(section)X
-1765(boundaries.)X
-776 1662(The)N
-3 f
-925(]])X
-1 f
-1003(command)X
-1343(is)X
-1420(an)X
-1520(absolute)X
-1811(movement.)X
-2213(The)X
-3 f
-2362(]])X
-1 f
-2440(command)X
-2780(may)X
-2942(be)X
-3042(used)X
-3213(as)X
-3304(the)X
-3426(motion)X
-3676(component)X
-776 1752(of)N
-871(other)X
-3 f
-1064(vi)X
-1 f
-1153(commands,)X
-1547(in)X
-1636(which)X
-1859(case)X
-2025(any)X
-2168(text)X
-2315(copied)X
-2556(into)X
-2707(a)X
-2770(buffer)X
-2994(is)X
-3074(character)X
-3397(oriented,)X
-3707(unless)X
-3934(the)X
-776 1842(starting)N
-1036(position)X
-1313(is)X
-1386(column)X
-1646(0,)X
-1726(in)X
-1808(which)X
-2024(case)X
-2183(it)X
-2247(is)X
-2320(line)X
-2460(oriented.)X
-776 2022(This)N
-938(is)X
-1011(an)X
-1107(error)X
-1284(if)X
-1353(the)X
-1471(movement)X
-1829(is)X
-1902(past)X
-2051(the)X
-2169(end)X
-2305(of)X
-2392(the)X
-2510(\256le.)X
-776 2202(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(that)X
-1738(is)X
-7 f
-1811(count)X
-1 f
-2072(section)X
-2320(boundaries)X
-2693(forward,)X
-2989(or)X
-3077(to)X
-3160(the)X
-3279(last)X
-3411(line)X
-3552(of)X
-3640(the)X
-3759(\256le)X
-3882(if)X
-3952(no)X
-1136 2292(more)N
-1321(section)X
-1568(boundaries)X
-1940(exist)X
-2111(following)X
-2442(the)X
-2560(current)X
-2808(line.)X
-776 2382(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(in)X
-2318(the)X
-2436(line.)X
-776 2472(Options:)N
-1136(Affected)X
-1438(by)X
-1538(the)X
-3 f
-1656(sections)X
-1 f
-1943(option.)X
-3 f
-576 2652(\303)N
-1 f
-776 2742(Move)N
-983(to)X
-1065(\256rst)X
-1209(nonblank)X
-1527(character)X
-1843(on)X
-1943(the)X
-2061(current)X
-2309(line.)X
-776 2922(The)N
-3 f
-922(\303)X
-1 f
-970(command)X
-1307(may)X
-1466(be)X
-1563(used)X
-1731(as)X
-1819(the)X
-1938(motion)X
-2185(component)X
-2562(of)X
-2651(other)X
-3 f
-2838(vi)X
-1 f
-2922(commands,)X
-3311(in)X
-3395(which)X
-3613(case)X
-3774(any)X
-3912(text)X
-776 3012(copied)N
-1010(into)X
-1154(a)X
-1210(buffer)X
-1427(is)X
-1500(character)X
-1816(oriented.)X
-776 3192(Line:)N
-1136(Unchanged.)X
-776 3282(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(of)X
-2323(the)X
-2441(current)X
-2689(line.)X
-776 3372(Options:)N
-1136(None.)X
-3 f
-576 3552([count])N
-841(_)X
-1 f
-776 3642(Move)N
-985(down)X
-7 f
-1185(count)X
-1475(-)X
-1573(1)X
-1 f
-1643(lines,)X
-1836(to)X
-1920(the)X
-2040(\256rst)X
-2186(nonblank)X
-2506(character.)X
-2864(The)X
-3 f
-3012(_)X
-1 f
-3075(command)X
-3414(may)X
-3575(be)X
-3674(used)X
-3844(as)X
-3934(the)X
-776 3732(motion)N
-1022(component)X
-1398(of)X
-1485(other)X
-3 f
-1670(vi)X
-1 f
-1752(commands,)X
-2139(in)X
-2221(which)X
-2437(case)X
-2596(any)X
-2732(text)X
-2872(copied)X
-3106(into)X
-3250(a)X
-3306(buffer)X
-3523(is)X
-3596(line)X
-3736(oriented.)X
-776 3912(It)N
-845(is)X
-918(not)X
-1040(an)X
-1136(error)X
-1313(to)X
-1395(execute)X
-1661(the)X
-3 f
-1779(_)X
-1 f
-1839(command)X
-2175(when)X
-2369(the)X
-2487(cursor)X
-2708(is)X
-2781(on)X
-2881(the)X
-2999(\256rst)X
-3143(character)X
-3459(in)X
-3541(the)X
-3659(line.)X
-776 4092(Line:)N
-1136(The)X
-1281(current)X
-1529(line)X
-1669(plus)X
-7 f
-1822(count)X
-2110(-)X
-2206(1)X
-1 f
-(.)S
-776 4182(Column:)N
-1136(The)X
-1281(\256rst)X
-1425(nonblank)X
-1743(character)X
-2059(in)X
-2141(the)X
-2259(line.)X
-776 4272(Options:)N
-1136(None.)X
-3 f
-576 4452([count])N
-841(a)X
-1 f
-776 4542(Enter)N
-971(input)X
-1156(mode,)X
-1375(appending)X
-1730(the)X
-1850(text)X
-1992(after)X
-2162(the)X
-2282(cursor.)X
-2545(If)X
-7 f
-2621(count)X
-1 f
-2883(is)X
-2958(speci\256ed,)X
-3285(the)X
-3405(text)X
-3547(input)X
-3733(is)X
-3808(repeat-)X
-776 4632(edly)N
-934(input)X
-7 f
-1118(count)X
-1406(-)X
-1502(1)X
-1 f
-1570(more)X
-1755(times.)X
-776 4812(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(line)X
-1729(upon)X
-1909(which)X
-2125(characters)X
-2472(were)X
-2649(entered.)X
-776 4902(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(character)X
-1905(entered.)X
-776 4992(Options:)N
-1136(Affected)X
-1440(by)X
-1542(the)X
-3 f
-1662(altwerase)X
-1 f
-1988(,)X
-3 f
-2030(autoindent)X
-1 f
-2398(,)X
-3 f
-2440(beautify)X
-1 f
-(,)S
-3 f
-2762(showmatch)X
-1 f
-3149(,)X
-3 f
-3191(ttywerase)X
-1 f
-3545(and)X
-3 f
-3684(wrapmar-)X
-1136 5082(gin)N
-1 f
-1262(options.)X
-3 f
-576 5262([count])N
-841(b)X
-1 f
-776 5352(Move)N
-986(backward)X
-7 f
-1322(count)X
-1 f
-1585(words.)X
-1844(Move)X
-2054(the)X
-2175(cursor)X
-2400(backward)X
-2737(to)X
-2823(the)X
-2945(beginning)X
-3289(of)X
-3380(a)X
-3440(word)X
-3629(by)X
-3733(repeating)X
-776 5442(the)N
-895(following)X
-1227(algorithm:)X
-1581(if)X
-1651(the)X
-1770(current)X
-2018(position)X
-2295(is)X
-2368(at)X
-2446(the)X
-2564(beginning)X
-2904(of)X
-2991(a)X
-3047(word,)X
-3252(move)X
-3450(to)X
-3532(the)X
-3650(\256rst)X
-3794(charac-)X
-776 5532(ter)N
-883(of)X
-972(the)X
-1092(preceding)X
-1431(word.)X
-1658(Otherwise,)X
-2030(the)X
-2150(current)X
-2400(position)X
-2679(moves)X
-2910(to)X
-2994(the)X
-3114(\256rst)X
-3260(character)X
-3578(of)X
-3667(the)X
-3787(word)X
-3974(at)X
-776 5622(the)N
-895(current)X
-1144(position.)X
-1462(If)X
-1537(no)X
-1638(preceding)X
-1976(word)X
-2161(exists)X
-2363(on)X
-2463(the)X
-2581(current)X
-2829(line,)X
-2989(move)X
-3187(to)X
-3269(the)X
-3387(\256rst)X
-3531(character)X
-3847(of)X
-3934(the)X
-776 5712(last)N
-907(word)X
-1092(on)X
-1192(the)X
-1310(\256rst)X
-1454(preceding)X
-1791(line)X
-1931(that)X
-2071(contains)X
-2358(a)X
-2414(word.)X
-
-26 p
-%%Page: 26 25
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-26)N
-2826(Nvi/Nex)X
-3122 0.3906(Reference)AX
-3487(\(Vi)X
-3614(Commands\))X
-1 f
-776 762(The)N
-3 f
-921(b)X
-1 f
-985(command)X
-1321(may)X
-1479(be)X
-1575(used)X
-1742(as)X
-1829(the)X
-1947(motion)X
-2193(component)X
-2570(of)X
-2658(other)X
-3 f
-2844(vi)X
-1 f
-2927(commands,)X
-3315(in)X
-3398(which)X
-3615(case)X
-3775(any)X
-3912(text)X
-776 852(copied)N
-1010(into)X
-1154(a)X
-1210(buffer)X
-1427(is)X
-1500(character)X
-1816(oriented.)X
-776 1032(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(containing)X
-1956(the)X
-2074(word)X
-2259(selected.)X
-776 1122(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(character)X
-1918(of)X
-2005(the)X
-2123(word)X
-2308(selected.)X
-776 1212(Options:)N
-1136(None.)X
-3 f
-576 1392([buffer])N
-864([count])X
-1129(c)X
-1185(motion)X
-1 f
-776 1482(Change)N
-1041(a)X
-1097(region)X
-1322(of)X
-1409(text.)X
-1589(If)X
-1663(only)X
-1825(part)X
-1970(of)X
-2057(a)X
-2113(single)X
-2324(line)X
-2464(is)X
-2537(affected,)X
-2838(then)X
-2997(the)X
-3116(last)X
-3248(character)X
-3565(being)X
-3764(changed)X
-776 1572(is)N
-849(marked)X
-1110(with)X
-1272(a)X
-1328(``)X
-7 f
-1382($)X
-1 f
-(''.)S
-1544(Otherwise,)X
-1914(the)X
-2032(region)X
-2257(of)X
-2344(text)X
-2484(is)X
-2557(deleted,)X
-2829(and)X
-2965(input)X
-3149(mode)X
-3347(is)X
-3420(entered.)X
-776 1752(If)N
-7 f
-850(count)X
-1 f
-1110(is)X
-1183(speci\256ed,)X
-1508(it)X
-1572(is)X
-1645(applied)X
-1901(to)X
-1983(the)X
-7 f
-2101(motion)X
-1 f
-(.)S
-776 1932(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(line)X
-1729(upon)X
-1909(which)X
-2125(characters)X
-2472(were)X
-2649(entered.)X
-776 2022(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(character)X
-1905(entered.)X
-776 2112(Options:)N
-1136(Affected)X
-1440(by)X
-1542(the)X
-3 f
-1662(altwerase)X
-1 f
-1988(,)X
-3 f
-2030(autoindent)X
-1 f
-2398(,)X
-3 f
-2440(beautify)X
-1 f
-(,)S
-3 f
-2762(showmatch)X
-1 f
-3149(,)X
-3 f
-3191(ttywerase)X
-1 f
-3545(and)X
-3 f
-3684(wrapmar-)X
-1136 2202(gin)N
-1 f
-1262(options.)X
-3 f
-576 2382([buffer])N
-864([count])X
-1129(d)X
-1193(motion)X
-1 f
-776 2472(Delete)N
-1006(a)X
-1062(region)X
-1287(of)X
-1374(text.)X
-1554(If)X
-7 f
-1628(count)X
-1 f
-1888(is)X
-1961(speci\256ed,)X
-2286(it)X
-2350(is)X
-2423(applied)X
-2679(to)X
-2761(the)X
-7 f
-2879(motion)X
-1 f
-(.)S
-776 2652(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(where)X
-1815(the)X
-1933(region)X
-2158(starts.)X
-776 2742(Column:)N
-1136(Set)X
-1261(to)X
-1346(the)X
-1467(\256rst)X
-1615(character)X
-1935(in)X
-2021(the)X
-2143(line)X
-2287(after)X
-2459(the)X
-2581(last)X
-2716(character)X
-3036(in)X
-3122(the)X
-3244(region.)X
-3513(If)X
-3591(no)X
-3695(such)X
-3866(char-)X
-1136 2832(acter)N
-1313(exists,)X
-1535(set)X
-1644(to)X
-1726(the)X
-1844(last)X
-1975(character)X
-2291(before)X
-2517(the)X
-2635(region.)X
-776 2922(Options:)N
-1136(None.)X
-3 f
-576 3102([count])N
-841(e)X
-1 f
-776 3192(Move)N
-984(forward)X
-7 f
-1260(count)X
-1 f
-1521(end-of-words.)X
-2015(Move)X
-2223(the)X
-2342(cursor)X
-2564(forward)X
-2840(to)X
-2923(the)X
-3042(end)X
-3179(of)X
-3267(a)X
-3324(word)X
-3511(by)X
-3613(repeating)X
-3934(the)X
-776 3282(following)N
-1108(algorithm:)X
-1462(if)X
-1532(the)X
-1651(current)X
-1900(position)X
-2178(is)X
-2252(the)X
-2371(end)X
-2508(of)X
-2596(a)X
-2653(word,)X
-2859(move)X
-3058(to)X
-3141(the)X
-3260(last)X
-3392(character)X
-3709(of)X
-3797(the)X
-3916(fol-)X
-776 3372(lowing)N
-1034(word.)X
-1275(Otherwise,)X
-1661(move)X
-1876(to)X
-1975(the)X
-2110(last)X
-2258(character)X
-2591(of)X
-2695(the)X
-2830(word)X
-3032(at)X
-3127(the)X
-3262(current)X
-3527(position.)X
-3861(If)X
-3952(no)X
-776 3462(succeeding)N
-1161(word)X
-1354(exists)X
-1564(on)X
-1672(the)X
-1798(current)X
-2053(line,)X
-2220(move)X
-2425(to)X
-2514(the)X
-2639(last)X
-2777(character)X
-3100(of)X
-3194(the)X
-3319(\256rst)X
-3470(word)X
-3662(on)X
-3769(the)X
-3894(next)X
-776 3552(following)N
-1107(line)X
-1247(that)X
-1387(contains)X
-1674(a)X
-1730(word.)X
-776 3732(The)N
-3 f
-921(e)X
-1 f
-978(command)X
-1315(may)X
-1474(be)X
-1571(used)X
-1739(as)X
-1827(the)X
-1946(motion)X
-2193(component)X
-2570(of)X
-2658(other)X
-3 f
-2844(vi)X
-1 f
-2927(commands,)X
-3315(in)X
-3398(which)X
-3615(case)X
-3775(any)X
-3912(text)X
-776 3822(copied)N
-1010(into)X
-1154(a)X
-1210(buffer)X
-1427(is)X
-1500(character)X
-1816(oriented.)X
-776 4002(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(containing)X
-1956(the)X
-2074(word)X
-2259(selected.)X
-776 4092(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(character)X
-1905(of)X
-1992(the)X
-2110(word)X
-2295(selected.)X
-776 4182(Options:)N
-1136(None.)X
-3 f
-576 4362([count])N
-841(f)X
-888 0.3125(<character>)AX
-1 f
-776 4452(Search)N
-1015(forward,)X
-7 f
-1310(count)X
-1 f
-1570(times,)X
-1783(through)X
-2052(the)X
-2170(rest)X
-2306(of)X
-2393(the)X
-2511(current)X
-2759(line)X
-2899(for)X
-7 f
-3013(<character>)X
-1 f
-(.)S
-776 4632(The)N
-3 f
-922(f)X
-1 f
-970(command)X
-1307(may)X
-1466(be)X
-1563(used)X
-1731(as)X
-1819(the)X
-1938(motion)X
-2185(component)X
-2562(of)X
-2651(other)X
-3 f
-2838(vi)X
-1 f
-2922(commands,)X
-3311(in)X
-3395(which)X
-3613(case)X
-3774(any)X
-3912(text)X
-776 4722(copied)N
-1010(into)X
-1154(a)X
-1210(buffer)X
-1427(is)X
-1500(character)X
-1816(oriented.)X
-776 4902(Line:)N
-1136(Unchanged.)X
-776 4992(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458 0.3068(searched-for)AX
-1881(character.)X
-776 5082(Options:)N
-1136(None.)X
-3 f
-576 5262([count])N
-841(i)X
-1 f
-776 5352(Enter)N
-971(input)X
-1156(mode,)X
-1375(inserting)X
-1676(the)X
-1795(text)X
-1936(before)X
-2163(the)X
-2282(cursor.)X
-2545(If)X
-7 f
-2621(count)X
-1 f
-2883(is)X
-2958(speci\256ed,)X
-3285(the)X
-3405(text)X
-3547(input)X
-3733(is)X
-3808(repeat-)X
-776 5442(edly)N
-934(input)X
-7 f
-1118(count)X
-1406(-)X
-1502(1)X
-1 f
-1570(more)X
-1755(times.)X
-776 5622(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(line)X
-1729(upon)X
-1909(which)X
-2125(characters)X
-2472(were)X
-2649(entered.)X
-776 5712(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(character)X
-1905(entered.)X
-
-27 p
-%%Page: 27 26
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Vi)X
-1364(Commands\))X
-3658(USD:13-27)X
-1 f
-776 762(Options:)N
-1136(Affected)X
-1440(by)X
-1542(the)X
-3 f
-1662(altwerase)X
-1 f
-1988(,)X
-3 f
-2030(autoindent)X
-1 f
-2398(,)X
-3 f
-2440(beautify)X
-1 f
-(,)S
-3 f
-2762(showmatch)X
-1 f
-3149(,)X
-3 f
-3191(ttywerase)X
-1 f
-3545(and)X
-3 f
-3684(wrapmar-)X
-1136 852(gin)N
-1 f
-1262(options.)X
-3 f
-576 1032(m)N
-663 0.3125(<character>)AX
-1 f
-776 1122(Save)N
-956(the)X
-1078(current)X
-1330(context)X
-1590(\(line)X
-1761(and)X
-1902(column\))X
-2194(as)X
-7 f
-2286(<character>)X
-1 f
-(.)S
-2879(The)X
-3029(exact)X
-3224(position)X
-3506(is)X
-3584(referred)X
-3865(to)X
-3952(by)X
-776 1212(``)N
-7 f
-830(`<character>)X
-1 f
-(''.)S
-1520(The)X
-1665(line)X
-1805(is)X
-1878(referred)X
-2154(to)X
-2236(by)X
-2336(``)X
-7 f
-2390('<character>)X
-1 f
-(''.)S
-776 1392(Historically,)N
-7 f
-1205(<character>)X
-1 f
-1764(was)X
-1920(restricted)X
-2250(to)X
-2343(lower-case)X
-2723(letters)X
-2950(only,)X
-3 f
-3143(nvi)X
-1 f
-3280(permits)X
-3551(the)X
-3680(use)X
-3818(of)X
-3916(any)X
-776 1482(character.)N
-776 1662(Line:)N
-1136(Unchanged.)X
-776 1752(Column:)N
-1136(Unchanged.)X
-776 1842(Options:)N
-1136(None.)X
-3 f
-576 2022([count])N
-841(o)X
-1 f
-776 2112(Enter)N
-970(input)X
-1154(mode,)X
-1372(appending)X
-1727(text)X
-1868(in)X
-1951(a)X
-2008(new)X
-2163(line)X
-2304(under)X
-2508(the)X
-2627(current)X
-2876(line.)X
-3057(If)X
-7 f
-3132(count)X
-1 f
-3393(is)X
-3467(speci\256ed,)X
-3793(the)X
-3912(text)X
-776 2202(input)N
-960(is)X
-1033(repeatedly)X
-1388(input)X
-7 f
-1572(count)X
-1860(-)X
-1956(1)X
-1 f
-2024(more)X
-2209(times.)X
-776 2382(Historically,)N
-1194(any)X
-7 f
-1330(count)X
-1 f
-1590(speci\256ed)X
-1895(to)X
-1977(the)X
-3 f
-2095(o)X
-1 f
-2155(command)X
-2491(was)X
-2636(ignored.)X
-776 2562(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(line)X
-1729(upon)X
-1909(which)X
-2125(characters)X
-2472(were)X
-2649(entered.)X
-776 2652(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(character)X
-1905(entered.)X
-776 2742(Options:)N
-1136(Affected)X
-1440(by)X
-1542(the)X
-3 f
-1662(altwerase)X
-1 f
-1988(,)X
-3 f
-2030(autoindent)X
-1 f
-2398(,)X
-3 f
-2440(beautify)X
-1 f
-(,)S
-3 f
-2762(showmatch)X
-1 f
-3149(,)X
-3 f
-3191(ttywerase)X
-1 f
-3545(and)X
-3 f
-3684(wrapmar-)X
-1136 2832(gin)N
-1 f
-1262(options.)X
-3 f
-576 3012([buffer])N
-864(p)X
-1 f
-776 3102(Append)N
-1055(text)X
-1200(from)X
-1381(a)X
-1442(buffer.)X
-1704(Text)X
-1876(from)X
-2057(the)X
-2180(buffer)X
-2402(\(the)X
-2552(unnamed)X
-2871(buffer)X
-3093(by)X
-3198(default\))X
-3473(is)X
-3551(appended)X
-3884(after)X
-776 3192(the)N
-894(current)X
-1142(column)X
-1402(or,)X
-1509(if)X
-1578(the)X
-1696(buffer)X
-1913(is)X
-1986(line)X
-2126(oriented,)X
-2429(after)X
-2597(the)X
-2715(current)X
-2963(line.)X
-776 3372(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(line)X
-1742(appended,)X
-2090(if)X
-2159(the)X
-2277(buffer)X
-2494(is)X
-2567(line)X
-2707(oriented,)X
-3010(otherwise)X
-3342(unchanged.)X
-776 3462(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2237(of)X
-2325(the)X
-2444(appended)X
-2773(text)X
-2914(if)X
-2984(the)X
-3103(buffer)X
-3321(is)X
-3395(line)X
-3536(oriented,)X
-3840(other-)X
-1136 3552(wise,)N
-1323(the)X
-1441(last)X
-1572(character)X
-1888(of)X
-1975(the)X
-2093(appended)X
-2421(text.)X
-776 3642(Options:)N
-1136(None.)X
-3 f
-576 3822([count])N
-841(r)X
-897 0.3125(<character>)AX
-1 f
-776 3912(Replace)N
-1073(characters.)X
-1478(The)X
-1641(next)X
-7 f
-1817(count)X
-1 f
-2095(characters)X
-2460(in)X
-2560(the)X
-2696(line)X
-2854(are)X
-2991(replaced)X
-3303(with)X
-7 f
-3484(<character>)X
-1 f
-(.)S
-776 4002(Replacing)N
-1121(characters)X
-1468(with)X
-7 f
-1630(<newline>)X
-1 f
-2082(characters)X
-2429(results)X
-2658(in)X
-2740(creating)X
-3019(new,)X
-3193(empty)X
-3413(lines)X
-3584(into)X
-3728(the)X
-3846(\256le.)X
-776 4182(If)N
-7 f
-850(<character>)X
-1 f
-1398(is)X
-7 f
-1471(<escape>)X
-1 f
-(,)S
-1895(the)X
-2013(command)X
-2349(is)X
-2422(cancelled.)X
-776 4362(Line:)N
-1136(Unchanged)X
-1527(unless)X
-1752(the)X
-1875(replacement)X
-2293(character)X
-2614(is)X
-2692(a)X
-7 f
-2753(<newline>)X
-1 f
-(,)S
-3231(in)X
-3319(which)X
-3541(case)X
-3706(it)X
-3776(is)X
-3855(set)X
-3970(to)X
-1136 4452(the)N
-1254(current)X
-1502(line)X
-1642(plus)X
-7 f
-1795(count)X
-2083(-)X
-2179(1)X
-1 f
-(.)S
-776 4542(Column:)N
-1136(Set)X
-1264(to)X
-1352(the)X
-1476(last)X
-1613(character)X
-1935(replaced,)X
-2254(unless)X
-2480(the)X
-2605(replacement)X
-3025(character)X
-3348(is)X
-3428(a)X
-7 f
-3491(<newline>)X
-1 f
-(,)S
-3970(in)X
-1136 4632(which)N
-1352(case)X
-1511(the)X
-1629(cursor)X
-1850(is)X
-1923(in)X
-2005(column)X
-2265(1)X
-2325(of)X
-2412(the)X
-2530(last)X
-2661(line)X
-2801(inserted.)X
-776 4722(Options:)N
-1136(None.)X
-3 f
-576 4902([buffer])N
-864([count])X
-1129(s)X
-1 f
-776 4992(Substitute)N
-7 f
-1115(count)X
-1 f
-1375(characters)X
-1722(in)X
-1804(the)X
-1922(current)X
-2170(line)X
-2310(starting)X
-2570(with)X
-2732(the)X
-2850(current)X
-3098(character.)X
-776 5172(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(line)X
-1729(upon)X
-1909(which)X
-2125(characters)X
-2472(were)X
-2649(entered.)X
-776 5262(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(last)X
-1589(character)X
-1905(entered.)X
-776 5352(Options:)N
-1136(Affected)X
-1440(by)X
-1542(the)X
-3 f
-1662(altwerase)X
-1 f
-1988(,)X
-3 f
-2030(autoindent)X
-1 f
-2398(,)X
-3 f
-2440(beautify)X
-1 f
-(,)S
-3 f
-2762(showmatch)X
-1 f
-3149(,)X
-3 f
-3191(ttywerase)X
-1 f
-3545(and)X
-3 f
-3684(wrapmar-)X
-1136 5442(gin)N
-1 f
-1262(options.)X
-3 f
-576 5622([count])N
-841(t)X
-888 0.3125(<character>)AX
-1 f
-776 5712(Search)N
-1014(forward,)X
-7 f
-1308(count)X
-1 f
-1567(times,)X
-1779(through)X
-2047(the)X
-2164(current)X
-2411(line)X
-2551(for)X
-2665(the)X
-2783(character)X
-3099(immediately)X
-2 f
-3519(before)X
-7 f
-3744(<char-)X
-776 5802(acter>)N
-1 f
-(.)S
-
-28 p
-%%Page: 28 27
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-28)N
-2826(Nvi/Nex)X
-3122 0.3906(Reference)AX
-3487(\(Vi)X
-3614(Commands\))X
-1 f
-776 762(The)N
-3 f
-922(t)X
-1 f
-970(command)X
-1307(may)X
-1466(be)X
-1563(used)X
-1731(as)X
-1819(the)X
-1938(motion)X
-2185(component)X
-2562(of)X
-2651(other)X
-3 f
-2838(vi)X
-1 f
-2922(commands,)X
-3311(in)X
-3395(which)X
-3613(case)X
-3774(any)X
-3912(text)X
-776 852(copied)N
-1010(into)X
-1154(a)X
-1210(buffer)X
-1427(is)X
-1500(character)X
-1816(oriented.)X
-776 1032(Line:)N
-1136(Unchanged.)X
-776 1122(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(character)X
-2 f
-1774(before)X
-1 f
-1999(the)X
-2117 0.3068(searched-for)AX
-2540(character.)X
-776 1212(Options:)N
-1136(None.)X
-3 f
-576 1392(u)N
-1 f
-776 1482(Undo)N
-985(the)X
-1114(last)X
-1256(change)X
-1515(made)X
-1720(to)X
-1813(the)X
-1942(\256le.)X
-2115(If)X
-2200(repeated,)X
-2524(the)X
-3 f
-2653(u)X
-1 f
-2728(command)X
-3075(alternates)X
-3415(between)X
-3715(these)X
-3912(two)X
-776 1572(states,)N
-997(and)X
-1136(is)X
-1212(its)X
-1310(own)X
-1471(inverse.)X
-1766(When)X
-1981(used)X
-2151(after)X
-2322(an)X
-2421(insert)X
-2622(that)X
-2765(inserted)X
-3042(text)X
-3185(on)X
-3287(more)X
-3474(than)X
-3634(one)X
-3772(line,)X
-3934(the)X
-776 1662(lines)N
-947(are)X
-1066(saved)X
-1269(in)X
-1351(the)X
-1469(numeric)X
-1752(buffers.)X
-776 1842(The)N
-3 f
-928(.)X
-1 f
-995(command,)X
-1358(when)X
-1560(used)X
-1735(immediately)X
-2163(after)X
-2339(the)X
-3 f
-2465(u)X
-1 f
-2537(command,)X
-2901(causes)X
-3139(the)X
-3265(change)X
-3521(log)X
-3651(to)X
-3741(be)X
-3845(rolled)X
-776 1932(forward)N
-1051(or)X
-1138(backward,)X
-1491(depending)X
-1845(on)X
-1945(the)X
-2063(action)X
-2279(of)X
-2366(the)X
-3 f
-2484(u)X
-1 f
-2548(command.)X
-776 2112(Line:)N
-1136(Set)X
-1276(to)X
-1376(the)X
-1512(position)X
-1807(of)X
-1912(the)X
-2048(\256rst)X
-2211(line)X
-2370(changed,)X
-2697(if)X
-2785(the)X
-2922(reversal)X
-3216(affects)X
-3470(only)X
-3651(one)X
-3806(line)X
-3965(or)X
-1136 2202(represents)N
-1482(an)X
-1578(addition)X
-1860(or)X
-1947(change;)X
-2217(otherwise,)X
-2569(the)X
-2687(line)X
-2827(preceding)X
-3164(the)X
-3282(deleted)X
-3534(text.)X
-776 2292(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(cursor)X
-1679(position)X
-1956(before)X
-2182(the)X
-2300(change)X
-2548(was)X
-2693(made.)X
-776 2382(Options:)N
-1136(None.)X
-3 f
-576 2562([count])N
-841(w)X
-1 f
-776 2652(Move)N
-986(forward)X
-7 f
-1264(count)X
-1 f
-1527(words.)X
-1786(Move)X
-1996(the)X
-2117(cursor)X
-2341(forward)X
-2619(to)X
-2704(the)X
-2825(beginning)X
-3168(of)X
-3258(a)X
-3318(word)X
-3507(by)X
-3611(repeating)X
-3934(the)X
-776 2742(following)N
-1111(algorithm:)X
-1468(if)X
-1541(the)X
-1663(current)X
-1915(position)X
-2196(is)X
-2273(at)X
-2355(the)X
-2477(beginning)X
-2821(of)X
-2912(a)X
-2972(word,)X
-3181(move)X
-3383(to)X
-3468(the)X
-3589(\256rst)X
-3736(character)X
-776 2832(of)N
-866(the)X
-987(next)X
-1148(word.)X
-1376(If)X
-1453(no)X
-1556(subsequent)X
-1935(word)X
-2123(exists)X
-2328(on)X
-2431(the)X
-2552(current)X
-2803(line,)X
-2966(move)X
-3167(to)X
-3253(the)X
-3375(\256rst)X
-3523(character)X
-3843(of)X
-3934(the)X
-776 2922(\256rst)N
-920(word)X
-1105(on)X
-1205(the)X
-1323(\256rst)X
-1467(following)X
-1798(line)X
-1938(that)X
-2078(contains)X
-2365(a)X
-2421(word.)X
-776 3102(The)N
-3 f
-928(w)X
-1 f
-1014(command)X
-1358(may)X
-1524(be)X
-1628(used)X
-1803(as)X
-1898(the)X
-2024(motion)X
-2278(component)X
-2662(of)X
-2757(other)X
-3 f
-2950(vi)X
-1 f
-3040(commands,)X
-3435(in)X
-3525(which)X
-3749(case)X
-3916(any)X
-776 3192(text)N
-916(copied)X
-1150(into)X
-1294(a)X
-1350(buffer)X
-1567(is)X
-1640(character)X
-1956(oriented.)X
-776 3372(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(containing)X
-1956(the)X
-2074(word)X
-2259(selected.)X
-776 3462(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(character)X
-1918(of)X
-2005(the)X
-2123(word)X
-2308(selected.)X
-776 3552(Options:)N
-1136(None.)X
-3 f
-576 3732([buffer])N
-864([count])X
-1129(x)X
-1 f
-776 3822(Delete)N
-7 f
-1007(count)X
-1 f
-1268(characters.)X
-1656(The)X
-1802(deletion)X
-2081(is)X
-2155(at)X
-2235(the)X
-2355(current)X
-2605(character)X
-2923(position.)X
-3242(If)X
-3318(the)X
-3438(number)X
-3705(of)X
-3794(charac-)X
-776 3912(ters)N
-915(to)X
-1000(be)X
-1099(deleted)X
-1354(is)X
-1430(greater)X
-1676(than)X
-1836(or)X
-1925(equal)X
-2121(to)X
-2205(the)X
-2325(number)X
-2592(of)X
-2681(characters)X
-3030(to)X
-3114(the)X
-3234(end)X
-3372(of)X
-3461(the)X
-3581(line,)X
-3743(all)X
-3845(of)X
-3934(the)X
-776 4002(characters)N
-1123(from)X
-1299(the)X
-1417(current)X
-1665(cursor)X
-1886(position)X
-2163(to)X
-2245(the)X
-2363(end)X
-2499(of)X
-2586(the)X
-2704(line)X
-2844(are)X
-2963(deleted.)X
-776 4182(Line:)N
-1136(Unchanged.)X
-776 4272(Column:)N
-1136(Unchanged)X
-1525(unless)X
-1748(the)X
-1869(last)X
-2003(character)X
-2322(in)X
-2407(the)X
-2528(line)X
-2671(is)X
-2747(deleted)X
-3002(and)X
-3141(the)X
-3263(cursor)X
-3488(is)X
-3565(not)X
-3691(already)X
-3952(on)X
-1136 4362(the)N
-1254(\256rst)X
-1398(character)X
-1714(in)X
-1796(the)X
-1914(line,)X
-2074(in)X
-2156(which)X
-2372(case)X
-2531(it)X
-2595(is)X
-2668(set)X
-2777(to)X
-2859(the)X
-2977(previous)X
-3273(character.)X
-776 4452(Options:)N
-1136(None.)X
-3 f
-576 4632([buffer])N
-864([count])X
-1129(y)X
-1189(motion)X
-1 f
-776 4722(Copy)N
-981(\(or)X
-1107(``yank''\))X
-1430(a)X
-1498(text)X
-1650(region)X
-1887(speci\256ed)X
-2204(by)X
-2316(the)X
-7 f
-2446(count)X
-1 f
-2718(and)X
-2866(motion)X
-3124(into)X
-3280(a)X
-3349(buffer.)X
-3619(If)X
-7 f
-3706(count)X
-1 f
-3979(is)X
-776 4812(speci\256ed,)N
-1101(it)X
-1165(is)X
-1238(applied)X
-1494(to)X
-1576(the)X
-7 f
-1694(motion)X
-1 f
-(.)S
-776 4992(Line:)N
-1136(Unchanged,)X
-1544(unless)X
-1766(the)X
-1886(region)X
-2113(covers)X
-2345(more)X
-2532(than)X
-2692(a)X
-2751(single)X
-2965(line,)X
-3128(in)X
-3213(which)X
-3432(case)X
-3594(it)X
-3661(is)X
-3737(set)X
-3849(to)X
-3934(the)X
-1136 5082(line)N
-1276(where)X
-1493(the)X
-1611(region)X
-1836(starts.)X
-776 5172(Column:)N
-1136(Unchanged,)X
-1544(unless)X
-1766(the)X
-1886(region)X
-2113(covers)X
-2345(more)X
-2532(than)X
-2692(a)X
-2751(single)X
-2965(line,)X
-3128(in)X
-3213(which)X
-3432(case)X
-3594(it)X
-3661(is)X
-3737(set)X
-3849(to)X
-3934(the)X
-1136 5262(character)N
-1452(were)X
-1629(the)X
-1747(region)X
-1972(starts.)X
-776 5352(Options:)N
-1136(None.)X
-3 f
-576 5532([count1])N
-881(z)X
-937([count2])X
-1242(type)X
-1 f
-776 5622(Redraw)N
-1049(the)X
-1170(screen)X
-1399(with)X
-1564(a)X
-1623(window)X
-7 f
-1904(count2)X
-1 f
-2215(lines)X
-2389(long,)X
-2574(with)X
-2740(line)X
-7 f
-2884(count1)X
-1 f
-3196(placed)X
-3430(as)X
-3521(speci\256ed)X
-3830(by)X
-3934(the)X
-7 f
-776 5712(type)N
-1 f
-1005(character.)X
-1378(If)X
-7 f
-1469(count1)X
-1 f
-1794(is)X
-1884(not)X
-2023(speci\256ed,)X
-2365(it)X
-2445(defaults)X
-2735(to)X
-2833(the)X
-2967(current)X
-3231(line.)X
-3427(If)X
-7 f
-3517(count2)X
-1 f
-3841(is)X
-3930(not)X
-776 5802(speci\256ed,)N
-1101(it)X
-1165(defaults)X
-1439(to)X
-1521(the)X
-1639(current)X
-1887(window)X
-2165(size.)X
-
-29 p
-%%Page: 29 28
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Vi)X
-1364(Commands\))X
-3658(USD:13-29)X
-1 f
-776 762(The)N
-921(following)X
-7 f
-1252(type)X
-1 f
-1464(characters)X
-1811(may)X
-1969(be)X
-2065(used:)X
-776 942(+)N
-1136(If)X
-7 f
-1225(count1)X
-1 f
-1548(is)X
-1636(speci\256ed,)X
-1977(place)X
-2183(the)X
-2317(line)X
-7 f
-2473(count1)X
-1 f
-2797(at)X
-2891(the)X
-3025(top)X
-3163(of)X
-3266(the)X
-3400(screen.)X
-3682(Otherwise,)X
-1136 1032(display)N
-1387(the)X
-1505(screen)X
-1731(after)X
-1899(the)X
-2017(current)X
-2265(screen,)X
-2511(similarly)X
-2815(to)X
-2897(the)X
-3 f
-3015(<control-F>)X
-1 f
-3448(command.)X
-776 1122 0.2266(<carriage-return>)AN
-1136 1212(Place)N
-1330(the)X
-1448(line)X
-7 f
-1588(count1)X
-1 f
-1896(at)X
-1974(the)X
-2092(top)X
-2214(of)X
-2301(the)X
-2419(screen.)X
-776 1302(.)N
-1136(Place)X
-1330(the)X
-1448(line)X
-7 f
-1588(count1)X
-1 f
-1896(in)X
-1978(the)X
-2096(center)X
-2313(of)X
-2400(the)X
-2518(screen.)X
-9 f
-776 1392(-)N
-1 f
-1136(Place)X
-1330(the)X
-1448(line)X
-7 f
-1588(count1)X
-1 f
-1896(at)X
-1974(the)X
-2092(bottom)X
-2338(of)X
-2425(the)X
-2543(screen.)X
-776 1482(\303)N
-1136(If)X
-7 f
-1214(count1)X
-1 f
-1526(is)X
-1603(speci\256ed,)X
-1932(place)X
-2126(the)X
-2248(line)X
-2392(that)X
-2536(is)X
-2613(at)X
-2695(the)X
-2817(top)X
-2943(of)X
-3034(the)X
-3156(screen)X
-3386(when)X
-7 f
-3584(count1)X
-1 f
-3896(is)X
-3974(at)X
-1136 1572(the)N
-1264(bottom)X
-1520(of)X
-1617(the)X
-1745(screen,)X
-2001(at)X
-2089(the)X
-2217(bottom)X
-2472(of)X
-2568(the)X
-2695(screen,)X
-2950(i.e.)X
-3077(display)X
-3337(the)X
-3464(screen)X
-3699(before)X
-3934(the)X
-1136 1662(screen)N
-1362(before)X
-7 f
-1588(count1)X
-1 f
-(.)S
-1937(Otherwise,)X
-2308(display)X
-2560(the)X
-2679(screen)X
-2906(before)X
-3133(the)X
-3252(current)X
-3501(screen,)X
-3748(similarly)X
-1136 1752(to)N
-1218(the)X
-3 f
-1336(<control-B>)X
-1 f
-1773(command.)X
-776 1932(Line:)N
-1136(Set)X
-1263(to)X
-7 f
-1350(count1)X
-1 f
-1663(unless)X
-7 f
-1888(count1)X
-1 f
-2201(is)X
-2279(not)X
-2406(speci\256ed)X
-2716(and)X
-2857(the)X
-7 f
-2980(type)X
-1 f
-3197(character)X
-3518(was)X
-3668(either)X
-3876(``)X
-7 f
-3930(\303)X
-1 f
-('')S
-1136 2022(or)N
-1224(``)X
-7 f
-1278(+)X
-1 f
-('',)S
-1421(in)X
-1504(which)X
-1721(case)X
-1881(it)X
-1946(is)X
-2020(set)X
-2130(to)X
-2213(the)X
-2332(line)X
-2473(before)X
-2700(the)X
-2819(\256rst)X
-2964(line)X
-3105(on)X
-3206(the)X
-3325(previous)X
-3621(screen)X
-3847(or)X
-3934(the)X
-1136 2112(line)N
-1276(after)X
-1444(the)X
-1562(last)X
-1693(line)X
-1833(on)X
-1933(the)X
-2051(previous)X
-2347(screen,)X
-2593(respectively.)X
-776 2202(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(in)X
-2318(the)X
-2436(line.)X
-776 2292(Options:)N
-1136(None.)X
-3 f
-576 2472([count])N
-841({)X
-1 f
-776 2562(Move)N
-983(backward)X
-7 f
-1316(count)X
-1 f
-1576(paragraphs.)X
-776 2742(The)N
-3 f
-922({)X
-1 f
-975(command)X
-1312(is)X
-1386(an)X
-1483(absolute)X
-1771(movement.)X
-2170(The)X
-3 f
-2316({)X
-1 f
-2369(command)X
-2706(may)X
-2865(be)X
-2962(used)X
-3130(as)X
-3219(the)X
-3339(motion)X
-3587(component)X
-3965(of)X
-776 2832(other)N
-3 f
-963(vi)X
-1 f
-1047(commands,)X
-1436(in)X
-1520(which)X
-1738(case)X
-1899(any)X
-2036(text)X
-2177(copied)X
-2412(into)X
-2557(a)X
-2614(buffer)X
-2832(is)X
-2906(character)X
-3223(oriented,)X
-3527(unless)X
-3748(the)X
-3867(start-)X
-776 2922(ing)N
-898(character)X
-1214(is)X
-1287(the)X
-1405(\256rst)X
-1549(character)X
-1865(on)X
-1965(its)X
-2060(line,)X
-2220(in)X
-2302(which)X
-2518(case)X
-2677(it)X
-2741(is)X
-2814(line)X
-2954(oriented.)X
-776 3102(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(containing)X
-1956(the)X
-2074(beginning)X
-2414(of)X
-2501(the)X
-2619(previous)X
-2915(paragraph.)X
-776 3192(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(in)X
-2318(the)X
-2436(line.)X
-776 3282(Options:)N
-1136(Affected)X
-1438(by)X
-1538(the)X
-3 f
-1656(paragraph)X
-1 f
-2040(option.)X
-3 f
-576 3462([count])N
-841(|)X
-1 f
-776 3552(Move)N
-983(to)X
-1065(a)X
-1121(speci\256c)X
-2 f
-1386(column)X
-1 f
-1642(position)X
-1919(on)X
-2019(the)X
-2137(current)X
-2385(line.)X
-776 3732(The)N
-3 f
-922(|)X
-1 f
-962(command)X
-1300(may)X
-1460(be)X
-1558(used)X
-1727(as)X
-1816(the)X
-1936(motion)X
-2184(component)X
-2562(of)X
-2651(other)X
-3 f
-2838(vi)X
-1 f
-2922(commands,)X
-3311(in)X
-3395(which)X
-3613(case)X
-3774(any)X
-3912(text)X
-776 3822(copied)N
-1012(into)X
-1158(a)X
-1216(buffer)X
-1435(is)X
-1510(character)X
-1828(oriented.)X
-2153(It)X
-2224(is)X
-2299(an)X
-2397(error)X
-2576(to)X
-2660(use)X
-2789(the)X
-3 f
-2908(|)X
-1 f
-2947(command)X
-3284(as)X
-3372(a)X
-3429(motion)X
-3676(component)X
-776 3912(and)N
-912(for)X
-1026(the)X
-1144(cursor)X
-1365(not)X
-1487(to)X
-1569(move.)X
-776 4092(Line:)N
-1136(Unchanged.)X
-776 4182(Column:)N
-1136(Set)X
-1265(to)X
-1355(the)X
-1481(character)X
-1805(occupying)X
-2167(the)X
-2293(column)X
-2561(position)X
-2846(identi\256ed)X
-3176(by)X
-7 f
-3284(count)X
-1 f
-(,)S
-3572(if)X
-3649(the)X
-3775(position)X
-1136 4272(exists)N
-1339(in)X
-1422(the)X
-1541(line.)X
-1722(If)X
-1797(the)X
-1916(column)X
-2176(length)X
-2396(of)X
-2483(the)X
-2601(current)X
-2849(line)X
-2989(is)X
-3062(less)X
-3202(than)X
-7 f
-3360(count)X
-1 f
-(,)S
-3640(the)X
-3758(cursor)X
-3979(is)X
-1136 4362(moved)N
-1374(to)X
-1456(the)X
-1574(last)X
-1705(character)X
-2021(in)X
-2103(the)X
-2221(line.)X
-776 4452(Options:)N
-1136(None.)X
-3 f
-576 4632([count])N
-841(})X
-1 f
-776 4722(Move)N
-983(forward)X
-7 f
-1258(count)X
-1 f
-1518(paragraphs.)X
-776 4902(The)N
-3 f
-922(})X
-1 f
-975(command)X
-1312(is)X
-1386(an)X
-1483(absolute)X
-1771(movement.)X
-2170(The)X
-3 f
-2316(})X
-1 f
-2369(command)X
-2706(may)X
-2865(be)X
-2962(used)X
-3130(as)X
-3219(the)X
-3339(motion)X
-3587(component)X
-3965(of)X
-776 4992(other)N
-3 f
-963(vi)X
-1 f
-1047(commands,)X
-1436(in)X
-1520(which)X
-1738(case)X
-1899(any)X
-2036(text)X
-2177(copied)X
-2412(into)X
-2557(a)X
-2614(buffer)X
-2832(is)X
-2906(character)X
-3223(oriented,)X
-3527(unless)X
-3748(the)X
-3867(start-)X
-776 5082(ing)N
-898(character)X
-1214(is)X
-1287(at)X
-1365(or)X
-1452(before)X
-1678(any)X
-1814(nonblank)X
-2132(characters)X
-2479(in)X
-2561(its)X
-2656(line,)X
-2816(in)X
-2898(which)X
-3114(case)X
-3273(it)X
-3337(is)X
-3410(line)X
-3550(oriented.)X
-776 5262(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(containing)X
-1956(the)X
-2074(beginning)X
-2414(of)X
-2501(the)X
-2619(next)X
-2777(paragraph.)X
-776 5352(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(\256rst)X
-1602(nonblank)X
-1920(character)X
-2236(in)X
-2318(the)X
-2436(line.)X
-776 5442(Options:)N
-1136(Affected)X
-1438(by)X
-1538(the)X
-3 f
-1656(paragraph)X
-1 f
-2040(option.)X
-3 f
-576 5622([count])N
-841(\304)X
-1 f
-776 5712(Reverse)N
-1062(the)X
-1187(case)X
-1353(of)X
-1447(the)X
-1572(next)X
-7 f
-1738(count)X
-1 f
-2006 0.3021(character\(s\).)AX
-2455(This)X
-2625(is)X
-2706(the)X
-2832(historic)X
-3100(semantic)X
-3413(for)X
-3535(the)X
-3 f
-3661(\304)X
-1 f
-3716(command)X
-776 5802(and)N
-912(it)X
-976(is)X
-1049(only)X
-1211(in)X
-1293(effect)X
-1497(if)X
-1566(the)X
-3 f
-1684(tildeop)X
-1 f
-1939(option)X
-2163(is)X
-2236(not)X
-2358(set.)X
-
-30 p
-%%Page: 30 29
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-30)N
-2826(Nvi/Nex)X
-3122 0.3906(Reference)AX
-3487(\(Vi)X
-3614(Commands\))X
-1 f
-776 762(Lowercase)N
-1148(alphabetic)X
-1501(characters)X
-1851(are)X
-1974(changed)X
-2266(to)X
-2352(uppercase,)X
-2718(and)X
-2858(uppercase)X
-3204(characters)X
-3555(are)X
-3678(changed)X
-3970(to)X
-776 852(lowercase.)N
-1158(No)X
-1276(other)X
-1461(characters)X
-1808(are)X
-1927(affected.)X
-776 1032(Historically,)N
-1203(the)X
-3 f
-1330(\304)X
-1 f
-1386(command)X
-1731(did)X
-1863(not)X
-1995(take)X
-2159(an)X
-2265(associated)X
-2625(count,)X
-2853(nor)X
-2990(did)X
-3122(it)X
-3196(move)X
-3404(past)X
-3563(the)X
-3691(end)X
-3837(of)X
-3934(the)X
-776 1122(current)N
-1025(line.)X
-1206(As)X
-1316(it)X
-1381(had)X
-1518(no)X
-1619(associated)X
-1970(motion)X
-2217(it)X
-2282(was)X
-2428(dif\256cult)X
-2701(to)X
-2783(change)X
-3031(the)X
-3149(case)X
-3308(of)X
-3395(large)X
-3576(blocks)X
-3805(of)X
-3892(text.)X
-776 1212(In)N
-3 f
-868(nvi)X
-1 f
-974(,)X
-1019(if)X
-1093(the)X
-1216(cursor)X
-1442(is)X
-1520(on)X
-1625(the)X
-1748(last)X
-1884(character)X
-2205(of)X
-2297(a)X
-2359(line,)X
-2525(and)X
-2667(there)X
-2854(are)X
-2979(more)X
-3170(lines)X
-3347(in)X
-3435(the)X
-3559(\256le,)X
-3707(the)X
-3831(cursor)X
-776 1302(moves)N
-1005(to)X
-1087(the)X
-1205(next)X
-1363(line.)X
-776 1482(It)N
-849(is)X
-926(not)X
-1052(an)X
-1152(error)X
-1333(to)X
-1419(specify)X
-1675(a)X
-1735(count)X
-1938(larger)X
-2151(than)X
-2314(the)X
-2437(number)X
-2707(of)X
-2799(characters)X
-3151(between)X
-3444(the)X
-3567(cursor)X
-3793(and)X
-3934(the)X
-776 1572(end)N
-912(of)X
-999(the)X
-1117(\256le.)X
-776 1752(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(of)X
-1685(the)X
-1803(character)X
-2119(after)X
-7 f
-2287(count)X
-1 f
-2547(characters,)X
-2914(or,)X
-3021(end)X
-3157(of)X
-3244(\256le.)X
-776 1842(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(character)X
-1774(after)X
-7 f
-1942(count)X
-1 f
-2202(characters,)X
-2569(or,)X
-2676(end-of-\256le.)X
-776 1932(Options:)N
-1136(Affected)X
-1438(by)X
-1538(the)X
-3 f
-1656(tildeop)X
-1 f
-1911(option.)X
-3 f
-576 2112([count])N
-841(\304)X
-888(motion)X
-1 f
-776 2202(Reverse)N
-1063(the)X
-1189(case)X
-1356(of)X
-1451(the)X
-1577(characters)X
-1932(in)X
-2022(a)X
-2086(text)X
-2234(region)X
-2467(speci\256ed)X
-2780(by)X
-2888(the)X
-7 f
-3014(count)X
-1 f
-3282(and)X
-7 f
-3426(motion)X
-1 f
-(.)S
-3782(Only)X
-3970(in)X
-776 2292(effect)N
-980(if)X
-1049(the)X
-3 f
-1167(tildeop)X
-1 f
-1422(option)X
-1646(is)X
-1719(set.)X
-776 2472(Lowercase)N
-1147(characters)X
-1496(are)X
-1617(changed)X
-1908(to)X
-1993(uppercase,)X
-2358(and)X
-2497(uppercase)X
-2842(characters)X
-3192(are)X
-3314(changed)X
-3605(to)X
-3690(lowercase.)X
-776 2562(No)N
-894(other)X
-1079(characters)X
-1426(are)X
-1545(affected.)X
-776 2742(Line:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(line)X
-1598(of)X
-1685(the)X
-1803(character)X
-2119(after)X
-2287(the)X
-2405(last)X
-2536(character)X
-2852(in)X
-2934(the)X
-3052(region.)X
-776 2832(Column:)N
-1136(Set)X
-1258(to)X
-1340(the)X
-1458(character)X
-1774(after)X
-1942(the)X
-2060(last)X
-2191(character)X
-2507(in)X
-2589(the)X
-2707(region.)X
-776 2922(Options:)N
-1136(Affected)X
-1438(by)X
-1538(the)X
-3 f
-1656(tildeop)X
-1 f
-1911(option.)X
-3 f
-576 3102(<interrupt>)N
-1 f
-776 3192(Interrupt)N
-1087(the)X
-1215(current)X
-1473(operation.)X
-1846(Many)X
-2063(of)X
-2160(the)X
-2289(potentially)X
-2662(long-running)X
-3 f
-3111(vi)X
-1 f
-3204(commands)X
-3582(may)X
-3751(be)X
-3858(inter-)X
-776 3282(rupted)N
-1014(using)X
-1220(the)X
-1351(terminal)X
-1650(interrupt)X
-1958(character.)X
-2326(These)X
-2550(operations)X
-2916(include)X
-3184(searches,)X
-3509(\256le)X
-3643(reading)X
-3916(and)X
-776 3372(writing,)N
-1059(\256lter)X
-1242(operations)X
-1608(and)X
-1756(map)X
-1927(character)X
-2256(expansion.)X
-2654(Interrupts)X
-2999(are)X
-3131(also)X
-3293(enabled)X
-3576(when)X
-3783(running)X
-776 3462(commands)N
-1143(outside)X
-1394(of)X
-3 f
-1481(vi)X
-1 f
-1543(.)X
-776 3642(If)N
-853(the)X
-7 f
-974(<interrupt>)X
-1 f
-1525(character)X
-1844(is)X
-1920(used)X
-2090(to)X
-2175(interrupt)X
-2474(while)X
-2675(entering)X
-2961(an)X
-3 f
-3060(ex)X
-1 f
-3159(command,)X
-3518(the)X
-3639(command)X
-3979(is)X
-776 3732(aborted,)N
-1057(the)X
-1175(cursor)X
-1396(returns)X
-1639(to)X
-1721(its)X
-1816(previous)X
-2112(position,)X
-2409(and)X
-3 f
-2545(vi)X
-1 f
-2627(remains)X
-2901(in)X
-2983(command)X
-3319(mode.)X
-776 3912(Generally,)N
-1145(if)X
-1226(the)X
-7 f
-1356(<interrupt>)X
-1 f
-1916(character)X
-2244(is)X
-2329(used)X
-2508(to)X
-2603(interrupt)X
-2912(any)X
-3061(operation,)X
-3417(any)X
-3566(changes)X
-3858(made)X
-776 4002(before)N
-1002(the)X
-1120(interrupt)X
-1416(are)X
-1535(left)X
-1662(in)X
-1744(place.)X
-776 4182(Line:)N
-1136(Dependent)X
-1504(on)X
-1604(the)X
-1722(operation)X
-2045(being)X
-2243(interrupted.)X
-776 4272(Column:)N
-1136(Dependent)X
-1504(on)X
-1604(the)X
-1722(operation)X
-2045(being)X
-2243(interrupted.)X
-776 4362(Options:)N
-1136(None.)X
-3 f
-776 4548(11.)N
-916(Vi)X
-1016(Text)X
-1192(Input)X
-1402(Commands)X
-1 f
-976 4671(The)N
-1121(following)X
-1452(section)X
-1699(describes)X
-2018(the)X
-2136(commands)X
-2503(available)X
-2813(in)X
-2895(the)X
-3013(text)X
-3153(input)X
-3337(mode)X
-3535(of)X
-3622(the)X
-3 f
-3740(vi)X
-1 f
-3822(editor.)X
-976 4794(Historically,)N
-3 f
-1394(vi)X
-1 f
-1476(implementations)X
-2030(only)X
-2193(permitted)X
-2521(the)X
-2640(characters)X
-2988(inserted)X
-3263(on)X
-3364(the)X
-3483(current)X
-3732(line)X
-3873(to)X
-3956(be)X
-776 4884(erased.)N
-1060(In)X
-1165(addition,)X
-1485(only)X
-1665(the)X
-7 f
-1801(<control-D>)X
-1 f
-2367(erase)X
-2571(character)X
-2905(and)X
-3059(the)X
-3195(``)X
-7 f
-3249(0<control-D>)X
-1 f
-('')S
-3916(and)X
-776 4974(``)N
-7 f
-830(\303<control-D>)X
-1 f
-('')S
-1488(erase)X
-1683(strings)X
-1925(could)X
-2132(erase)X
-2327(autoindent)X
-2694(characters.)X
-3090(This)X
-3261(implementation)X
-3792(permits)X
-776 5064(erasure)N
-1038(to)X
-1129(continue)X
-1434(past)X
-1592(the)X
-1719(beginning)X
-2068(of)X
-2164(the)X
-2291(current)X
-2548(line,)X
-2717(and)X
-2862(back)X
-3043(to)X
-3134(where)X
-3360(text)X
-3509(input)X
-3701(mode)X
-3907(was)X
-776 5154(entered.)N
-1080(In)X
-1174(addition,)X
-1483(autoindent)X
-1848(characters)X
-2202(may)X
-2367(be)X
-2471(erased)X
-2705(using)X
-2906(the)X
-3032(standard)X
-3332(erase)X
-3526(characters.)X
-3921(For)X
-776 5244(the)N
-908(line)X
-1061(and)X
-1210(word)X
-1408(erase)X
-1607(characters,)X
-1987(reaching)X
-2297(the)X
-2428(autoindent)X
-2799(characters)X
-3159(forms)X
-3379(a)X
-3448(``soft'')X
-3709(boundary,)X
-776 5334(denoting)N
-1081(the)X
-1204(end)X
-1345(of)X
-1437(the)X
-1561(current)X
-1815(word)X
-2006(or)X
-2099(line)X
-2245(erase.)X
-2477(Repeating)X
-2828(the)X
-2952(word)X
-3143(or)X
-3236(line)X
-3382(erase)X
-3574(key)X
-3716(will)X
-3866(erase)X
-776 5424(the)N
-894(autoindent)X
-1252(characters.)X
-976 5547(Historically,)N
-3 f
-1396(vi)X
-1 f
-1480(always)X
-1725(used)X
-7 f
-1894(<control-H>)X
-1 f
-2444(and)X
-7 f
-2582(<control-W>)X
-1 f
-3132(as)X
-3221(character)X
-3539(and)X
-3678(word)X
-3866(erase)X
-776 5637(characters,)N
-1148(respectively,)X
-1581(regardless)X
-1932(of)X
-2024(the)X
-2146(current)X
-2398(terminal)X
-2689(settings.)X
-2997(This)X
-3163(implementation)X
-3689(accepts,)X
-3970(in)X
-776 5727(addition)N
-1058(to)X
-1140(these)X
-1325(two)X
-1465(characters,)X
-1832(the)X
-1950(current)X
-2198(terminal)X
-2485(characters)X
-2832(for)X
-2946(those)X
-3135(operations.)X
-
-31 p
-%%Page: 31 30
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Vi)X
-1364(Commands\))X
-3658(USD:13-31)X
-776 762(<nul>)N
-1 f
-976 852(If)N
-1050(the)X
-1168(\256rst)X
-1312(character)X
-1628(of)X
-1715(the)X
-1833(input)X
-2017(is)X
-2090(a)X
-7 f
-2146(<nul>)X
-1 f
-(,)S
-2426(the)X
-2544(previous)X
-2840(input)X
-3024(is)X
-3097(replayed,)X
-3414(as)X
-3501(if)X
-3570(just)X
-3705(entered.)X
-3 f
-776 1032(<control-D>)N
-1 f
-976 1122(If)N
-1058(the)X
-1184(previous)X
-1488(character)X
-1813(on)X
-1922(the)X
-2049(line)X
-2198(was)X
-2352(an)X
-2457(autoindent)X
-2824(character,)X
-3169(erase)X
-3364(it.)X
-3477(Otherwise,)X
-3856(if)X
-3934(the)X
-976 1212(user)N
-1135(is)X
-1213(entering)X
-1501(the)X
-1624(\256rst)X
-1773(character)X
-2094(in)X
-2181(the)X
-2304(line,)X
-7 f
-2469(<control-D>)X
-1 f
-3022(is)X
-3100(ignored.)X
-3410(Otherwise,)X
-3785(a)X
-3845(literal)X
-7 f
-976 1302(<control-D>)N
-1 f
-1524(character)X
-1840(is)X
-1913(entered.)X
-3 f
-776 1482(\303<control-D>)N
-1 f
-976 1572(If)N
-1058(the)X
-1184(previous)X
-1488(character)X
-1812(on)X
-1920(the)X
-2047(line)X
-2196(was)X
-2350(an)X
-2455(autoindent)X
-2822(character,)X
-3167(erase)X
-3362(all)X
-3471(of)X
-3567(the)X
-3694(autoindent)X
-976 1662(characters)N
-1323(on)X
-1423(the)X
-1541(line.)X
-1721(In)X
-1808(addition,)X
-2110(the)X
-2228(autoindent)X
-2586(level)X
-2762(is)X
-2835(reset)X
-3007(to)X
-3089(0.)X
-3 f
-776 1842(0<control-D>)N
-1 f
-976 1932(If)N
-1058(the)X
-1184(previous)X
-1488(character)X
-1812(on)X
-1920(the)X
-2047(line)X
-2196(was)X
-2350(an)X
-2455(autoindent)X
-2822(character,)X
-3167(erase)X
-3362(all)X
-3471(of)X
-3567(the)X
-3694(autoindent)X
-976 2022(characters)N
-1323(on)X
-1423(the)X
-1541(line.)X
-3 f
-776 2202(<control-T>)N
-1 f
-976 2292(Insert)N
-1191(suf\256cient)X
-7 f
-1521(<tab>)X
-1 f
-1793(and)X
-7 f
-1941(<space>)X
-1 f
-2309(characters)X
-2669(to)X
-2764(move)X
-2975(the)X
-3106(cursor)X
-3340(forward)X
-3628(to)X
-3723(a)X
-3792(column)X
-976 2382(immediately)N
-1396(after)X
-1564(the)X
-1682(next)X
-1840(column)X
-2100(which)X
-2316(is)X
-2389(an)X
-2485(even)X
-2657(multiple)X
-2943(of)X
-3030(the)X
-3 f
-3148(shiftwidth)X
-1 f
-3514(option.)X
-976 2562(Historically,)N
-3 f
-1397(vi)X
-1 f
-1482(did)X
-1607(not)X
-1732(permit)X
-1965(the)X
-7 f
-2087(<control-T>)X
-1 f
-2639(command)X
-2979(to)X
-3065(be)X
-3165(used)X
-3336(unless)X
-3560(the)X
-3682(cursor)X
-3907(was)X
-976 2652(at)N
-1056(the)X
-1176(\256rst)X
-1322(column)X
-1584(of)X
-1673(a)X
-1731(new)X
-1887(line)X
-2029(or)X
-2117(it)X
-2182(was)X
-2328(preceded)X
-2640(only)X
-2803(by)X
-2904(autoindent)X
-3263(characters.)X
-3 f
-3651(Nvi)X
-1 f
-3792(permits)X
-976 2742(it)N
-1040(to)X
-1122(be)X
-1218(used)X
-1385(at)X
-1463(any)X
-1599(time)X
-1761(during)X
-1990(insert)X
-2188(mode.)X
-3 f
-776 2922(<erase>)N
-776 3012(<control-H>)N
-1 f
-976 3102(Erase)N
-1175(the)X
-1293(last)X
-1424(character.)X
-3 f
-776 3282(<literal)N
-1047(next>)X
-1 f
-976 3372(Quote)N
-1197(the)X
-1320(next)X
-1483(character.)X
-1844(The)X
-1994(next)X
-2157(character)X
-2479(will)X
-2629(not)X
-2757(be)X
-2859(mapped)X
-3139(\(see)X
-3295(the)X
-3 f
-3419(map)X
-1 f
-3596(command)X
-3938(for)X
-976 3462(more)N
-1162(information\))X
-1588(or)X
-1676(interpreted)X
-2045(specially.)X
-2391(A)X
-2470(carat)X
-2648(\(``)X
-7 f
-2729(\303)X
-1 f
-(''\))S
-2878(character)X
-3194(will)X
-3338(be)X
-3434(displayed)X
-3761(immedi-)X
-976 3552(ately)N
-1152(as)X
-1239(a)X
-1295(placeholder,)X
-1710(but)X
-1832(will)X
-1976(be)X
-2072(replaced)X
-2365(by)X
-2465(the)X
-2583(next)X
-2741(character.)X
-3 f
-776 3732(<escape>)N
-1 f
-976 3822(Resolve)N
-1254(all)X
-1354(text)X
-1494(input)X
-1678(into)X
-1822(the)X
-1940(\256le,)X
-2082(and)X
-2218(return)X
-2430(to)X
-2512(command)X
-2848(mode.)X
-3 f
-776 4002(<line)N
-966(erase>)X
-1 f
-976 4092(Erase)N
-1175(the)X
-1293(current)X
-1541(line.)X
-3 f
-776 4272(<control-W>)N
-776 4362(<word)N
-1020(erase>)X
-1 f
-976 4452(Erase)N
-1188(the)X
-1319(last)X
-1463(word.)X
-1701(The)X
-1859(de\256nition)X
-2198(of)X
-2298(word)X
-2496(is)X
-2582(dependent)X
-2945(on)X
-3059(the)X
-3 f
-3191(altwerase)X
-1 f
-3551(and)X
-3 f
-3701(ttywerase)X
-1 f
-976 4542(options.)N
-3 f
-776 4722 0.2102(<control-X>[0-9A-Fa-f]*)AN
-1 f
-976 4812(Insert)N
-1179(a)X
-1235(character)X
-1551(with)X
-1713(the)X
-1831(speci\256ed)X
-2136(hexadecimal)X
-2562(value)X
-2756(into)X
-2900(the)X
-3018(text.)X
-3 f
-776 4992(<interrupt>)N
-1 f
-976 5082(Interrupt)N
-1288(text)X
-1439(input)X
-1634(mode,)X
-1863(returning)X
-2188(to)X
-2281(command)X
-2628(mode.)X
-2877(If)X
-2962(the)X
-7 f
-3091(<interrupt>)X
-1 f
-3651(character)X
-3979(is)X
-976 5172(used)N
-1151(to)X
-1241(interrupt)X
-1545(inserting)X
-1852(text)X
-1999(into)X
-2150(the)X
-2275(\256le,)X
-2424(it)X
-2495(is)X
-2575(as)X
-2669(if)X
-2745(the)X
-7 f
-2870(<escape>)X
-1 f
-3281(character)X
-3604(was)X
-3756(used;)X
-3952(all)X
-976 5262(text)N
-1116(input)X
-1300(up)X
-1400(to)X
-1482(the)X
-1600(interruption)X
-1998(is)X
-2071(resolved)X
-2363(into)X
-2507(the)X
-2625(\256le.)X
-3 f
-776 5448(12.)N
-916(Ex)X
-1029(Addressing)X
-1 f
-976 5571(Addressing)N
-1363(in)X
-3 f
-1447(ex)X
-1 f
-1545(\(and)X
-1710(when)X
-3 f
-1906(ex)X
-1 f
-2004(commands)X
-2373(are)X
-2494(executed)X
-2802(from)X
-3 f
-2980(vi)X
-1 f
-3042(\))X
-3092(relates)X
-3325(to)X
-3410(the)X
-3531(current)X
-3782(line.)X
-3965(In)X
-776 5661(general,)N
-1054(the)X
-1172(current)X
-1420(line)X
-1560(is)X
-1633(the)X
-1751(last)X
-1882(line)X
-2022(affected)X
-2302(by)X
-2402(a)X
-2458(command.)X
-2834(The)X
-2979(exact)X
-3169(effect)X
-3373(on)X
-3473(the)X
-3591(current)X
-3839(line)X
-3979(is)X
-776 5751(discussed)N
-1103(under)X
-1306(the)X
-1424(description)X
-1800(of)X
-1888(each)X
-2057(command.)X
-2434(When)X
-2647(the)X
-2766(\256le)X
-2889(contains)X
-3177(no)X
-3278(lines,)X
-3470(the)X
-3589(current)X
-3838(line)X
-3979(is)X
-
-32 p
-%%Page: 32 31
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-32)N
-3391(Nvi/Nex)X
-3687 0.3906(Reference)AX
-1 f
-776 762(zero.)N
-976 885(Addresses)N
-1326(are)X
-1445(constructed)X
-1835(by)X
-1935(one)X
-2071(or)X
-2158(more)X
-2343(of)X
-2430(the)X
-2548(following)X
-2879(methods:)X
-816 1008(\(1\))N
-1030(The)X
-1175(address)X
-1436(``)X
-7 f
-1490(.)X
-1 f
-('')S
-1632(refers)X
-1836(to)X
-1918(the)X
-2036(current)X
-2284(line.)X
-816 1131(\(2\))N
-1030(The)X
-1175(address)X
-1436(``)X
-7 f
-1490($)X
-1 f
-('')S
-1612(refers)X
-1816(to)X
-1898(the)X
-2016(last)X
-2147(line)X
-2287(of)X
-2374(the)X
-2492(\256le.)X
-816 1254(\(3\))N
-1030(The)X
-1175(address)X
-1436(``)X
-7 f
-1490(N)X
-1 f
-('',)S
-1632(where)X
-7 f
-1849(N)X
-1 f
-1917(is)X
-1990(a)X
-2046(positive)X
-2319(number,)X
-2604(refers)X
-2808(to)X
-2890(the)X
-3008(N-th)X
-3175(line)X
-3315(of)X
-3402(the)X
-3520(\256le.)X
-816 1377(\(4\))N
-1030(The)X
-1178(address)X
-1442(``)X
-7 f
-1496('<character>)X
-1 f
-('')S
-2149(or)X
-2239(``)X
-7 f
-2293(`<character>)X
-1 f
-('')S
-2946(refers)X
-3153(to)X
-3238(the)X
-3359(line)X
-3503(marked)X
-3768(with)X
-3934(the)X
-1030 1467(name)N
-7 f
-1234(<character>)X
-1 f
-(.)S
-1832(\(See)X
-2005(the)X
-3 f
-2133(k)X
-1 f
-2207(or)X
-3 f
-2304(m)X
-1 f
-2400(commands)X
-2776(for)X
-2899(more)X
-3093(information)X
-3500(on)X
-3609(how)X
-3776(to)X
-3867(mark)X
-1030 1557(lines.\))N
-816 1680(\(5\))N
-1030(A)X
-1113(regular)X
-1366(expression)X
-1734(\(RE\))X
-1915(enclosed)X
-2221(by)X
-2326(slashes)X
-2578(\(``)X
-7 f
-2659(/)X
-1 f
-(''\))S
-2813(is)X
-2891(an)X
-2992(address,)X
-3278(and)X
-3419(it)X
-3488(refers)X
-3697(to)X
-3784(the)X
-3908(\256rst)X
-1030 1770(line)N
-1171(found)X
-1379(by)X
-1480(searching)X
-1809(forward)X
-2085(from)X
-2262(the)X
-2381(line)X
-2 f
-2522(after)X
-1 f
-2694(the)X
-2813(current)X
-3062(line)X
-3203(toward)X
-3447(the)X
-3566(end)X
-3703(of)X
-3791(the)X
-3910(\256le,)X
-1030 1860(and)N
-1170(stopping)X
-1469(at)X
-1551(the)X
-1673(\256rst)X
-1821(line)X
-1965(containing)X
-2327(a)X
-2387(string)X
-2593(matching)X
-2915(the)X
-3037(RE.)X
-3203(\(The)X
-3379(trailing)X
-3634(slash)X
-3819(can)X
-3956(be)X
-1030 1950(omitted)N
-1294(at)X
-1372(the)X
-1490(end)X
-1626(of)X
-1713(the)X
-1831(command)X
-2167(line.\))X
-1030 2130(If)N
-1104(no)X
-1204(RE)X
-1326(is)X
-1399(speci\256ed,)X
-1724(i.e.)X
-1842(the)X
-1960(pattern)X
-2203(is)X
-2276(``)X
-7 f
-2330(//)X
-1 f
-('',)S
-2520(the)X
-2638(last)X
-2769(RE)X
-2891(used)X
-3058(in)X
-3140(any)X
-3276(command)X
-3612(is)X
-3685(used)X
-3852(in)X
-3934(the)X
-1030 2220(search.)N
-1030 2400(If)N
-1111(the)X
-3 f
-1236(extended)X
-1 f
-1570(option)X
-1801(is)X
-1881(set,)X
-2017(the)X
-2142(RE)X
-2271(is)X
-2351(handled)X
-2632(as)X
-2726(an)X
-2829(extended)X
-3146(RE,)X
-3295(not)X
-3425(a)X
-3489(basic)X
-3682(RE.)X
-3852(If)X
-3934(the)X
-3 f
-1030 2490(wrapscan)N
-1 f
-1381(option)X
-1607(is)X
-1681(set,)X
-1811(the)X
-1930(search)X
-2157(wraps)X
-2370(around)X
-2614(to)X
-2697(the)X
-2816(beginning)X
-3157(of)X
-3245(the)X
-3364(\256le)X
-3487(and)X
-3624(continues)X
-3952(up)X
-1030 2580(to)N
-1112(and)X
-1248(including)X
-1570(the)X
-1688(current)X
-1936(line,)X
-2096(so)X
-2187(that)X
-2327(the)X
-2445(entire)X
-2648(\256le)X
-2770(is)X
-2843(searched.)X
-1030 2760(The)N
-1175(form)X
-1351(``)X
-7 f
-1405(\\/)X
-1 f
-('')S
-1575(is)X
-1648(accepted)X
-1950(for)X
-2064(historic)X
-2324(reasons,)X
-2605(and)X
-2741(is)X
-2814(identical)X
-3110(to)X
-3192(``)X
-7 f
-3246(//)X
-1 f
-(''.)S
-816 2883(\(6\))N
-1030(An)X
-1153(RE)X
-1280(enclosed)X
-1586(in)X
-1673(question)X
-1969(marks)X
-2190(\(``)X
-7 f
-2271(?)X
-1 f
-(''\))S
-2446(addresses)X
-2780(the)X
-2904(\256rst)X
-3054(line)X
-3200(found)X
-3413(by)X
-3519(searching)X
-3853(back-)X
-1030 2973(ward)N
-1212(from)X
-1389(the)X
-1508(line)X
-2 f
-1648(preceding)X
-1 f
-1989(the)X
-2107(current)X
-2355(line,)X
-2515(toward)X
-2758(the)X
-2876(beginning)X
-3216(of)X
-3303(the)X
-3421(\256le)X
-3543(and)X
-3679(stopping)X
-3974(at)X
-1030 3063(the)N
-1149(\256rst)X
-1294(line)X
-1435(containing)X
-1794(a)X
-1851(string)X
-2054(matching)X
-2373(the)X
-2492(RE.)X
-2655(\(The)X
-2828(trailing)X
-3080(question)X
-3372(mark)X
-3558(can)X
-3691(be)X
-3788(omitted)X
-1030 3153(at)N
-1108(the)X
-1226(end)X
-1362(of)X
-1449(a)X
-1505(command)X
-1841(line.\))X
-1030 3333(If)N
-1104(no)X
-1204(RE)X
-1326(is)X
-1399(speci\256ed,)X
-1724(i.e.)X
-1842(the)X
-1960(pattern)X
-2203(is)X
-2276(``)X
-7 f
-2330(??)X
-1 f
-('',)S
-2520(the)X
-2638(last)X
-2769(RE)X
-2891(used)X
-3058(in)X
-3140(any)X
-3276(command)X
-3612(is)X
-3685(used)X
-3852(in)X
-3934(the)X
-1030 3423(search.)N
-1030 3603(If)N
-1111(the)X
-3 f
-1236(extended)X
-1 f
-1570(option)X
-1801(is)X
-1881(set,)X
-2017(the)X
-2142(RE)X
-2271(is)X
-2351(handled)X
-2632(as)X
-2726(an)X
-2829(extended)X
-3146(RE,)X
-3295(not)X
-3425(a)X
-3489(basic)X
-3682(RE.)X
-3852(If)X
-3934(the)X
-3 f
-1030 3693(wrapscan)N
-1 f
-1382(option)X
-1609(is)X
-1685(set,)X
-1817(the)X
-1938(search)X
-2187(wraps)X
-2402(around)X
-2648(from)X
-2827(the)X
-2948(beginning)X
-3290(of)X
-3379(the)X
-3499(\256le)X
-3623(to)X
-3707(the)X
-3827(end)X
-3965(of)X
-1030 3783(the)N
-1148(\256le)X
-1270(and)X
-1406(continues)X
-1733(up)X
-1833(to)X
-1915(and)X
-2051(including)X
-2373(the)X
-2491(current)X
-2739(line,)X
-2899(so)X
-2990(that)X
-3130(the)X
-3248(entire)X
-3451(\256le)X
-3573(is)X
-3646(searched.)X
-1030 3963(The)N
-1175(form)X
-1351(``)X
-7 f
-1405(\\?)X
-1 f
-('')S
-1595(is)X
-1668(accepted)X
-1970(for)X
-2084(historic)X
-2344(reasons,)X
-2625(and)X
-2761(is)X
-2834(identical)X
-3130(to)X
-3212(``)X
-7 f
-3266(??)X
-1 f
-(''.)S
-816 4086(\(7\))N
-1030(An)X
-1148(address)X
-1409(followed)X
-1714(by)X
-1814(a)X
-1870(plus)X
-2023(sign)X
-2176(\(``)X
-7 f
-2257(+)X
-1 f
-(''\))S
-2406(or)X
-2494(a)X
-2551(minus)X
-2767(sign)X
-2921(\(``)X
-7 f
-3002(-)X
-1 f
-(''\))S
-3152(followed)X
-3458(by)X
-3559(a)X
-3616(number)X
-3882(is)X
-3956(an)X
-1030 4176(offset)N
-1237(address)X
-1502(and)X
-1642(refers)X
-1850(to)X
-1936(the)X
-2058(address)X
-2323(plus)X
-2480(\(or)X
-2598(minus\))X
-2844(the)X
-2966(indicated)X
-3284(number)X
-3553(of)X
-3643(lines.)X
-3857(If)X
-3934(the)X
-1030 4266(address)N
-1291(is)X
-1364(omitted,)X
-1648(the)X
-1766(addition)X
-2048(or)X
-2135(subtraction)X
-2511(is)X
-2584(done)X
-2760(with)X
-2922(respect)X
-3170(to)X
-3252(the)X
-3370(current)X
-3618(line.)X
-816 4389(\(8\))N
-1030(An)X
-1158(address)X
-1429(of)X
-1526(``)X
-7 f
-1580(+)X
-1 f
-('')S
-1712(or)X
-1809(``)X
-7 f
-9 f
-1863(-)X
-1 f
-1907('')X
-1991(followed)X
-2306(by)X
-2416(a)X
-2482(number)X
-2757(is)X
-2840(an)X
-2946(offset)X
-3159(from)X
-3345(the)X
-3473(current)X
-3731(line.)X
-3921(For)X
-1030 4479(example,)N
-1342(``)X
-7 f
-9 f
-1396(-)X
-7 f
-1440(5)X
-1 f
-('')S
-1562(is)X
-1635(the)X
-1753(same)X
-1938(as)X
-2025(``)X
-7 f
-2079(.)X
-9 f
-(-)S
-7 f
-2171(5)X
-1 f
-(''.)S
-816 4602(\(9\))N
-1030(An)X
-1151(address)X
-1415(ending)X
-1656(with)X
-1821(``)X
-7 f
-1875(+)X
-1 f
-('')S
-2000(or)X
-2090(``)X
-7 f
-2144(-)X
-1 f
-('')S
-2270(has)X
-2401(1)X
-2465(added)X
-2681(to)X
-2767(or)X
-2858(subtracted)X
-3212(from)X
-3392(the)X
-3514(address,)X
-3799(respec-)X
-1030 4692(tively.)N
-1276(As)X
-1389(a)X
-1449(consequence)X
-1884(of)X
-1975(this)X
-2114(rule)X
-2263(and)X
-2403(of)X
-2494(the)X
-2615(previous)X
-2914(rule,)X
-3082(the)X
-3203(address)X
-3467(``)X
-7 f
-9 f
-3521(-)X
-1 f
-3565('')X
-3642(refers)X
-3849(to)X
-3934(the)X
-1030 4782(line)N
-1173(preceding)X
-1513(the)X
-1634(current)X
-1886(line.)X
-2070(Moreover,)X
-2431(trailing)X
-2686(``)X
-7 f
-2740(+)X
-1 f
-('')S
-2866(and)X
-3006(``)X
-7 f
-9 f
-3060(-)X
-1 f
-3104('')X
-3182(characters)X
-3533(have)X
-3709(a)X
-3769(cumula-)X
-1030 4872(tive)N
-1170(effect.)X
-1414(For)X
-1545(example,)X
-1857(``)X
-7 f
-1911(++)X
-9 f
-(-)S
-7 f
-2051(++)X
-1 f
-('')S
-2221(refers)X
-2425(to)X
-2507(the)X
-2625(current)X
-2873(line)X
-3013(plus)X
-3166(3.)X
-816 4995(\(10\))N
-1030(A)X
-1108(percent)X
-1365(sign)X
-1518(\(``)X
-7 f
-1599(%)X
-1 f
-(''\))S
-1748(is)X
-1821(equivalent)X
-2175(to)X
-2257(the)X
-2375(address)X
-2636(range)X
-2835(``)X
-7 f
-2889(1,$)X
-1 f
-(''.)S
-3 f
-976 5118(Ex)N
-1 f
-1099(commands)X
-1476(require)X
-1734(zero,)X
-1923(one,)X
-2089(or)X
-2186(two)X
-2336(addresses.)X
-2714(It)X
-2793(is)X
-2876(an)X
-2982(error)X
-3169(to)X
-3261(specify)X
-3524(an)X
-3631(address)X
-3903(to)X
-3996(a)X
-776 5208(command)N
-1112(which)X
-1328(requires)X
-1607(zero)X
-1766(addresses.)X
-976 5331(If)N
-1053(the)X
-1174(user)X
-1331(provides)X
-1630(more)X
-1818(than)X
-1979(the)X
-2100(expected)X
-2409(number)X
-2677(of)X
-2768(addresses)X
-3100(to)X
-3186(any)X
-3 f
-3326(ex)X
-1 f
-3426(command,)X
-3786(the)X
-3908(\256rst)X
-776 5421(addresses)N
-1108(speci\256ed)X
-1417(are)X
-1540(discarded.)X
-1912(For)X
-2047(example,)X
-2362(``)X
-7 f
-2416(1,2,3,5)X
-1 f
-(''print)S
-2980(prints)X
-3185(lines)X
-3359(3)X
-3422(through)X
-3694(5,)X
-3777(because)X
-776 5511(the)N
-3 f
-894(print)X
-1 f
-1087(command)X
-1423(only)X
-1585(takes)X
-1770(two)X
-1910(addresses.)X
-976 5634(The)N
-1131(addresses)X
-1469(in)X
-1561(a)X
-1627(range)X
-1836(are)X
-1965(separated)X
-2299(from)X
-2485(each)X
-2663(other)X
-2858(by)X
-2968(a)X
-3034(comma)X
-3300(\(``)X
-7 f
-3381(,)X
-1 f
-(''\))S
-3540(or)X
-3637(a)X
-3703(semicolon)X
-776 5724(\(``)N
-7 f
-857(;)X
-1 f
-(''\).)S
-1058(In)X
-1157(the)X
-1287(latter)X
-1484(case,)X
-1675(the)X
-1805(current)X
-2065(line)X
-2217(\(``)X
-7 f
-2298(.)X
-1 f
-(''\))S
-2479(is)X
-2564(set)X
-2685(to)X
-2779(the)X
-2909(\256rst)X
-3065(address,)X
-3358(and)X
-3506(only)X
-3680(then)X
-3850(is)X
-3934(the)X
-
-33 p
-%%Page: 33 32
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-3658(USD:13-33)X
-1 f
-776 762(second)N
-1026(address)X
-1295(calculated.)X
-1689(This)X
-1859(feature)X
-2111(can)X
-2251(be)X
-2355(used)X
-2530(to)X
-2620(determine)X
-2969(the)X
-3095(starting)X
-3363(line)X
-3511(for)X
-3633(forward)X
-3916(and)X
-776 852(backward)N
-1116(searches)X
-1416(\(see)X
-1572(rules)X
-1754(\(5\))X
-1874(and)X
-2016(\(6\))X
-2136(above\).)X
-2421(The)X
-2572(second)X
-2821(address)X
-3088(of)X
-3181(any)X
-3323(two-address)X
-3737(sequence)X
-776 942(corresponds)N
-1193(to)X
-1284(a)X
-1349(line)X
-1498(that)X
-1647(follows,)X
-1936(in)X
-2027(the)X
-2154(\256le,)X
-2305(the)X
-2432(line)X
-2581(corresponding)X
-3069(to)X
-3160(the)X
-3288(\256rst)X
-3442(address.)X
-3753(The)X
-3908(\256rst)X
-776 1032(address)N
-1044(must)X
-1226(be)X
-1329(less)X
-1475(than)X
-1639(or)X
-1732(equal)X
-1932(to)X
-2020(the)X
-2144(second)X
-2393(address.)X
-2700(The)X
-2851(\256rst)X
-3001(address)X
-3268(must)X
-3449(be)X
-3551(greater)X
-3801(than)X
-3965(or)X
-776 1122(equal)N
-973(to)X
-1058(the)X
-1179(\256rst)X
-1326(line)X
-1469(of)X
-1559(the)X
-1680(\256le,)X
-1825(and)X
-1964(the)X
-2085(last)X
-2219(address)X
-2483(must)X
-2661(be)X
-2761(less)X
-2905(than)X
-3067(or)X
-3158(equal)X
-3356(to)X
-3442(the)X
-3564(last)X
-3699(line)X
-3843(of)X
-3934(the)X
-776 1212(\256le.)N
-3 f
-776 1398(13.)N
-916(Ex)X
-1029(Description)X
-1 f
-976 1521(The)N
-1121(following)X
-1452(words)X
-1668(have)X
-1840(special)X
-2083(meanings)X
-2410(for)X
-3 f
-2524(ex)X
-1 f
-2620(commands.)X
-3 f
-776 1701(<eof>)N
-1 f
-976 1791(The)N
-1130(end-of-\256le)X
-1498(character)X
-1823(is)X
-1905(used)X
-2081(to)X
-2172(scroll)X
-2379(the)X
-2506(screen)X
-2741(in)X
-2832(the)X
-3 f
-2959(ex)X
-1 f
-3064(editor.)X
-3320(This)X
-3491(character)X
-3816(is)X
-3898(nor-)X
-976 1881(mally)N
-7 f
-1178(<control-D>)X
-1 f
-(,)S
-1746(however,)X
-2063(whatever)X
-2378(character)X
-2694(is)X
-2767(set)X
-2876(for)X
-2990(the)X
-3108(current)X
-3356(terminal)X
-3643(is)X
-3716(used.)X
-3 f
-776 2061(line)N
-1 f
-976 2151(A)N
-1054(single-line)X
-1412(address,)X
-1693(given)X
-1891(in)X
-1973(any)X
-2109(of)X
-2196(the)X
-2314(forms)X
-2521(described)X
-2849(in)X
-2931(the)X
-3049(section)X
-3296(entitled)X
-3557(``)X
-3 f
-3611(Ex)X
-3725(Address-)X
-976 2241(ing)N
-1 f
-1082(''.)X
-1196(The)X
-1341(default)X
-1584(for)X
-7 f
-1698(line)X
-1 f
-1910(is)X
-1983(the)X
-2101(current)X
-2349(line.)X
-3 f
-776 2421(range)N
-1 f
-976 2511(A)N
-1058(line,)X
-1222(or)X
-1313(a)X
-1373(pair)X
-1522(of)X
-1613(line)X
-1757(addresses,)X
-2109(separated)X
-2437(by)X
-2541(a)X
-2601(comma)X
-2861(or)X
-2952(semicolon.)X
-3345(\(See)X
-3512(the)X
-3634(section)X
-3885(enti-)X
-976 2601(tled)N
-1123(``)X
-3 f
-1177(Ex)X
-1297(Addressing)X
-1 f
-1683('')X
-1764(for)X
-1884(more)X
-2075(information.\))X
-2546(The)X
-2697(default)X
-2946(for)X
-3066(range)X
-3271(is)X
-3350(the)X
-3474(current)X
-3728(line)X
-2 f
-3874(only)X
-1 f
-4012(,)X
-976 2691(i.e.)N
-1114(``)X
-7 f
-1168(.,.)X
-1 f
-(''.)S
-1426(A)X
-1504(percent)X
-1761(sign)X
-1914(\(``)X
-7 f
-1995(%)X
-1 f
-(''\))S
-2144(stands)X
-2364(for)X
-2479(the)X
-2598(range)X
-2798(``)X
-7 f
-2852(1,$)X
-1 f
-(''.)S
-3111(The)X
-3257(starting)X
-3518(address)X
-3780(must)X
-3956(be)X
-976 2781(less)N
-1116(than,)X
-1294(or)X
-1381(equal)X
-1575(to,)X
-1677(the)X
-1795(ending)X
-2033(address.)X
-3 f
-776 2961(count)N
-1 f
-976 3051(A)N
-1058(positive)X
-1335(integer,)X
-1602(specifying)X
-1961(the)X
-2084(number)X
-2354(of)X
-2446(lines)X
-2622(to)X
-2709(be)X
-2810(affected)X
-3095(by)X
-3200(the)X
-3323(command;)X
-3686(the)X
-3809(default)X
-976 3141(is)N
-1055(1.)X
-1161(Generally,)X
-1524(a)X
-1586(count)X
-1790(past)X
-1945(the)X
-2068(end-of-\256le)X
-2432(may)X
-2595(be)X
-2696(speci\256ed,)X
-3026(e.g.)X
-3167(the)X
-3290(command)X
-3631(``)X
-7 f
-3685(p)X
-3786(3000)X
-1 f
-('')S
-976 3231(in)N
-1064(a)X
-1127(10)X
-1234(line)X
-1381(\256le)X
-1510(is)X
-1590(acceptable,)X
-1977(and)X
-2120(will)X
-2271(print)X
-2449(from)X
-2632(the)X
-2757(current)X
-3012(line)X
-3159(through)X
-3435(the)X
-3560(last)X
-3698(line)X
-3845(in)X
-3934(the)X
-976 3321(\256le.)N
-3 f
-776 3501(\257ags)N
-1 f
-976 3591(One)N
-1132(or)X
-1221(more)X
-1408(of)X
-1497(the)X
-1617(characters)X
-1966(``#'',)X
-2156(``p'',)X
-2346(and)X
-2484(``l''.)X
-2677(When)X
-2892(a)X
-2951(command)X
-3290(that)X
-3433(accepts)X
-3693(these)X
-3881(\257ags)X
-976 3681(completes,)N
-1343(the)X
-1463(addressed)X
-1802(line\(s\))X
-2029(are)X
-2150(written)X
-2399(out)X
-2523(as)X
-2612(if)X
-2683(by)X
-2785(the)X
-2905(corresponding)X
-3 f
-3386(#)X
-1 f
-(,)S
-3 f
-3468(l)X
-1 f
-3512(or)X
-3 f
-3600(p)X
-1 f
-3665(commands.)X
-976 3771(In)N
-1064(addition,)X
-1367(any)X
-1504(number)X
-1770(of)X
-1858(``)X
-7 f
-1912(+)X
-1 f
-('')S
-2035(or)X
-2123(``)X
-7 f
-9 f
-2177(-)X
-1 f
-2221('')X
-2296(characters)X
-2644(can)X
-2777(be)X
-2874(speci\256ed)X
-3180(before,)X
-3427(after,)X
-3616(or)X
-3704(during)X
-3934(the)X
-976 3861(\257ags,)N
-1175(in)X
-1265(which)X
-1489(case)X
-1656(the)X
-1782(line)X
-1930(written)X
-2185(is)X
-2266(not)X
-2396(necessarily)X
-2780(the)X
-2905(one)X
-3048(affected)X
-3335(by)X
-3442(the)X
-3567(command,)X
-3930(but)X
-976 3951(rather)N
-1184(the)X
-1302(line)X
-1442(addressed)X
-1779(by)X
-1879(the)X
-1997(offset)X
-2200(address)X
-2461(speci\256ed.)X
-2806(The)X
-2951(default)X
-3194(for)X
-7 f
-3308(flags)X
-1 f
-3568(is)X
-3641(none.)X
-3 f
-776 4131(\256le)N
-1 f
-976 4221(A)N
-1055(pattern)X
-1299(used)X
-1467(to)X
-1550(derive)X
-1772(a)X
-1829(pathname;)X
-2184(the)X
-2303(default)X
-2547(is)X
-2621(the)X
-2740(current)X
-2989(\256le.)X
-3152(File)X
-3297(names)X
-3524(are)X
-3645(subjected)X
-3970(to)X
-976 4311(normal)N
-2 f
-1223(sh)X
-1 f
-1294(\(1\))X
-1408(word)X
-1593(expansions.)X
-976 4434(Anywhere)N
-1336(a)X
-1397(\256le)X
-1524(name)X
-1723(is)X
-1801(speci\256ed,)X
-2131(it)X
-2200(is)X
-2279(also)X
-2434(possible)X
-2722(to)X
-2810(use)X
-2943(the)X
-3067(special)X
-3316(string)X
-3524(``)X
-7 f
-3578(/tmp)X
-1 f
-(''.)S
-3890(This)X
-776 4524(will)N
-936(be)X
-1048(replaced)X
-1357(with)X
-1535(a)X
-1607(temporary)X
-1973(\256le)X
-2111(name)X
-2321(which)X
-2553(can)X
-2701(be)X
-2813(used)X
-2996(for)X
-3126(temporary)X
-3491(work,)X
-3711(e.g.)X
-3882(``)X
-7 f
-3936(:e)X
-776 4614(/tmp)N
-1 f
-('')S
-1042(creates)X
-1286(and)X
-1422(edits)X
-1593(a)X
-1649(new)X
-1803(\256le.)X
-976 4737(If)N
-1052(both)X
-1216(a)X
-1274(count)X
-1474(and)X
-1613(a)X
-1672(range)X
-1874(are)X
-1996(speci\256ed)X
-2304(for)X
-2421(commands)X
-2791(that)X
-2934(use)X
-3064(either,)X
-3290(the)X
-3411(starting)X
-3674(line)X
-3817(for)X
-3934(the)X
-776 4827(command)N
-1120(is)X
-1200(the)X
-2 f
-1325(last)X
-1 f
-1467(line)X
-1614(addressed)X
-1958(by)X
-2065(the)X
-2190(range,)X
-2416(and)X
-7 f
-2559(count)X
-1 f
-(-)S
-2853(subsequent)X
-3236(lines)X
-3414(are)X
-3540(affected)X
-3827(by)X
-3934(the)X
-776 4917(command,)N
-1132(e.g.)X
-1268(the)X
-1386(command)X
-1722(``)X
-7 f
-1776(2,3p4)X
-1 f
-('')S
-2090(prints)X
-2292(out)X
-2414(lines)X
-2585(3,)X
-2665(4,)X
-2745(5)X
-2805(and)X
-2941(6.)X
-976 5040(When)N
-1188(only)X
-1350(a)X
-1406(line)X
-1546(or)X
-1633(range)X
-1833(is)X
-1907(speci\256ed,)X
-2233(with)X
-2396(no)X
-2497(command,)X
-2854(the)X
-2973(implied)X
-3238(command)X
-3575(is)X
-3649(either)X
-3853(a)X
-3 f
-3910(list)X
-1 f
-4012(,)X
-3 f
-776 5130(number)N
-1 f
-1073(or)X
-3 f
-1166(print)X
-1 f
-1365(command.)X
-1747(The)X
-1898(command)X
-2240(used)X
-2413(is)X
-2492(the)X
-2616(most)X
-2797(recent)X
-3020(of)X
-3112(the)X
-3235(three)X
-3421(commands)X
-3793(to)X
-3880(have)X
-776 5220(been)N
-949(used)X
-1117(\(including)X
-1467(any)X
-1604(use)X
-1732(as)X
-1820(a)X
-1877(\257ag\).)X
-2085(If)X
-2160(none)X
-2337(of)X
-2425(these)X
-2611(commands)X
-2979(have)X
-3152(been)X
-3325(used)X
-3493(before,)X
-3740(the)X
-3 f
-3859(print)X
-1 f
-776 5310(command)N
-1117(is)X
-1195(the)X
-1318(implied)X
-1587(command.)X
-1968(When)X
-2185(no)X
-2290(range)X
-2494(or)X
-2585(count)X
-2787(is)X
-2864(speci\256ed)X
-3173(and)X
-3313(the)X
-3435(command)X
-3775(line)X
-3919(is)X
-3996(a)X
-776 5400(blank)N
-974(line,)X
-1134(the)X
-1252(current)X
-1500(line)X
-1640(is)X
-1713(incremented)X
-2130(by)X
-2230(1)X
-2290(and)X
-2426(then)X
-2584(the)X
-2702(current)X
-2950(line)X
-3090(is)X
-3163(displayed.)X
-976 5523(Zero)N
-1149(or)X
-1237(more)X
-1423(whitespace)X
-1801(characters)X
-2149(may)X
-2308(precede)X
-2580(or)X
-2668(follow)X
-2898(the)X
-3017(addresses,)X
-3366(count,)X
-3585(\257ags,)X
-3778(or)X
-3867(com-)X
-776 5613(mand)N
-980(name.)X
-1220(Any)X
-1384(object)X
-1606(following)X
-1943(a)X
-2004(command)X
-2345(name)X
-2544(\(such)X
-2743(as)X
-2835(buffer,)X
-3077(\256le,)X
-3224(etc.\),)X
-3410(that)X
-3555(begins)X
-3789(with)X
-3956(an)X
-776 5703(alphabetic)N
-1130(character,)X
-1471(should)X
-1709(be)X
-1810(separated)X
-2139(from)X
-2320(the)X
-2443(command)X
-2784(name)X
-2983(by)X
-3088(at)X
-3171(least)X
-3343(one)X
-3484(whitespace)X
-3866(char-)X
-776 5793(acter.)N
-
-34 p
-%%Page: 34 33
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-34)N
-2813(Nvi/Nex)X
-3109 0.3906(Reference)AX
-3474(\(Ex)X
-3614(Commands\))X
-1 f
-976 762(Any)N
-1148(character,)X
-1498(including)X
-7 f
-1834(<carriage-return>)X
-1 f
-(,)S
-2704(``)X
-7 f
-2758(%)X
-1 f
-('')S
-2894(and)X
-3045(``)X
-7 f
-3099(#)X
-1 f
-('')S
-3236(retain)X
-3454(their)X
-3636(literal)X
-3858(value)X
-776 852(when)N
-970(preceded)X
-1281(by)X
-1381(a)X
-1437(backslash.)X
-3 f
-776 1038(14.)N
-916(Ex)X
-1029(Commands)X
-1 f
-976 1161(The)N
-1122(following)X
-1454(section)X
-1702(describes)X
-2022(the)X
-2141(commands)X
-2509(available)X
-2820(in)X
-2903(the)X
-3 f
-3023(ex)X
-1 f
-3121(editor.)X
-3370(In)X
-3459(each)X
-3629(entry)X
-3816(below,)X
-776 1251(the)N
-894(tag)X
-1012(line)X
-1152(is)X
-1225(a)X
-1281(usage)X
-1484(synopsis)X
-1779(for)X
-1893(the)X
-2011(command.)X
-976 1374(Each)N
-1161(command)X
-1501(can)X
-1637(be)X
-1737(entered)X
-1998(as)X
-2089(the)X
-2211(abbreviation)X
-2636(\(those)X
-2856(characters)X
-3207(in)X
-3293(the)X
-3416(synopsis)X
-3716(command)X
-776 1464(word)N
-966(preceding)X
-1307(the)X
-1429(``['')X
-1588 0.3375(character\),)AX
-1955(the)X
-2077(full)X
-2212(command)X
-2552(\(all)X
-2683(characters)X
-3034(shown)X
-3267(for)X
-3385(the)X
-3507(command)X
-3847(word,)X
-776 1554(omitting)N
-1067(the)X
-1187(``['')X
-1344(and)X
-1482(``]'')X
-1639 0.2955(characters\),)AX
-2035(or)X
-2124(any)X
-2262(leading)X
-2520(subset)X
-2742(of)X
-2831(the)X
-2951(full)X
-3084(command)X
-3422(down)X
-3622(to)X
-3706(the)X
-3826(abbre-)X
-776 1644(viation.)N
-1064(For)X
-1201(example,)X
-1519(the)X
-1643(args)X
-1803(command)X
-2145(\(shown)X
-2407(as)X
-2500(``)X
-7 f
-2554(ar[gs])X
-1 f
-('')S
-2922(in)X
-3010(the)X
-3134(synopsis\))X
-3462(can)X
-3600(be)X
-3702(entered)X
-3965(as)X
-776 1734(``)N
-7 f
-830(ar)X
-1 f
-('',)S
-1020(``)X
-7 f
-1074(arg)X
-1 f
-('')S
-1292(or)X
-1379(``)X
-7 f
-1433(args)X
-1 f
-(''.)S
-976 1857(Each)N
-3 f
-1163(ex)X
-1 f
-1265(command)X
-1607(described)X
-1941(below)X
-2163(notes)X
-2359(the)X
-2484(new)X
-2645(current)X
-2900(line)X
-3047(after)X
-3222(it)X
-3293(is)X
-3373(executed,)X
-3706(as)X
-3800(well)X
-3965(as)X
-776 1947(any)N
-912(options)X
-1167(that)X
-1307(affect)X
-1511(the)X
-1629(command.)X
-976 2127(A)N
-1063(comment.)X
-1430(Command)X
-1792(lines)X
-1972(beginning)X
-2321(with)X
-2492(the)X
-2619(double-quote)X
-3072(character)X
-3398(\(``)X
-7 f
-3479(")X
-1 f
-(''\))S
-3638(are)X
-3767(ignored.)X
-976 2217(This)N
-1138(permits)X
-1398(comments)X
-1747(in)X
-1829(editor)X
-2036(scripts)X
-2265(and)X
-2401(startup)X
-2639(\256les.)X
-3 f
-776 2397(<end-of-\256le>)N
-1 f
-976 2487(Scroll)N
-1189(the)X
-1309(screen.)X
-1577(Write)X
-1782(the)X
-1902(next)X
-2062(N)X
-2142(lines,)X
-2336(where)X
-2556(N)X
-2637(is)X
-2713(the)X
-2834(value)X
-3031(of)X
-3121(the)X
-3 f
-3242(scroll)X
-1 f
-3452(option.)X
-3719(The)X
-3867(com-)X
-976 2577(mand)N
-1191(is)X
-1281(the)X
-1416(end-of-\256le)X
-1792(terminal)X
-2096(character,)X
-2449(which)X
-2682(may)X
-2857(be)X
-2970(different)X
-3284(on)X
-3401(different)X
-3714(terminals.)X
-976 2667(Traditionally,)N
-1434(it)X
-1498(is)X
-1571(the)X
-7 f
-1689(<control-D>)X
-1 f
-2237(key.)X
-976 2847(Historically,)N
-1397(the)X
-3 f
-1518(eof)X
-1 f
-1644(command)X
-1984(ignored)X
-2253(any)X
-2393(preceding)X
-2734(count,)X
-2956(and)X
-3096(the)X
-7 f
-3218(<end-of-file>)X
-1 f
-3866(char-)X
-976 2937(acter)N
-1155(was)X
-1302(ignored)X
-1569(unless)X
-1791(it)X
-1857(was)X
-2004(entered)X
-2263(as)X
-2352(the)X
-2472(\256rst)X
-2618(character)X
-2936(of)X
-3025(the)X
-3145(command.)X
-3522(This)X
-3685(implemen-)X
-976 3027(tation)N
-1178(treats)X
-1372(it)X
-1436(as)X
-1523(a)X
-1579(command)X
-2 f
-1915(only)X
-1 f
-2073(if)X
-2142(entered)X
-2399(as)X
-2486(the)X
-2604(\256rst)X
-2748(character)X
-3064(of)X
-3151(the)X
-3269(command)X
-3605(line,)X
-3766(and)X
-3903(oth-)X
-976 3117(erwise)N
-1206(treats)X
-1400(it)X
-1464(as)X
-1551(any)X
-1687(other)X
-1872(character.)X
-976 3297(Line:)N
-1336(Set)X
-1458(to)X
-1540(the)X
-1658(last)X
-1789(line)X
-1929(written.)X
-976 3387(Options:)N
-1336(None.)X
-3 f
-776 3567(!)N
-823(argument\(s\))X
-776 3657([range]!)N
-1073(argument\(s\))X
-1 f
-976 3747(Execute)N
-1263(a)X
-1327(shell)X
-1506(command,)X
-1870(or)X
-1966(\256lter)X
-2146(lines)X
-2326(through)X
-2604(a)X
-2669(shell)X
-2849(command.)X
-3234(In)X
-3330(the)X
-3457(\256rst)X
-3610(synopsis,)X
-3934(the)X
-976 3837(remainder)N
-1333(of)X
-1430(the)X
-1558(line)X
-1708(after)X
-1886(the)X
-2014(``)X
-7 f
-2068(!)X
-1 f
-('')S
-2220(character)X
-2546(is)X
-2629(passed)X
-2873(to)X
-2965(the)X
-3093(program)X
-3395(named)X
-3639(by)X
-3749(the)X
-3 f
-3877(shell)X
-1 f
-976 3927(option,)N
-1220(as)X
-1307(a)X
-1363(single)X
-1574(argument.)X
-976 4107(Within)N
-1227(the)X
-1354(rest)X
-1499(of)X
-1595(the)X
-1722(line,)X
-1891(``)X
-7 f
-1945(%)X
-1 f
-('')S
-2076(and)X
-2221(``)X
-7 f
-2275(#)X
-1 f
-('')S
-2407(are)X
-2536(expanded)X
-2874(into)X
-3028(the)X
-3156(current)X
-3414(and)X
-3560(alternate)X
-3867(path-)X
-976 4197(names,)N
-1223(respectively.)X
-1673(The)X
-1820(character)X
-2138(``)X
-7 f
-2192(!)X
-1 f
-('')S
-2336(is)X
-2411(expanded)X
-2741(with)X
-2904(the)X
-3023(command)X
-3360(text)X
-3501(of)X
-3589(the)X
-3708(previous)X
-3 f
-4005(!)X
-1 f
-976 4287(command.)N
-1354 0.3125(\(Therefore,)AX
-1741(the)X
-1861(command)X
-3 f
-2199(!!)X
-1 f
-2295(repeats)X
-2545(the)X
-2665(previous)X
-3 f
-2963(!)X
-1 f
-3032(command.\))X
-3437(The)X
-3585(special)X
-3831(mean-)X
-976 4377(ings)N
-1130(of)X
-1218(``)X
-7 f
-1272(%)X
-1 f
-('',)S
-1415(``)X
-7 f
-1469(#)X
-1 f
-('',)S
-1612(and)X
-1749(``)X
-7 f
-1803(!)X
-1 f
-('')S
-1946(can)X
-2079(be)X
-2176(overridden)X
-2545(by)X
-2646(escaping)X
-2948(them)X
-3129(with)X
-3292(a)X
-3349(backslash.)X
-3722(If)X
-3797(no)X
-3 f
-3898(!)X
-1 f
-3965(or)X
-3 f
-976 4467(:!)N
-1 f
-1075(command)X
-1416(has)X
-1548(yet)X
-1671(been)X
-1848(executed,)X
-2179(it)X
-2248(is)X
-2326(an)X
-2427(error)X
-2609(to)X
-2696(use)X
-2828(an)X
-2929(unescaped)X
-3290(``)X
-7 f
-3344(!)X
-1 f
-('')S
-3492(character.)X
-3854(The)X
-3 f
-4005(!)X
-1 f
-976 4557(command)N
-1325(does)X
-2 f
-1505(not)X
-1 f
-1640(do)X
-1752(shell)X
-1935(expansion)X
-2292(on)X
-2404(the)X
-2534(strings)X
-2779(provided)X
-3096(as)X
-3195(arguments.)X
-3601(If)X
-3687(any)X
-3835(of)X
-3934(the)X
-976 4647(above)N
-1197(expansions)X
-1582(change)X
-1839(the)X
-1966(command)X
-2311(the)X
-2438(user)X
-2602(entered,)X
-2889(the)X
-3017(command)X
-3363(is)X
-3446(redisplayed)X
-3846(at)X
-3934(the)X
-976 4737(bottom)N
-1222(of)X
-1309(the)X
-1427(screen.)X
-3 f
-976 4917(Ex)N
-1 f
-1092(then)X
-1253(executes)X
-1553(the)X
-1674(program)X
-1969(named)X
-2206(by)X
-2309(the)X
-3 f
-2430(shell)X
-1 f
-2608(option,)X
-2855(with)X
-3020(a)X
-3 f
-9 f
-3079(-)X
-3081(-)X
-3 f
-3125(c)X
-1 f
-3184(\257ag)X
-3327(followed)X
-3636(by)X
-3740(the)X
-3862(argu-)X
-976 5007(ments)N
-1187(\(which)X
-1430(are)X
-1549(bundled)X
-1827(into)X
-1971(a)X
-2027(single)X
-2238(argument\).)X
-976 5187(The)N
-3 f
-1121(!)X
-1 f
-1188(command)X
-1524(is)X
-1597(permitted)X
-1924(in)X
-2006(an)X
-2102(empty)X
-2322(\256le.)X
-976 5367(If)N
-1050(the)X
-1168(\256le)X
-1290(has)X
-1417(been)X
-1589(modi\256ed)X
-1893(since)X
-2078(it)X
-2142(was)X
-2287(last)X
-2418(completely)X
-2794(written,)X
-3061(the)X
-3179(command)X
-3515(will)X
-3659(warn)X
-3840(you.)X
-976 5547(A)N
-1054(single)X
-1265(``)X
-7 f
-1319(!)X
-1 f
-('')S
-1461(character)X
-1777(is)X
-1850(displayed)X
-2177(when)X
-2371(the)X
-2489(command)X
-2825(completes.)X
-976 5727(In)N
-1064(the)X
-1183(second)X
-1427(form)X
-1604(of)X
-1692(the)X
-3 f
-1811(!)X
-1 f
-1879(command,)X
-2236(the)X
-2355(remainder)X
-2702(of)X
-2790(the)X
-2909(line)X
-3051(after)X
-3221(the)X
-3341(``)X
-7 f
-3395(!)X
-1 f
-('')S
-3539(is)X
-3614(passed)X
-3850(to)X
-3934(the)X
-
-35 p
-%%Page: 35 34
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Ex)X
-1377(Commands\))X
-3658(USD:13-35)X
-1 f
-976 762(program)N
-1273(named)X
-1512(by)X
-1617(the)X
-3 f
-1740(shell)X
-1 f
-1920(option,)X
-2169(as)X
-2261(described)X
-2594(above.)X
-2851(The)X
-3001(speci\256ed)X
-3311(lines)X
-3487(are)X
-3610(passed)X
-3848(to)X
-3934(the)X
-976 852(program)N
-1273(as)X
-1365(standard)X
-1662(input,)X
-1871(and)X
-2012(the)X
-2135(standard)X
-2432(and)X
-2573(standard)X
-2871(error)X
-3054(output)X
-3284(of)X
-3377(the)X
-3501(program)X
-3799(replace)X
-976 942(the)N
-1094(original)X
-1363(lines.)X
-976 1122(Line:)N
-1336(Unchanged)X
-1722(if)X
-1791(no)X
-1891(range)X
-2090(was)X
-2235(speci\256ed,)X
-2560(otherwise)X
-2892(set)X
-3001(to)X
-3083(the)X
-3201(\256rst)X
-3345(line)X
-3485(of)X
-3572(the)X
-3690(range.)X
-976 1212(Options:)N
-1336(Affected)X
-1638(by)X
-1738(the)X
-3 f
-1856(autowrite)X
-1 f
-2206(and)X
-3 f
-2342(writeany)X
-1 f
-2665(options.)X
-3 f
-776 1392([range])N
-1046(nu[mber])X
-1391([count])X
-1656([\257ags])X
-776 1482([range])N
-1046(#)X
-1106([count])X
-1371([\257ags])X
-1 f
-976 1572(Display)N
-1245(the)X
-1363(selected)X
-1642(lines,)X
-1833(each)X
-2001(preceded)X
-2312(with)X
-2474(its)X
-2569(line)X
-2709(number.)X
-976 1752(The)N
-1121(line)X
-1261(number)X
-1526(format)X
-1760(is)X
-1833(``%6d'',)X
-2128(followed)X
-2433(by)X
-2533(two)X
-2673(spaces.)X
-976 1932(Line:)N
-1336(Set)X
-1458(to)X
-1540(the)X
-1658(last)X
-1789(line)X
-1929(displayed.)X
-976 2022(Options:)N
-1336(None.)X
-3 f
-776 2202(@)N
-870(buffer)X
-776 2292(*)N
-836(buffer)X
-1 f
-976 2382(Execute)N
-1255(a)X
-1311(buffer.)X
-1568(Each)X
-1749(line)X
-1890(in)X
-1973(the)X
-2092(named)X
-2327(buffer)X
-2545(is)X
-2619(executed)X
-2926(as)X
-3014(an)X
-3 f
-3111(ex)X
-1 f
-3208(command.)X
-3585(If)X
-3660(no)X
-3761(buffer)X
-3979(is)X
-976 2472(speci\256ed,)N
-1301(or)X
-1388(if)X
-1457(the)X
-1575(speci\256ed)X
-1880(buffer)X
-2097(is)X
-2170(``)X
-7 f
-2224(@)X
-1 f
-('')S
-2346(or)X
-2433(``)X
-7 f
-2487(*)X
-1 f
-('',)S
-2629(the)X
-2747(last)X
-2878(buffer)X
-3095(executed)X
-3401(is)X
-3474(used.)X
-3 f
-776 2652([range])N
-1046(<[<)X
-1185(...])X
-1292([count])X
-1557([\257ags])X
-1 f
-976 2742(Shift)N
-1154(lines)X
-1328(left)X
-1458(or)X
-1548(right.)X
-1762(The)X
-1910(speci\256ed)X
-2218(lines)X
-2392(are)X
-2514(shifted)X
-2755(to)X
-2840(the)X
-2961(left)X
-3091(\(for)X
-3235(the)X
-3 f
-3356(<)X
-1 f
-3425(command\))X
-3791(or)X
-3881(right)X
-976 2832(\(for)N
-1130(the)X
-3 f
-1261(>)X
-1 f
-1340(command\),)X
-1736(by)X
-1849(the)X
-1980(number)X
-2257(of)X
-2356(columns)X
-2659(speci\256ed)X
-2976(by)X
-3088(the)X
-3 f
-3218(shiftwidth)X
-1 f
-3596(option.)X
-3872(Only)X
-976 2922(leading)N
-1237(whitespace)X
-1619(characters)X
-1971(are)X
-2095(deleted)X
-2352(when)X
-2552(shifting)X
-2822(left;)X
-2977(once)X
-3155(the)X
-3279(\256rst)X
-3429(column)X
-3695(of)X
-3788(the)X
-3912(line)X
-976 3012(contains)N
-1283(a)X
-1359(nonblank)X
-1697(character,)X
-2053(the)X
-3 f
-2191(shift)X
-1 f
-2382(command)X
-2738(will)X
-2901(succeed,)X
-3215(but)X
-3356(the)X
-3493(line)X
-3652(will)X
-3815(not)X
-3956(be)X
-976 3102(modi\256ed.)N
-976 3282(If)N
-1050(the)X
-1168(command)X
-1504(character)X
-3 f
-1820(<)X
-1 f
-1886(or)X
-3 f
-1973(>)X
-1 f
-2039(is)X
-2112(repeated)X
-2405(more)X
-2590(than)X
-2748(once,)X
-2941(the)X
-3060(command)X
-3397(is)X
-3471(repeated)X
-3765(once)X
-3938(for)X
-976 3372(each)N
-1144(additional)X
-1484(command)X
-1820(character.)X
-976 3552(Line:)N
-1336(If)X
-1416(the)X
-1540(current)X
-1794(line)X
-1940(is)X
-2019(set)X
-2134(to)X
-2222(one)X
-2364(of)X
-2457(the)X
-2581(lines)X
-2758(that)X
-2904(are)X
-3029(affected)X
-3315(by)X
-3421(the)X
-3545(command,)X
-3908(it)X
-3979(is)X
-1336 3642(unchanged.)N
-1751(Otherwise,)X
-2128(it)X
-2199(is)X
-2279(set)X
-2395(to)X
-2484(the)X
-2609(\256rst)X
-2760(nonblank)X
-3085(character)X
-3408(of)X
-3502(the)X
-3627(lowest)X
-3863(num-)X
-1336 3732(bered)N
-1535(line)X
-1675(shifted.)X
-976 3822(Options:)N
-1336(Affected)X
-1638(by)X
-1738(the)X
-3 f
-1856(shiftwidth)X
-1 f
-2222(option.)X
-3 f
-776 4002([line])N
-974(=)X
-1040([\257ags])X
-1 f
-976 4092(Display)N
-1250(the)X
-1373(line)X
-1518(number.)X
-1828(Display)X
-2102(the)X
-2225(line)X
-2370(number)X
-2640(of)X
-7 f
-2732(line)X
-1 f
-2949(\(which)X
-3197(defaults)X
-3476(to)X
-3563(the)X
-3687(last)X
-3824(line)X
-3970(in)X
-976 4182(the)N
-1094(\256le\).)X
-976 4362(Line:)N
-1336(Unchanged.)X
-976 4452(Options:)N
-1336(None.)X
-3 f
-776 4632([range])N
-1046(>[>)X
-1185(...])X
-1292([count])X
-1557([\257ags])X
-1 f
-976 4722(Shift)N
-1155(right.)X
-1370(The)X
-1519(speci\256ed)X
-1828(lines)X
-2003(are)X
-2127(shifted)X
-2370(to)X
-2457(the)X
-2580(right)X
-2756(by)X
-2861(the)X
-2984(number)X
-3254(of)X
-3346(columns)X
-3642(speci\256ed)X
-3952(by)X
-976 4812(the)N
-3 f
-1094(shiftwidth)X
-1 f
-1460(option,)X
-1704(by)X
-1804(inserting)X
-2104(tab)X
-2222(and)X
-2358(space)X
-2557(characters.)X
-2944(Empty)X
-3177(lines)X
-3348(are)X
-3467(not)X
-3589(changed.)X
-976 4992(If)N
-1053(the)X
-1174(command)X
-1513(character)X
-1832(``)X
-7 f
-1886(>)X
-1 f
-('')S
-2011(is)X
-2087(repeated)X
-2383(more)X
-2571(than)X
-2732(once,)X
-2927(the)X
-3048(command)X
-3388(is)X
-3465(repeated)X
-3762(once)X
-3938(for)X
-976 5082(each)N
-1144(additional)X
-1484(command)X
-1820(character.)X
-976 5262(Line:)N
-1336(Set)X
-1458(to)X
-1540(the)X
-1658(last)X
-1789(line)X
-1929(modi\256ed)X
-2233(by)X
-2333(the)X
-2451(command.)X
-976 5352(Options:)N
-1336(None.)X
-3 f
-776 5532(ab[brev])N
-1090(lhs)X
-1207(rhs)X
-1 f
-976 5622(Add)N
-1135(an)X
-1232(abbreviation)X
-1654(to)X
-1737(the)X
-1856(current)X
-2105(abbreviation)X
-2527(list.)X
-2686(In)X
-3 f
-2775(vi)X
-1 f
-2837(,)X
-2879(if)X
-7 f
-2950(lhs)X
-1 f
-3116(is)X
-3191(entered)X
-3450(such)X
-3619(that)X
-3761(it)X
-3827(is)X
-3902(pre-)X
-976 5712(ceded)N
-1194(and)X
-1340(followed)X
-1655(by)X
-1765(characters)X
-2122(that)X
-2272(cannot)X
-2516(be)X
-2622(part)X
-2777(of)X
-2874(a)X
-2940(word,)X
-3155(it)X
-3229(is)X
-3312(replaced)X
-3614(by)X
-3723(the)X
-3850(string)X
-7 f
-976 5802(rhs)N
-1 f
-(.)S
-
-36 p
-%%Page: 36 35
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-36)N
-2813(Nvi/Nex)X
-3109 0.3906(Reference)AX
-3474(\(Ex)X
-3614(Commands\))X
-1 f
-976 762(Line:)N
-1336(Unchanged.)X
-976 852(Options:)N
-1336(None.)X
-3 f
-776 1032([line])N
-974(a[ppend][!])X
-1 f
-976 1122(The)N
-1123(input)X
-1309(text)X
-1451(is)X
-1526(appended)X
-1856(to)X
-1940(the)X
-2060(speci\256ed)X
-2367(line.)X
-2549(If)X
-2626(line)X
-2769(0)X
-2832(is)X
-2908(speci\256ed,)X
-3236(the)X
-3357(text)X
-3500(is)X
-3576(inserted)X
-3853(at)X
-3934(the)X
-976 1212(beginning)N
-1317(of)X
-1405(the)X
-1524(\256le.)X
-1687(Set)X
-1810(to)X
-1893(the)X
-2012(last)X
-2144(line)X
-2285(input.)X
-2510(If)X
-2585(no)X
-2686(lines)X
-2858(are)X
-2978(input,)X
-3183(then)X
-3342(set)X
-3451(to)X
-7 f
-3533(line)X
-1 f
-(,)S
-3765(or)X
-3852(to)X
-3934(the)X
-976 1302(\256rst)N
-1125(line)X
-1270(of)X
-1362(the)X
-1485(\256le)X
-1612(if)X
-1686(a)X
-7 f
-1747(line)X
-1 f
-1965(of)X
-2058(0)X
-2124(was)X
-2275(speci\256ed.)X
-2626(Following)X
-2980(the)X
-3104(command)X
-3446(name)X
-3646(with)X
-3814(a)X
-3876(``)X
-7 f
-3930(!)X
-1 f
-('')S
-976 1392(character)N
-1292(causes)X
-1522(the)X
-3 f
-1640(autoindent)X
-1 f
-2028(option)X
-2252(to)X
-2334(be)X
-2430(toggled)X
-2690(for)X
-2804(the)X
-2922(duration)X
-3209(of)X
-3296(the)X
-3414(command.)X
-976 1572(Line:)N
-1336(Unchanged.)X
-976 1662(Options:)N
-1336(Affected)X
-1661(by)X
-1784(the)X
-3 f
-1925(altwerase)X
-1 f
-2251(,)X
-3 f
-2314(autoindent)X
-1 f
-2682(,)X
-3 f
-2746(beautify)X
-1 f
-(,)S
-3 f
-3090(showmatch)X
-1 f
-3477(,)X
-3 f
-3541(ttywerase)X
-1 f
-3916(and)X
-3 f
-1336 1752(wrapmargin)N
-1 f
-1783(options.)X
-3 f
-776 1932(ar[gs])N
-1 f
-976 2022(Display)N
-1248(the)X
-1369(argument)X
-1695(list.)X
-1855(The)X
-2003(current)X
-2254(argument)X
-2580(is)X
-2657(displayed)X
-2988(inside)X
-3203(of)X
-3294(``)X
-7 f
-3348([)X
-1 f
-('')S
-3474(and)X
-3614(``)X
-7 f
-3668(])X
-1 f
-('')S
-3794(charac-)X
-976 2112(ters.)N
-1154(The)X
-1300(argument)X
-1624(list)X
-1742(is)X
-1816(the)X
-1935(list)X
-2053(of)X
-2141(operands)X
-2452(speci\256ed)X
-2758(on)X
-2859(startup,)X
-3118(which)X
-3335(can)X
-3468(be)X
-3565(replaced)X
-3859(using)X
-976 2202(the)N
-3 f
-1094(next)X
-1 f
-1261(command.)X
-976 2382(Line:)N
-1336(Unchanged.)X
-976 2472(Options:)N
-1336(None.)X
-3 f
-776 2652(bg)N
-976 2742(Vi)N
-1 f
-1076(mode)X
-1274(only.)X
-1476(Background)X
-1888(the)X
-2006(current)X
-2254(screen.)X
-976 2922(Line:)N
-1336(Set)X
-1458(to)X
-1540(the)X
-1658(current)X
-1906(line)X
-2046(when)X
-2240(the)X
-2358(screen)X
-2584(was)X
-2729(last)X
-2860(edited.)X
-976 3012(Options:)N
-1336(None.)X
-3 f
-776 3192([range])N
-1046(c[hange][!])X
-1441([count])X
-1 f
-976 3282(Replace)N
-1256(the)X
-1375(lines)X
-1548(with)X
-1712(input)X
-1898(text.)X
-2080(Following)X
-2430(the)X
-2550(command)X
-2888(name)X
-3084(with)X
-3248(a)X
-3306(``)X
-7 f
-3360(!)X
-1 f
-('')S
-3504(character)X
-3822(causes)X
-976 3372(the)N
-3 f
-1094(autoindent)X
-1 f
-1482(option)X
-1706(to)X
-1788(be)X
-1884(toggled)X
-2144(for)X
-2258(the)X
-2376(duration)X
-2663(of)X
-2750(the)X
-2868(command.)X
-976 3552(Line:)N
-1336(Set)X
-1463(to)X
-1550(the)X
-1673(last)X
-1809(line)X
-1954(input,)X
-2163(or,)X
-2275(if)X
-2349(no)X
-2454(lines)X
-2630(were)X
-2812(input,)X
-3021(set)X
-3135(to)X
-3223(the)X
-3347(line)X
-3493(before)X
-3725(the)X
-3849(target)X
-1336 3642(line,)N
-1496(or)X
-1583(to)X
-1665(the)X
-1783(\256rst)X
-1927(line)X
-2067(of)X
-2154(the)X
-2272(\256le)X
-2394(if)X
-2463(there)X
-2644(are)X
-2763(no)X
-2863(lines)X
-3034(preceding)X
-3371(the)X
-3489(target)X
-3692(line.)X
-976 3732(Options:)N
-1336(Affected)X
-1661(by)X
-1784(the)X
-3 f
-1925(altwerase)X
-1 f
-2251(,)X
-3 f
-2314(autoindent)X
-1 f
-2682(,)X
-3 f
-2746(beautify)X
-1 f
-(,)S
-3 f
-3090(showmatch)X
-1 f
-3477(,)X
-3 f
-3541(ttywerase)X
-1 f
-3916(and)X
-3 f
-1336 3822(wrapmargin)N
-1 f
-1783(options.)X
-3 f
-776 4002(chd[ir][!])N
-1113([directory])X
-776 4092(cd[!])N
-957([directory])X
-1 f
-976 4182(Change)N
-1244(the)X
-1365(current)X
-1616(working)X
-1906(directory.)X
-2259(The)X
-7 f
-2407(directory)X
-1 f
-2862(argument)X
-3188(is)X
-3265(subjected)X
-3592(to)X
-2 f
-3678(sh)X
-1 f
-3749(\(1\))X
-3867(word)X
-976 4272(expansions.)N
-1395(When)X
-1610(invoked)X
-1891(with)X
-2056(no)X
-2159(directory)X
-2472(argument)X
-2798(and)X
-2937(the)X
-7 f
-3057(HOME)X
-1 f
-3271(environment)X
-3698(variable)X
-3979(is)X
-976 4362(set,)N
-1105(the)X
-1223(directory)X
-1533(named)X
-1767(by)X
-1867(the)X
-7 f
-1985(HOME)X
-1 f
-2197(environment)X
-2622(variable)X
-2901(becomes)X
-3202(the)X
-3320(new)X
-3474(current)X
-3722(directory.)X
-976 4452(Otherwise,)N
-1353(the)X
-1478(new)X
-1639(current)X
-1894(directory)X
-2211(becomes)X
-2519(the)X
-2644(directory)X
-2961(returned)X
-3256(by)X
-3363(the)X
-2 f
-3488(getpwent)X
-1 f
-3777(\(3\))X
-3898(rou-)X
-976 4542(tine.)N
-976 4722(The)N
-3 f
-1125(chdir)X
-1 f
-1331(command)X
-1671(will)X
-1819(fail)X
-1950(if)X
-2023(the)X
-2145(\256le)X
-2271(has)X
-2402(been)X
-2578(modi\256ed)X
-2886(since)X
-3075(the)X
-3197(last)X
-3333(complete)X
-3652(write)X
-3842(of)X
-3934(the)X
-976 4812(\256le.)N
-1138(You)X
-1296(can)X
-1428(override)X
-1716(this)X
-1851(check)X
-2059(by)X
-2159(appending)X
-2513(a)X
-2569(``)X
-7 f
-2623(!)X
-1 f
-('')S
-2765(character)X
-3081(to)X
-3163(the)X
-3281(command.)X
-976 4992(Line:)N
-1336(Unchanged.)X
-976 5082(Options:)N
-1336(Affected)X
-1638(by)X
-1738(the)X
-3 f
-1856(cdpath)X
-1 f
-2111(option.)X
-3 f
-776 5262([range])N
-1046(co[py])X
-1280(line)X
-1424([\257ags])X
-776 5352([range])N
-1046(t)X
-1093(line)X
-1237([\257ags])X
-1 f
-976 5442(Copy)N
-1169(the)X
-1288(speci\256ed)X
-1594(lines)X
-1766(\(range\))X
-2020(after)X
-2189(the)X
-2308(destination)X
-2680(line.)X
-2861(Line)X
-3029(0)X
-3090(may)X
-3249(be)X
-3346(speci\256ed)X
-3652(to)X
-3735(insert)X
-3934(the)X
-976 5532(lines)N
-1147(at)X
-1225(the)X
-1343(beginning)X
-1683(of)X
-1770(the)X
-1888(\256le.)X
-976 5712(Line:)N
-1336(Unchanged.)X
-
-37 p
-%%Page: 37 36
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Ex)X
-1377(Commands\))X
-3658(USD:13-37)X
-1 f
-976 762(Options:)N
-1336(None.)X
-3 f
-776 942([range])N
-1046(d[elete])X
-1321([buffer])X
-1609([count])X
-1874([\257ags])X
-1 f
-976 1032(Delete)N
-1208(the)X
-1329(lines)X
-1503(from)X
-1682(the)X
-1803(\256le.)X
-1968(The)X
-2116(deleted)X
-2371(text)X
-2514(is)X
-2590(saved)X
-2796(in)X
-2881(the)X
-3002(speci\256ed)X
-3310(buffer,)X
-3550(or,)X
-3660(if)X
-3732(no)X
-3835(buffer)X
-976 1122(is)N
-1051(speci\256ed,)X
-1378(in)X
-1462(the)X
-1582(unnamed)X
-1898(buffer.)X
-2157(If)X
-2233(the)X
-2353(command)X
-2691(name)X
-2887(is)X
-2962(followed)X
-3269(by)X
-3371(a)X
-3429(letter)X
-3616(that)X
-3757(could)X
-3956(be)X
-976 1212(interpreted)N
-1346(as)X
-1435(either)X
-1640(a)X
-1698(buffer)X
-1917(name)X
-2113(or)X
-2202(a)X
-2261(\257ag)X
-2404(value)X
-2601(\(because)X
-2906(neither)X
-3152(a)X
-7 f
-3211(count)X
-1 f
-3474(or)X
-7 f
-3564(flags)X
-1 f
-3827(values)X
-976 1302(were)N
-1160(given\),)X
-3 f
-1412(ex)X
-1 f
-1515(treats)X
-1716(the)X
-1841(letter)X
-2033(as)X
-2127(a)X
-7 f
-2190(flags)X
-1 f
-2457(value)X
-2658(if)X
-2734(the)X
-2859(letter)X
-3051(immediately)X
-3477(follows)X
-3743(the)X
-3867(com-)X
-976 1392(mand)N
-1174(name,)X
-1388(without)X
-1652(any)X
-1788(whitespace)X
-2165(separation.)X
-2555(If)X
-2629(the)X
-2747(letter)X
-2932(is)X
-3005(preceded)X
-3316(by)X
-3416(whitespace)X
-3794(charac-)X
-976 1482(ters,)N
-1132(it)X
-1196(treats)X
-1390(it)X
-1454(as)X
-1541(a)X
-1597(buffer)X
-1814(name.)X
-976 1662(Line:)N
-1336(Set)X
-1459(to)X
-1542(the)X
-1661(line)X
-1802(following)X
-2134(the)X
-2253(deleted)X
-2506(lines,)X
-2698(or)X
-2786(to)X
-2869(the)X
-2988(last)X
-3120(line)X
-3261(if)X
-3331(the)X
-3450(deleted)X
-3703(lines)X
-3875(were)X
-1336 1752(at)N
-1414(the)X
-1532(end.)X
-976 1842(Options:)N
-1336(None.)X
-3 f
-776 2022(di[splay])N
-1093(b[uffers])X
-1412(|)X
-1450(s[creens])X
-1774(|)X
-1812(t[ags])X
-1 f
-976 2112(Display)N
-1256(buffers,)X
-1535(screens)X
-1803(or)X
-1901(tags.)X
-2101(The)X
-3 f
-2257(display)X
-1 f
-2531(command)X
-2878(takes)X
-3074(one)X
-3221(of)X
-3319(three)X
-3511(additional)X
-3862(argu-)X
-976 2202(ments,)N
-1207(which)X
-1423(are)X
-1542(as)X
-1629(follows:)X
-976 2382(b[uffers])N
-1336(Display)X
-1605(all)X
-1705(buffers)X
-1953(\(including)X
-2302(named,)X
-2556(unnamed,)X
-2890(and)X
-3026(numeric\))X
-3336(that)X
-3476(contain)X
-3732(text.)X
-976 2472(s[creens])N
-1336(Display)X
-1605(the)X
-1723(\256le)X
-1845(names)X
-2070(of)X
-2157(all)X
-2257(background)X
-2656(screens.)X
-976 2562(t[ags])N
-1336(Display)X
-1605(the)X
-1723(tags)X
-1872(stack.)X
-976 2742(Line:)N
-1336(Unchanged.)X
-976 2832(Options:)N
-1336(None.)X
-3 f
-776 3012(e[dit][!])N
-1060([+cmd])X
-1327([\256le])X
-776 3102(ex[!])N
-953([+cmd])X
-1220([\256le])X
-1 f
-976 3192(Edit)N
-1133(a)X
-1193(different)X
-1494(\256le.)X
-1661(If)X
-1740(the)X
-1863(current)X
-2116(buffer)X
-2338(has)X
-2470(been)X
-2647(modi\256ed)X
-2956(since)X
-3146(the)X
-3269(last)X
-3405(complete)X
-3724(write,)X
-3934(the)X
-976 3282(command)N
-1324(will)X
-1480(fail.)X
-1659(You)X
-1829(can)X
-1972(override)X
-2271(this)X
-2417(by)X
-2528(appending)X
-2893(a)X
-2960(``)X
-7 f
-3014(!)X
-1 f
-('')S
-3167(character)X
-3494(to)X
-3587(the)X
-3716(command)X
-976 3372(name.)N
-976 3552(If)N
-1053(the)X
-1174(``)X
-7 f
-1228(+cmd)X
-1 f
-('')S
-1497(option)X
-1724(is)X
-1800(speci\256ed,)X
-2128(that)X
-3 f
-2271(ex)X
-1 f
-2370(command)X
-2709(will)X
-2856(be)X
-2955(executed)X
-3264(in)X
-3349(the)X
-3470(new)X
-3628(\256le.)X
-3794(Any)X
-3 f
-3956(ex)X
-1 f
-976 3642(command)N
-1326(may)X
-1498(be)X
-1607(used,)X
-1807(although)X
-2120(the)X
-2251(most)X
-2439(common)X
-2752(use)X
-2892(of)X
-2992(this)X
-3140(feature)X
-3397(is)X
-3483(to)X
-3578(specify)X
-3843(a)X
-3912(line)X
-976 3732(number)N
-1241(or)X
-1328(search)X
-1554(pattern)X
-1797(to)X
-1879(set)X
-1988(the)X
-2106(initial)X
-2312(location)X
-2590(in)X
-2672(the)X
-2790(new)X
-2944(\256le.)X
-976 3912(Line:)N
-1336(If)X
-1415(you)X
-1560(have)X
-1737(previously)X
-2100(edited)X
-2321(the)X
-2444(\256le,)X
-2591(the)X
-2714(current)X
-2967(line)X
-3112(will)X
-3261(be)X
-3362(set)X
-3476(to)X
-3563(your)X
-3735(last)X
-3872(posi-)X
-1336 4002(tion)N
-1482(in)X
-1566(the)X
-1686(\256le.)X
-1850(If)X
-1926(that)X
-2068(position)X
-2347(does)X
-2516(not)X
-2640(exist,)X
-2833(or)X
-2921(you)X
-3062(have)X
-3235(not)X
-3358(previously)X
-3717(edited)X
-3934(the)X
-1336 4092(\256le,)N
-1481(the)X
-1602(current)X
-1853(line)X
-1996(will)X
-2143(be)X
-2242(set)X
-2354(to)X
-2439(the)X
-2560(\256rst)X
-2707(line)X
-2850(of)X
-2940(the)X
-3061(\256le)X
-3186(if)X
-3258(you)X
-3401(are)X
-3523(in)X
-3 f
-3608(vi)X
-1 f
-3694(mode,)X
-3916(and)X
-1336 4182(the)N
-1454(last)X
-1585(line)X
-1725(of)X
-1812(the)X
-1930(\256le)X
-2052(if)X
-2121(you)X
-2261(are)X
-2380(in)X
-3 f
-2462(ex)X
-1 f
-2538(.)X
-976 4272(Options:)N
-1336(Affected)X
-1638(by)X
-1738(the)X
-3 f
-1856(autowrite)X
-1 f
-2206(and)X
-3 f
-2342(writeany)X
-1 f
-2665(options.)X
-3 f
-776 4452(exu[sage])N
-1117([command])X
-1 f
-976 4542(Display)N
-1249(usage)X
-1456(for)X
-1574(an)X
-3 f
-1674(ex)X
-1 f
-1774(command.)X
-2154(If)X
-7 f
-2233(command)X
-1 f
-2594(is)X
-2672(speci\256ed,)X
-3002(a)X
-3063(usage)X
-3271(statement)X
-3603(for)X
-3722(that)X
-3867(com-)X
-976 4632(mand)N
-1174(is)X
-1247(displayed.)X
-1614(Otherwise,)X
-1984(usage)X
-2187(statements)X
-2545(for)X
-2659(all)X
-3 f
-2759(ex)X
-1 f
-2855(commands)X
-3222(are)X
-3341(displayed.)X
-976 4812(Line:)N
-1336(Unchanged.)X
-976 4902(Options:)N
-1336(None.)X
-3 f
-776 5082(f[ile])N
-957([\256le])X
-1 f
-976 5172(Display)N
-1249(and)X
-1389(optionally)X
-1737(change)X
-1989(the)X
-2111(\256le)X
-2237(name.)X
-2475(If)X
-2553(a)X
-2613(\256le)X
-2739(name)X
-2937(is)X
-3014(speci\256ed,)X
-3344(the)X
-3467(current)X
-3720(pathname)X
-976 5262(is)N
-1054(changed)X
-1347(to)X
-1434(the)X
-1557(speci\256ed)X
-1867(name.)X
-2106(The)X
-2256(current)X
-2509(pathname,)X
-2865(the)X
-2987(number)X
-3256(of)X
-3347(lines,)X
-3542(and)X
-3682(the)X
-3804(current)X
-976 5352(position)N
-1253(in)X
-1335(the)X
-1453(\256le)X
-1575(are)X
-1694(displayed.)X
-976 5532(Line:)N
-1336(Unchanged.)X
-976 5622(Options:)N
-1336(None.)X
-
-38 p
-%%Page: 38 37
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-38)N
-2813(Nvi/Nex)X
-3109 0.3906(Reference)AX
-3474(\(Ex)X
-3614(Commands\))X
-776 762(fg)N
-863([name])X
-976 852(Vi)N
-1 f
-1085(mode)X
-1292(only.)X
-1503(Foreground)X
-1906(the)X
-2033(speci\256ed)X
-2347(screen.)X
-2622(Swap)X
-2829(the)X
-2956(current)X
-3213(screen)X
-3448(with)X
-3619(the)X
-3747(speci\256ed)X
-976 942(backgrounded)N
-1451(screen.)X
-1717(If)X
-1791(no)X
-1891(screen)X
-2117(is)X
-2190(speci\256ed,)X
-2515(the)X
-2633(\256rst)X
-2777(background)X
-3176(screen)X
-3402(is)X
-3475(foregrounded.)X
-976 1122(Line:)N
-1336(Set)X
-1458(to)X
-1540(the)X
-1658(current)X
-1906(line)X
-2046(when)X
-2240(the)X
-2358(screen)X
-2584(was)X
-2729(last)X
-2860(edited.)X
-976 1212(Options:)N
-1336(None.)X
-3 f
-776 1392([range])N
-1046(g[lobal])X
-1328(/pattern/)X
-1646([commands])X
-776 1482([range])N
-1046(v)X
-1106(/pattern/)X
-1424([commands])X
-1 f
-976 1572(Apply)N
-1206(commands)X
-1583(to)X
-1675(lines)X
-1856(matching)X
-2184(\(or)X
-2308(not)X
-2440(matching\))X
-2795(a)X
-2861(pattern.)X
-3154(The)X
-3309(lines)X
-3490(within)X
-3725(the)X
-3854(given)X
-976 1662(range)N
-1191(that)X
-1347(match)X
-1579(\(``)X
-7 f
-1660(g[lobal])X
-1 f
-(''\),)S
-2181(or)X
-2284(do)X
-2400(not)X
-2538(match)X
-2770(\(``)X
-7 f
-2851(v)X
-1 f
-(''\))S
-3015(the)X
-3148(given)X
-3361(pattern)X
-3619(are)X
-3753(selected.)X
-976 1752(Then,)N
-1197(the)X
-1331(speci\256ed)X
-3 f
-1652(ex)X
-1 f
-1764(command\(s\))X
-2201(are)X
-2336(executed)X
-2658(with)X
-2836(the)X
-2970(current)X
-3235(line)X
-3392(\(``)X
-7 f
-3473(.)X
-1 f
-(''\))S
-3659(set)X
-3785(to)X
-3884(each)X
-976 1842(selected)N
-1257(line.)X
-1439(If)X
-1515(no)X
-1617(range)X
-1818(is)X
-1893(speci\256ed,)X
-2220(the)X
-2340(entire)X
-2545(\256le)X
-2669(is)X
-2744(searched)X
-3048(for)X
-3164(matching,)X
-3503(or)X
-3591(not)X
-3714(matching,)X
-976 1932(lines.)N
-976 2112(Multiple)N
-1279(commands)X
-1654(can)X
-1794(be)X
-1899(speci\256ed,)X
-2233(one)X
-2378(per)X
-2510(line,)X
-2679(by)X
-2788(escaping)X
-3098(each)X
-7 f
-3275(<newline>)X
-1 f
-3736(character)X
-976 2202(with)N
-1152(a)X
-1222(backslash,)X
-1588(or)X
-1689(by)X
-1803(separating)X
-2167(commands)X
-2548(with)X
-2724(a)X
-2794(``)X
-7 f
-2848(|)X
-1 f
-('')S
-2984(character.)X
-3353(If)X
-3440(no)X
-3553(commands)X
-3933(are)X
-976 2292(speci\256ed,)N
-1301(the)X
-1419(command)X
-1755(defaults)X
-2029(to)X
-2111(the)X
-3 f
-2229(print)X
-1 f
-2422(command.)X
-976 2472(For)N
-1111(the)X
-3 f
-1233(append)X
-1 f
-1485(,)X
-3 f
-1529(change)X
-1 f
-1793(and)X
-3 f
-1933(insert)X
-1 f
-2153(commands,)X
-2544(the)X
-2666(input)X
-2854(text)X
-2998(must)X
-3177(be)X
-3277(part)X
-3427(of)X
-3519(the)X
-3642(global)X
-3867(com-)X
-976 2562(mand)N
-1174(line.)X
-1354(In)X
-1441(this)X
-1576(case,)X
-1755(the)X
-1873(terminating)X
-2262(period)X
-2487(can)X
-2619(be)X
-2715(omitted)X
-2979(if)X
-3048(it)X
-3112(ends)X
-3279(the)X
-3397(commands.)X
-976 2742(The)N
-3 f
-1123(visual)X
-1 f
-1344(command)X
-1682(may)X
-1842(also)X
-1993(be)X
-2091(speci\256ed)X
-2398(as)X
-2487(one)X
-2625(of)X
-2714(the)X
-3 f
-2834(ex)X
-1 f
-2933(commands.)X
-3343(In)X
-3433(this)X
-3571(mode,)X
-3792(input)X
-3979(is)X
-976 2832(taken)N
-1173(from)X
-1352(the)X
-1473(terminal.)X
-1803(Entering)X
-2102(a)X
-3 f
-2161(Q)X
-1 f
-2246(command)X
-2585(in)X
-3 f
-2670(vi)X
-1 f
-2755(mode)X
-2956(causes)X
-3189(the)X
-3310(next)X
-3471(line)X
-3614(matching)X
-3934(the)X
-976 2922(pattern)N
-1219(to)X
-1301(be)X
-1397(selected)X
-1676(and)X
-3 f
-1812(vi)X
-1 f
-1894(to)X
-1976(be)X
-2072(reentered,)X
-2412(until)X
-2578(the)X
-2696(list)X
-2813(is)X
-2886(exhausted.)X
-976 3102(The)N
-3 f
-1121(global)X
-1 f
-1329(,)X
-3 f
-1369(v)X
-1 f
-1429(and)X
-3 f
-1565(undo)X
-1 f
-1757(commands)X
-2124(cannot)X
-2358(be)X
-2454(used)X
-2621(as)X
-2708(part)X
-2853(of)X
-2940(these)X
-3125(commands.)X
-976 3282(The)N
-1131(editor)X
-1348(options)X
-3 f
-1613(autoprint)X
-1 f
-1937(,)X
-3 f
-1987(autoindent)X
-1 f
-2355(,)X
-2405(and)X
-3 f
-2551(report)X
-1 f
-2800(are)X
-2929(turned)X
-3164(off)X
-3288(for)X
-3412(the)X
-3540(duration)X
-3837(of)X
-3934(the)X
-3 f
-976 3372(global)N
-1 f
-1204(and)X
-3 f
-1340(v)X
-1 f
-1400(commands.)X
-976 3552(Line:)N
-1336(The)X
-1481(last)X
-1612(line)X
-1752(modi\256ed.)X
-976 3642(Options:)N
-1336(None.)X
-3 f
-776 3822(he[lp])N
-1 f
-3912(Display)Y
-1245(a)X
-1301(help)X
-1459(message.)X
-976 4092(Line:)N
-1336(Unchanged.)X
-976 4182(Options:)N
-1336(None.)X
-3 f
-776 4362([line])N
-974(i[nsert][!])X
-1 f
-976 4452(The)N
-1123(input)X
-1309(text)X
-1451(is)X
-1526(inserted)X
-1803(before)X
-2032(the)X
-2153(speci\256ed)X
-2461(line.)X
-2644(Following)X
-2995(the)X
-3116(command)X
-3455(name)X
-3652(with)X
-3817(a)X
-3876(``)X
-7 f
-3930(!)X
-1 f
-('')S
-976 4542(character)N
-1292(causes)X
-1522(the)X
-3 f
-1640(autoindent)X
-1 f
-2028(option)X
-2252(setting)X
-2485(to)X
-2567(be)X
-2663(toggled)X
-2923(for)X
-3037(the)X
-3155(duration)X
-3442(of)X
-3529(this)X
-3664(command.)X
-976 4722(Line:)N
-1336(Set)X
-1460(to)X
-1544(the)X
-1664(last)X
-1797(line)X
-1939(input;)X
-2147(if)X
-2218(no)X
-2320(lines)X
-2493(were)X
-2672(input,)X
-2878(set)X
-2989(to)X
-3073(the)X
-3193(line)X
-3336(before)X
-3565(the)X
-3686(target)X
-3892(line,)X
-1336 4812(or)N
-1423(to)X
-1505(the)X
-1623(\256rst)X
-1767(line)X
-1907(of)X
-1994(the)X
-2112(\256le)X
-2234(if)X
-2303(there)X
-2484(are)X
-2603(no)X
-2703(lines)X
-2874(preceding)X
-3211(the)X
-3329(target)X
-3532(line.)X
-976 4902(Options:)N
-1336(Affected)X
-1661(by)X
-1784(the)X
-3 f
-1925(altwerase)X
-1 f
-2251(,)X
-3 f
-2314(autoindent)X
-1 f
-2682(,)X
-3 f
-2746(beautify)X
-1 f
-(,)S
-3 f
-3090(showmatch)X
-1 f
-3477(,)X
-3 f
-3541(ttywerase)X
-1 f
-3916(and)X
-3 f
-1336 4992(wrapmargin)N
-1 f
-1783(options.)X
-3 f
-776 5172([range])N
-1046(j[oin][!])X
-1334([count])X
-1599([\257ags])X
-1 f
-976 5262(Join)N
-1129(lines)X
-1300(of)X
-1387(text)X
-1527(together.)X
-976 5442(A)N
-7 f
-1056(count)X
-1 f
-1318(speci\256ed)X
-1625(to)X
-1709(the)X
-1829(command)X
-2167(speci\256es)X
-2465(that)X
-2607(the)X
-2727(last)X
-2860(line)X
-3002(of)X
-3091(the)X
-7 f
-3212(range)X
-1 f
-3475(plus)X
-7 f
-3631(count)X
-1 f
-3894(sub-)X
-976 5532(sequent)N
-1258(lines)X
-1445(will)X
-1605(be)X
-1717(joined.)X
-1993(\(Note,)X
-2232(this)X
-2383(differs)X
-2629(by)X
-2745(one)X
-2897(from)X
-3089(the)X
-3223(general)X
-3496(rule)X
-3657(where)X
-3890(only)X
-7 f
-976 5622(count)N
-1 f
-(-)S
-1263(subsequent)X
-1639(lines)X
-1810(are)X
-1929(affected.\))X
-976 5802(If)N
-1057(the)X
-1182(current)X
-1438(line)X
-1586(ends)X
-1761(with)X
-1931(a)X
-1995(whitespace)X
-2380(character,)X
-2724(all)X
-2832(whitespace)X
-3217(is)X
-3298(stripped)X
-3584(from)X
-3768(the)X
-3894(next)X
-
-39 p
-%%Page: 39 38
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Ex)X
-1377(Commands\))X
-3658(USD:13-39)X
-1 f
-976 762(line.)N
-1160(Otherwise,)X
-1534(if)X
-1607(the)X
-1729(next)X
-1891(line)X
-2035(starts)X
-2228(with)X
-2394(a)X
-2454(open)X
-2634(parenthesis)X
-3019(\(``)X
-7 f
-3100(\()X
-1 f
-(''\),)S
-3272(do)X
-3375(nothing.)X
-3682(Otherwise,)X
-976 852(if)N
-1061(the)X
-1195(current)X
-1459(line)X
-1615(ends)X
-1798(with)X
-1976(a)X
-2049(question)X
-2357(mark)X
-2559(\(``)X
-7 f
-2640(?)X
-1 f
-(''\),)S
-2826(period)X
-3068(\(``)X
-7 f
-3149(.)X
-1 f
-(''\))S
-3335(or)X
-3439(exclamation)X
-3868(point)X
-976 942(\(``)N
-7 f
-1057(!)X
-1 f
-(''\),)S
-1226(insert)X
-1424(two)X
-1564(spaces.)X
-1834(Otherwise,)X
-2204(insert)X
-2402(a)X
-2458(single)X
-2669(space.)X
-976 1122(Appending)N
-1355(a)X
-1414(``)X
-7 f
-1468(!)X
-1 f
-('')S
-1613(character)X
-1932(to)X
-2017(the)X
-2138(command)X
-2477(name)X
-2674(causes)X
-2907(a)X
-2966(simpler)X
-3230(join)X
-3378(with)X
-3544(no)X
-3648(white-space)X
-976 1212(processing.)N
-976 1392(Line:)N
-1336(Unchanged.)X
-976 1482(Options:)N
-1336(None.)X
-3 f
-776 1662([range])N
-1046(l[ist])X
-1222([count])X
-1487([\257ags])X
-1 f
-976 1752(Display)N
-1258(the)X
-1389(lines)X
-1573(unambiguously.)X
-2139(Tabs)X
-2328(are)X
-2460(displayed)X
-2801(as)X
-2902(``)X
-7 f
-2956(\303I)X
-1 f
-('',)S
-3160(and)X
-3310(the)X
-3442(end)X
-3592(of)X
-3693(the)X
-3825(line)X
-3979(is)X
-976 1842(marked)N
-1237(with)X
-1399(a)X
-1455(``)X
-7 f
-1509($)X
-1 f
-('')S
-1631(character.)X
-976 2022(Line:)N
-1336(Set)X
-1458(to)X
-1540(the)X
-1658(last)X
-1789(line)X
-1929(displayed.)X
-976 2112(Options:)N
-1336(None.)X
-3 f
-776 2292(map[!])N
-1028([lhs)X
-1172(rhs])X
-1 f
-976 2382(De\256ne)N
-1210(or)X
-1297(display)X
-1548(maps)X
-1737(\(for)X
-3 f
-1878(vi)X
-1 f
-1960(only\).)X
-976 2562(If)N
-1050(``)X
-7 f
-1104(lhs)X
-1 f
-('')S
-1322(and)X
-1458(``)X
-7 f
-1512(rhs)X
-1 f
-('')S
-1730(are)X
-1849(not)X
-1971(speci\256ed,)X
-2296(the)X
-2414(current)X
-2662(set)X
-2771(of)X
-2859(command)X
-3196(mode)X
-3395(maps)X
-3585(are)X
-3705(displayed.)X
-976 2652(If)N
-1050(a)X
-1106(``)X
-7 f
-1160(!)X
-1 f
-('')S
-1302(character)X
-1618(is)X
-1691(appended)X
-2019(to)X
-2101(to)X
-2183(the)X
-2301(command,)X
-2657(the)X
-2775(text)X
-2915(input)X
-3099(mode)X
-3297(maps)X
-3486(are)X
-3605(displayed.)X
-976 2832(Otherwise,)N
-1365(when)X
-1578(the)X
-1715(``)X
-7 f
-1769(lhs)X
-1 f
-('')S
-2006(character)X
-2342(sequence)X
-2677(is)X
-2770(entered)X
-3047(in)X
-3 f
-3149(vi)X
-1 f
-3211(,)X
-3271(the)X
-3409(action)X
-3645(is)X
-3738(as)X
-3845(if)X
-3934(the)X
-976 2922(corresponding)N
-1466(``)X
-7 f
-1520(rhs)X
-1 f
-('')S
-1749(had)X
-1896(been)X
-2079(entered.)X
-2387(If)X
-2472(a)X
-2539(``)X
-7 f
-2593(!)X
-1 f
-('')S
-2746(character)X
-3073(is)X
-3157(appended)X
-3496(to)X
-3588(the)X
-3716(command)X
-976 3012(name,)N
-1196(the)X
-1320(mapping)X
-1626(is)X
-1705(effective)X
-2013(during)X
-2249(text)X
-2396(input)X
-2587(mode,)X
-2812(otherwise,)X
-3171(it)X
-3242(is)X
-3322(effective)X
-3631(during)X
-3867(com-)X
-976 3102(mand)N
-1175(mode.)X
-1414(This)X
-1577(allows)X
-1807(``)X
-7 f
-1861(lhs)X
-1 f
-('')S
-2080(to)X
-2163(have)X
-2336(two)X
-2476(different)X
-2773(macro)X
-2994(de\256nitions)X
-3351(at)X
-3429(the)X
-3547(same)X
-3732(time:)X
-3916(one)X
-976 3192(for)N
-1090(command)X
-1426(mode)X
-1624(and)X
-1760(one)X
-1896(for)X
-2010(input)X
-2194(mode.)X
-976 3372(Whitespace)N
-1373(characters)X
-1722(require)X
-1972(escaping)X
-2275(with)X
-2439(a)X
-7 f
-2497(<literal)X
-1 f
-(next>)S
-3086(character)X
-3405(to)X
-3490(be)X
-3589(entered)X
-3849(in)X
-3934(the)X
-7 f
-976 3462(lhs)N
-1 f
-1140(string)X
-1342(in)X
-1424(visual)X
-1635(mode.)X
-976 3642(Normally,)N
-1330(keys)X
-1504(in)X
-1593(the)X
-7 f
-1718(rhs)X
-1 f
-1889(string)X
-2098(are)X
-2224(remapped)X
-2569(\(see)X
-2727(the)X
-3 f
-2853(remap)X
-1 f
-3104(option\),)X
-3383(and)X
-3527(it)X
-3599(is)X
-3680(possible)X
-3970(to)X
-976 3732(create)N
-1207(in\256nite)X
-1471(loops.)X
-1722(However,)X
-2075(keys)X
-2260(which)X
-2494(map)X
-2670(to)X
-2770(themselves)X
-3164(are)X
-3300(not)X
-3439(further)X
-3695(remapped,)X
-976 3822(regardless)N
-1327(of)X
-1419(the)X
-1542(setting)X
-1780(of)X
-1872(the)X
-3 f
-1995(remap)X
-1 f
-2243(option.)X
-2512(For)X
-2648(example,)X
-2966(the)X
-3090(command)X
-3432(``)X
-7 f
-3486(:map)X
-3732(n)X
-3834(nz.)X
-1 f
-('')S
-976 3912(maps)N
-1165(the)X
-1283(``)X
-7 f
-1337(n)X
-1 f
-('')S
-1459(key)X
-1595(to)X
-1677(the)X
-3 f
-1795(n)X
-1 f
-1859(and)X
-3 f
-1995(z)X
-1 f
-2051(commands.)X
-976 4092(To)N
-1085(exit)X
-1225(an)X
-1321(in\256nitely)X
-1629(looping)X
-1893(map,)X
-2071(use)X
-2198(the)X
-2316(terminal)X
-7 f
-2603(<interrupt>)X
-1 f
-3151(character.)X
-976 4272(Line:)N
-1336(Unchanged.)X
-976 4362(Options:)N
-1336(None.)X
-3 f
-776 4542([line])N
-974(ma[rk])X
-1235 0.3125(<character>)AX
-776 4632([line])N
-974(k)X
-1038 0.3125(<character>)AX
-1 f
-976 4722(Mark)N
-1189(the)X
-1326(line)X
-1485(with)X
-1666(the)X
-1803(mark)X
-7 f
-2007(<character>)X
-1 f
-(.)S
-2614(The)X
-2778(expressions)X
-3192(``)X
-7 f
-3246('<character>)X
-1 f
-('')S
-3916(and)X
-976 4812(``)N
-7 f
-1030(`<character>)X
-1 f
-('')S
-1680(can)X
-1812(then)X
-1970(be)X
-2066(used)X
-2233(as)X
-2320(an)X
-2416(address)X
-2677(in)X
-2759(any)X
-2895(command)X
-3231(that)X
-3371(uses)X
-3529(one.)X
-976 4992(Line:)N
-1336(Unchanged.)X
-976 5082(Options:)N
-1336(None.)X
-3 f
-776 5262([range])N
-1046(m[ove])X
-1303(line)X
-1 f
-976 5352(Move)N
-1188(the)X
-1312(speci\256ed)X
-1623(lines)X
-1800(after)X
-1974(the)X
-2098(target)X
-2307(line.)X
-2493(A)X
-2577(target)X
-2786(line)X
-2932(of)X
-3025(0)X
-3091(places)X
-3318(the)X
-3442(lines)X
-3619(at)X
-3703(the)X
-3827(begin-)X
-976 5442(ning)N
-1138(of)X
-1225(the)X
-1343(\256le.)X
-976 5622(Line:)N
-1336(Set)X
-1458(to)X
-1540(the)X
-1658(\256rst)X
-1802(of)X
-1889(the)X
-2007(moved)X
-2245(lines.)X
-976 5712(Options:)N
-1336(None.)X
-
-40 p
-%%Page: 40 39
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-40)N
-2813(Nvi/Nex)X
-3109 0.3906(Reference)AX
-3474(\(Ex)X
-3614(Commands\))X
-776 762 0.3250(mk[exrc][!])AN
-1190(\256le)X
-1 f
-976 852(Write)N
-1180(the)X
-1299(abbreviations,)X
-1772(editor)X
-1980(options)X
-2237(and)X
-2375(maps)X
-2566(to)X
-2650(the)X
-2770(speci\256ed)X
-3077(\256le.)X
-3241(Information)X
-3646(is)X
-3721(written)X
-3970(in)X
-976 942(a)N
-1034(form)X
-1212(which)X
-1430(can)X
-1564(later)X
-1729(be)X
-1827(read)X
-1988(back)X
-2162(in)X
-2246(using)X
-2441(the)X
-3 f
-2561(ex)X
-2659(source)X
-1 f
-2904(command.)X
-3282(If)X
-7 f
-3358(file)X
-1 f
-3572(already)X
-3830(exists,)X
-976 1032(the)N
-3 f
-1097(mkexrc)X
-1 f
-1379(command)X
-1718(will)X
-1865(fail.)X
-2035(This)X
-2200(check)X
-2411(can)X
-2546(be)X
-2645(overridden)X
-3016(by)X
-3119(appending)X
-3476(a)X
-3536(``)X
-7 f
-3590(!)X
-1 f
-('')S
-3736(character)X
-976 1122(to)N
-1058(the)X
-1176(command.)X
-976 1302(Line:)N
-1336(Unchanged.)X
-976 1392(Options:)N
-1336(None.)X
-3 f
-776 1572(n[ext][!])N
-1078([\256le)X
-1227(...])X
-1 f
-976 1662(Edit)N
-1142(the)X
-1273(next)X
-1444(\256le)X
-1579(from)X
-1768(the)X
-1899(argument)X
-2235(list.)X
-2405(The)X
-3 f
-2563(next)X
-1 f
-2743(command)X
-3092(will)X
-3249(fail)X
-3389(if)X
-3471(the)X
-3603(\256le)X
-3739(has)X
-3880(been)X
-976 1752(modi\256ed)N
-1287(since)X
-1478(the)X
-1602(last)X
-1739(complete)X
-2059(write.)X
-2290(This)X
-2458(check)X
-2672(can)X
-2810(be)X
-2912(overridden)X
-3286(by)X
-3392(appending)X
-3752(the)X
-3876(``)X
-7 f
-3930(!)X
-1 f
-('')S
-976 1842(character)N
-1294(to)X
-1378(the)X
-1498(command)X
-1836(name.)X
-2072(The)X
-2219(argument)X
-2544(list)X
-2663(can)X
-2797(optionally)X
-3143(be)X
-3241(replaced)X
-3536(by)X
-3639(specifying)X
-3996(a)X
-976 1932(new)N
-1131(one)X
-1268(as)X
-1355(arguments)X
-1709(to)X
-1791(this)X
-1926(command.)X
-2302(In)X
-2389(this)X
-2524(case,)X
-2703(editing)X
-2945(starts)X
-3134(with)X
-3296(the)X
-3414(\256rst)X
-3558(\256le)X
-3680(on)X
-3780(the)X
-3898(new)X
-976 2022(list.)N
-976 2202(Line:)N
-1336(Set)X
-1458(as)X
-1545(described)X
-1873(for)X
-1987(the)X
-3 f
-2105(edit)X
-1 f
-2254(command.)X
-976 2292(Options:)N
-1336(Affected)X
-1638(by)X
-1738(the)X
-1856(options)X
-3 f
-2111(autowrite)X
-1 f
-2461(and)X
-3 f
-2597(writeany)X
-1 f
-2900(.)X
-3 f
-776 2472([line])N
-974(o[pen])X
-1212(/pattern/)X
-1530([\257ags])X
-1 f
-976 2562(Enter)N
-1172(open)X
-1350(mode.)X
-1590(Open)X
-1786(mode)X
-1987(is)X
-2063(the)X
-2184(same)X
-2372(as)X
-2462(being)X
-2663(in)X
-3 f
-2748(vi)X
-1 f
-2810(,)X
-2853(but)X
-2978(with)X
-3143(a)X
-3202(one-line)X
-3488(window.)X
-3809(All)X
-3934(the)X
-976 2652(standard)N
-3 f
-1278(vi)X
-1 f
-1370(commands)X
-1747(are)X
-1876(available.)X
-2236(If)X
-2320(a)X
-2386(match)X
-2612(is)X
-2694(found)X
-2910(for)X
-3033(the)X
-3160(optional)X
-3451(RE)X
-3582(argument,)X
-3934(the)X
-976 2742(cursor)N
-1197(is)X
-1270(set)X
-1379(to)X
-1461(the)X
-1579(start)X
-1737(of)X
-1824(the)X
-1942(matching)X
-2260(pattern.)X
-2 f
-976 2922(This)N
-1133(command)X
-1465(is)X
-1538(not)X
-1660(yet)X
-1774(implemented.)X
-1 f
-976 3102(Line:)N
-1336(Unchanged,)X
-1750(unless)X
-1978(the)X
-2104(optional)X
-2394(RE)X
-2524(is)X
-2605(speci\256ed,)X
-2938(in)X
-3028(which)X
-3253(case)X
-3421(it)X
-3494(is)X
-3576(set)X
-3694(to)X
-3785(the)X
-3912(line)X
-1336 3192(where)N
-1553(the)X
-1671(matching)X
-1989(pattern)X
-2232(is)X
-2305(found.)X
-976 3282(Options:)N
-1336(Affected)X
-1638(by)X
-1738(the)X
-3 f
-1856(open)X
-1 f
-2040(option.)X
-3 f
-776 3462(pre[serve])N
-1 f
-976 3552(Save)N
-1161(the)X
-1288(\256le)X
-1419(in)X
-1510(a)X
-1575(form)X
-1760(that)X
-1909(can)X
-2050(later)X
-2222(be)X
-2327(recovered)X
-2674(using)X
-2877(the)X
-3 f
-3005(ex)X
-9 f
-3111(-)X
-3113(-)X
-3 f
-3157(r)X
-1 f
-3223(option.)X
-3497(When)X
-3719(the)X
-3847(\256le)X
-3979(is)X
-976 3642(preserved,)N
-1329(an)X
-1425(email)X
-1623(message)X
-1915(is)X
-1988(sent)X
-2137(to)X
-2219(the)X
-2337(user.)X
-976 3822(Line:)N
-1336(Unchanged.)X
-976 3912(Options:)N
-1336(None.)X
-3 f
-776 4092(prev[ious][!])N
-1 f
-976 4182(Edit)N
-1136(the)X
-1261(previous)X
-1564(\256le)X
-1693(from)X
-1876(the)X
-2001(argument)X
-2331(list.)X
-2495(The)X
-3 f
-2647(previous)X
-1 f
-2967(command)X
-3310(will)X
-3461(fail)X
-3595(if)X
-3671(the)X
-3796(\256le)X
-3925(has)X
-976 4272(been)N
-1155(modi\256ed)X
-1466(since)X
-1658(the)X
-1783(last)X
-1921(complete)X
-2241(write.)X
-2472(This)X
-2640(check)X
-2854(can)X
-2992(be)X
-3094(overridden)X
-3468(by)X
-3574(appending)X
-3934(the)X
-976 4362(``)N
-7 f
-1030(!)X
-1 f
-('')S
-1172(character)X
-1488(to)X
-1570(the)X
-1688(command)X
-2024(name.)X
-976 4542(Line:)N
-1336(Set)X
-1458(as)X
-1545(described)X
-1873(for)X
-1987(the)X
-3 f
-2105(edit)X
-1 f
-2254(command.)X
-976 4632(Options:)N
-1336(Affected)X
-1638(by)X
-1738(the)X
-1856(options)X
-3 f
-2111(autowrite)X
-1 f
-2461(and)X
-3 f
-2597(writeany)X
-1 f
-2900(.)X
-2960(None.)X
-3 f
-776 4812([range])N
-1046(p[rint])X
-1293([count])X
-1558([\257ags])X
-1 f
-976 4902(Display)N
-1245(the)X
-1363(speci\256ed)X
-1668(lines.)X
-976 5082(Line:)N
-1336(Set)X
-1458(to)X
-1540(the)X
-1658(last)X
-1789(line)X
-1929(displayed.)X
-976 5172(Options:)N
-1336(None.)X
-3 f
-776 5352([line])N
-974(pu[t])X
-1163([buffer])X
-1 f
-976 5442(Append)N
-1250(buffer)X
-1467(contents)X
-1755(to)X
-1838(the)X
-1957(current)X
-2206(line.)X
-2387(If)X
-2462(a)X
-2519(buffer)X
-2737(is)X
-2811(speci\256ed,)X
-3137(its)X
-3233(contents)X
-3521(are)X
-3641(appended)X
-3970(to)X
-976 5532(the)N
-1094(line,)X
-1254(otherwise,)X
-1606(the)X
-1724(contents)X
-2011(of)X
-2098(the)X
-2216(unnamed)X
-2530(buffer)X
-2747(are)X
-2866(used.)X
-976 5712(Line:)N
-1336(Set)X
-1458(to)X
-1540(the)X
-1658(line)X
-1798(after)X
-1966(the)X
-2084(current)X
-2332(line.)X
-
-41 p
-%%Page: 41 40
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Ex)X
-1377(Commands\))X
-3658(USD:13-41)X
-1 f
-976 762(Options:)N
-1336(None.)X
-3 f
-776 942(q[uit][!])N
-1 f
-976 1032(End)N
-1133(the)X
-1259(editing)X
-1509(session.)X
-1808(If)X
-1890(the)X
-2016(\256le)X
-2146(has)X
-2281(been)X
-2461(modi\256ed)X
-2773(since)X
-2966(the)X
-3092(last)X
-3231(complete)X
-3554(write,)X
-3768(the)X
-3 f
-3895(quit)X
-1 f
-976 1122(command)N
-1314(will)X
-1460(fail.)X
-1629(This)X
-1793(check)X
-2003(may)X
-2163(be)X
-2261(overridden)X
-2631(by)X
-2733(appending)X
-3089(a)X
-3147(``)X
-7 f
-3201(!)X
-1 f
-('')S
-3345(character)X
-3663(to)X
-3747(the)X
-3867(com-)X
-976 1212(mand.)N
-976 1392(If)N
-1053(there)X
-1237(are)X
-1359(more)X
-1547(\256les)X
-1703(to)X
-1788(edit,)X
-1951(the)X
-3 f
-2072(quit)X
-1 f
-2232(command)X
-2571(will)X
-2718(fail.)X
-2888(Appending)X
-3268(a)X
-3328(``)X
-7 f
-3382(!)X
-1 f
-('')S
-3528(character)X
-3848(to)X
-3934(the)X
-976 1482(command)N
-1315(name)X
-1511(or)X
-1600(entering)X
-1885(two)X
-3 f
-2027(quit)X
-1 f
-2186(commands)X
-2555(\(i.e.)X
-3 f
-2722(wq)X
-1 f
-2824(,)X
-3 f
-2866(quit)X
-1 f
-3003(,)X
-3 f
-3045(xit)X
-1 f
-3156(or)X
-3 f
-3245(ZZ)X
-1 f
-3351(\))X
-3400(in)X
-3484(a)X
-3542(row\))X
-3716(will)X
-3862(over-)X
-976 1572(ride)N
-1121(this)X
-1256(check)X
-1464(and)X
-1600(the)X
-1718(editor)X
-1925(will)X
-2069(exit.)X
-976 1752(Line:)N
-1336(Unchanged.)X
-976 1842(Options:)N
-1336(None.)X
-3 f
-776 2022([line])N
-974(r[ead][!])X
-1285([\256le])X
-1 f
-976 2112(Read)N
-1171(a)X
-1237(\256le.)X
-1409(A)X
-1497(copy)X
-1683(of)X
-1780(the)X
-1908(speci\256ed)X
-2223(\256le)X
-2355(is)X
-2438(appended)X
-2776(to)X
-2868(the)X
-2996(line.)X
-3186(If)X
-7 f
-3270(line)X
-1 f
-3492(is)X
-3575(0,)X
-3665(the)X
-3793(copy)X
-3979(is)X
-976 2202(inserted)N
-1252(at)X
-1332(the)X
-1452(beginning)X
-1794(of)X
-1883(the)X
-2003(\256le.)X
-2167(If)X
-2243(no)X
-2345(\256le)X
-2469(is)X
-2544(speci\256ed,)X
-2871(the)X
-2991(current)X
-3241(\256le)X
-3365(is)X
-3440(read;)X
-3623(if)X
-3694(there)X
-3877(is)X
-3952(no)X
-976 2292(current)N
-1233(\256le,)X
-1384(then)X
-7 f
-1552(file)X
-1 f
-1774(becomes)X
-2085(the)X
-2213(current)X
-2471(\256le.)X
-2643(If)X
-2727(there)X
-2918(is)X
-3001(no)X
-3111(current)X
-3369(\256le)X
-3501(and)X
-3647(no)X
-7 f
-3757(file)X
-1 f
-3979(is)X
-976 2382(speci\256ed,)N
-1301(then)X
-1459(the)X
-3 f
-1577(read)X
-1 f
-1753(command)X
-2089(will)X
-2233(fail.)X
-976 2562(If)N
-7 f
-1054(file)X
-1 f
-1270(is)X
-1347(preceded)X
-1662(by)X
-1766(a)X
-1826(``)X
-7 f
-1880(!)X
-1 f
-('')S
-2026(character,)X
-7 f
-2366(file)X
-1 f
-2582(is)X
-2659(treated)X
-2902(as)X
-2993(if)X
-3067(it)X
-3136(were)X
-3318(a)X
-3379(shell)X
-3555(command,)X
-3916(and)X
-976 2652(passed)N
-1213(to)X
-1298(the)X
-1419(program)X
-1713(named)X
-1949(by)X
-2051(the)X
-7 f
-2171(SHELL)X
-1 f
-2433(environment)X
-2860(variable.)X
-3181(The)X
-3328(standard)X
-3622(and)X
-3760(standard)X
-976 2742(error)N
-1155(outputs)X
-1412(of)X
-1501(that)X
-1643(command)X
-1981(are)X
-2102(read)X
-2263(into)X
-2409(the)X
-2529(\256le)X
-2654(after)X
-2825(the)X
-2946(speci\256ed)X
-3254(line.)X
-3437(The)X
-3585(special)X
-3831(mean-)X
-976 2832(ing)N
-1098(of)X
-1185(the)X
-1303(``)X
-7 f
-1357(!)X
-1 f
-('')S
-1499(character)X
-1815(can)X
-1947(be)X
-2043(overridden)X
-2411(by)X
-2511(escaping)X
-2812(it)X
-2876(with)X
-3038(a)X
-3094(backslash)X
-3426(\(``)X
-7 f
-3507(\\)X
-1 f
-(''\))S
-3656(character.)X
-976 3012(Line:)N
-1336(When)X
-1550(executed)X
-1858(from)X
-3 f
-2036(ex)X
-1 f
-2112(,)X
-2154(the)X
-2274(current)X
-2524(line)X
-2666(is)X
-2741(set)X
-2852(to)X
-2936(the)X
-3056(last)X
-3189(line)X
-3331(read.)X
-3532(When)X
-3746(executed)X
-1336 3102(from)N
-3 f
-1512(vi)X
-1 f
-1574(,)X
-1614(the)X
-1732(current)X
-1980(line)X
-2120(is)X
-2193(set)X
-2302(to)X
-2384(the)X
-2502(\256rst)X
-2646(line)X
-2786(read.)X
-976 3192(Options:)N
-1336(None.)X
-3 f
-776 3372 0.4063(rec[over])AN
-1110(\256le)X
-1 f
-976 3462(Recover)N
-7 f
-1273(file)X
-1 f
-1494(if)X
-1572(it)X
-1645(was)X
-1799(previously)X
-2166(saved.)X
-2418(If)X
-2501(no)X
-2610(saved)X
-2822(\256le)X
-2953(by)X
-3062(that)X
-3211(name)X
-3414(exists,)X
-3645(the)X
-3 f
-3772(recover)X
-1 f
-976 3552(command)N
-1312(behaves)X
-1591(similarly)X
-1895(to)X
-1977(the)X
-3 f
-2095(edit)X
-1 f
-2244(command.)X
-976 3732(Line:)N
-1336(Set)X
-1458(as)X
-1545(described)X
-1873(for)X
-1987(the)X
-3 f
-2105(edit)X
-1 f
-2254(command.)X
-976 3822(Options:)N
-1336(None.)X
-3 f
-776 4002(res[ize])N
-1047([+|-]size)X
-976 4092(Vi)N
-1 f
-1081(mode)X
-1284(only.)X
-1492(Grow)X
-1701(or)X
-1794(shrink)X
-2020(the)X
-2144(current)X
-2398(screen.)X
-2670(If)X
-7 f
-2750(size)X
-1 f
-2968(is)X
-3047(a)X
-3109(positive,)X
-3408(signed)X
-3643(number,)X
-3934(the)X
-976 4182(current)N
-1227(screen)X
-1456(is)X
-1532(grown)X
-1760(by)X
-1863(that)X
-2006(many)X
-2207(lines.)X
-2421(If)X
-7 f
-2498(size)X
-1 f
-2713(is)X
-2789(a)X
-2848(negative,)X
-3163(signed)X
-3395(number,)X
-3683(the)X
-3804(current)X
-976 4272(screen)N
-1212(is)X
-1295(shrunk)X
-1543(by)X
-1653(that)X
-1803(many)X
-2011(lines.)X
-2232(If)X
-7 f
-2316(size)X
-1 f
-2538(is)X
-2621(not)X
-2753(signed,)X
-3012(the)X
-3141(current)X
-3400(screen)X
-3637(is)X
-3721(set)X
-3841(to)X
-3934(the)X
-976 4362(speci\256ed)N
-7 f
-1281(size)X
-1 f
-(.)S
-1533(Applicable)X
-1905(only)X
-2067(to)X
-2149(split)X
-2306(screens.)X
-976 4542(Line:)N
-1336(Unchanged.)X
-976 4632(Options:)N
-1336(None.)X
-3 f
-776 4812(rew[ind][!])N
-1 f
-976 4902(Rewind)N
-1251(the)X
-1375(argument)X
-1704(list.)X
-1867(If)X
-1947(the)X
-2071(current)X
-2325(\256le)X
-2453(has)X
-2586(been)X
-2764(modi\256ed)X
-3074(since)X
-3265(the)X
-3389(last)X
-3526(complete)X
-3847(write,)X
-976 4992(the)N
-3 f
-1097(rewind)X
-1 f
-1360(command)X
-1699(will)X
-1846(fail.)X
-2016(This)X
-2180(check)X
-2390(may)X
-2550(be)X
-2648(overridden)X
-3018(by)X
-3120(appending)X
-3476(the)X
-3596(``)X
-7 f
-3650(!)X
-1 f
-('')S
-3794(charac-)X
-976 5082(ter)N
-1081(to)X
-1163(the)X
-1281(command.)X
-976 5262(Otherwise,)N
-1346(the)X
-1464(current)X
-1712(\256le)X
-1834(is)X
-1907(set)X
-2016(to)X
-2098(the)X
-2216(\256rst)X
-2360(\256le)X
-2482(in)X
-2564(the)X
-2682(argument)X
-3005(list.)X
-976 5442(Line:)N
-1336(Set)X
-1458(as)X
-1545(described)X
-1873(for)X
-1987(the)X
-3 f
-2105(edit)X
-1 f
-2254(command.)X
-976 5532(Options:)N
-1336(Affected)X
-1638(by)X
-1738(the)X
-3 f
-1856(autowrite)X
-1 f
-2206(and)X
-3 f
-2342(writeany)X
-1 f
-2665(options.)X
-3 f
-776 5712(se[t])N
-944([option[=[value]])X
-1544(...])X
-1651([nooption)X
-1999(...])X
-2106([option?)X
-2410(...])X
-2517([all])X
-1 f
-976 5802(Display)N
-1252(or)X
-1346(set)X
-1462(editor)X
-1676(options.)X
-1979(When)X
-2199(no)X
-2307(arguments)X
-2669(are)X
-2796(speci\256ed,)X
-3129(the)X
-3255(editor)X
-3470(option)X
-3 f
-3702(term)X
-1 f
-3868(,)X
-3916(and)X
-
-42 p
-%%Page: 42 41
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-42)N
-2813(Nvi/Nex)X
-3109 0.3906(Reference)AX
-3474(\(Ex)X
-3614(Commands\))X
-1 f
-976 762(any)N
-1115(editor)X
-1325(options)X
-1583(whose)X
-1811(values)X
-2039(have)X
-2214(been)X
-2389(changed)X
-2679(from)X
-2857(the)X
-2977(default)X
-3222(settings)X
-3488(are)X
-3609(displayed.)X
-3978(If)X
-976 852(the)N
-1094(argument)X
-7 f
-1417(all)X
-1 f
-1581(is)X
-1654(speci\256ed,)X
-1979(the)X
-2097(values)X
-2322(of)X
-2409(all)X
-2509(of)X
-2596(editor)X
-2803(options)X
-3058(are)X
-3177(displayed.)X
-976 1032(Specifying)N
-1353(an)X
-1459(option)X
-1693(name)X
-1897(followed)X
-2212(by)X
-2322(the)X
-2450(character)X
-2776(``)X
-7 f
-2830(?)X
-1 f
-('')S
-2982(causes)X
-3222(the)X
-3350(current)X
-3609(value)X
-3814(of)X
-3912(that)X
-976 1122(option)N
-1203(to)X
-1288(be)X
-1387(displayed.)X
-1757(The)X
-1905(``)X
-7 f
-1959(?)X
-1 f
-('')S
-2104(can)X
-2239(be)X
-2338(separated)X
-2665(from)X
-2843(the)X
-2963(option)X
-3189(name)X
-3385(by)X
-3487(whitespace)X
-3866(char-)X
-976 1212(acters.)N
-1225(The)X
-1371(``)X
-7 f
-1425(?)X
-1 f
-('')S
-1568(is)X
-1642(necessary)X
-1976(only)X
-2139(for)X
-2254(Boolean)X
-2543(valued)X
-2779(options.)X
-3076(Boolean)X
-3365(options)X
-3622(can)X
-3756(be)X
-3854(given)X
-976 1302(values)N
-1209(by)X
-1317(the)X
-1443(form)X
-1627(``)X
-7 f
-1681(set)X
-1881(option)X
-1 f
-('')S
-2251(to)X
-2341(turn)X
-2498(them)X
-2686(on,)X
-2814(or)X
-2909(``)X
-7 f
-2963(set)X
-3162(nooption)X
-1 f
-('')S
-3627(to)X
-3716(turn)X
-3872(them)X
-976 1392(off.)N
-1131(String)X
-1347(and)X
-1484(numeric)X
-1768(options)X
-2024(can)X
-2158(be)X
-2256(assigned)X
-2554(by)X
-2656(the)X
-2776(form)X
-2954(``)X
-7 f
-3008(set)X
-3202(option=value)X
-1 f
-(''.)S
-3894(Any)X
-976 1482(whitespace)N
-1359(characters)X
-1712(in)X
-1800(strings)X
-2039(can)X
-2176(be)X
-2277(included)X
-2578(literally)X
-2852(by)X
-2957(preceding)X
-3299(each)X
-3472(with)X
-3639(a)X
-3700(backslash.)X
-976 1572(More)N
-1180(than)X
-1349(one)X
-1496(option)X
-1731(can)X
-1874(be)X
-1981(set)X
-2101(or)X
-2199(listed)X
-2403(by)X
-2514(a)X
-2581(single)X
-2803(set)X
-2923(command,)X
-3290(by)X
-3401(specifying)X
-3766(multiple)X
-976 1662(arguments,)N
-1350(each)X
-1518(separated)X
-1842(from)X
-2018(the)X
-2136(next)X
-2294(by)X
-2394(whitespace)X
-2771(characters.)X
-976 1842(Line:)N
-1336(Unchanged.)X
-976 1932(Options:)N
-1336(None.)X
-3 f
-776 2112(sh[ell])N
-1 f
-976 2202(Run)N
-1131(a)X
-1189(shell)X
-1362(program.)X
-1696(The)X
-1843(program)X
-2137(named)X
-2373(by)X
-2475(the)X
-3 f
-2596(shell)X
-1 f
-2774(option)X
-3001(is)X
-3077(run)X
-3207(with)X
-3372(a)X
-3 f
-9 f
-3431(-)X
-3433(-)X
-3 f
-3477(i)X
-1 f
-3522(\(for)X
-3666(interactive\))X
-976 2292(\257ag.)N
-1156(Editing)X
-1411(is)X
-1484(resumed)X
-1776(when)X
-1970(that)X
-2110(program)X
-2402(exits.)X
-976 2472(Line:)N
-1336(Unchanged.)X
-976 2562(Options:)N
-1336(None.)X
-3 f
-776 2742(so[urce])N
-1073(\256le)X
-1 f
-976 2832(Read)N
-1161(and)X
-1297(execute)X
-3 f
-1563(ex)X
-1 f
-1659(commands)X
-2026(from)X
-2202(a)X
-2258(\256le.)X
-3 f
-2420(Source)X
-1 f
-2676(commands)X
-3043(may)X
-3201(be)X
-3297(nested.)X
-976 3012(Line:)N
-1336(Unchanged.)X
-976 3102(Options:)N
-1336(None.)X
-3 f
-776 3282(sp[lit])N
-996([\256le)X
-1145(...])X
-976 3372(Vi)N
-1 f
-1078(mode)X
-1278(only.)X
-1482(Split)X
-1655(the)X
-1776(screen.)X
-2045(The)X
-2193(current)X
-2444(screen)X
-2673(is)X
-2749(split)X
-2909(into)X
-3056(two)X
-3199(screens,)X
-3479(of)X
-3569(approximately)X
-976 3462(equal)N
-1173(size.)X
-1361(If)X
-1438(the)X
-1559(cursor)X
-1783(is)X
-1859(in)X
-1944(the)X
-2065(lower)X
-2271(half)X
-2419(of)X
-2509(the)X
-2630(screen,)X
-2879(the)X
-3000(screen)X
-3229(will)X
-3376(split)X
-3536(up,)X
-3658(i.e.)X
-3778(the)X
-3898(new)X
-976 3552(screen)N
-1213(will)X
-1368(be)X
-1475(above)X
-1699(the)X
-1829(old)X
-1963(one.)X
-2151(If)X
-2237(the)X
-2367(cursor)X
-2600(is)X
-2685(in)X
-2779(the)X
-2909(upper)X
-3124(half)X
-3281(of)X
-3380(the)X
-3510(screen,)X
-3768(the)X
-3898(new)X
-976 3642(screen)N
-1202(will)X
-1346(be)X
-1442(below)X
-1658(the)X
-1776(old)X
-1898(one.)X
-976 3822(If)N
-7 f
-1052(file)X
-1 f
-1267(is)X
-1343(speci\256ed,)X
-1671(the)X
-1792(new)X
-1949(screen)X
-2178(is)X
-2254(editing)X
-2499(that)X
-2642(\256le,)X
-2787(otherwise,)X
-3142(both)X
-3307(screens)X
-3567(are)X
-3689(editing)X
-3934(the)X
-976 3912(same)N
-1165(\256le,)X
-1310(and)X
-1449(changes)X
-1731(in)X
-1816(each)X
-1987(will)X
-2134(be)X
-2233(be)X
-2332(re\257ected)X
-2632(in)X
-2717(the)X
-2838(other.)X
-3066(The)X
-3214(argument)X
-3540(list)X
-3660(for)X
-3777(the)X
-3898(new)X
-976 4002(screen)N
-1204(consists)X
-1479(of)X
-1568(the)X
-1688(list)X
-1807(of)X
-1896(\256les)X
-2051(speci\256ed)X
-2358(as)X
-2447(arguments)X
-2803(to)X
-2888(this)X
-3026(command,)X
-3385(or,)X
-3495(the)X
-3616(current)X
-3867(path-)X
-976 4092(name)N
-1170(if)X
-1239(no)X
-1339(\256les)X
-1492(are)X
-1611(speci\256ed.)X
-976 4272(Line:)N
-1336(If)X
-7 f
-1410(file)X
-1 f
-1622(is)X
-1695(speci\256ed,)X
-2020(set)X
-2129(as)X
-2216(for)X
-2330(the)X
-3 f
-2448(edit)X
-1 f
-2597(command,)X
-2953(otherwise)X
-3285(unchanged.)X
-976 4362(Options:)N
-1336(None.)X
-3 f
-776 4542([range])N
-1046(s[ubstitute])X
-1453([/pattern/replace/])X
-2097([options])X
-2419([count])X
-2684([\257ags])X
-776 4632([range])N
-1046(&)X
-1133([options])X
-1455([count])X
-1720([\257ags])X
-776 4722([range])N
-1046(\304)X
-1093([options])X
-1415([count])X
-1680([\257ags])X
-1 f
-976 4812(Make)N
-1185(substitutions.)X
-1654(Replace)X
-1939(the)X
-2063(\256rst)X
-2214(instance)X
-2504(of)X
-7 f
-2598(pattern)X
-1 f
-2961(with)X
-3130(the)X
-3255(string)X
-7 f
-3464(replace)X
-1 f
-3827(on)X
-3934(the)X
-976 4902(speci\256ed)N
-1343(line\(s\).)X
-1670(If)X
-1806(the)X
-1986(``)X
-7 f
-2040(/pattern/repl/)X
-1 f
-('')S
-2847(argument)X
-3231(is)X
-3365(not)X
-3548(speci\256ed,)X
-3934(the)X
-976 4992(``)N
-7 f
-1030(/pattern/repl/)X
-1 f
-('')S
-1776(from)X
-1952(the)X
-2070(previous)X
-3 f
-2366(substitute)X
-1 f
-2719(command)X
-3055(is)X
-3128(used.)X
-976 5172(If)N
-7 f
-1054(options)X
-1 f
-1414(includes)X
-1705(the)X
-1827(letter)X
-2017(``)X
-7 f
-2071(c)X
-1 f
-('')S
-2198(\(con\256rm\),)X
-2546(you)X
-2691(will)X
-2840(be)X
-2941(prompted)X
-3273(for)X
-3392(con\256rmation)X
-3826(before)X
-976 5262(each)N
-1152(replacement)X
-1573(is)X
-1654(done.)X
-1878(An)X
-2004(af\256rmative)X
-2384(response)X
-2693(\(in)X
-2810(English,)X
-3101(a)X
-3164(``)X
-7 f
-3218(y)X
-1 f
-('')S
-3347 0.3750(character\))AX
-3697(causes)X
-3934(the)X
-976 5352(replacement)N
-1393(to)X
-1479(be)X
-1579(made.)X
-1817(A)X
-1899(quit)X
-2047(response)X
-2352(\(in)X
-2465(English,)X
-2753(a)X
-2813(``)X
-7 f
-2867(q)X
-1 f
-('')S
-2993 0.3750(character\))AX
-3341(causes)X
-3576(the)X
-3 f
-3699(substitute)X
-1 f
-976 5442(command)N
-1320(to)X
-1410(be)X
-1514(terminated.)X
-1925(Any)X
-2091(other)X
-2284(response)X
-2592(causes)X
-2829(the)X
-2954(replacement)X
-3374(not)X
-3503(to)X
-3592(be)X
-3695(made,)X
-3916(and)X
-976 5532(the)N
-3 f
-1094(substitute)X
-1 f
-1447(command)X
-1783(continues.)X
-2150(If)X
-7 f
-2224(options)X
-1 f
-2580(includes)X
-2867(the)X
-2985(letter)X
-3170(``)X
-7 f
-3224(g)X
-1 f
-('')S
-3346(\(global\),)X
-3641(all)X
-3742(nonover-)X
-976 5622(lapping)N
-1236(instances)X
-1550(of)X
-7 f
-1637(pattern)X
-1 f
-1993(in)X
-2075(the)X
-2193(line)X
-2333(are)X
-2452(replaced.)X
-976 5802(The)N
-3 f
-1122(&)X
-1 f
-1210(version)X
-1467(of)X
-1555(the)X
-1674(command)X
-2011(is)X
-2085(the)X
-2204(same)X
-2390(as)X
-2479(not)X
-2603(specifying)X
-2959(a)X
-3017(pattern)X
-3262(or)X
-3351(replacement)X
-3766(string)X
-3970(to)X
-
-43 p
-%%Page: 43 42
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Ex)X
-1377(Commands\))X
-3658(USD:13-43)X
-1 f
-976 762(the)N
-3 f
-1098(substitute)X
-1 f
-1455(command,)X
-1815(and)X
-1955(the)X
-2077(``)X
-7 f
-2131(&)X
-1 f
-('')S
-2257(is)X
-2333(replaced)X
-2629(by)X
-2732(the)X
-2853(pattern)X
-3099(and)X
-3238(replacement)X
-3654(information)X
-976 852(from)N
-1152(the)X
-1270(previous)X
-1566(substitute)X
-1892(command.)X
-976 1032(The)N
-3 f
-1121(\304)X
-1 f
-1168(version)X
-1424(of)X
-1511(the)X
-1629(command)X
-1966(is)X
-2040(the)X
-2159(same)X
-2345(as)X
-3 f
-2433(&)X
-1 f
-2521(and)X
-3 f
-2658(s)X
-1 f
-2689(,)X
-2730(except)X
-2961(that)X
-3102(the)X
-3221(search)X
-3448(pattern)X
-3692(used)X
-3860(is)X
-3934(the)X
-976 1122(last)N
-1107(RE)X
-1229(used)X
-1396(in)X
-2 f
-1478(any)X
-1 f
-1614(command,)X
-1970(not)X
-2092(necessarily)X
-2469(the)X
-2587(one)X
-2723(used)X
-2890(in)X
-2972(the)X
-3090(last)X
-3 f
-3221(substitute)X
-1 f
-3574(command.)X
-976 1302(For)N
-1107(example,)X
-1419(in)X
-1501(the)X
-1619(sequence)X
-7 f
-1296 1425(s/red/blue/)N
-1296 1515(/green)N
-1296 1605(\304)N
-1 f
-976 1728(the)N
-1094(``)X
-7 f
-1148(\304)X
-1 f
-('')S
-1270(is)X
-1343(equivalent)X
-1697(to)X
-1779(``)X
-7 f
-1833(s/green/blue/)X
-1 f
-(''.)S
-976 1908(The)N
-3 f
-1126(substitute)X
-1 f
-1484(command)X
-1825(may)X
-1988(be)X
-2089(interrupted,)X
-2486(using)X
-2685(the)X
-2809(terminal)X
-3102(interrupt)X
-3404(character.)X
-3766(All)X
-3894(sub-)X
-976 1998(stitutions)N
-1288(completed)X
-1642(before)X
-1868(the)X
-1986(interrupt)X
-2282(are)X
-2401(retained.)X
-976 2178(Line:)N
-1336(Set)X
-1458(to)X
-1540(the)X
-1658(last)X
-1789(line)X
-1929(upon)X
-2109(which)X
-2325(a)X
-2381(substitution)X
-2773(was)X
-2918(made.)X
-976 2268(Options:)N
-1336(None.)X
-3 f
-776 2448(su[spend][!])N
-776 2538(st[op][!])N
-776 2628(<control-Z>)N
-1 f
-976 2718(Suspend)N
-1285(the)X
-1422(edit)X
-1581(session.)X
-1891(Appending)X
-2286(a)X
-2361(``)X
-7 f
-2415(!)X
-1 f
-('')S
-2576(character)X
-2911(to)X
-3012(these)X
-3216(commands)X
-3602(turns)X
-3801(off)X
-3934(the)X
-3 f
-976 2808(autowrite)N
-1 f
-1326(option)X
-1550(for)X
-1664(the)X
-1782(command.)X
-976 2988(Line:)N
-1336(Unchanged.)X
-976 3078(Options:)N
-1336(Affected)X
-1638(by)X
-1738(the)X
-3 f
-1856(autowrite)X
-1 f
-2206(option.)X
-3 f
-776 3258(ta[g][!])N
-1038(tagstring)X
-1 f
-976 3348(Edit)N
-1133(the)X
-1255(\256le)X
-1381(containing)X
-1743(the)X
-1865(speci\256ed)X
-2174(tag.)X
-2337(Search)X
-2581(for)X
-2700(the)X
-2823(tagstring,)X
-3148(which)X
-3369(can)X
-3506(be)X
-3607(in)X
-3694(a)X
-3755(different)X
-976 3438(\256le.)N
-1149(If)X
-1234(the)X
-1363(tag)X
-1492(is)X
-1576(in)X
-1669(a)X
-1736(different)X
-2044(\256le,)X
-2197(then)X
-2366(the)X
-2495(new)X
-2660(\256le)X
-2792(is)X
-2875(edited.)X
-3141(If)X
-3225(the)X
-3353(current)X
-3611(\256le)X
-3743(has)X
-3880(been)X
-976 3528(modi\256ed)N
-1283(since)X
-1471(the)X
-1592(last)X
-1726(complete)X
-2043(write,)X
-2251(the)X
-3 f
-2372(tag)X
-1 f
-2502(command)X
-2841(will)X
-2988(fail.)X
-3159(This)X
-3325(check)X
-3537(can)X
-3673(be)X
-3773(overrid-)X
-976 3618(den)N
-1112(by)X
-1212(appending)X
-1566(the)X
-1684(``)X
-7 f
-1738(!)X
-1 f
-('')S
-1880(character)X
-2196(to)X
-2278(the)X
-2396(command)X
-2732(name.)X
-976 3798(The)N
-3 f
-1128(tag)X
-1 f
-1262(command)X
-1605(searches)X
-1905(for)X
-7 f
-2026(tagstring)X
-1 f
-2485(in)X
-2574(the)X
-2699(tags)X
-2855(\256le\(s\))X
-3070(speci\256ed)X
-3383(by)X
-3491(the)X
-3617(option.)X
-3889(\(See)X
-2 f
-976 3888(ctags)N
-1 f
-1145(\(1\))X
-1259(for)X
-1373(more)X
-1558(information)X
-1956(on)X
-2056(tags)X
-2205(\256les.\))X
-976 4068(Line:)N
-1336(Set)X
-1458(to)X
-1540(the)X
-1658(line)X
-1798(indicated)X
-2112(by)X
-2212(the)X
-2330(tag.)X
-976 4158(Options:)N
-1336(Affected)X
-1638(by)X
-1738(the)X
-3 f
-1856(autowrite)X
-1 f
-2186(,)X
-3 f
-2226(taglength)X
-1 f
-(,)S
-3 f
-2586(tags)X
-1 f
-2744(and)X
-3 f
-2880(writeany)X
-1 f
-3203(options.)X
-3 f
-776 4338(tagp[op][!])N
-1166([\256le)X
-1315(|)X
-1353(number])X
-1 f
-976 4428(Pop)N
-1122(to)X
-1206(the)X
-1326(speci\256ed)X
-1633(tag)X
-1753(in)X
-1837(the)X
-1957(tags)X
-2108(stack.)X
-2335(If)X
-2411(neither)X
-7 f
-2656(file)X
-1 f
-2871(or)X
-7 f
-2961(number)X
-1 f
-3272(is)X
-3348(speci\256ed,)X
-3676(the)X
-3 f
-3797(tagpop)X
-1 f
-976 4518(command)N
-1313(pops)X
-1485(to)X
-1568(the)X
-1686(most)X
-1861(recent)X
-2078(entry)X
-2263(on)X
-2363(the)X
-2481(tags)X
-2630(stack.)X
-2855(If)X
-7 f
-2929(file)X
-1 f
-3141(or)X
-7 f
-3228(number)X
-1 f
-3536(is)X
-3609(speci\256ed,)X
-3934(the)X
-3 f
-976 4608(tagpop)N
-1 f
-1242(command)X
-1589(pops)X
-1771(to)X
-1864(the)X
-1993(most)X
-2179(recent)X
-2407(entry)X
-2603(in)X
-2696(the)X
-2825(tags)X
-2985(stack)X
-3181(for)X
-3306(that)X
-3458(\256le,)X
-3612(or)X
-3711(numbered)X
-976 4698(entry)N
-1165(in)X
-1251(the)X
-1373(tags)X
-1526(stack,)X
-1735(respectively.)X
-2186(\(See)X
-2352(the)X
-3 f
-2473(display)X
-1 f
-2739(command)X
-3078(for)X
-3195(information)X
-3596(on)X
-3699(displaying)X
-976 4788(the)N
-1094(tags)X
-1243(stack.\))X
-976 4968(If)N
-1051(the)X
-1170(\256le)X
-1293(has)X
-1421(been)X
-1594(modi\256ed)X
-1899(since)X
-2085(the)X
-2204(last)X
-2337(complete)X
-2653(write,)X
-2860(the)X
-3 f
-2980(tagpop)X
-1 f
-3237(command)X
-3575(will)X
-3721(fail.)X
-3890(This)X
-976 5058(check)N
-1184(may)X
-1342(be)X
-1438(overridden)X
-1806(by)X
-1906(appending)X
-2260(a)X
-2316(``)X
-7 f
-2370(!)X
-1 f
-('')S
-2512(character)X
-2828(to)X
-2910(the)X
-3028(command)X
-3364(name.)X
-976 5238(Line:)N
-1336(Set)X
-1458(to)X
-1540(the)X
-1658(line)X
-1798(indicated)X
-2112(by)X
-2212(the)X
-2330(tag.)X
-976 5328(Options:)N
-1336(Affected)X
-1638(by)X
-1738(the)X
-3 f
-1856(autowrite)X
-1 f
-2186(,)X
-2226(and)X
-3 f
-2362(writeany)X
-1 f
-2685(options.)X
-3 f
-776 5508(tagt[op][!])N
-1 f
-976 5598(Pop)N
-1120(to)X
-1202(the)X
-1320(least)X
-1487(recent)X
-1704(tag)X
-1822(on)X
-1922(the)X
-2040(tags)X
-2189(stack,)X
-2394(clearing)X
-2673(the)X
-2791(tags)X
-2940(stack.)X
-976 5778(If)N
-1051(the)X
-1170(\256le)X
-1293(has)X
-1421(been)X
-1594(modi\256ed)X
-1899(since)X
-2085(the)X
-2204(last)X
-2337(complete)X
-2653(write,)X
-2860(the)X
-3 f
-2980(tagpop)X
-1 f
-3237(command)X
-3575(will)X
-3721(fail.)X
-3890(This)X
-
-44 p
-%%Page: 44 43
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-44)N
-2813(Nvi/Nex)X
-3109 0.3906(Reference)AX
-3474(\(Ex)X
-3614(Commands\))X
-1 f
-976 762(check)N
-1184(may)X
-1342(be)X
-1438(overridden)X
-1806(by)X
-1906(appending)X
-2260(a)X
-2316(``)X
-7 f
-2370(!)X
-1 f
-('')S
-2512(character)X
-2828(to)X
-2910(the)X
-3028(command)X
-3364(name.)X
-976 942(Line:)N
-1336(Set)X
-1458(to)X
-1540(the)X
-1658(line)X
-1798(indicated)X
-2112(by)X
-2212(the)X
-2330(tag.)X
-976 1032(Options:)N
-1336(Affected)X
-1638(by)X
-1738(the)X
-3 f
-1856(autowrite)X
-1 f
-2186(,)X
-2226(and)X
-3 f
-2362(writeany)X
-1 f
-2685(options.)X
-3 f
-776 1212(una[bbrev])N
-1178(lhs)X
-1 f
-976 1302(Delete)N
-1206(an)X
-1302(abbreviation.)X
-1763(Delete)X
-7 f
-1993(lhs)X
-1 f
-2157(from)X
-2333(the)X
-2451(current)X
-2699(list)X
-2816(of)X
-2903(abbreviations.)X
-976 1482(Line:)N
-1336(Unchanged.)X
-976 1572(Options:)N
-1336(None.)X
-3 f
-776 1752(u[ndo])N
-1 f
-976 1842(Undo)N
-1177(the)X
-1298(last)X
-1432(change)X
-1683(made)X
-1880(to)X
-1965(the)X
-2086(\256le.)X
-2251(Changes)X
-2550(made)X
-2747(by)X
-3 f
-2850(global)X
-1 f
-3058(,)X
-3 f
-3101(v)X
-1 f
-(,)S
-3 f
-3184(visual)X
-1 f
-3406(and)X
-3545(map)X
-3706(sequences)X
-976 1932(are)N
-1103(considered)X
-1479(a)X
-1543(single)X
-1762(command.)X
-2146(If)X
-2228(repeated,)X
-2549(the)X
-3 f
-2675(u)X
-1 f
-2747(command)X
-3090(alternates)X
-3425(between)X
-3720(these)X
-3912(two)X
-976 2022(states,)N
-1194(and)X
-1330(is)X
-1403(its)X
-1498(own)X
-1656(inverse.)X
-976 2202(Line:)N
-1336(Set)X
-1458(to)X
-1540(the)X
-1658(last)X
-1789(line)X
-1929(modi\256ed)X
-2233(by)X
-2333(the)X
-2451(command.)X
-976 2292(Options:)N
-1336(None.)X
-3 f
-776 2472(unm[ap][!])N
-1170(lhs)X
-1 f
-976 2562(Unmap)N
-1235(a)X
-1294(mapped)X
-1571(string.)X
-1816(Delete)X
-2049(the)X
-2170(command)X
-2509(mode)X
-2710(map)X
-2872(de\256nition)X
-3202(for)X
-7 f
-3320(lhs)X
-1 f
-(.)S
-3528(If)X
-3606(a)X
-3666(``)X
-7 f
-3720(!)X
-1 f
-('')S
-3866(char-)X
-976 2652(acter)N
-1153(is)X
-1226(appended)X
-1554(to)X
-1636(the)X
-1754(command)X
-2090(name,)X
-2304(delete)X
-2516(the)X
-2634(text)X
-2774(input)X
-2958(mode)X
-3156(map)X
-3314(de\256nition)X
-3640(instead.)X
-976 2832(Line:)N
-1336(Unchanged.)X
-976 2922(Options:)N
-1336(None.)X
-3 f
-776 3102(ve[rsion])N
-1 f
-976 3192(Display)N
-1245(the)X
-1363(version)X
-1619(of)X
-1706(the)X
-3 f
-1824(ex/vi)X
-1 f
-2004(editor.)X
-3 f
-776 3372([line])N
-974(vi[sual])X
-1247([type])X
-1468([count])X
-1733([\257ags])X
-976 3462(Ex)N
-1 f
-1092(mode)X
-1293(only.)X
-1498(Enter)X
-3 f
-1695(vi)X
-1 f
-1757(.)X
-1820(The)X
-7 f
-1968(type)X
-1 f
-2183(is)X
-2259(optional,)X
-2564(and)X
-2703(can)X
-2838(be)X
-2937(``)X
-7 f
-9 f
-2991(-)X
-1 f
-3035('',)X
-3132(``)X
-7 f
-3186(+)X
-1 f
-('')S
-3311(or)X
-3401(``)X
-7 f
-3455(\303)X
-1 f
-('',)S
-3600(as)X
-3690(in)X
-3775(the)X
-3 f
-3896(ex)X
-3996(z)X
-1 f
-976 3552(command,)N
-1337(to)X
-1424(specify)X
-1681(the)X
-1804(the)X
-1926(position)X
-2207(of)X
-2298(the)X
-2420(speci\256ed)X
-2729(line)X
-2873(in)X
-2959(the)X
-3081(screen)X
-3311(window.)X
-3633(\(The)X
-3809(default)X
-976 3642(is)N
-1054(to)X
-1141(place)X
-1336(the)X
-1459(line)X
-1605(at)X
-1689(the)X
-1813(top)X
-1941(of)X
-2034(the)X
-2158(screen)X
-2390(window.\))X
-2741(A)X
-7 f
-2825(count)X
-1 f
-3091(speci\256es)X
-3393(the)X
-3517(number)X
-3788(of)X
-3881(lines)X
-976 3732(that)N
-1116(will)X
-1260(initially)X
-1528(be)X
-1624(displayed.)X
-1991(\(The)X
-2163(default)X
-2406(is)X
-2479(the)X
-2597(value)X
-2791(of)X
-2878(the)X
-3 f
-2996(window)X
-1 f
-3282(editor)X
-3489(option.\))X
-976 3912(Line:)N
-1336(Unchanged)X
-1722(unless)X
-7 f
-1942(line)X
-1 f
-2154(is)X
-2227(speci\256ed,)X
-2552(in)X
-2634(which)X
-2850(case)X
-3009(it)X
-3073(is)X
-3146(set)X
-3255(to)X
-3337(that)X
-3477(line.)X
-976 4002(Options:)N
-1336(None.)X
-3 f
-776 4182(vi[sual][!])N
-1130([+cmd])X
-1397([\256le])X
-976 4272(Vi)N
-1 f
-1076(mode)X
-1274(only.)X
-1476(Edit)X
-1629(a)X
-1685(new)X
-1839(\256le.)X
-2001(Identical)X
-2302(to)X
-2384(the)X
-2502(``)X
-7 f
-2556(edit[!])X
-2940([+cmd])X
-3276([file])X
-1 f
-('')S
-3638(command.)X
-3 f
-776 4452(viu[sage])N
-1103([command])X
-1 f
-976 4542(Display)N
-1253(usage)X
-1464(for)X
-1586(a)X
-3 f
-1650(vi)X
-1 f
-1740(command.)X
-2124(If)X
-7 f
-2206(command)X
-1 f
-2570(is)X
-2651(speci\256ed,)X
-2984(a)X
-3048(usage)X
-3259(statement)X
-3595(for)X
-3718(that)X
-3867(com-)X
-976 4632(mand)N
-1174(is)X
-1247(displayed.)X
-1614(Otherwise,)X
-1984(usage)X
-2187(statements)X
-2545(for)X
-2659(all)X
-3 f
-2759(vi)X
-1 f
-2841(commands)X
-3208(are)X
-3327(displayed.)X
-976 4812(Line:)N
-1336(Unchanged.)X
-976 4902(Options:)N
-1336(None.)X
-3 f
-776 5082([range])N
-1046 0.3611(w[rite][!])AX
-1380([>>])X
-1546([\256le])X
-776 5172([range])N
-1046(w[rite])X
-1299([!])X
-1400([\256le])X
-776 5262([range])N
-1046(wn[!])X
-1249([>>])X
-1415([\256le])X
-776 5352([range])N
-1046(wq[!])X
-1249([>>])X
-1415([\256le])X
-1 f
-976 5442(Write)N
-1183(the)X
-1305(\256le.)X
-1472(The)X
-1622(speci\256ed)X
-1932(lines)X
-2108(\(the)X
-2258(entire)X
-2466(\256le,)X
-2613(if)X
-2687(no)X
-2792(range)X
-2996(is)X
-3074(given\))X
-3304(is)X
-3382(written)X
-3634(to)X
-7 f
-3721(file)X
-1 f
-(.)S
-3978(If)X
-7 f
-976 5532(file)N
-1 f
-1195(is)X
-1275(not)X
-1403(speci\256ed,)X
-1734(the)X
-1858(current)X
-2112(pathname)X
-2450(is)X
-2529(used.)X
-2742(If)X
-7 f
-2822(file)X
-1 f
-3040(is)X
-3119(speci\256ed,)X
-3450(and)X
-3592(it)X
-3662(exists,)X
-3890(or)X
-3983(if)X
-976 5622(the)N
-1101(current)X
-1356(pathname)X
-1695(was)X
-1847(set)X
-1963(using)X
-2163(the)X
-3 f
-2288(\256le)X
-1 f
-2417(command,)X
-2780(and)X
-2923(the)X
-3049(\256le)X
-3179(already)X
-3444(exists,)X
-3674(these)X
-3867(com-)X
-976 5712(mands)N
-1212(will)X
-1363(fail.)X
-1537(Appending)X
-1919(a)X
-1981(``)X
-7 f
-2035(!)X
-1 f
-('')S
-2183(character)X
-2505(to)X
-2593(the)X
-2717(command)X
-3059(name)X
-3259(will)X
-3409(override)X
-3703(this)X
-3844(check)X
-976 5802(and)N
-1112(the)X
-1230(write)X
-1415(will)X
-1559(be)X
-1655(attempted,)X
-2011(regardless.)X
-
-45 p
-%%Page: 45 44
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-1237(\(Ex)X
-1377(Commands\))X
-3658(USD:13-45)X
-1 f
-976 762(Specifying)N
-1348(the)X
-1471(optional)X
-1758(``)X
-7 f
-1812(>>)X
-1 f
-('')S
-1987(string)X
-2194(will)X
-2344(cause)X
-2549(the)X
-2673(write)X
-2864(to)X
-2952(be)X
-3054(appended)X
-3388(to)X
-3476(the)X
-3600(\256le,)X
-3748(in)X
-3836(which)X
-976 852(case)N
-1135(no)X
-1235(tests)X
-1397(are)X
-1516(made)X
-1710(for)X
-1824(the)X
-1942(\256le)X
-2064(already)X
-2321(existing.)X
-976 1032(If)N
-1060(the)X
-1188(\256le)X
-1320(is)X
-1403(preceded)X
-1724(by)X
-1834(a)X
-1900(``)X
-7 f
-1954(!)X
-1 f
-('')S
-2106(character,)X
-2452(the)X
-2580(program)X
-2882(named)X
-3126(in)X
-3218(the)X
-3347(SHELL)X
-3627(environment)X
-976 1122(variable)N
-1258(is)X
-1334(invoked)X
-1615(with)X
-1780(\256le)X
-1905(as)X
-1995(its)X
-2093(second)X
-2339(argument,)X
-2685(and)X
-2824(the)X
-2945(speci\256ed)X
-3253(lines)X
-3427(are)X
-3549(passed)X
-3786(as)X
-3876(stan-)X
-976 1212(dard)N
-1143(input)X
-1331(to)X
-1417(that)X
-1561(command.)X
-1941(The)X
-2090(``)X
-7 f
-2144(!)X
-1 f
-('')S
-2291(in)X
-2378(this)X
-2518(usage)X
-2726(must)X
-2906(be)X
-3007(separated)X
-3336(from)X
-3517(command)X
-3858(name)X
-976 1302(by)N
-1080(at)X
-1162(least)X
-1333(one)X
-1473(whitespace)X
-1854(character.)X
-2214(The)X
-2363(special)X
-2610(meaning)X
-2910(of)X
-3001(the)X
-3122(``)X
-7 f
-3176(!)X
-1 f
-('')S
-3321(may)X
-3482(be)X
-3581(overridden)X
-3952(by)X
-976 1392(escaping)N
-1277(it)X
-1341(with)X
-1503(a)X
-1559(backslash)X
-1891(\(``)X
-7 f
-1972(\\)X
-1 f
-(''\))S
-2121(character.)X
-976 1572(The)N
-3 f
-1124(wq)X
-1 f
-1249(version)X
-1509(of)X
-1600(the)X
-1722(write)X
-1911(command)X
-2251(will)X
-2399(exit)X
-2543(the)X
-2665(editor)X
-2876(after)X
-3048(writing)X
-3303(the)X
-3425(\256le,)X
-3571(if)X
-3644(there)X
-3829(are)X
-3952(no)X
-976 1662(further)N
-1232(\256les)X
-1402(to)X
-1501(edit.)X
-1698(Appending)X
-2091(a)X
-2164(``)X
-7 f
-2218(!)X
-1 f
-('')S
-2377(character)X
-2710(to)X
-2809(the)X
-2944(command)X
-3297(name)X
-3508(or)X
-3612(entering)X
-3912(two)X
-976 1752(``quit'')N
-1232(commands)X
-1603(\(i.e.)X
-3 f
-1772(wq)X
-1 f
-1874(,)X
-3 f
-1918(quit)X
-1 f
-2055(,)X
-3 f
-2099(xit)X
-1 f
-2212(or)X
-3 f
-2303(ZZ)X
-1 f
-2409(\))X
-2461(in)X
-2548(a)X
-2609(row\))X
-2786(will)X
-2935(override)X
-3228(this)X
-3368(check)X
-3581(and)X
-3722(the)X
-3845(editor)X
-976 1842(will)N
-1120(exit,)X
-1280(ignoring)X
-1571(any)X
-1707(\256les)X
-1860(that)X
-2000(have)X
-2172(not)X
-2294(yet)X
-2412(been)X
-2584(edited.)X
-976 2022(The)N
-3 f
-1127(wn)X
-1 f
-1255(version)X
-1517(of)X
-1610(the)X
-1734(write)X
-1925(command)X
-2267(will)X
-2417(move)X
-2621(to)X
-2709(the)X
-2833(next)X
-2997(\256le)X
-3125(after)X
-3300(writing)X
-3558(the)X
-3683(\256le,)X
-3832(unless)X
-976 2112(the)N
-1094(write)X
-1279(fails.)X
-976 2292(Line:)N
-1336(Unchanged.)X
-976 2382(Options:)N
-1336(Affected)X
-1638(by)X
-1738(the)X
-3 f
-1856(readonly)X
-1 f
-2178(and)X
-3 f
-2314(writeany)X
-1 f
-2637(options.)X
-3 f
-776 2562([range])N
-1046(x[it][!])X
-1290([\256le])X
-1 f
-976 2652(Write)N
-1185(the)X
-1309(\256le)X
-1437(if)X
-1512(it)X
-1582(has)X
-1715(been)X
-1894(modi\256ed.)X
-2245(The)X
-2397(speci\256ed)X
-2709(lines)X
-2887(are)X
-3013(written)X
-3267(to)X
-7 f
-3356(file)X
-1 f
-(,)S
-3595(if)X
-3671(the)X
-3796(\256le)X
-3925(has)X
-976 2742(been)N
-1149(modi\256ed)X
-1454(since)X
-1640(the)X
-1759(last)X
-1891(complete)X
-2206(write)X
-2392(to)X
-2475(any)X
-2612(\256le.)X
-2775(If)X
-2850(no)X
-7 f
-2951(range)X
-1 f
-3211(is)X
-3284(speci\256ed,)X
-3609(the)X
-3727(entire)X
-3930(\256le)X
-976 2832(is)N
-1049(written.)X
-976 3012(The)N
-3 f
-1126(xit)X
-1 f
-1240(command)X
-1581(will)X
-1730(exit)X
-1875(the)X
-1998(editor)X
-2210(after)X
-2383(writing)X
-2639(the)X
-2762(\256le,)X
-2909(if)X
-2983(there)X
-3169(are)X
-3294(no)X
-3400(further)X
-3645(\256les)X
-3804(to)X
-3892(edit.)X
-976 3102(Appending)N
-1362(a)X
-1428(``)X
-7 f
-1482(!)X
-1 f
-('')S
-1634(character)X
-1960(to)X
-2052(the)X
-2180(command)X
-2526(name)X
-2730(or)X
-2827(entering)X
-3120(two)X
-3270(``quit'')X
-3531(commands)X
-3907(\(i.e.)X
-3 f
-976 3192(wq)N
-1 f
-1078(,)X
-3 f
-1125(quit)X
-1 f
-1262(,)X
-3 f
-1309(xit)X
-1 f
-1425(or)X
-3 f
-1519(ZZ)X
-1 f
-1625(\))X
-1679(in)X
-1768(a)X
-1831(row\))X
-2010(will)X
-2161(override)X
-2456(this)X
-2598(check)X
-2813(and)X
-2956(the)X
-3082(editor)X
-3297(will)X
-3449(exit,)X
-3617(ignoring)X
-3916(any)X
-976 3282(\256les)N
-1129(that)X
-1269(have)X
-1441(not)X
-1563(yet)X
-1681(been)X
-1853(edited.)X
-976 3462(Line:)N
-1336(Unchanged.)X
-976 3552(Options:)N
-1336(Affected)X
-1638(by)X
-1738(the)X
-3 f
-1856(readonly)X
-1 f
-2178(and)X
-3 f
-2314(writeany)X
-1 f
-2637(options.)X
-3 f
-776 3732([range])N
-1046(ya[nk])X
-1288([buffer])X
-1576([count])X
-1 f
-976 3822(Copy)N
-1169(the)X
-1287(speci\256ed)X
-1592(lines)X
-1763(to)X
-1845(a)X
-1901(buffer.)X
-2158(If)X
-2232(no)X
-2332(buffer)X
-2549(is)X
-2622(speci\256ed,)X
-2947(the)X
-3065(unnamed)X
-3379(buffer)X
-3596(is)X
-3669(used.)X
-976 4002(Line:)N
-1336(Unchanged.)X
-976 4092(Options:)N
-1336(None.)X
-3 f
-776 4272([line])N
-974(z)X
-1030([type])X
-1251([count])X
-1516([\257ags])X
-1 f
-976 4362(Adjust)N
-1210(the)X
-1329(window.)X
-1648(If)X
-1723(no)X
-7 f
-1824(type)X
-1 f
-2037(is)X
-2111(speci\256ed,)X
-2437(then)X
-7 f
-2596(count)X
-1 f
-2858(lines)X
-3031(following)X
-3364(the)X
-3484(speci\256ed)X
-3791(line)X
-3933(are)X
-976 4452(displayed.)N
-1362(The)X
-1526(default)X
-7 f
-1788(count)X
-1 f
-2067(is)X
-2159(the)X
-2296(value)X
-2509(of)X
-2614(the)X
-3 f
-2750(window)X
-1 f
-3054(option.)X
-3336(The)X
-7 f
-3499(type)X
-1 f
-3729(argument)X
-976 4542(changes)N
-1266(the)X
-1395(position)X
-1683(at)X
-1772(which)X
-7 f
-1999(line)X
-1 f
-2222(is)X
-2306(displayed)X
-2644(on)X
-2755(the)X
-2884(screen)X
-3121(by)X
-3232(changing)X
-3558(the)X
-3688(number)X
-3965(of)X
-976 4632(lines)N
-1147(displayed)X
-1474(before)X
-1700(and)X
-1836(after)X
-7 f
-2004(line)X
-1 f
-(.)S
-2256(The)X
-2401(following)X
-7 f
-2732(type)X
-1 f
-2944(characters)X
-3291(may)X
-3449(be)X
-3545(used:)X
-9 f
-976 4812(-)N
-1 f
-1336(Place)X
-1530(the)X
-1648(line)X
-1788(at)X
-1866(the)X
-1984(bottom)X
-2230(of)X
-2317(the)X
-2435(screen.)X
-976 4902(+)N
-1336(Place)X
-1530(the)X
-1648(line)X
-1788(at)X
-1866(the)X
-1984(top)X
-2106(of)X
-2193(the)X
-2311(screen.)X
-976 4992(.)N
-1336(Place)X
-1530(the)X
-1648(line)X
-1788(in)X
-1870(the)X
-1988(middle)X
-2230(of)X
-2317(the)X
-2435(screen.)X
-976 5082(\303)N
-1336(Write)X
-1540(out)X
-1663(count)X
-1862(lines)X
-2034(starting)X
-7 f
-2295(count)X
-2584(*)X
-2681(2)X
-1 f
-2750(lines)X
-2922(before)X
-7 f
-3149(line)X
-1 f
-(;)S
-3384(the)X
-3503(net)X
-3622(effect)X
-3828(of)X
-3917(this)X
-1336 5172(is)N
-1409(that)X
-1549(a)X
-1605(``)X
-7 f
-1659(z\303)X
-1 f
-('')S
-1829(command)X
-2165(following)X
-2496(a)X
-3 f
-2552(z)X
-1 f
-2608(command)X
-2944(writes)X
-3160(the)X
-3278(previous)X
-3574(page.)X
-976 5262(=)N
-1336(Center)X
-7 f
-1580(line)X
-1 f
-1802(on)X
-1912(the)X
-2040(screen)X
-2276(with)X
-2448(a)X
-2514(line)X
-2664(of)X
-2761(hyphens)X
-3058(displayed)X
-3395(immediately)X
-3826(before)X
-1336 5352(and)N
-1485(after)X
-1666(it.)X
-1783(The)X
-1941(number)X
-2219(of)X
-2319(preceding)X
-2669(and)X
-2817(following)X
-3160(lines)X
-3343(of)X
-3442(text)X
-3594(displayed)X
-3933(are)X
-1336 5442(reduced)N
-1611(to)X
-1693(account)X
-1963(for)X
-2077(those)X
-2266(lines.)X
-976 5622(Line:)N
-1336(Set)X
-1458(to)X
-1540(the)X
-1658(last)X
-1789(line)X
-1929(displayed,)X
-2276(with)X
-2438(the)X
-2556(exception)X
-2888(of)X
-2975(the)X
-7 f
-3093(type)X
-1 f
-(,)S
-3326(where)X
-3544(the)X
-3663(current)X
-3912(line)X
-1336 5712(is)N
-1409(set)X
-1518(to)X
-1600(the)X
-1718(line)X
-1858(speci\256ed)X
-2163(by)X
-2263(the)X
-2381(command.)X
-
-46 p
-%%Page: 46 45
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-46)N
-2813(Nvi/Nex)X
-3109 0.3906(Reference)AX
-3474(\(Ex)X
-3614(Commands\))X
-1 f
-976 762(Options:)N
-1336(Affected)X
-1638(by)X
-1738(the)X
-1856(option.)X
-3 f
-776 948(15.)N
-916(Set)X
-1043(Options)X
-1 f
-976 1071(There)N
-1186(are)X
-1307(a)X
-1365(large)X
-1548(number)X
-1815(of)X
-1904(options)X
-2161(that)X
-2303(may)X
-2463(be)X
-2561(set)X
-2672(\(or)X
-2788(unset\))X
-3006(to)X
-3091(change)X
-3342(the)X
-3463(editor's)X
-3731(behavior.)X
-776 1161(This)N
-938(section)X
-1185(describes)X
-1504(the)X
-1622(options,)X
-1897(their)X
-2064(abbreviations)X
-2516(and)X
-2652(their)X
-2819(default)X
-3062(values.)X
-976 1284(In)N
-1064(each)X
-1233(entry)X
-1419(below,)X
-1656(the)X
-1775(\256rst)X
-1920(part)X
-2066(of)X
-2154(the)X
-2273(tag)X
-2392(line)X
-2533(is)X
-2607(the)X
-2726(full)X
-2858(name)X
-3053(of)X
-3141(the)X
-3261(option,)X
-3507(followed)X
-3814(by)X
-3916(any)X
-776 1374(equivalent)N
-1135(abbreviations.)X
-1632(\(Regardless)X
-2036(of)X
-2128(the)X
-2251(abbreviations,)X
-2728(it)X
-2797(is)X
-2875(only)X
-3042(necessary)X
-3380(to)X
-3467(use)X
-3599(the)X
-3722(minimum)X
-776 1464(number)N
-1047(of)X
-1140(characters)X
-1493(necessary)X
-1832(to)X
-1920(distinguish)X
-2296(an)X
-2398(abbreviation)X
-2825(from)X
-3007(all)X
-3113(other)X
-3304(commands)X
-3677(for)X
-3797(it)X
-3867(to)X
-3956(be)X
-776 1554(accepted,)N
-1099(in)X
-3 f
-1182(nex)X
-1 f
-(/)S
-3 f
-1324(nvi)X
-1 f
-1430(.)X
-1491(Historically,)X
-1910(only)X
-2073(the)X
-2192(full)X
-2324(name)X
-2519(and)X
-2656(the)X
-2774(of\256cial)X
-3021(abbreviations)X
-3473(were)X
-3650(accepted)X
-3952(by)X
-3 f
-776 1644(ex)N
-1 f
-852(/)X
-3 f
-874(vi)X
-1 f
-936(.)X
-1002(Using)X
-1220(full)X
-1358(names)X
-1590(in)X
-1679(your)X
-1853(startup)X
-2098(\256les)X
-2258(and)X
-2401(environmental)X
-2891(variables)X
-3208(will)X
-3359(probably)X
-3671(make)X
-3872(them)X
-776 1734(more)N
-968(portable.\))X
-1325(The)X
-1477(part)X
-1629(in)X
-1718(square)X
-1955(brackets)X
-2250(is)X
-2330(the)X
-2454(default)X
-2703(value)X
-2903(of)X
-2996(the)X
-3120(option.)X
-3390(Most)X
-3580(of)X
-3673(the)X
-3797(options)X
-776 1824(are)N
-895(boolean,)X
-1189(i.e.)X
-1307(they)X
-1465(are)X
-1584(either)X
-1787(on)X
-1887(or)X
-1974(off,)X
-2108(and)X
-2244(do)X
-2344(not)X
-2466(have)X
-2638(an)X
-2734(associated)X
-3084(value.)X
-976 1947(Options)N
-1249(apply)X
-1447(to)X
-1529(both)X
-3 f
-1691(ex)X
-1 f
-1787(and)X
-3 f
-1923(vi)X
-1 f
-2005(modes,)X
-2254(unless)X
-2474(otherwise)X
-2806(speci\256ed.)X
-976 2070(For)N
-1107(information)X
-1505(on)X
-1605(modifying)X
-1958(the)X
-2076(options)X
-2331(or)X
-2419(to)X
-2502(display)X
-2754(the)X
-2873(options)X
-3129(and)X
-3266(their)X
-3434(current)X
-3683(values,)X
-3929(see)X
-776 2160(the)N
-894(``set'')X
-1111(command)X
-1447(in)X
-1529(the)X
-1647(section)X
-1894(entitled)X
-2154(``)X
-3 f
-2208(Ex)X
-2321(Commands)X
-1 f
-2712(''.)X
-3 f
-776 2340(altwerase)N
-1122([off])X
-976 2430(Vi)N
-1 f
-1084(only.)X
-1295(Change)X
-1569(how)X
-3 f
-1736(vi)X
-1 f
-1827(does)X
-2003(word)X
-2197(erase)X
-2392(during)X
-2630(text)X
-2779(input.)X
-3012(When)X
-3233(this)X
-3377(option)X
-3610(is)X
-3692(set,)X
-3830(text)X
-3979(is)X
-976 2520(broken)N
-1230(up)X
-1340(into)X
-1494(three)X
-1685(classes:)X
-1960(alphabetic,)X
-2340(numeric)X
-2633(and)X
-2779(underscore)X
-3162(characters,)X
-3539(other)X
-3734(nonblank)X
-976 2610(characters,)N
-1343(and)X
-1479(blank)X
-1677(characters.)X
-2064(Changing)X
-2395(from)X
-2571(one)X
-2707(class)X
-2884(to)X
-2967(another)X
-3229(marks)X
-3446(the)X
-3565(end)X
-3702(of)X
-3790(a)X
-3847(word.)X
-976 2700(In)N
-1070(addition,)X
-1379(the)X
-1504(class)X
-1687(of)X
-1781(the)X
-1906(\256rst)X
-2057(character)X
-2380(erased)X
-2612(is)X
-2691(ignored)X
-2962(\(which)X
-3211(is)X
-3290(exactly)X
-3548(what)X
-3730(you)X
-3876(want)X
-976 2790(when)N
-1170(erasing)X
-1422(pathname)X
-1754(components\).)X
-3 f
-776 2970(autoindent,)N
-1184(ai)X
-1266([off])X
-1 f
-976 3060(If)N
-1052(this)X
-1189(option)X
-1415(is)X
-1490(set,)X
-1621(whenever)X
-1956(you)X
-2098(create)X
-2313(a)X
-2371(new)X
-2527(line)X
-2669(\(using)X
-2891(the)X
-3 f
-3012(vi)X
-3097(A)X
-1 f
-3155(,)X
-3 f
-3198(a)X
-1 f
-(,)S
-3 f
-3281(C)X
-1 f
-3339(,)X
-3 f
-3382(c)X
-1 f
-3418(,)X
-3 f
-3461(I)X
-1 f
-3492(,)X
-3 f
-3535(i)X
-1 f
-3557(,)X
-3 f
-3600(O)X
-1 f
-3662(,)X
-3 f
-3705(o)X
-1 f
-(,)S
-3 f
-3788(R)X
-1 f
-3846(,)X
-3 f
-3889(r)X
-1 f
-3925(,)X
-3 f
-3968(S)X
-1 f
-4012(,)X
-976 3150(and)N
-3 f
-1117(s)X
-1 f
-1173(commands,)X
-1565(or)X
-1657(the)X
-3 f
-1780(ex)X
-1881(append)X
-1 f
-2133(,)X
-3 f
-2178(change)X
-1 f
-(,)S
-2463(and)X
-3 f
-2604(insert)X
-1 f
-2825(commands\))X
-3224(the)X
-3346(new)X
-3504(line)X
-3648(is)X
-3725(automati-)X
-976 3240(cally)N
-1156(indented)X
-1456(to)X
-1542(align)X
-1726(the)X
-1848(cursor)X
-2073(with)X
-2239(the)X
-2361(\256rst)X
-2509(nonblank)X
-2831(character)X
-3151(of)X
-3242(the)X
-3365(line)X
-3510(from)X
-3691(which)X
-3912(you)X
-976 3330(created)N
-1231(it.)X
-1337(Lines)X
-1537(are)X
-1658(indented)X
-1956(using)X
-2150(tab)X
-2269(characters)X
-2617(to)X
-2700(the)X
-2819(extent)X
-3036(possible)X
-3319(\(based)X
-3550(on)X
-3651(the)X
-3770(value)X
-3965(of)X
-976 3420(the)N
-3 f
-1094(tabstop)X
-1 f
-1367(option\))X
-1618(and)X
-1754(then)X
-1912(using)X
-2105(space)X
-2304(characters)X
-2651(as)X
-2738(necessary.)X
-3111(For)X
-3243(commands)X
-3611(inserting)X
-3912(text)X
-976 3510(into)N
-1124(the)X
-1246(middle)X
-1492(of)X
-1583(a)X
-1643(line,)X
-1807(any)X
-1947(blank)X
-2149(characters)X
-2500(to)X
-2586(the)X
-2708(right)X
-2883(of)X
-2974(the)X
-3096(cursor)X
-3321(are)X
-3444(discarded,)X
-3795(and)X
-3934(the)X
-976 3600(\256rst)N
-1120(nonblank)X
-1438(character)X
-1754(to)X
-1836(the)X
-1954(right)X
-2125(of)X
-2212(the)X
-2330(cursor)X
-2551(is)X
-2624(aligned)X
-2880(as)X
-2967(described)X
-3295(above.)X
-976 3780(The)N
-1128(indent)X
-1355(characters)X
-1709(are)X
-1835(themselves)X
-2218(somewhat)X
-2570(special.)X
-2860(If)X
-2941(you)X
-3088(do)X
-3195(not)X
-3324(enter)X
-3512(more)X
-3705(characters)X
-976 3870(on)N
-1085(the)X
-1212(new)X
-1375(line)X
-1524(before)X
-1759(moving)X
-2032(to)X
-2123(another)X
-2393(line,)X
-2562(or)X
-2658(entering)X
-7 f
-2950(<escape>)X
-1 f
-(,)S
-3382(the)X
-3508(indent)X
-3736(character)X
-976 3960(will)N
-1121(be)X
-1218(deleted)X
-1471(and)X
-1608(the)X
-1727(line)X
-1868(will)X
-2013(be)X
-2111(empty.)X
-2373(For)X
-2506(example,)X
-2820(if)X
-2891(you)X
-3033(enter)X
-7 f
-3216(<carriage-return>)X
-1 f
-976 4050(twice)N
-1181(in)X
-1274(succession,)X
-1668(the)X
-1797(line)X
-1947(created)X
-2210(by)X
-2320(the)X
-2448(\256rst)X
-7 f
-2602(<carriage-return>)X
-1 f
-3448(will)X
-3602(not)X
-3734(have)X
-3916(any)X
-976 4140(characters)N
-1323(in)X
-1405(it,)X
-1489(regardless)X
-1835(of)X
-1922(the)X
-2040(indentation)X
-2420(of)X
-2507(the)X
-2625(previous)X
-2921(or)X
-3008(subsequent)X
-3384(line.)X
-976 4320(Indent)N
-1210(characters)X
-1566(also)X
-1725(require)X
-1983(that)X
-2133(you)X
-2283(enter)X
-2474(additional)X
-2824(erase)X
-3020(characters)X
-3377(to)X
-3469(delete)X
-3691(them.)X
-3921(For)X
-976 4410(example,)N
-1290(if)X
-1361(you)X
-1503(have)X
-1677(an)X
-1775(indented)X
-2072(line,)X
-2233(containing)X
-2592(only)X
-2755(blanks,)X
-3005(the)X
-3124(\256rst)X
-7 f
-3269(<word-erase>)X
-1 f
-3866(char-)X
-976 4500(acter)N
-1156(you)X
-1299(enter)X
-1483(will)X
-1630(erase)X
-1819(up)X
-1922(to)X
-2007(end)X
-2146(of)X
-2236(the)X
-2357(indent)X
-2580(characters,)X
-2950(and)X
-3089(the)X
-3210(second)X
-3456(will)X
-3604(erase)X
-3794(back)X
-3970(to)X
-976 4590(the)N
-1094(beginning)X
-1434(of)X
-1521(the)X
-1639(line.)X
-1819(\(Historically,)X
-2264(only)X
-2426(the)X
-3 f
-2544(<control-D>)X
-1 f
-2986(key)X
-3122(would)X
-3342(erase)X
-3528(the)X
-3646(indent)X
-3866(char-)X
-976 4680(acters.)N
-1231(Both)X
-1413(the)X
-3 f
-1538(<control-D>)X
-1 f
-1988(key)X
-2132(and)X
-2276(the)X
-2402(usual)X
-2599(erase)X
-2793(keys)X
-2968(work)X
-3161(in)X
-3 f
-3251(nvi)X
-1 f
-3357(.\))X
-3452(In)X
-3547(addition,)X
-3857(if)X
-3934(the)X
-976 4770(cursor)N
-1211(is)X
-1298(positioned)X
-1665(at)X
-1756(the)X
-1887(end)X
-2036(of)X
-2136(the)X
-2267(indent)X
-2500(characters,)X
-2880(the)X
-3011(keys)X
-3191(``)X
-7 f
-3245(0<control-D>)X
-1 f
-('')S
-3908(will)X
-976 4860(erase)N
-1163(all)X
-1264(of)X
-1352(the)X
-1472(indent)X
-1694(characters)X
-2043(for)X
-2159(the)X
-2279(current)X
-2529(line,)X
-2691(resetting)X
-2989(the)X
-3109(indentation)X
-3491(level)X
-3669(to)X
-3753(0.)X
-3855(Simi-)X
-976 4950(larly,)N
-1168(the)X
-1291(keys)X
-1462(``)X
-7 f
-1516(\303<control-D>)X
-1 f
-('')S
-2170(will)X
-2318(erase)X
-2508(all)X
-2612(of)X
-2703(the)X
-2825(indent)X
-3049(characters)X
-3400(for)X
-3518(the)X
-3640(current)X
-3892(line,)X
-976 5040(leaving)N
-1232(the)X
-1350(indentation)X
-1730(level)X
-1906(for)X
-2020(future)X
-2232(created)X
-2485(lines)X
-2656(unaffected.)X
-976 5220(Finally,)N
-1243(if)X
-1313(the)X
-3 f
-1432(autoindent)X
-1 f
-1821(option)X
-2047(is)X
-2122(set,)X
-2253(the)X
-3 f
-2373(S)X
-1 f
-2439(and)X
-3 f
-2577(cc)X
-1 f
-2671(commands)X
-3040(change)X
-3290(from)X
-3468(the)X
-3588(\256rst)X
-3734(nonblank)X
-976 5310(of)N
-1063(the)X
-1181(line)X
-1321(to)X
-1403(the)X
-1521(end)X
-1657(of)X
-1744(the)X
-1862(line,)X
-2022(instead)X
-2269(of)X
-2356(from)X
-2532(the)X
-2650(beginning)X
-2990(of)X
-3077(the)X
-3195(line)X
-3335(to)X
-3417(the)X
-3535(end)X
-3671(of)X
-3758(the)X
-3876(line.)X
-3 f
-776 5490(autoprint,)N
-1140(ap)X
-1244([off])X
-976 5580(Ex)N
-1 f
-1099(only.)X
-1311(Cause)X
-1537(the)X
-1665(current)X
-1923(line)X
-2073(to)X
-2165(be)X
-2271(automatically)X
-2738(displayed)X
-3076(after)X
-3255(the)X
-3 f
-3384(ex)X
-1 f
-3491(commands)X
-3 f
-3869(<)X
-1 f
-3915(,)X
-3 f
-3966(>)X
-1 f
-4012(,)X
-3 f
-976 5670(copy)N
-1 f
-(,)S
-3 f
-1176(delete)X
-1 f
-1377(,)X
-3 f
-1417(join)X
-1 f
-1550(,)X
-3 f
-1590(move)X
-1 f
-1773(,)X
-3 f
-1813(put)X
-1 f
-1928(,)X
-3 f
-1968(t)X
-1 f
-1995(,)X
-3 f
-2035(Undo)X
-1 f
-2221(,)X
-2261(and)X
-3 f
-2397(undo)X
-1 f
-2569(.)X
-2629(This)X
-2791(automatic)X
-3127(display)X
-3378(is)X
-3451(suppressed)X
-3823(during)X
-3 f
-976 5760(global)N
-1 f
-1226(and)X
-3 f
-1384(vglobal)X
-1 f
-1675(commands,)X
-2085(and)X
-2244(for)X
-2381(any)X
-2540(command)X
-2899(where)X
-3139(optional)X
-3444(\257ags)X
-3638(are)X
-3780(used)X
-3970(to)X
-
-47 p
-%%Page: 47 46
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-3658(USD:13-47)X
-1 f
-976 762(explicitly)N
-1298(display)X
-1549(the)X
-1667(line.)X
-3 f
-776 942(autowrite,)N
-1146(aw)X
-1264([off])X
-1 f
-976 1032(If)N
-1053(this)X
-1191(option)X
-1418(is)X
-1494(set,)X
-1626(the)X
-3 f
-1747(vi)X
-1832(!)X
-1 f
-1859(,)X
-3 f
-1902(\303\303)X
-1 f
-1956(,)X
-3 f
-1999(\303])X
-1 f
-2076(and)X
-3 f
-2215(<control-Z>)X
-1 f
-2655(commands,)X
-3046(and)X
-3186(the)X
-3 f
-3308(ex)X
-3408(edit)X
-1 f
-3537(,)X
-3 f
-3581(next)X
-1 f
-3728(,)X
-3 f
-3772(rewind)X
-1 f
-(,)S
-3 f
-976 1122(stop)N
-1 f
-1118(,)X
-3 f
-1161(suspend)X
-1 f
-1435(,)X
-3 f
-1478(tag)X
-1 f
-1585(,)X
-3 f
-1628(tagpop)X
-1 f
-1863(,)X
-1906(and)X
-3 f
-2045(tagtop)X
-1 f
-2286(commands)X
-2656(automatically)X
-3115(write)X
-3302(the)X
-3422(current)X
-3672(\256le)X
-3796(back)X
-3970(to)X
-976 1212(the)N
-1103(current)X
-1360(\256le)X
-1491(name)X
-1694(if)X
-1772(it)X
-1845(has)X
-1981(been)X
-2163(modi\256ed)X
-2477(since)X
-2672(it)X
-2746(was)X
-2901(last)X
-3042(written.)X
-3339(If)X
-3423(the)X
-3551(write)X
-3746(fails,)X
-3934(the)X
-976 1302(command)N
-1312(fails)X
-1470(and)X
-1606(goes)X
-1773(no)X
-1873(further.)X
-976 1482(Appending)N
-1363(the)X
-1492(optional)X
-1785(force)X
-1982(\257ag)X
-2133(character)X
-2460(``)X
-7 f
-2514(!)X
-1 f
-('')S
-2668(to)X
-2762(the)X
-3 f
-2892(ex)X
-1 f
-3000(commands)X
-3 f
-3379(next)X
-1 f
-3526(,)X
-3 f
-3578(rewind)X
-1 f
-(,)S
-3 f
-3870(stop)X
-1 f
-4012(,)X
-3 f
-976 1572(suspend)N
-1 f
-1250(,)X
-3 f
-1290(tag)X
-1 f
-1397(,)X
-3 f
-1437(tagpop)X
-1 f
-1672(,)X
-1712(and)X
-3 f
-1848(tagtop)X
-1 f
-2086(stops)X
-2270(the)X
-2388(automatic)X
-2724(write)X
-2909(from)X
-3085(being)X
-3283(attempted.)X
-976 1752(\(Historically,)N
-1421(the)X
-3 f
-1539(next)X
-1 f
-1706(command)X
-2042(ignored)X
-2307(the)X
-2425(optional)X
-2707(force)X
-2894(\257ag.\))X
-3102(Note,)X
-3299(the)X
-3 f
-3418(ex)X
-1 f
-3515(commands)X
-3 f
-3883(edit)X
-1 f
-4012(,)X
-3 f
-976 1842(quit)N
-1 f
-1113(,)X
-3 f
-1153(shell)X
-1 f
-1308(,)X
-1348(and)X
-3 f
-1484(xit)X
-1 f
-1593(are)X
-2 f
-1712(not)X
-1 f
-1834(affected)X
-2114(by)X
-2214(the)X
-3 f
-2332(autowrite)X
-1 f
-2682(option.)X
-3 f
-776 2022(beautify,)N
-1096(bf)X
-1187([off])X
-1 f
-976 2112(If)N
-1061(this)X
-1207(option)X
-1442(is)X
-1527(set,)X
-1668(all)X
-1780(control)X
-2039(characters)X
-2398(that)X
-2550(are)X
-2681(not)X
-2815(currently)X
-3137(being)X
-3347(specially)X
-3664(interpreted,)X
-976 2202(other)N
-1166(than)X
-7 f
-1329(<tab>)X
-1 f
-(,)S
-7 f
-1613(<newline>)X
-1 f
-(,)S
-2089(and)X
-7 f
-2229(<form-feed>)X
-1 f
-(,)S
-2801(are)X
-2924(discarded)X
-3256(from)X
-3436(commands)X
-3807(read)X
-3970(in)X
-976 2292(by)N
-3 f
-1078(ex)X
-1 f
-1176(from)X
-1354(command)X
-1692(\256les,)X
-1867(and)X
-2005(from)X
-2183(input)X
-2369(text)X
-2511(entered)X
-2770(to)X
-3 f
-2854(vi)X
-1 f
-2938(\(either)X
-3170(into)X
-3316(the)X
-3436(\256le)X
-3560(or)X
-3649(to)X
-3733(the)X
-3854(colon)X
-976 2382(command)N
-1312(line\).)X
-1519(Text)X
-1686(\256les)X
-1839(read)X
-1998(by)X
-3 f
-2098(ex)X
-1 f
-2174(/)X
-3 f
-2196(vi)X
-1 f
-2278(are)X
-2 f
-2397(not)X
-1 f
-2519(affected)X
-2799(by)X
-2899(the)X
-3 f
-3017(beautify)X
-1 f
-3317(option.)X
-3 f
-776 2562(cdpath)N
-1031([environment)X
-1514(variable)X
-1814(CDPATH,)X
-2192(or)X
-2288(current)X
-2567(directory])X
-1 f
-976 2652(This)N
-1152(option)X
-1390(is)X
-1477(used)X
-1658(to)X
-1754(specify)X
-2020(a)X
-2090(colon)X
-2302(separated)X
-2640(list)X
-2771(of)X
-2872(directories)X
-3245(which)X
-3476(are)X
-3610(used)X
-3792(as)X
-3894(path)X
-976 2742(pre\256xes)N
-1252(for)X
-1368(any)X
-1506(relative)X
-1769(path)X
-1929(names)X
-2156(used)X
-2325(as)X
-2414(arguments)X
-2770(for)X
-2886(the)X
-3 f
-3006(cd)X
-1 f
-3108(command.)X
-3486(The)X
-3633(value)X
-3829(of)X
-3917(this)X
-976 2832(option)N
-1202(defaults)X
-1478(to)X
-1562(the)X
-1682(value)X
-1878(of)X
-1967(the)X
-2088(environmental)X
-2574(variable)X
-7 f
-2856(CDPATH)X
-1 f
-3167(if)X
-3239(it)X
-3306(is)X
-3382(set,)X
-3514(otherwise)X
-3849(to)X
-3934(the)X
-976 2922(current)N
-1232(directory.)X
-1590(For)X
-1729(compatibility)X
-2183(with)X
-2353(the)X
-2478(POSIX)X
-2736(1003.2)X
-2983(shell,)X
-3181(the)X
-3 f
-3306(cd)X
-1 f
-3413(command)X
-3756(does)X
-2 f
-3930(not)X
-1 f
-976 3012(check)N
-1200(the)X
-1334(current)X
-1598(directory)X
-1924(as)X
-2027(a)X
-2099(path)X
-2273(pre\256x)X
-2496(for)X
-2627(relative)X
-2905(path)X
-3080(names)X
-3322(unless)X
-3559(it)X
-3640(is)X
-3730(explicitly)X
-976 3102(speci\256ed.)N
-1334(It)X
-1416(may)X
-1586(be)X
-1694(so)X
-1797(speci\256ed)X
-2114(by)X
-2226(entering)X
-2521(an)X
-2629(empty)X
-2861(string)X
-3075(or)X
-3174(a)X
-3242(``)X
-7 f
-3296(.)X
-1 f
-('')S
-3450(character)X
-3778(into)X
-3934(the)X
-7 f
-976 3192(CDPATH)N
-1 f
-1284(variable)X
-1563(or)X
-1650(the)X
-1768(option)X
-1992(value.)X
-3 f
-776 3372(columns,)N
-1100(co)X
-1196([80])X
-1 f
-976 3462(The)N
-1132(number)X
-1408(of)X
-1506(columns)X
-1808(in)X
-1901(the)X
-2030(screen.)X
-2307(Setting)X
-2565(this)X
-2712(option)X
-2948(causes)X
-3 f
-3190(ex)X
-1 f
-3266(/)X
-3 f
-3288(vi)X
-1 f
-3382(to)X
-3476(set)X
-3597(\(or)X
-3723(reset\))X
-3934(the)X
-976 3552(environmental)N
-1464(variable)X
-7 f
-1748(COLUMNS)X
-1 f
-(.)S
-2149(See)X
-2290(the)X
-2413(section)X
-2665(entitled)X
-2930(``)X
-3 f
-2984(Sizing)X
-3217(the)X
-3349(Screen)X
-1 f
-3581('')X
-3660(more)X
-3849(infor-)X
-976 3642(mation.)N
-3 f
-776 3822(comment)N
-1113([off])X
-976 3912(Vi)N
-1 f
-1079(only.)X
-1284(If)X
-1361(the)X
-1482(\256rst)X
-1629(non-empty)X
-1999(line)X
-2142(of)X
-2232(the)X
-2354(\256le)X
-2480(begins)X
-2713(with)X
-2879(the)X
-3001(string)X
-3207(``)X
-7 f
-3261(/*)X
-1 f
-('',)S
-3455(this)X
-3594(option)X
-3822(causes)X
-3 f
-976 4002(vi)N
-1 f
-1072(to)X
-1167(skip)X
-1333(to)X
-1428(the)X
-1559(end)X
-1708(of)X
-1808(that)X
-1961(C-language)X
-2364(comment)X
-2695(\(probably)X
-3040(a)X
-3109(terribly)X
-3378(boring)X
-3620(legal)X
-3809(notice\))X
-976 4092(before)N
-1202(displaying)X
-1555(the)X
-1673(\256le.)X
-3 f
-776 4272(directory,)N
-1133(dir)X
-1255([environment)X
-1738(variable)X
-2038(TMPDIR,)X
-2403(or)X
-2499(/tmp])X
-1 f
-976 4362(The)N
-1123(directory)X
-1435(where)X
-1655(temporary)X
-2008(\256les)X
-2164(are)X
-2286(created.)X
-2582(The)X
-2730(environmental)X
-3216(variable)X
-7 f
-3498(TMPDIR)X
-1 f
-3809(is)X
-3885(used)X
-976 4452(as)N
-1063(the)X
-1181(default)X
-1424(value)X
-1618(if)X
-1687(it)X
-1751(exists,)X
-1973(otherwise)X
-7 f
-2305(/tmp)X
-1 f
-2517(is)X
-2590(used.)X
-3 f
-776 4632(edcompatible,)N
-1274(ed)X
-1374([off])X
-1 f
-976 4722(Remember)N
-1349(the)X
-1468(values)X
-1694(of)X
-1782(the)X
-1901(``c'')X
-2066(and)X
-2203(``g'')X
-2372(suf\256ces)X
-2638(to)X
-2721(the)X
-3 f
-2840(substitute)X
-1 f
-3194(commands,)X
-3583(instead)X
-3832(of)X
-3921(ini-)X
-976 4812(tializing)N
-1262(them)X
-1446(as)X
-1537(unset)X
-1730(for)X
-1848(each)X
-2020(new)X
-2178(command.)X
-2558(Specifying)X
-2929(pattern)X
-3176(and)X
-3316(replacement)X
-3733(strings)X
-3970(to)X
-976 4902(the)N
-3 f
-1094(substitute)X
-1 f
-1447(command)X
-1783(unsets)X
-2003(the)X
-2121(``c'')X
-2285(and)X
-2421(``g'')X
-2589(suf\256ces)X
-2854(as)X
-2941(well.)X
-3 f
-776 5082(errorbells,)N
-1155(eb)X
-1255([off])X
-976 5172(Ex)N
-1 f
-1089(only.)X
-3 f
-1292(Ex)X
-1 f
-1406(error)X
-1584(messages)X
-1908(are)X
-2028(normally)X
-2338(presented)X
-2667(in)X
-2750(inverse)X
-3003(video.)X
-3242(If)X
-3317(that)X
-3458(is)X
-3532(not)X
-3655(possible)X
-3938(for)X
-976 5262(the)N
-1096(terminal,)X
-1405(setting)X
-1640(this)X
-1777(option)X
-2003(causes)X
-2235(error)X
-2414(messages)X
-2739(to)X
-2823(be)X
-2921(announced)X
-3291(by)X
-3393(ringing)X
-3646(the)X
-3765(terminal)X
-976 5352(bell.)N
-3 f
-776 5532(exrc,)N
-964(ex)X
-1060([off])X
-1 f
-976 5622(If)N
-1061(this)X
-1207(option)X
-1442(is)X
-1526(turned)X
-1762(off)X
-1887(in)X
-1980(the)X
-2109(system)X
-2362(or)X
-2460($HOME)X
-2767(startup)X
-3016(\256les,)X
-3200(the)X
-3330(local)X
-3518(startup)X
-3768(\256les)X
-3933(are)X
-976 5712(never)N
-1177(read)X
-1338(\(unless)X
-1587(they)X
-1747(are)X
-1868(the)X
-1988(same)X
-2175(as)X
-2264(the)X
-2384(system)X
-2628(or)X
-2717($HOME)X
-3015(startup)X
-3255(\256les\).)X
-3477(Turning)X
-3757(it)X
-3823(on)X
-3925(has)X
-976 5802(no)N
-1091(effect,)X
-1330(i.e.)X
-1463(the)X
-1596(normal)X
-1858(checks)X
-2112(for)X
-2241(local)X
-2432(startup)X
-2685(\256les)X
-2854(are)X
-2989(performed,)X
-3380(regardless.)X
-3782(See)X
-3934(the)X
-
-48 p
-%%Page: 48 47
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-48)N
-3391(Nvi/Nex)X
-3687 0.3906(Reference)AX
-1 f
-976 762(section)N
-1223(entitled)X
-1483(``)X
-3 f
-1537(Startup)X
-1819(Information)X
-1 f
-2237('')X
-2311(for)X
-2425(more)X
-2610(information.)X
-3 f
-776 942(extended)N
-1103([off])X
-1 f
-976 1032(This)N
-1147(option)X
-1380(causes)X
-1619(all)X
-1728(regular)X
-1986(expressions)X
-2390(to)X
-2482(be)X
-2588(treated)X
-2837(as)X
-2934(POSIX)X
-3195(1003.2)X
-3445(Extended)X
-3778(Regular)X
-976 1122(Expressions)N
-1383(\(which)X
-1626(are)X
-1745(similar)X
-1987(to)X
-2069(historic)X
-2 f
-2329(egrep)X
-1 f
-2512(\(1\))X
-2626(style)X
-2797(expressions\).)X
-3 f
-776 1302(\257ash)N
-955([on])X
-1 f
-976 1392(This)N
-1139(option)X
-1364(causes)X
-1595(the)X
-1714(screen)X
-1941(to)X
-2025(\257ash)X
-2198(instead)X
-2447(of)X
-2536(beeping)X
-2812(the)X
-2932(keyboard,)X
-3273(on)X
-3375(error,)X
-3574(if)X
-3645(the)X
-3765(terminal)X
-976 1482(has)N
-1103(the)X
-1221(capability.)X
-3 f
-776 1662(hardtabs,)N
-1122(ht)X
-1213([8])X
-1 f
-976 1752(This)N
-1141(option)X
-1369(de\256nes)X
-1620(the)X
-1742(spacing)X
-2011(between)X
-2303(hardware)X
-2627(tab)X
-2749(settings,)X
-3037(i.e.)X
-3179(the)X
-3301(tab)X
-3423(expansion)X
-3772(done)X
-3952(by)X
-976 1842(the)N
-1099(operating)X
-1427(system)X
-1674(and/or)X
-1904(the)X
-2027(terminal)X
-2319(itself.)X
-2544(As)X
-3 f
-2658(nex)X
-1 f
-(/)S
-3 f
-2800(nvi)X
-1 f
-2931(never)X
-3135(writes)X
-7 f
-3355(<tab>)X
-1 f
-3619(characters)X
-3970(to)X
-976 1932(the)N
-1094(terminal,)X
-1401(unlike)X
-1621(historic)X
-1881(versions)X
-2168(of)X
-3 f
-2255(ex)X
-1 f
-2331(/)X
-3 f
-2353(vi)X
-1 f
-2415(,)X
-2455(this)X
-2590(option)X
-2814(does)X
-2981(not)X
-3103(currently)X
-3413(have)X
-3585(any)X
-3721(affect.)X
-3 f
-776 2112(ignorecase,)N
-1177(ic)X
-1255([off])X
-1 f
-976 2202(This)N
-1141(option)X
-1368(causes)X
-1602(regular)X
-1854(expressions,)X
-2272(both)X
-2438(in)X
-3 f
-2524(ex)X
-1 f
-2624(commands)X
-2995(and)X
-3135(in)X
-3221(searches,)X
-3538(to)X
-3624(be)X
-3724(evaluated)X
-976 2292(in)N
-1058(a)X
-1114(case-insensitive)X
-1642(manner.)X
-3 f
-776 2472(keytime)N
-1068([6])X
-1 f
-976 2562(The)N
-1121(10th's)X
-1341(of)X
-1428(a)X
-1484(second)X
-3 f
-1727(ex)X
-1 f
-1803(/)X
-3 f
-1825(vi)X
-1 f
-1907(waits)X
-2096(for)X
-2210(a)X
-2266(subsequent)X
-2642(key)X
-2778(to)X
-2860(complete)X
-3174(a)X
-3230(key)X
-3366(mapping.)X
-3 f
-776 2742(leftright)N
-1077([off])X
-976 2832(Vi)N
-1 f
-1083(only.)X
-1293(This)X
-1463(option)X
-1695(causes)X
-1933(the)X
-2059(screen)X
-2293(to)X
-2383(be)X
-2487(scrolled)X
-2769(left-right)X
-3082(to)X
-3172(view)X
-3356(lines)X
-3535(longer)X
-3768(than)X
-3934(the)X
-976 2922(screen,)N
-1232(instead)X
-1489(of)X
-1586(the)X
-1714(traditional)X
-3 f
-2073(vi)X
-1 f
-2165(screen)X
-2401(interface)X
-2713(which)X
-2939(folds)X
-3129(long)X
-3301(lines)X
-3482(at)X
-3570(the)X
-3698(right-hand)X
-976 3012(margin)N
-1223(of)X
-1310(the)X
-1428(terminal.)X
-3 f
-776 3192(lines,)N
-971(li)X
-1035([24])X
-976 3282(Vi)N
-1 f
-1076(only.)X
-1278(The)X
-1423(number)X
-1688(of)X
-1775(lines)X
-1946(in)X
-2028(the)X
-2146(screen.)X
-2412(Setting)X
-2658(this)X
-2793(option)X
-3017(causes)X
-3 f
-3247(ex)X
-1 f
-3323(/)X
-3 f
-3345(vi)X
-1 f
-3427(to)X
-3509(set)X
-3619(\(or)X
-3734(reset\))X
-3934(the)X
-976 3372(environmental)N
-1462(variable)X
-7 f
-1744(LINES)X
-1 f
-(.)S
-2047(See)X
-2186(the)X
-2307(section)X
-2557(entitled)X
-2820(``)X
-3 f
-2874(Sizing)X
-3105(the)X
-3235(Screen)X
-1 f
-3467('')X
-3544(for)X
-3661(more)X
-3849(infor-)X
-976 3462(mation.)N
-3 f
-776 3642(lisp)N
-915([off])X
-976 3732(Vi)N
-1 f
-1078(only.)X
-1282(This)X
-1447(option)X
-1674(changes)X
-1956(the)X
-2077(behavior)X
-2381(of)X
-2471(the)X
-3 f
-2592(vi)X
-2677(\()X
-1 f
-2704(,)X
-3 f
-2747(\))X
-1 f
-2774(,)X
-3 f
-2817({)X
-1 f
-2849(,)X
-3 f
-2892(})X
-1 f
-2924(,)X
-3 f
-2967([[)X
-1 f
-3044(and)X
-3 f
-3183(]])X
-1 f
-3260(commands)X
-3630(to)X
-3715(match)X
-3934(the)X
-976 3822(Lisp)N
-1138(language.)X
-1488(Also,)X
-1679(the)X
-3 f
-1797(autoindent)X
-1 f
-2185(option's)X
-2467(behavior)X
-2768(is)X
-2841(changed)X
-3129(to)X
-3211(be)X
-3307(appropriate)X
-3693(for)X
-3807(Lisp.)X
-2 f
-976 4002(This)N
-1133(option)X
-1357(is)X
-1430(not)X
-1552(yet)X
-1666(implemented.)X
-3 f
-776 4182(list)N
-898([off])X
-1 f
-976 4272(This)N
-1151(option)X
-1388(causes)X
-1631(lines)X
-1815(to)X
-1910(be)X
-2019(displayed)X
-2359(in)X
-2454(an)X
-2563(unambiguous)X
-3028(fashion.)X
-3338(Speci\256cally,)X
-3770(tabs)X
-3933(are)X
-976 4362(displayed)N
-1305(as)X
-1394(control)X
-1643(characters,)X
-2012(i.e.)X
-2152(``)X
-7 f
-2206(\303I)X
-1 f
-('',)S
-2398(and)X
-2536(the)X
-2656(ends)X
-2825(of)X
-2914(lines)X
-3087(are)X
-3207(marked)X
-3469(with)X
-3632(a)X
-3689(``)X
-7 f
-3743($)X
-1 f
-('')S
-3866(char-)X
-976 4452(acter.)N
-3 f
-776 4632(magic)N
-1001([on])X
-1 f
-976 4722(This)N
-1141(option)X
-1368(is)X
-1444(on)X
-1547(by)X
-1650(default.)X
-1936(Turning)X
-2217(the)X
-3 f
-2338(magic)X
-1 f
-2566(option)X
-2793(off)X
-2910(causes)X
-3143(all)X
-3247(regular)X
-3499(expression)X
-3866(char-)X
-976 4812(acters)N
-1189(except)X
-1423(for)X
-1541(``)X
-7 f
-1595(\303)X
-1 f
-('')S
-1721(and)X
-1861(``)X
-7 f
-1915($)X
-1 f
-('',)S
-2061(to)X
-2147(be)X
-2247(treated)X
-2490(as)X
-2581(ordinary)X
-2877(characters.)X
-3268(To)X
-3381(re-enable)X
-3705(characters)X
-976 4902(individually,)N
-1402(when)X
-1597(the)X
-3 f
-1716(magic)X
-1 f
-1942(option)X
-2167(is)X
-2241(off,)X
-2376(precede)X
-2648(them)X
-2829(with)X
-2992(a)X
-3049(backslash)X
-3382(``)X
-7 f
-3436(\\)X
-1 f
-('')S
-3559(character.)X
-3916(See)X
-976 4992(the)N
-1094(section)X
-1341(entitled)X
-1601(``)X
-3 f
-1655(Regular)X
-1951(Expressions)X
-2379(and)X
-2527(Replacement)X
-2993(Strings)X
-1 f
-3237('')X
-3311(for)X
-3425(more)X
-3610(information.)X
-3 f
-776 5172(matchtime)N
-1162([7])X
-976 5262(Vi)N
-1 f
-1078(only.)X
-1282(The)X
-1429(10th's)X
-1651(of)X
-1740(a)X
-1798(second)X
-3 f
-2043(ex)X
-1 f
-2119(/)X
-3 f
-2141(vi)X
-1 f
-2226(pauses)X
-2463(on)X
-2566(the)X
-2687(matching)X
-3008(character)X
-3327(when)X
-3524(the)X
-3 f
-3645(showmatch)X
-1 f
-976 5352(option)N
-1200(is)X
-1273(set.)X
-3 f
-776 5532(mesg)N
-970([on])X
-1 f
-976 5622(This)N
-1140(option)X
-1366(allows)X
-1597(other)X
-1784(users)X
-1972(to)X
-2057(contact)X
-2312(you)X
-2455(using)X
-2651(the)X
-2 f
-2772(talk)X
-1 f
-(\(1\))S
-3009(and)X
-2 f
-3148(write)X
-1 f
-3312(\(1\))X
-3429(utilities,)X
-3711(while)X
-3912(you)X
-976 5712(are)N
-1101(editing.)X
-3 f
-1389(Ex)X
-1 f
-1482(/)X
-3 f
-1504(vi)X
-1 f
-1592(does)X
-1764(not)X
-1891(turn)X
-2045(message)X
-2342(on,)X
-2467(i.e.)X
-2590(if)X
-2664(messages)X
-2992(were)X
-3174(turned)X
-3404(off)X
-3523(when)X
-3722(the)X
-3845(editor)X
-976 5802(was)N
-1124(invoked,)X
-1425(they)X
-1586(will)X
-1733(stay)X
-1885(turned)X
-2113(off.)X
-2270(This)X
-2435(option)X
-2662(only)X
-2827(permits)X
-3090(you)X
-3233(to)X
-3318(disallow)X
-3612(messages)X
-3938(for)X
-
-49 p
-%%Page: 49 48
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-3658(USD:13-49)X
-1 f
-976 762(the)N
-1094(edit)X
-1234(session.)X
-1525(See)X
-1661(the)X
-2 f
-1779(mesg)X
-1 f
-1944(\(1\))X
-2058(utility)X
-2268(for)X
-2382(more)X
-2567(information.)X
-3 f
-776 942(modelines,)N
-1158(modeline)X
-1489([off])X
-1 f
-976 1032(If)N
-1052(the)X
-3 f
-1172(modelines)X
-1 f
-1536(option)X
-1762(is)X
-1837(set,)X
-3 f
-1968(ex)X
-1 f
-2044(/)X
-3 f
-2066(vi)X
-1 f
-2150(has)X
-2279(historically)X
-2661(scanned)X
-2942(the)X
-3062(\256rst)X
-3208(and)X
-3346(last)X
-3479(\256ve)X
-3621(lines)X
-3794(of)X
-3884(each)X
-976 1122(\256le)N
-1101(as)X
-1191(it)X
-1258(is)X
-1334(read)X
-1496(for)X
-1613(editing,)X
-1877(looking)X
-2143(for)X
-2259(any)X
-3 f
-2397(ex)X
-1 f
-2495(commands)X
-2864(that)X
-3006(have)X
-3180(been)X
-3354(placed)X
-3586(in)X
-3670(those)X
-3861(lines.)X
-976 1212(After)N
-1167(the)X
-1286(startup)X
-1525(information)X
-1924(has)X
-2052(been)X
-2225(processed,)X
-2583(and)X
-2720(before)X
-2947(the)X
-3066(user)X
-3221(starts)X
-3411(editing)X
-3654(the)X
-3773(\256le,)X
-3916(any)X
-976 1302(commands)N
-1343(embedded)X
-1693(in)X
-1775(the)X
-1893(\256le)X
-2015(are)X
-2134(executed.)X
-976 1482(Commands)N
-1362(were)X
-1541(recognized)X
-1916(by)X
-2018(the)X
-2138(letters)X
-2356(``e'')X
-2522(or)X
-2611(``v'')X
-2781(followed)X
-3088(by)X
-3191(``x'')X
-3362(or)X
-3452(``i'',)X
-3625(at)X
-3706(the)X
-3827(begin-)X
-976 1572(ning)N
-1144(of)X
-1237(a)X
-1299(line)X
-1445(or)X
-1538(following)X
-1875(a)X
-1937(tab)X
-2061(or)X
-2154(space)X
-2359(character,)X
-2701(and)X
-2843(followed)X
-3153(by)X
-3258(a)X
-3319(``:'',)X
-3494(an)X
-3 f
-3595(ex)X
-1 f
-3696(command,)X
-976 1662(and)N
-1112(another)X
-1373(``:''.)X
-976 1842(This)N
-1144(option)X
-1374(is)X
-1453(a)X
-1516(security)X
-1797(problem)X
-2091(of)X
-2185(immense)X
-2501(proportions,)X
-2917(and)X
-3060(should)X
-3300(not)X
-3429(be)X
-3532(used)X
-3706(under)X
-3916(any)X
-976 1932(circumstances.)N
-2 f
-976 2112(This)N
-1133(option)X
-1357(will)X
-1496(never)X
-1695(be)X
-1791(implemented.)X
-3 f
-776 2292(number,)N
-1087(nu)X
-1195([off])X
-1 f
-976 2382(Precede)N
-1251(each)X
-1419(line)X
-1559(displayed)X
-1886(with)X
-2048(its)X
-2143(current)X
-2391(line)X
-2531(number.)X
-3 f
-776 2562(octal)N
-961([off])X
-1 f
-976 2652(Display)N
-1245(unknown)X
-1563(characters)X
-1910(as)X
-1997(octal)X
-2173(numbers,)X
-2489(instead)X
-2736(of)X
-2823(the)X
-2941(default)X
-3184(hexadecimal.)X
-3 f
-776 2832(open)N
-960([on])X
-976 2922(Ex)N
-1 f
-1089(only.)X
-1291(If)X
-1365(this)X
-1500(option)X
-1724(is)X
-1797(not)X
-1919(set,)X
-2048(the)X
-3 f
-2166(open)X
-1 f
-2350(and)X
-3 f
-2486(visual)X
-1 f
-2705(commands)X
-3072(are)X
-3191(disallowed.)X
-3 f
-776 3102(optimize,)N
-1110(opt)X
-1241([on])X
-976 3192(Vi)N
-1 f
-1081(only.)X
-1288(Throughput)X
-1691(of)X
-1783(text)X
-1929(is)X
-2008(expedited)X
-2346(by)X
-2452(setting)X
-2691(the)X
-2815(terminal)X
-3108(not)X
-3236(to)X
-3324(do)X
-3430(automatic)X
-3772(carriage)X
-976 3282(returns)N
-1222(when)X
-1419(printing)X
-1695(more)X
-1883(than)X
-2044(one)X
-2183(\(logical\))X
-2478(line)X
-2621(of)X
-2710(output,)X
-2956(greatly)X
-3201(speeding)X
-3508(output)X
-3734(on)X
-3836(termi-)X
-976 3372(nals)N
-1125(without)X
-1389(addressable)X
-1784(cursors)X
-2036(when)X
-2230(text)X
-2370(with)X
-2532(leading)X
-2788(white)X
-2986(space)X
-3185(is)X
-3258(printed.)X
-2 f
-976 3552(This)N
-1133(option)X
-1357(is)X
-1430(not)X
-1552(yet)X
-1666(implemented.)X
-3 f
-776 3732(paragraphs,)N
-1211(para)X
-1391([IPLPPPQPP)X
-1878 -0.3625(LIpplpipbp])AX
-976 3822(Vi)N
-1 f
-1079(only.)X
-1284(De\256ne)X
-1521(additional)X
-1864(paragraph)X
-2209(boundaries)X
-2584(for)X
-2701(the)X
-3 f
-2822({)X
-1 f
-2877(and)X
-3 f
-3016(})X
-1 f
-3071(commands.)X
-3481(The)X
-3629(value)X
-3826(of)X
-3917(this)X
-976 3912(option)N
-1200(must)X
-1375(be)X
-1471(a)X
-1527(character)X
-1843(string)X
-2045(consisting)X
-2389(of)X
-2476(zero)X
-2635(or)X
-2722(more)X
-2907(character)X
-3223(pairs.)X
-976 4092(In)N
-1070(the)X
-1195(text)X
-1342(to)X
-1431(be)X
-1534(edited,)X
-1777(the)X
-1902(character)X
-2226(string)X
-7 f
-2436(<newline>.<char-pair>)X
-1 f
-(,)S
-3492(\(where)X
-7 f
-3744(<char-)X
-976 4182(pair>)N
-1 f
-1241(is)X
-1319(one)X
-1460(of)X
-1552(the)X
-1675(character)X
-1996(pairs)X
-2177(in)X
-2264(the)X
-2386(option's)X
-2672(value\))X
-2897(de\256nes)X
-3148(a)X
-3208(paragraph)X
-3554(boundary.)X
-3921(For)X
-976 4272(example,)N
-1291(if)X
-1363(the)X
-1484(option)X
-1711(were)X
-1891(set)X
-2003(to)X
-7 f
-2088(LaA<space>##)X
-1 f
-(,)S
-2708(then)X
-2870(all)X
-2974(of)X
-3065(the)X
-3187(following)X
-3522(additional)X
-3866(para-)X
-976 4362(graph)N
-1179(boundaries)X
-1551(would)X
-1771(be)X
-1867(recognized:)X
-1296 4575(<newline>.La)N
-1296 4665(<newline>.A<space>)N
-1296 4755(<newline>.##)N
-3 f
-776 4968(prompt)N
-1054([on])X
-976 5058(Ex)N
-1 f
-1090(only.)X
-1293(This)X
-1456(option)X
-1681(causes)X
-3 f
-1912(ex)X
-1 f
-2009(to)X
-2092(prompt)X
-2344(for)X
-2459(command)X
-2796(input)X
-2981(with)X
-3144(a)X
-3201(``)X
-7 f
-3255(:)X
-1 f
-('')S
-3378(character;)X
-3717(when)X
-3913(it)X
-3979(is)X
-976 5148(not)N
-1098(set,)X
-1227(no)X
-1327(prompt)X
-1578(is)X
-1651(displayed.)X
-3 f
-776 5328(readonly,)N
-1118(ro)X
-1214([off])X
-1 f
-976 5418(This)N
-1138(option)X
-1362(causes)X
-1592(a)X
-1648(force)X
-1834(\257ag)X
-1974(to)X
-2056(be)X
-2152(required)X
-2440(to)X
-2522(attempt)X
-2782(to)X
-2864(write)X
-3049(the)X
-3167(\256le)X
-3289(back)X
-3461(to)X
-3543(the)X
-3661(original)X
-3930(\256le)X
-976 5508(name.)N
-1215(Setting)X
-1466(this)X
-1605(option)X
-1833(is)X
-1910(equivalent)X
-2268(to)X
-2354(using)X
-2551(the)X
-3 f
-9 f
-2673(-)X
-2675(-)X
-3 f
-2719(R)X
-1 f
-2801(command)X
-3141(line)X
-3285(option,)X
-3533(or)X
-3624(editing)X
-3870(a)X
-3930(\256le)X
-976 5598(which)N
-1192(lacks)X
-1377(write)X
-1562(permission.)X
-
-50 p
-%%Page: 50 49
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-50)N
-3391(Nvi/Nex)X
-3687 0.3906(Reference)AX
-776 762(recdir)N
-1006([/var/tmp/vi.recover])X
-1 f
-976 852(The)N
-1121(directory)X
-1431(where)X
-1648(recovery)X
-1950(\256les)X
-2103(are)X
-2222(stored.)X
-976 1032(If)N
-1051(you)X
-1192(change)X
-1441(the)X
-1561(value)X
-1757(of)X
-3 f
-1846(recdir)X
-1 f
-2056(,)X
-2098(be)X
-2196(careful)X
-2442(to)X
-2526(choose)X
-2771(a)X
-2829(directory)X
-3141(whose)X
-3368(contents)X
-3657(are)X
-3778(not)X
-3902(reg-)X
-976 1122(ularly)N
-1197(deleted.)X
-1503(Bad)X
-1666(choices)X
-1941(include)X
-2211(directories)X
-2584(in)X
-2680(memory)X
-2981(based)X
-3198(\256lesystems,)X
-3607(or)X
-7 f
-3707(/tmp)X
-1 f
-(,)S
-3952(on)X
-976 1212(most)N
-1151(systems,)X
-1444(as)X
-1531(their)X
-1698(contents)X
-1985(are)X
-2104(removed)X
-2405(when)X
-2599(the)X
-2717(machine)X
-3009(is)X
-3082(rebooted.)X
-976 1392(Public)N
-1219(directories)X
-1597(like)X
-7 f
-1757(/usr/tmp)X
-1 f
-2181(and)X
-7 f
-2337(/var/tmp)X
-1 f
-2761(are)X
-2900(usually)X
-3171(safe,)X
-3361(although)X
-3681(some)X
-3890(sites)X
-976 1482(periodically)N
-1387(prune)X
-1598(old)X
-1728(\256les)X
-1889(from)X
-2073(them.)X
-2301(There)X
-2517(is)X
-2598(no)X
-2706(requirement)X
-3122(that)X
-3270(you)X
-3418(use)X
-3553(a)X
-3617(public)X
-3844(direc-)X
-976 1572(tory,)N
-1145(e.g.)X
-1281(a)X
-1337(sub-directory)X
-1785(of)X
-1872(your)X
-2039(home)X
-2237(directory)X
-2547(will)X
-2691(work)X
-2876(\256ne.)X
-976 1752(Finally,)N
-1248(if)X
-1323(you)X
-1469(change)X
-1723(the)X
-1847(value)X
-2047(of)X
-3 f
-2140(recdir)X
-1 f
-2350(,)X
-2396(you)X
-2542(must)X
-2723(modify)X
-2980(the)X
-3104(recovery)X
-3412(script)X
-3617(to)X
-3706(operate)X
-3970(in)X
-976 1842(your)N
-1143(chosen)X
-1386(recovery)X
-1688(area.)X
-976 2022(See)N
-1112(the)X
-1230(section)X
-1477(entitled)X
-1737(``)X
-3 f
-1791(Recovery)X
-1 f
-2113('')X
-2187(for)X
-2301(further)X
-2540(information.)X
-3 f
-776 2202(redraw,)N
-1066(re)X
-1158([off])X
-976 2292(Vi)N
-1 f
-1087(only.)X
-1301(The)X
-1458(editor)X
-1677(simulates)X
-2011(\(using)X
-2243(great)X
-2436(amounts)X
-2739(of)X
-2838(output\),)X
-3121(an)X
-3229(intelligent)X
-3585(terminal)X
-3884(on)X
-3996(a)X
-976 2382(dumb)N
-1200(terminal)X
-1509(\(e.g.)X
-1694(during)X
-1945(insertions)X
-2297(in)X
-3 f
-2400(vi)X
-1 f
-2503(the)X
-2642(characters)X
-3010(to)X
-3113(the)X
-3252(right)X
-3444(of)X
-3552(the)X
-3691(cursor)X
-3933(are)X
-976 2472(refreshed)N
-1296(as)X
-1383(each)X
-1551(input)X
-1735(character)X
-2051(is)X
-2124(typed\).)X
-2 f
-976 2652(This)N
-1133(option)X
-1357(is)X
-1430(not)X
-1552(yet)X
-1666(implemented.)X
-3 f
-776 2832(remap)N
-1019([on])X
-1 f
-976 2922(If)N
-1055(this)X
-1195(option)X
-1424(is)X
-1502(set,)X
-1636(it)X
-1705(is)X
-1783(possible)X
-2070(to)X
-2157(de\256ne)X
-2378(macros)X
-2635(in)X
-2722(terms)X
-2926(of)X
-3019(other)X
-3210(macros.)X
-3508(Otherwise,)X
-3884(each)X
-976 3012(key)N
-1121(is)X
-1203(only)X
-1374(remapped)X
-1720(up)X
-1829(to)X
-1920(one)X
-2064(time.)X
-2274(For)X
-2413(example,)X
-2733(if)X
-2810(``)X
-7 f
-2864(A)X
-1 f
-('')S
-2994(is)X
-3075(mapped)X
-3357(to)X
-3447(``)X
-7 f
-3501(B)X
-1 f
-('',)S
-3651(and)X
-3795(``)X
-7 f
-3849(B)X
-1 f
-('')S
-3979(is)X
-976 3102(mapped)N
-1251(to)X
-1334(``)X
-7 f
-1388(C)X
-1 f
-('',)S
-1531(The)X
-1677(keystroke)X
-2010(``)X
-7 f
-2064(A)X
-1 f
-('')S
-2187(will)X
-2332(be)X
-2429(mapped)X
-2704(to)X
-2787(``)X
-7 f
-2841(C)X
-1 f
-('')S
-2964(if)X
-3035(the)X
-3 f
-3155(remap)X
-1 f
-3400(option)X
-3626(is)X
-3701(set,)X
-3832(and)X
-3970(to)X
-976 3192(``)N
-7 f
-1030(B)X
-1 f
-('')S
-1152(if)X
-1221(it)X
-1285(is)X
-1358(not)X
-1480(set.)X
-3 f
-776 3372(report)N
-1015([5])X
-1 f
-976 3462(Set)N
-1103(the)X
-1226(threshold)X
-1549(of)X
-1642(the)X
-1766(number)X
-2037(of)X
-2130(lines)X
-2307(that)X
-2453(need)X
-2631(to)X
-2719(be)X
-2821(changed)X
-3115(or)X
-3208(yanked)X
-3466(before)X
-3698(a)X
-3760(message)X
-976 3552(will)N
-1127(be)X
-1230(displayed)X
-1564(to)X
-1653(the)X
-1778(user.)X
-1979(For)X
-2117(everything)X
-2487(but)X
-2616(the)X
-2741(yank)X
-2924(command,)X
-3287(the)X
-3412(value)X
-3613(is)X
-3693(the)X
-3818(largest)X
-976 3642(value)N
-1172(about)X
-1372(which)X
-1590(the)X
-1711(editor)X
-1921(is)X
-1997(silent,)X
-2213(i.e.)X
-2334(by)X
-2437(default,)X
-2703(6)X
-2766(lines)X
-2940(must)X
-3118(be)X
-3217(deleted)X
-3472(before)X
-3701(the)X
-3822(user)X
-3979(is)X
-976 3732(noti\256ed.)N
-1283(However,)X
-1621(if)X
-1693(the)X
-1814(number)X
-2082(of)X
-2172(lines)X
-2346(yanked)X
-2601(is)X
-2677(greater)X
-2924(than)X
-2 f
-3085(or)X
-3179(equal)X
-3380(to)X
-1 f
-3465(the)X
-3586(set)X
-3697(value,)X
-3913(it)X
-3979(is)X
-976 3822(reported)N
-1264(to)X
-1346(the)X
-1464(user.)X
-3 f
-776 4002(ruler)N
-970([off])X
-976 4092(Vi)N
-1 f
-1076(only.)X
-1278(Display)X
-1547(a)X
-1603(row/column)X
-2010(ruler)X
-2182(on)X
-2282(the)X
-2400(colon)X
-2598(command)X
-2934(line.)X
-3 f
-776 4272(scroll,)N
-1003(scr)X
-1126([window)X
-1439(/)X
-1481(2])X
-1 f
-976 4362(Set)N
-1098(the)X
-1216(number)X
-1481(of)X
-1568(lines)X
-1739(scrolled)X
-2013(by)X
-2113(the)X
-3 f
-2231(vi)X
-2313(<control-D>)X
-1 f
-2755(and)X
-3 f
-2891(<control-U>)X
-1 f
-3333(commands.)X
-976 4542(Historically,)N
-1395(the)X
-3 f
-1514(ex)X
-1611(z)X
-1 f
-1668(command,)X
-2025(when)X
-2221(speci\256ed)X
-2528(without)X
-2794(a)X
-2852(count,)X
-3072(used)X
-3241(two)X
-3383(times)X
-3578(the)X
-3698(size)X
-3845(of)X
-3934(the)X
-976 4632(scroll)N
-1174(value;)X
-1390(the)X
-1508(POSIX)X
-1759(1003.2)X
-1999(standard)X
-2291(speci\256ed)X
-2596(the)X
-2714(window)X
-2992(size,)X
-3157(which)X
-3373(is)X
-3446(a)X
-3502(better)X
-3705(choice.)X
-3 f
-776 4812(sections,)N
-1083(sect)X
-1233([NHSHH)X
-1568(HUnhsh])X
-976 4902(Vi)N
-1 f
-1076(only.)X
-1278(De\256ne)X
-1512(additional)X
-1852(section)X
-2099(boundaries)X
-2471(for)X
-2585(the)X
-3 f
-2703([[)X
-1 f
-2777(and)X
-3 f
-2913(]])X
-1 f
-2987(commands.)X
-3394(The)X
-3 f
-3540(sections)X
-1 f
-3828(option)X
-976 4992(should)N
-1213(be)X
-1313(set)X
-1426(to)X
-1512(a)X
-1572(character)X
-1892(string)X
-2098(consisting)X
-2446(of)X
-2537(zero)X
-2700(or)X
-2791(more)X
-2979(character)X
-3298(pairs.)X
-3517(In)X
-3607(the)X
-3728(text)X
-3871(to)X
-3956(be)X
-976 5082(edited,)N
-1219(the)X
-1344(character)X
-1667(string)X
-7 f
-1876(<newline>.<char-pair>)X
-1 f
-(,)S
-2932(\(where)X
-7 f
-3184(<char-pair>)X
-1 f
-3740(is)X
-3821(one)X
-3965(of)X
-976 5172(the)N
-1100(character)X
-1422(pairs)X
-1604(in)X
-1692(the)X
-1816(option's)X
-2104(value\),)X
-2351(de\256nes)X
-2604(a)X
-2666(section)X
-2918(boundary)X
-3246(in)X
-3333(the)X
-3456(same)X
-3646(manner)X
-3912(that)X
-3 f
-976 5262(paragraph)N
-1 f
-1360(option)X
-1584(boundaries)X
-1956(are)X
-2075(de\256ned.)X
-3 f
-776 5442(shell,)N
-971(sh)X
-1066([environment)X
-1549(variable)X
-1849(SHELL,)X
-2154(or)X
-2250(/bin/sh])X
-1 f
-976 5532(Select)N
-1195(the)X
-1316(shell)X
-1490(used)X
-1660(by)X
-1763(the)X
-1884(editor.)X
-2134(The)X
-2282(speci\256ed)X
-2590(path)X
-2751(is)X
-2827(the)X
-2948(pathname)X
-3283(of)X
-3373(the)X
-3495(shell)X
-3670(invoked)X
-3952(by)X
-976 5622(the)N
-3 f
-1103(vi)X
-1194(!)X
-1 f
-1270(shell)X
-1450(escape)X
-1694(command)X
-2038(and)X
-2182(by)X
-2290(the)X
-3 f
-2416(ex)X
-2520(shell)X
-1 f
-2703(command.)X
-3087(This)X
-3257(program)X
-3557(is)X
-3638(also)X
-3795(used)X
-3970(to)X
-976 5712(resolve)N
-1228(any)X
-1364(shell)X
-1535 0.2679(meta-characters)AX
-2065(in)X
-3 f
-2147(ex)X
-1 f
-2243(commands.)X
-
-51 p
-%%Page: 51 50
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-3658(USD:13-51)X
-776 762(shiftwidth,)N
-1162(sw)X
-1271([8])X
-1 f
-976 852(Set)N
-1098(the)X
-1216(autoindent)X
-1575(and)X
-1712(shift)X
-1875(command)X
-2212(indentation)X
-2593(width.)X
-2836(This)X
-2999(width)X
-3202(is)X
-3276(used)X
-3444(by)X
-3545(the)X
-3 f
-3664(autoindent)X
-1 f
-976 942(option)N
-1200(and)X
-1336(by)X
-1436(the)X
-3 f
-1554(<)X
-1 f
-1600(,)X
-3 f
-1640(>)X
-1 f
-1686(,)X
-1726(and)X
-3 f
-1862(shift)X
-1 f
-2033(commands.)X
-3 f
-776 1122(showdirty)N
-1138([off])X
-976 1212(Vi)N
-1 f
-1076(only.)X
-1278(Display)X
-1547(an)X
-1643(asterisk)X
-1908(on)X
-2008(the)X
-2126(colon)X
-2324(command)X
-2660(line)X
-2800(if)X
-2869(the)X
-2987(\256le)X
-3109(has)X
-3236(been)X
-3408(modi\256ed.)X
-3 f
-776 1392(showmatch,)N
-1203(sm)X
-1321([off])X
-976 1482(Vi)N
-1 f
-1078(only.)X
-1282(This)X
-1446(option)X
-1673(causes)X
-3 f
-1906(vi)X
-1 f
-1968(,)X
-2011(when)X
-2208(a)X
-2267(``)X
-7 f
-2321(})X
-1 f
-('')S
-2446(or)X
-2536(``)X
-7 f
-2590(\))X
-1 f
-('')S
-2715(is)X
-2791(entered,)X
-3071(to)X
-3156(brie\257y)X
-3388(move)X
-3589(the)X
-3710(cursor)X
-3934(the)X
-976 1572(matching)N
-1294(``)X
-7 f
-1348({)X
-1 f
-('')S
-1470(or)X
-1557(``)X
-7 f
-1611(\()X
-1 f
-(''.)S
-1773(See)X
-1909(the)X
-3 f
-2027(matchtime)X
-1 f
-2413(option)X
-2637(for)X
-2751(more)X
-2936(information.)X
-3 f
-776 1752(showmode)N
-1156([off])X
-976 1842(Vi)N
-1 f
-1083(only.)X
-1292(This)X
-1461(option)X
-1693(causes)X
-3 f
-1931(vi)X
-1 f
-2021(to)X
-2111(display)X
-2370(a)X
-2434(string)X
-2644(identifying)X
-3023(the)X
-3149(current)X
-3405(editor)X
-3620(mode)X
-3826(on)X
-3934(the)X
-976 1932(colon)N
-1174(command)X
-1510(line.)X
-3 f
-776 2112(sidescroll)N
-1116([16])X
-976 2202(Vi)N
-1 f
-1078(only.)X
-1282(Sets)X
-1437(the)X
-1557(number)X
-1825(of)X
-1915(columns)X
-2209(that)X
-2352(are)X
-2474(shifted)X
-2715(to)X
-2800(the)X
-2921(left)X
-3051(or)X
-3141(right,)X
-3335(when)X
-3 f
-3532(vi)X
-1 f
-3617(is)X
-3693(doing)X
-3898(left-)X
-976 2292(right)N
-1151(scrolling)X
-1455(and)X
-1595(the)X
-1717(left)X
-1848(or)X
-1939(right)X
-2114(margin)X
-2365(is)X
-2442(crossed.)X
-2747(See)X
-2887(the)X
-3 f
-3009(leftright)X
-1 f
-3314(option)X
-3542(for)X
-3660(more)X
-3849(infor-)X
-976 2382(mation.)N
-3 f
-776 2562(slowopen,)N
-1131(slow)X
-1302([off])X
-1 f
-976 2652(This)N
-1141(option)X
-1368(affects)X
-1606(the)X
-1727(display)X
-1981(algorithm)X
-2315(used)X
-2485(by)X
-3 f
-2588(vi)X
-1 f
-2650(,)X
-2693(holding)X
-2960(off)X
-3077(display)X
-3331(updating)X
-3635(during)X
-3868(input)X
-976 2742(of)N
-1063(new)X
-1217(text)X
-1357(to)X
-1439(improve)X
-1726(throughput)X
-2097(when)X
-2291(the)X
-2409(terminal)X
-2696(in)X
-2778(use)X
-2905(is)X
-2978(slow)X
-3149(and)X
-3285(unintelligent.)X
-2 f
-976 2922(This)N
-1133(option)X
-1357(is)X
-1430(not)X
-1552(yet)X
-1666(implemented.)X
-3 f
-776 3102(sourceany)N
-1143([off])X
-1 f
-976 3192(If)N
-1054(this)X
-1193(option)X
-1421(is)X
-1498(turned)X
-1727(on,)X
-3 f
-1851(vi)X
-1 f
-1937(historically)X
-2321(read)X
-2485(startup)X
-2728(\256les)X
-2886(that)X
-3031(were)X
-3213(owned)X
-3452(by)X
-3557(someone)X
-3867(other)X
-976 3282(than)N
-1142(the)X
-1268(editor)X
-1483(user.)X
-1685(See)X
-1829(the)X
-1955(section)X
-2210(entitled)X
-2478(``)X
-3 f
-2532(Startup)X
-2822(Information)X
-1 f
-3240('')X
-3321(for)X
-3442(more)X
-3634(information.)X
-976 3372(This)N
-1144(option)X
-1374(is)X
-1453(a)X
-1516(security)X
-1797(problem)X
-2091(of)X
-2185(immense)X
-2501(proportions,)X
-2917(and)X
-3060(should)X
-3300(not)X
-3429(be)X
-3532(used)X
-3706(under)X
-3916(any)X
-976 3462(circumstances.)N
-2 f
-976 3642(This)N
-1133(option)X
-1357(will)X
-1496(never)X
-1695(be)X
-1791(implemented.)X
-3 f
-776 3822(tabstop,)N
-1069(ts)X
-1147([8])X
-1 f
-976 3912(This)N
-1138(option)X
-1362(sets)X
-1502(tab)X
-1620(widths)X
-1853(for)X
-1967(the)X
-2085(editor)X
-2292(display.)X
-3 f
-776 4092(taglength,)N
-1136(tl)X
-1205([0])X
-1 f
-976 4182(This)N
-1148(option)X
-1383(sets)X
-1534(the)X
-1663(maximum)X
-2018(number)X
-2294(of)X
-2392(characters)X
-2750(that)X
-2901(are)X
-3031(considered)X
-3410(signi\256cant)X
-3774(in)X
-3867(a)X
-3934(tag)X
-976 4272(name.)N
-1210(Setting)X
-1456(the)X
-1574(value)X
-1768(to)X
-1850(0)X
-1910(makes)X
-2135(all)X
-2235(of)X
-2322(the)X
-2440(characters)X
-2787(in)X
-2869(the)X
-2987(tag)X
-3105(name)X
-3299(signi\256cant.)X
-3 f
-776 4452(tags,)N
-954(tag)X
-1081([tags)X
-1266(/var/db/libc.tags)X
-1838(/sys/kern/tags])X
-1 f
-976 4542(Sets)N
-1129(the)X
-1247(list)X
-1364(of)X
-1451(tags)X
-1600(\256les,)X
-1773(in)X
-1855(search)X
-2081(order,)X
-2291(which)X
-2507(are)X
-2626(used)X
-2793(when)X
-2987(the)X
-3105(editor)X
-3312(searches)X
-3605(for)X
-3719(a)X
-3775(tag.)X
-3 f
-776 4722(term,)N
-982(ttytype,)X
-1263(tty)X
-1377([environment)X
-1860(variable)X
-2160(TERM])X
-1 f
-976 4812(Set)N
-1101(the)X
-1223(terminal)X
-1514(type.)X
-1716(Setting)X
-1966(this)X
-2105(option)X
-2333(causes)X
-3 f
-2567(ex)X
-1 f
-2643(/)X
-3 f
-2665(vi)X
-1 f
-2751(to)X
-2837(set)X
-2950(\(or)X
-3068(reset\))X
-3271(the)X
-3393(environmental)X
-3880(vari-)X
-976 4902(able)N
-7 f
-1130(TERM)X
-1 f
-(.)S
-3 f
-776 5082(terse)N
-962([off])X
-1 f
-976 5172(This)N
-1142(option)X
-1370(has)X
-1501(historically)X
-1885(made)X
-2083(editor)X
-2294(messages)X
-2621(less)X
-2765(verbose.)X
-3079(It)X
-3152(has)X
-3283(no)X
-3387(effect)X
-3596(in)X
-3683(this)X
-3823(imple-)X
-976 5262(mentation.)N
-1356(See)X
-1492(the)X
-3 f
-1610(verbose)X
-1 f
-1893(option)X
-2117(for)X
-2231(more)X
-2416(information.)X
-3 f
-776 5442(tildeop)N
-1 f
-976 5532(Modify)N
-1236(the)X
-3 f
-1354(\304)X
-1 f
-1401(command)X
-1737(to)X
-1819(take)X
-1973(an)X
-2069(associated)X
-2419(motion.)X
-3 f
-776 5712(timeout,)N
-1079(to)X
-1166([on])X
-1 f
-976 5802(If)N
-1057(this)X
-1199(option)X
-1431(is)X
-1512(set,)X
-3 f
-1649(ex)X
-1 f
-1725(/)X
-3 f
-1747(vi)X
-1 f
-1837(waits)X
-2034(for)X
-2156(a)X
-2220(speci\256c)X
-2493(period)X
-2726(for)X
-2848(a)X
-2912(subsequent)X
-3296(key)X
-3440(to)X
-3530(complete)X
-3852(a)X
-3916(key)X
-
-52 p
-%%Page: 52 51
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-52)N
-3391(Nvi/Nex)X
-3687 0.3906(Reference)AX
-1 f
-976 762(mapping)N
-1282(\(see)X
-1438(the)X
-3 f
-1561(keytime)X
-1 f
-1858(option\).)X
-2154(If)X
-2233(the)X
-2356(option)X
-2585(is)X
-2663(not)X
-2790(set,)X
-2924(the)X
-3047(editor)X
-3259(waits)X
-3453(until)X
-3624(enough)X
-3885(keys)X
-976 852(are)N
-1095(entered)X
-1352(to)X
-1434(resolve)X
-1686(the)X
-1804(ambiguity,)X
-2168(regardless)X
-2514(of)X
-2601(how)X
-2759(long)X
-2921(it)X
-2985(takes.)X
-3 f
-776 1032(ttywerase)N
-1127([off])X
-976 1122(Vi)N
-1 f
-1082(only.)X
-1290(This)X
-1458(option)X
-1688(changes)X
-1973(how)X
-3 f
-2137(vi)X
-1 f
-2225(does)X
-2398(word)X
-2589(erase)X
-2781(during)X
-3016(text)X
-3162(input.)X
-3392(If)X
-3472(this)X
-3613(option)X
-3843(is)X
-3923(set,)X
-976 1212(text)N
-1123(is)X
-1203(broken)X
-1452(up)X
-1558(into)X
-1708(two)X
-1854(classes,)X
-2123(blank)X
-2327(characters)X
-2680(and)X
-2822(nonblank)X
-3146(characters.)X
-3539(Changing)X
-3876(from)X
-976 1302(one)N
-1112(class)X
-1288(to)X
-1370(another)X
-1631(marks)X
-1847(the)X
-1965(end)X
-2101(of)X
-2188(a)X
-2244(word.)X
-3 f
-776 1482(verbose)N
-1059([off])X
-976 1572(Vi)N
-1 f
-1078(only.)X
-3 f
-1282(Vi)X
-1 f
-1384(historically)X
-1766(bells)X
-1939(the)X
-2059(terminal)X
-2348(for)X
-2464(many)X
-2665(obvious)X
-2941(mistakes,)X
-3264(e.g.)X
-3403(trying)X
-3617(to)X
-3702(move)X
-3903(past)X
-976 1662(the)N
-1108(left-hand)X
-1432(margin,)X
-1713(or)X
-1814(past)X
-1977(the)X
-2109(end)X
-2259(of)X
-2360(the)X
-2492(\256le.)X
-2668(If)X
-2756(this)X
-2905(option)X
-3143(is)X
-3230(set,)X
-3373(an)X
-3483(error)X
-3674(message)X
-3979(is)X
-976 1752(displayed)N
-1303(for)X
-1417(all)X
-1517(errors.)X
-3 f
-776 1932(w300)N
-974([no)X
-1105(default])X
-976 2022(Vi)N
-1 f
-1080(only.)X
-1286(Set)X
-1412(the)X
-1534(window)X
-1816(size)X
-1965(if)X
-2038(the)X
-2160(baud)X
-2340(rate)X
-2485(is)X
-2562(less)X
-2706(than)X
-2868(1200)X
-3052(baud.)X
-3273(See)X
-3414(the)X
-3 f
-3537(window)X
-1 f
-3828(option)X
-976 2112(for)N
-1090(more)X
-1275(information.)X
-3 f
-776 2292(w1200)N
-1014([no)X
-1145(default])X
-976 2382(Vi)N
-1 f
-1081(only.)X
-1288(Set)X
-1415(the)X
-1538(window)X
-1821(size)X
-1971(if)X
-2045(the)X
-2168(baud)X
-2349(rate)X
-2495(is)X
-2574(equal)X
-2774(to)X
-2862(1200)X
-3048(baud.)X
-3270(See)X
-3412(the)X
-3 f
-3536(window)X
-1 f
-3828(option)X
-976 2472(for)N
-1090(more)X
-1275(information.)X
-3 f
-776 2652(w9600)N
-1014([no)X
-1145(default])X
-976 2742(Vi)N
-1 f
-1087(only.)X
-1300(Set)X
-1433(the)X
-1562(window)X
-1851(size)X
-2007(if)X
-2087(the)X
-2216(baud)X
-2404(rate)X
-2557(is)X
-2642(greater)X
-2898(than)X
-3068(1200)X
-3260(baud.)X
-3488(See)X
-3636(the)X
-3 f
-3766(window)X
-1 f
-976 2832(option)N
-1200(for)X
-1314(more)X
-1499(information.)X
-3 f
-776 3012(warn)N
-974([on])X
-976 3102(Ex)N
-1 f
-1094(only.)X
-1302(This)X
-1470(option)X
-1700(causes)X
-1936(a)X
-1998(warning)X
-2287(message)X
-2585(to)X
-2673(the)X
-2797(terminal)X
-3090(if)X
-3165(the)X
-3289(\256le)X
-3417(has)X
-3550(been)X
-3728(modi\256ed,)X
-976 3192(since)N
-1161(it)X
-1225(was)X
-1370(last)X
-1501(written,)X
-1768(before)X
-1994(a)X
-3 f
-2050(!)X
-1 f
-2117(command.)X
-3 f
-776 3372(window,)N
-1082(w,)X
-1180(wi)X
-1280([environment)X
-1763(variable)X
-2063(LINES])X
-1 f
-976 3462(This)N
-1148(option)X
-1382(determines)X
-1764(the)X
-1892(default)X
-2145(number)X
-2420(of)X
-2517(lines)X
-2698(in)X
-2791(a)X
-2858(screenful,)X
-3204(as)X
-3302(written)X
-3560(by)X
-3671(the)X
-3 f
-3800(z)X
-1 f
-3867(com-)X
-976 3552(mand.)N
-1221(It)X
-1297(also)X
-1453(determines)X
-1832(the)X
-1957(number)X
-2229(of)X
-2323(lines)X
-2501(scrolled)X
-2782(by)X
-2889(the)X
-3 f
-3014(vi)X
-1 f
-3103(commands)X
-3 f
-3477(<control-F>)X
-1 f
-3916(and)X
-3 f
-976 3642(<control-B>)N
-1 f
-1393(.)X
-1457(The)X
-1606(value)X
-1804(of)X
-1895(window)X
-2177(can)X
-2313(be)X
-2413(unrelated)X
-2736(to)X
-2822(the)X
-2944(real)X
-3089(screen)X
-3319(size,)X
-3489(although)X
-3794(it)X
-3863(starts)X
-976 3732(out)N
-1110(as)X
-1209(the)X
-1338(number)X
-1614(of)X
-1712(lines)X
-1894(on)X
-2005(the)X
-2134(screen)X
-2371(\(see)X
-2532(the)X
-2661(section)X
-2919(entitled)X
-3190(``)X
-3 f
-3244(Sizing)X
-3483(the)X
-3621(Screen)X
-1 f
-3853('')X
-3938(for)X
-976 3822(more)N
-1165(information\).)X
-1634(Setting)X
-1884(the)X
-2006(value)X
-2204(of)X
-2295(the)X
-3 f
-2417(window)X
-1 f
-2707(option)X
-2935(is)X
-3012(the)X
-3135(same)X
-3325(as)X
-3417(using)X
-3615(the)X
-3 f
-9 f
-3738(-)X
-3740(-)X
-3 f
-3784(w)X
-1 f
-3867(com-)X
-976 3912(mand)N
-1174(line)X
-1314(option.)X
-976 4092(If)N
-1055(the)X
-1178(value)X
-1377(of)X
-1469(the)X
-3 f
-1592(window)X
-1 f
-1883(option)X
-2112(\(as)X
-2231(set)X
-2345(by)X
-2450(the)X
-3 f
-2574(window)X
-1 f
-2840(,)X
-3 f
-2886(w300)X
-1 f
-3064(,)X
-3 f
-3110(w1200)X
-1 f
-3354(or)X
-3 f
-3447(w9600)X
-1 f
-3691(options\))X
-3979(is)X
-976 4182(smaller)N
-1233(than)X
-1391(the)X
-1509(actual)X
-1721(size)X
-1866(of)X
-1953(the)X
-2071(screen,)X
-2317(large)X
-2498(screen)X
-2724(movements)X
-3113(will)X
-3257(result)X
-3455(in)X
-3537(displaying)X
-3890(only)X
-976 4272(that)N
-1116(smaller)X
-1373(number)X
-1639(of)X
-1727(lines)X
-1899(on)X
-2000(the)X
-2119(screen.)X
-2386(\(Further)X
-2670(movements)X
-3060(in)X
-3143(that)X
-3284(same)X
-3470(area)X
-3626(will)X
-3771(result)X
-3970(in)X
-976 4362(the)N
-1097(screen)X
-1325(being)X
-1525(\256lled.\))X
-1778(This)X
-1942(can)X
-2076(provide)X
-2343(a)X
-2401(performance)X
-2830(improvement)X
-3279(when)X
-3475(viewing)X
-3755(different)X
-976 4452(places)N
-1197(in)X
-1279(one)X
-1415(or)X
-1502(more)X
-1687(\256les)X
-1840(over)X
-2003(a)X
-2059(slow)X
-2230(link.)X
-3 f
-776 4632(wrapmargin,)N
-1243(wm)X
-1388([0])X
-976 4722(Vi)N
-1 f
-1077(only.)X
-1280(If)X
-1356(the)X
-1476(value)X
-1672(of)X
-1761(the)X
-3 f
-1881(wrapmargin)X
-1 f
-2330(option)X
-2556(is)X
-2631(non-zero,)X
-3 f
-2959(vi)X
-1 f
-3043(will)X
-3189(split)X
-3348(lines)X
-3521(so)X
-3614(that)X
-3756(they)X
-3916(end)X
-976 4812(at)N
-1057(least)X
-1227(that)X
-1370(number)X
-1638(of)X
-1728(characters)X
-2078(before)X
-2307(the)X
-2428(right-hand)X
-2785(margin)X
-3035(of)X
-3125(the)X
-3245(screen.)X
-3513(\(Note,)X
-3738(the)X
-3858(value)X
-976 4902(of)N
-3 f
-1063(wrapmargin)X
-1 f
-1510(is)X
-2 f
-1583(not)X
-1 f
-1705(a)X
-1761(text)X
-1901(length.)X
-2161(In)X
-2248(a)X
-2304(screen)X
-2530(that)X
-2670(is)X
-2743(80)X
-2843(columns)X
-3134(wide,)X
-3330(the)X
-3449(command)X
-3786(``)X
-7 f
-3840(:set)X
-976 4992(wrapmargin=8)N
-1 f
-('')S
-1626(attempts)X
-1917(to)X
-1999(keep)X
-2171(the)X
-2289(lines)X
-2460(less)X
-2600(than)X
-2758(or)X
-2845(equal)X
-3039(to)X
-3121(72)X
-3221(columns)X
-3512(wide.\))X
-976 5172(Lines)N
-1181(are)X
-1307(split)X
-1471(at)X
-1556(the)X
-1681(previous)X
-1984(whitespace)X
-2368(character)X
-2691(closest)X
-2936(to)X
-3025(the)X
-3150(number.)X
-3462(Any)X
-3627(trailing)X
-3885(whi-)X
-976 5262(tespace)N
-1239(characters)X
-1592(before)X
-1824(that)X
-1970(character)X
-2292(are)X
-2417(deleted.)X
-2715(If)X
-2795(the)X
-2919(line)X
-3065(is)X
-3143(split)X
-3305(because)X
-3585(of)X
-3677(an)X
-3778(inserted)X
-7 f
-976 5352(<space>)N
-1 f
-1346(or)X
-7 f
-1447(<tab>)X
-1 f
-1721(character,)X
-2072(and)X
-2223(you)X
-2378(then)X
-2551(enter)X
-2747(another)X
-7 f
-3023(<space>)X
-1 f
-3394(character,)X
-3745(it)X
-3824(is)X
-3912(dis-)X
-976 5442(carded.)N
-976 5622(If)N
-1052(wrapmargin)X
-1462(is)X
-1537(set)X
-1648(to)X
-1732(0,)X
-1815(or)X
-1905(if)X
-1977(there)X
-2161(is)X
-2237(no)X
-2340(blank)X
-2541(character)X
-2860(upon)X
-3043(which)X
-3262(to)X
-3347(split)X
-3507(the)X
-3628(line,)X
-3791(the)X
-3912(line)X
-976 5712(is)N
-1049(not)X
-1171(broken.)X
-
-53 p
-%%Page: 53 52
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-3658(USD:13-53)X
-776 762(wrapscan,)N
-1145(ws)X
-1254([on])X
-1 f
-976 852(This)N
-1138(option)X
-1362(causes)X
-1592(searches)X
-1885(to)X
-1967(wrap)X
-2148(around)X
-2391(the)X
-2509(end)X
-2645(or)X
-2732(the)X
-2850(beginning)X
-3191(of)X
-3279(the)X
-3398(\256le,)X
-3541(and)X
-3678(back)X
-3851(to)X
-3934(the)X
-976 942(starting)N
-1236(point.)X
-1460(Otherwise,)X
-1830(the)X
-1948(end)X
-2084(or)X
-2171(beginning)X
-2511(of)X
-2598(the)X
-2716(\256le)X
-2838(terminates)X
-3192(the)X
-3310(search.)X
-3 f
-776 1122(writeany,)N
-1119(wa)X
-1237([off])X
-1 f
-976 1212(If)N
-1056(this)X
-1197(option)X
-1427(is)X
-1506(set,)X
-1641(\256le-overwriting)X
-2170(checks)X
-2416(that)X
-2563(would)X
-2790(usually)X
-3048(be)X
-3151(made)X
-3352(before)X
-3585(the)X
-3 f
-3710(write)X
-1 f
-3916(and)X
-3 f
-976 1302(xit)N
-1 f
-1094(commands,)X
-1490(or)X
-1586(before)X
-1821(an)X
-1926(automatic)X
-2271(write)X
-2465(\(see)X
-2624(the)X
-3 f
-2751(autowrite)X
-1 f
-3110(option\),)X
-3390(are)X
-3518(not)X
-3648(made.)X
-3890(This)X
-976 1392(allows)N
-1205(a)X
-1261(write)X
-1446(to)X
-1528(any)X
-1664(\256le,)X
-1806(provided)X
-2111(the)X
-2229(\256le)X
-2351(permissions)X
-2753(allow)X
-2951(it.)X
-3 f
-776 1578(16.)N
-916(Additional)X
-1299(Features)X
-1618(in)X
-1704(Nex/Nvi)X
-1 f
-976 1701(There)N
-1190(are)X
-1315(a)X
-1377(few)X
-1524(features)X
-1805(in)X
-3 f
-1894(nex)X
-1 f
-(/)S
-3 f
-2036(nvi)X
-1 f
-2169(that)X
-2316(are)X
-2442(not)X
-2571(found)X
-2785(in)X
-2874(historic)X
-3141(versions)X
-3435(of)X
-3 f
-3529(ex)X
-1 f
-3605(/)X
-3 f
-3627(vi)X
-1 f
-3689(.)X
-3756(Some)X
-3965(of)X
-776 1791(the)N
-894(more)X
-1079(interesting)X
-1437(of)X
-1524(those)X
-1713(features)X
-1988(are)X
-2107(as)X
-2194(follows:)X
-3 f
-776 1971(8-bit)N
-956(clean)X
-1154(data,)X
-1345(large)X
-1539(lines,)X
-1734(\256les)X
-976 2061(Nex)N
-1 f
-1110(/)X
-3 f
-1132(nvi)X
-1 f
-1260(will)X
-1407(edit)X
-1550(any)X
-1689(format)X
-1926(\256le.)X
-2091(Line)X
-2261(lengths)X
-2515(are)X
-2637(limited)X
-2886(by)X
-2989(available)X
-3302(memory,)X
-3612(and)X
-3751(\256le)X
-3876(sizes)X
-976 2151(are)N
-1099(limited)X
-1349(by)X
-1453(available)X
-1767(disk)X
-1924(space.)X
-2167(The)X
-3 f
-2316(vi)X
-1 f
-2402(text)X
-2546(input)X
-2734(mode)X
-2935(command)X
-3 f
-3274(<control-X>)X
-1 f
-3719(can)X
-3854(insert)X
-976 2241(any)N
-1112(possible)X
-1394(character)X
-1710(value)X
-1904(into)X
-2048(the)X
-2166(text.)X
-3 f
-776 2421(Split)N
-955(screens)X
-1 f
-976 2511(The)N
-3 f
-1127(split)X
-1 f
-1299(command)X
-1641(divides)X
-1898(the)X
-2022(screen)X
-2254(into)X
-2404(multiple)X
-2696(editing)X
-2944(regions.)X
-3246(The)X
-3 f
-3397(<control-W>)X
-1 f
-3867(com-)X
-976 2601(mand)N
-1183(rotates)X
-1426(between)X
-1723(the)X
-1850(foreground)X
-2236(screens.)X
-2541(The)X
-3 f
-2694(resize)X
-1 f
-2919(command)X
-3263(can)X
-3403(be)X
-3507(used)X
-3682(to)X
-3772(grow)X
-3965(or)X
-976 2691(shrink)N
-1196(a)X
-1252(particular)X
-1580(screen.)X
-3 f
-776 2871(Background)N
-1217(and)X
-1365(foreground)X
-1772(screens)X
-1 f
-976 2961(The)N
-3 f
-1134(bg)X
-1 f
-1251(command)X
-1600(backgrounds)X
-2044(the)X
-2176(current)X
-2438(screen,)X
-2698(and)X
-2848(the)X
-3 f
-2980(fg)X
-1 f
-3081(command)X
-3431(foregrounds)X
-3853(back-)X
-976 3051(grounded)N
-1299(screens.)X
-1596(The)X
-3 f
-1741(display)X
-1 f
-2004(command)X
-2340(can)X
-2472(be)X
-2568(used)X
-2735(to)X
-2817(list)X
-2934(the)X
-3052(background)X
-3451(screens.)X
-3 f
-776 3231(Tag)N
-929(stacks)X
-1 f
-976 3321(Tags)N
-1159(are)X
-1285(now)X
-1450(maintained)X
-1834(in)X
-1924(a)X
-1988(stack.)X
-2221(The)X
-3 f
-2374(<control-T>)X
-1 f
-2819(command)X
-3163(returns)X
-3414(to)X
-3504(the)X
-3630(previous)X
-3934(tag)X
-976 3411(location.)N
-1299(The)X
-3 f
-1449(tagpop)X
-1 f
-1709(command)X
-2050(returns)X
-2298(to)X
-2385(the)X
-2508(most)X
-2688(recent)X
-2910(tag)X
-3033(location)X
-3316(by)X
-3421(default,)X
-3689(or,)X
-3801(option-)X
-976 3501(ally)N
-1119(to)X
-1204(a)X
-1263(speci\256c)X
-1531(tag)X
-1652(number)X
-1920(in)X
-2005(the)X
-2126(tag)X
-2248(stack,)X
-2457(or)X
-2548(the)X
-2670(most)X
-2849(recent)X
-3070(tag)X
-3192(from)X
-3372(a)X
-3432(speci\256ed)X
-3741(\256le.)X
-3907(The)X
-3 f
-976 3591(display)N
-1 f
-1241(command)X
-1579(can)X
-1713(be)X
-1810(used)X
-1978(to)X
-2061(list)X
-2179(the)X
-2298(tags)X
-2448(stack.)X
-2674(The)X
-3 f
-2820(tagtop)X
-1 f
-3059(command)X
-3396(returns)X
-3640(to)X
-3723(the)X
-3842(top)X
-3965(of)X
-976 3681(the)N
-1094(tag)X
-1212(stack.)X
-3 f
-776 3861(New)N
-948(displays)X
-1 f
-976 3951(The)N
-3 f
-1128(display)X
-1 f
-1398(command)X
-1741(can)X
-1880(be)X
-1984(used)X
-2159(to)X
-2249(display)X
-2508(the)X
-2634(current)X
-2890(buffers,)X
-3166(the)X
-3292(backgrounded)X
-3775(screens,)X
-976 4041(and)N
-1112(the)X
-1230(tags)X
-1379(stack.)X
-3 f
-776 4221(In\256nite)N
-1044(undo)X
-1 f
-976 4311(Changes)N
-1282(made)X
-1486(during)X
-1725(an)X
-1832(edit)X
-1983(session)X
-2245(may)X
-2414(be)X
-2521(rolled)X
-2739(backward)X
-3083(and)X
-3230(forward.)X
-3556(A)X
-3 f
-3645(.)X
-1 f
-3716(command)X
-976 4401(immediately)N
-1403(after)X
-1578(a)X
-3 f
-1640(u)X
-1 f
-1710(command)X
-2052(continues)X
-2385(either)X
-2594(forward)X
-2875(or)X
-2968(backward)X
-3307(depending)X
-3667(on)X
-3773(whether)X
-976 4491(the)N
-3 f
-1094(u)X
-1 f
-1158(command)X
-1494(was)X
-1639(an)X
-1735(undo)X
-1915(or)X
-2002(a)X
-2058(redo.)X
-3 f
-776 4671(Usage)N
-1001(information)X
-1 f
-976 4761(The)N
-3 f
-1126(exusage)X
-1 f
-1418(and)X
-3 f
-1559(viusage)X
-1 f
-1837(commands)X
-2209(provide)X
-2479(usage)X
-2688(information)X
-3092(for)X
-3212(all)X
-3318(of)X
-3411(the)X
-3 f
-3535(ex)X
-1 f
-3637(and)X
-3 f
-3779(vi)X
-1 f
-3867(com-)X
-976 4851(mands)N
-1205(by)X
-1305(default,)X
-1568(or,)X
-1675(optionally,)X
-2039(for)X
-2153(a)X
-2209(speci\256c)X
-2474(command)X
-2810(or)X
-2897(key.)X
-3 f
-776 5031(Extended)N
-1120(Regular)X
-1416(Expressions)X
-1 f
-976 5121(The)N
-3 f
-1133(extended)X
-1 f
-1472(option)X
-1708(causes)X
-1950(Regular)X
-2237(Expressions)X
-2657(to)X
-2752(be)X
-2861(interpreted)X
-3242(as)X
-3342(as)X
-3442(Extended)X
-3778(Regular)X
-976 5211(Expressions,)N
-1403(\(i.e.)X
-2 f
-1548(egrep)X
-1 f
-1731(\(1\))X
-1845(style)X
-2016(Regular)X
-2290(Expressions\).)X
-3 f
-776 5391(Word)N
-996(search)X
-1 f
-976 5481(The)N
-3 f
-1121(<control-A>)X
-1 f
-1563(command)X
-1899(searches)X
-2192(for)X
-2306(the)X
-2424(word)X
-2609 0.4028(referenced)AX
-2970(by)X
-3070(the)X
-3188(cursor.)X
-3 f
-776 5661(Number)N
-1081(increment)X
-1 f
-976 5751(The)N
-3 f
-1121(#)X
-1 f
-1181(command)X
-1517(increments)X
-1889(or)X
-1976(decrements)X
-2362(the)X
-2480(number)X
-2745 0.4028(referenced)AX
-3106(by)X
-3206(the)X
-3324(cursor.)X
-
-54 p
-%%Page: 54 53
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-54)N
-3391(Nvi/Nex)X
-3687 0.3906(Reference)AX
-776 762(Previous)N
-1094(\256le)X
-1 f
-976 852(The)N
-3 f
-1121(previous)X
-1 f
-1434(command)X
-1770(edits)X
-1941(the)X
-2059(previous)X
-2355(\256le)X
-2477(from)X
-2653(the)X
-2771(argument)X
-3094(list.)X
-3 f
-776 1032(Left-right)N
-1135(scrolling)X
-1 f
-976 1122(The)N
-3 f
-1130(leftright)X
-1 f
-1440(option)X
-1673(causes)X
-3 f
-1912(nvi)X
-1 f
-2047(to)X
-2138(do)X
-2248(left-right)X
-2563(screen)X
-2799(scrolling,)X
-3129(instead)X
-3386(of)X
-3483(the)X
-3611(traditional)X
-3 f
-3970(vi)X
-1 f
-976 1212(line)N
-1116(wrapping.)X
-
-55 p
-%%Page: 55 54
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(Nvi/Nex)N
-872 0.3906(Reference)AX
-3658(USD:13-55)X
-776 762(17.)N
-916(Index)X
-1 f
-776 885(.)N
-1549(18)X
-776 975(!)N
-1429(15,)X
-1549(34)X
-776 1065("")N
-1549(34)X
-776 1155(#)N
-1429(16,)X
-1549(35)X
-776 1245($)N
-1549(16)X
-776 1335(%)N
-1549(16)X
-776 1425(&)N
-1429(17,)X
-1549(42)X
-776 1515(\()N
-1549(17)X
-776 1605(\))N
-1549(17)X
-776 1695(*)N
-1549(35)X
-776 1785(+)N
-1549(13)X
-776 1875(,)N
-1549(18)X
-776 1965(/RE/)N
-1549(18)X
-776 2055(0)N
-1549(19)X
-776 2145(0<control-D>)N
-1549(31)X
-776 2235(:)N
-1549(19)X
-776 2325(;)N
-1549(19)X
-776 2415(<)N
-1429(20,)X
-1549(35)X
-776 2505(<control-A>)N
-1549(11)X
-776 2595(<control-B>)N
-1549(11)X
-776 2685(<control-D>)N
-1429(12,)X
-1549(31)X
-776 2775(<control-E>)N
-1549(12)X
-776 2865(<control-F>)N
-1549(12)X
-776 2955(<control-G>)N
-1549(12)X
-776 3045(<control-H>)N
-1429(12,)X
-1549(31)X
-776 3135(<control-J>)N
-1549(13)X
-776 3225(<control-L>)N
-1549(13)X
-776 3315(<control-M>)N
-1549(13)X
-776 3405(<control-N>)N
-1549(13)X
-776 3495(<control-P>)N
-1549(13)X
-776 3585(<control-R>)N
-1549(13)X
-776 3675(<control-T>)N
-1429(14,)X
-1549(31)X
-776 3765(<control-U>)N
-1549(14)X
-776 3855(<control-W>)N
-1429(14,)X
-1549(31)X
-776 3945(<control-X>)N
-1549(31)X
-776 4035(<control-Y>)N
-1549(14)X
-776 4125(<control-Z>)N
-1429(14,)X
-1549(43)X
-776 4215(<control-]>)N
-1549(15)X
-776 4305(<control-\303>)N
-1549(15)X
-776 4395(<end-of-\256le>)N
-1549(34)X
-776 4485(<eof>)N
-1549(33)X
-776 4575(<erase>)N
-1549(31)X
-776 4665(<escape>)N
-1429(14,)X
-1549(31)X
-776 4755(<interrupt>)N
-1349(7,)X
-1429(30,)X
-1549(31)X
-776 4845(<line)N
-961(erase>)X
-1549(31)X
-776 4935(<literal)N
-1028(next>)X
-1469(7,)X
-1549(31)X
-776 5025(<nul>)N
-1549(30)X
-776 5115(<space>)N
-1549(15)X
-776 5205(<word)N
-1006(erase>)X
-1549(31)X
-776 5295(=)N
-1549(35)X
-776 5385(>)N
-1429(20,)X
-1549(35)X
-776 5475(?RE?)N
-1549(18)X
-776 5565(@)N
-1429(20,)X
-1549(35)X
-776 5655(A)N
-1549(20)X
-776 5745(B)N
-1549(20)X
-2077 885(C)N
-2850(21)X
-2077 975(D)N
-2850(21)X
-2077 1065(E)N
-2850(21)X
-2077 1155(F)N
-2850(21)X
-2077 1245(G)N
-2850(21)X
-2077 1335(H)N
-2850(21)X
-2077 1425(I)N
-2850(22)X
-2077 1515(J)N
-2850(22)X
-2077 1605(L)N
-2850(22)X
-2077 1695(M)N
-2850(22)X
-2077 1785(N)N
-2850(18)X
-2077 1875(O)N
-2850(22)X
-2077 1965(P)N
-2850(23)X
-2077 2055(Q)N
-2850(23)X
-2077 2145(R)N
-2850(23)X
-2077 2235(S)N
-2850(23)X
-2077 2325(T)N
-2850(23)X
-2077 2415(U)N
-2850(23)X
-2077 2505(W)N
-2850(24)X
-2077 2595(X)N
-2850(24)X
-2077 2685(Y)N
-2850(24)X
-2077 2775(ZZ)N
-2850(24)X
-2077 2865([[)N
-2850(24)X
-9 f
-2077 2955(-)N
-1 f
-2850(18)X
-2077 3045(]])N
-2850(25)X
-2077 3135(\303)N
-2850(25)X
-2077 3225(\303<control-D>)N
-2850(31)X
-2077 3315(_)N
-2850(25)X
-2077 3405 0.2841(`<character>)AN
-2850(17)X
-2077 3495(a)N
-2850(25)X
-2077 3585(abbrev)N
-2850(35)X
-2077 3675(alternate)N
-2374(pathname)X
-2890(8)X
-2077 3765(altwerase)N
-2850(46)X
-2077 3855(append)N
-2850(36)X
-2077 3945(args)N
-2850(36)X
-2077 4035(autoindent)N
-2850(46)X
-2077 4125(autoprint)N
-2850(46)X
-2077 4215(autowrite)N
-2850(47)X
-2077 4305(b)N
-2850(25)X
-2077 4395(beautify)N
-2850(47)X
-2077 4485(bg)N
-2850(36)X
-2077 4575(bigword)N
-2850(10)X
-2077 4665(buffer)N
-2890(8)X
-2077 4755(c)N
-2850(26)X
-2077 4845(cd)N
-2850(36)X
-2077 4935(cdpath)N
-2850(47)X
-2077 5025(change)N
-2850(36)X
-2077 5115(chdir)N
-2850(36)X
-2077 5205(columns)N
-2850(47)X
-2077 5295(comment)N
-2850(47)X
-2077 5385(copy)N
-2850(36)X
-2077 5475(count)N
-2730(10,)X
-2850(33)X
-2077 5565(current)N
-2325(pathname)X
-2890(8)X
-2077 5655(d)N
-2850(26)X
-2077 5745(delete)N
-2850(37)X
-3378 885(directory)N
-4151(47)X
-3378 975(display)N
-4151(37)X
-3378 1065(e)N
-4151(26)X
-3378 1155(edcompatible)N
-4151(47)X
-3378 1245(edit)N
-4151(37)X
-3378 1335(errorbells)N
-4151(47)X
-3378 1425(exrc)N
-4151(47)X
-3378 1515(extended)N
-4151(48)X
-3378 1605(exusage)N
-4151(37)X
-3378 1695(f)N
-4151(26)X
-3378 1785(fg)N
-4151(37)X
-3378 1875(\256le)N
-4031(33,)X
-4151(37)X
-3378 1965(\257ags)N
-4151(33)X
-3378 2055(\257ash)N
-4151(48)X
-3378 2145(global)N
-4151(38)X
-3378 2235(hardtabs)N
-4151(48)X
-3378 2325(help)N
-4151(38)X
-3378 2415(i)N
-4151(26)X
-3378 2505(ignorecase)N
-4151(48)X
-3378 2595(insert)N
-4151(38)X
-3378 2685(j)N
-4151(13)X
-3378 2775(join)N
-4151(38)X
-3378 2865(k)N
-4031(13,)X
-4151(39)X
-3378 2955(keytime)N
-4151(48)X
-3378 3045(l)N
-4151(15)X
-3378 3135(leftright)N
-4151(48)X
-3378 3225(line)N
-4151(33)X
-3378 3315(lines)N
-4151(48)X
-3378 3405(lisp)N
-4151(48)X
-3378 3495(list)N
-4031(39,)X
-4151(48)X
-3378 3585(m)N
-4151(27)X
-3378 3675(magic)N
-4151(48)X
-3378 3765(map)N
-4151(39)X
-3378 3855(mark)N
-4151(39)X
-3378 3945(matchtime)N
-4151(48)X
-3378 4035(mesg)N
-4151(48)X
-3378 4125(mkexrc)N
-4151(39)X
-3378 4215(modelines)N
-4151(49)X
-3378 4305(motion)N
-4151(10)X
-3378 4395(move)N
-4151(39)X
-3378 4485(n)N
-4151(18)X
-3378 4575(next)N
-4151(40)X
-3378 4665(number)N
-4031(35,)X
-4151(49)X
-3378 4755(o)N
-4151(27)X
-3378 4845(octal)N
-4151(49)X
-3378 4935(open)N
-4031(40,)X
-4151(49)X
-3378 5025(optimize)N
-4151(49)X
-3378 5115(p)N
-4151(27)X
-3378 5205(paragraph)N
-4151(11)X
-3378 5295(paragraphs)N
-4151(49)X
-3378 5385(preserve)N
-4151(40)X
-3378 5475(previous)N
-4151(40)X
-3378 5565(previous)N
-3674(context)X
-4191(9)X
-3378 5655(print)N
-4151(40)X
-3378 5745(prompt)N
-4151(49)X
-
-56 p
-%%Page: 56 55
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-56)N
-3391(Nvi/Nex)X
-3687 0.3906(Reference)AX
-1 f
-776 762(put)N
-1549(40)X
-776 852(quit)N
-1549(41)X
-776 942(r)N
-1549(27)X
-776 1032(range)N
-1549(33)X
-776 1122(read)N
-1549(41)X
-776 1212(readonly)N
-1549(49)X
-776 1302(recdir)N
-1549(49)X
-776 1392(recover)N
-1549(41)X
-776 1482(redraw)N
-1549(50)X
-776 1572(remap)N
-1549(50)X
-776 1662(report)N
-1549(50)X
-776 1752(resize)N
-1549(41)X
-776 1842(rewind)N
-1549(41)X
-776 1932(ruler)N
-1549(50)X
-776 2022(s)N
-1549(27)X
-776 2112(scroll)N
-1549(50)X
-776 2202(section)N
-1549(11)X
-776 2292(sections)N
-1549(50)X
-776 2382(sentence)N
-1549(11)X
-776 2472(set)N
-1549(41)X
-776 2562(shell)N
-1429(42,)X
-1549(50)X
-776 2652(shiftwidth)N
-1549(50)X
-776 2742(showdirty)N
-1549(51)X
-776 2832(showmatch)N
-1549(51)X
-776 2922(showmode)N
-1549(51)X
-776 3012(sidescroll)N
-1549(51)X
-776 3102(slowopen)N
-1549(51)X
-776 3192(source)N
-1549(42)X
-776 3282(sourceany)N
-1549(51)X
-776 3372(split)N
-1549(42)X
-776 3462(stop)N
-1549(43)X
-776 3552(substitute)N
-1549(42)X
-776 3642(suspend)N
-1549(43)X
-776 3732(t)N
-1429(27,)X
-1549(36)X
-776 3822(tabstop)N
-1549(51)X
-776 3912(tag)N
-1549(43)X
-776 4002(taglength)N
-1549(51)X
-776 4092(tagpop)N
-1549(43)X
-776 4182(tags)N
-1549(51)X
-776 4272(tagtop)N
-1549(43)X
-776 4362(term)N
-1549(51)X
-776 4452(terse)N
-1549(51)X
-776 4542(tildeop)N
-1549(51)X
-776 4632(timeout)N
-1549(51)X
-776 4722(ttywerase)N
-1549(52)X
-776 4812(u)N
-1549(28)X
-776 4902(unabbrev)N
-1549(44)X
-776 4992(undo)N
-1549(44)X
-776 5082(unmap)N
-1549(44)X
-776 5172(unnamed)N
-1090(buffer)X
-1589(8)X
-776 5262(v)N
-1549(38)X
-776 5352(verbose)N
-1549(52)X
-776 5442(version)N
-1549(44)X
-776 5532(visual)N
-1549(44)X
-776 5622(viusage)N
-1549(44)X
-776 5712(w)N
-1549(28)X
-776 5802(w1200)N
-1549(52)X
-2077 762(w300)N
-2850(52)X
-2077 852(w9600)N
-2850(52)X
-2077 942(warn)N
-2850(52)X
-2077 1032(window)N
-2850(52)X
-2077 1122(wn)N
-2850(44)X
-2077 1212(word)N
-2850(10)X
-2077 1302(wq)N
-2850(44)X
-2077 1392(wrapmargin)N
-2850(52)X
-2077 1482(wrapscan)N
-2850(52)X
-2077 1572(write)N
-2850(44)X
-2077 1662(writeany)N
-2850(53)X
-2077 1752(x)N
-2850(28)X
-2077 1842(xit)N
-2850(45)X
-2077 1932(y)N
-2850(28)X
-2077 2022(yank)N
-2850(45)X
-2077 2112(z)N
-2730(28,)X
-2850(45)X
-2077 2202({)N
-2850(29)X
-2077 2292(|)N
-2850(29)X
-2077 2382(})N
-2850(29)X
-2077 2472(\304)N
-2610(29,)X
-2730(30,)X
-2850(42)X
-
-2 p
-%%Page: 2 56
-10 s 10 xH 0 xS 1 f 1 i
-3 f
-576 474(USD:13-2)N
-3391(Nvi/Nex)X
-3687 0.3906(Reference)AX
-12 s
-2039 762(Table)N
-2298(of)X
-2402(Contents)X
-1 f
-10 s
-776 961(Description)N
-1184(................................................................................................................................)X
-3992(3)X
-776 1070(Startup)N
-1027(Information)X
-1444(...................................................................................................................)X
-3992(3)X
-776 1179(Recovery)N
-1104(....................................................................................................................................)X
-3992(3)X
-776 1288(Sizing)N
-1000(the)X
-1118(Screen)X
-1364(.......................................................................................................................)X
-3992(5)X
-776 1397(Character)N
-1109(Display)X
-1384(......................................................................................................................)X
-3992(5)X
-776 1506(Multiple)N
-1071(Screens)X
-1344(........................................................................................................................)X
-3992(6)X
-776 1615(Regular)N
-1050(Expressions)X
-1457(and)X
-1593(Replacement)X
-2032(Strings)X
-2284(.........................................................................)X
-3992(6)X
-776 1724(General)N
-1051(Editor)X
-1271(Description)X
-1684(.......................................................................................................)X
-3992(7)X
-776 1833(Vi)N
-876(Description)X
-1284(...........................................................................................................................)X
-3992(8)X
-776 1942(Vi)N
-876(Commands)X
-1264(............................................................................................................................)X
-3952(11)X
-776 2051(Vi)N
-876(Text)X
-1043(Input)X
-1232(Commands)X
-1624(..........................................................................................................)X
-3952(30)X
-776 2160(Ex)N
-885(Addressing)X
-1284(...........................................................................................................................)X
-3952(31)X
-776 2269(Ex)N
-885(Description)X
-1284(...........................................................................................................................)X
-3952(33)X
-776 2378(Ex)N
-885(Commands)X
-1284(...........................................................................................................................)X
-3952(34)X
-776 2487(Set)N
-898(Options)X
-1184(................................................................................................................................)X
-3952(46)X
-776 2596(Additional)N
-1138(Features)X
-1430(in)X
-1512(Nex/Nvi)X
-1824(................................................................................................)X
-3952(53)X
-776 2705(Index)N
-984(..........................................................................................................................................)X
-3952(55)X
-
-56 p
-%%Trailer
-xt
-
-xs
diff --git a/usr.bin/vi/USD.doc/vi.ref/vi.ref.txt b/usr.bin/vi/USD.doc/vi.ref/vi.ref.txt
deleted file mode 100644
index 88a98c772989..000000000000
--- a/usr.bin/vi/USD.doc/vi.ref/vi.ref.txt
+++ /dev/null
@@ -1,5544 +0,0 @@
-
-
-
-
-
-
-
-
- EExx//VVii RReeffeerreennccee MMaannuuaall
-
- _K_e_i_t_h _B_o_s_t_i_c
-
- Computer Science Division
- Department of Electrical Engineering and Computer Science
- University of California, Berkeley
- Berkeley, California 94720
-
- August 15, 1994
-
-
-
- _A_b_s_t_r_a_c_t
-
-
-
-
- This document is the reference guide for the 4.4BSD
-implementations of nneexx/nnvvii, which are reimplementations
-of the historic Berkeley eexx/vvii editors.
-
-
-
-
-
- _A_c_k_n_o_w_l_e_d_g_e_m_e_n_t_s
-
-
-
-
- Bruce Englar encouraged the early development of
-the historic eexx/vvii editor. Peter Kessler helped bring
-sanity to version 2's command layout. Bill Joy wrote
-versions 1 and 2.0 through 2.7, and created the frame-
-work that users see in the present editor. Mark Horton
-added macros and other features and made eexx/vvii work on a
-large number of terminals and Unix systems.
-
- NNvvii is originally derived from software contributed
-to the University of California, Berkeley by Steve Kirk-
-endall, the author of the vvii clone eellvviiss.
-
- IEEE Standard Portable Operating System Interface
-for Computer Environments (POSIX) 1003.2 style Regular
-Expression support was done by Henry Spencer.
-
- The curses library was originally done by Ken
-Arnold. Scrolling and reworking for nnvvii was done by
-Elan Amir.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The Institute of Electrical and Electronics Engi-
-neers has given us permission to reprint portions of
-their documentation. Portions of this document are
-reprinted and reproduced from IEEE Std 1003.2-1992, IEEE
-Standard Portable Operating System Interface for Comput-
-er Environments (POSIX), copyright 1992 by the Institute
-of Electrical and Electronics Engineers, Inc.
-
- The financial support of UUNET Communications Ser-
-vices is gratefully acknowledged.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee UUSSDD::1133--33
-
-
-11.. DDeessccrriippttiioonn
-
- VVii is a screen oriented text editor. EExx is a line-
-oriented text editor. EExx and vvii are different interfaces to
-the same program, and it is possible to switch back and
-forth during an edit session. VViieeww is the equivalent of
-using the --RR (read-only) option of vvii.
-
- This reference manual is the one provided with the
-nneexx/nnvvii versions of the eexx/vvii text editors. NNeexx/nnvvii are
-intended as bug-for-bug compatible replacements for the
-original Fourth Berkeley Software Distribution (4BSD) eexx/vvii
-programs. This reference manual is accompanied by a tradi-
-tional-style manual page. That manual page describes the
-functionality found in eexx/vvii in far less detail than the
-description here. In addition, it describes the system
-interface to eexx/vvii, e.g. command line options, session
-recovery, signals, environmental variables, and similar
-things.
-
- This reference is intended for users already familiar
-with eexx/vvii. Anyone else should almost certainly read a good
-tutorial on the editor first. If you are in an unfamiliar
-environment, and you absolutely have to get work done imme-
-diately, see the section entitled "FFaasstt SSttaarrttuupp" in the man-
-ual page. It is probably enough to get you started.
-
- There are a few features in nneexx/nnvvii that are not found
-in historic versions of eexx/vvii. Some of the more interesting
-of those features are briefly described in the section enti-
-tled "AAddddiittiioonnaall FFeeaattuurreess" near the end of this document.
-For the rest of this document, nneexx/nnvvii is used only when it
-is necessary to distinguish it from the historic implementa-
-tions of eexx/vvii.
-
- Future versions of this software will be periodically
-made available by anonymous ftp, and can be retrieved from
-ffttpp..ccss..bbeerrkkeelleeyy..eedduu, in the directory uuccbb//44bbssdd.
-
-22.. SSttaarrttuupp IInnffoorrmmaattiioonn
-
- EExx/vvii interprets one of two possible environmental
-variables and reads up to three of five possible files dur-
-ing startup. The variables and files are expected to con-
-tain eexx commands, not vvii commands. In addition, they are
-interpreted _b_e_f_o_r_e the file to be edited is read, and there-
-fore many eexx commands may not be used. Generally, any com-
-mand that requires output to the screen or that needs a file
-upon which to operate, will cause an error if included in a
-startup file or environmental variable.
-
- Because the eexx command set supported by nneexx/nnvvii is a
-superset of the command set supported by most historical
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--44 NNvvii//NNeexx RReeffeerreennccee
-
-
-implementations of eexx, nneexx/nnvvii can use the startup files
-created for the historical implementations, but the converse
-may not be true.
-
- If the --ss (the historic - option) is specified, or if
-standard input is redirected from a file, all environmental
-variables and startup files are ignored.
-
- Otherwise, startup files and environmental variables
-are handled in the following order:
-
- (1) The file //eettcc//vvii..eexxrrcc is read, as long as it is owned
- by root or the effective user ID of the user.
-
- (2) The environmental variable NNEEXXIINNIITT (or the variable
- EEXXIINNIITT, if NNEEXXIINNIITT is not set) is interpreted.
-
- (3) If neither NNEEXXIINNIITT or EEXXIINNIITT was set, and the HHOOMMEE
- environmental variable is set, the file $$HHOOMMEE//..nneexxrrcc
- (or the file $$HHOOMMEE//..eexxrrcc, if $$HHOOMMEE//..nneexxrrcc does not
- exist) is read, as long as the effective user ID of
- the user is root or is the same as the owner of the
- file.
-
- (4) If the eexxrrcc option was turned on by one of the previ-
- ous startup information sources, the file ..nneexxrrcc (or
- the file ..eexxrrcc, if ..nneexxrrcc does not exist) is read, as
- long as the effective user ID of the user is the same
- as the owner of the file.
-
- No startup file is read if it is writable by anyone
-other than its owner.
-
- It is not an error for any of the startup environmental
-variables or files not to exist.
-
- Once all environmental variables are interpreted, and
-all startup files are read, the first file to be edited is
-read in (or a temporary file is created). Then, any com-
-mands specified using the --cc option are executed, in the
-context of that file.
-
-33.. RReeccoovveerryy
-
- There is no recovery program for nneexx/nnvvii, nor does
-nneexx/nnvvii run setuid. Recovery files are created readable and
-writable by the owner only. Users may recover any file
-which they can read, and the superuser may recover any edit
-session.
-
- Edit sessions are backed by files in the directory
-named by the rreeccddiirr option (the directory
-//vvaarr//ttmmpp//vvii..rreeccoovveerr by default), and are named "vvii..XXXXXXXXXXXX",
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee UUSSDD::1133--55
-
-
-where "XXXXXXXXXXXX" is a number related to the process ID. When
-a file is first modified, a second recovery file containing
-an email message for the user is created, and is named
-"rreeccoovveerr..XXXXXXXXXXXX", where, again, "XXXXXXXXXXXX" is associated with
-the process ID. Both files are removed at the end of a nor-
-mal edit session, but will remain if the edit session is
-abnormally terminated or the user runs the eexx pprreesseerrvvee com-
-mand.
-
- The rreeccddiirr option may be set in either the user's or
-system's startup information, changing the recovery direc-
-tory. (Note, however, that if a memory based file system is
-used as the backup directory, each system reboot will delete
-all of the recovery files! The same caution applies to
-directories such as //ttmmpp which are cleared of their contents
-by a system reboot, or //uussrr//ttmmpp which is periodically
-cleared of old files on many systems.)
-
- The recovery directory should be owned by root, or at
-least by a pseudo-user. In addition, if directory "sticky-
-bit" semantics are available, the directory should have the
-sticky-bit set so that files may only be removed by their
-owners. The recovery directory must be read, write, and
-executable by any user, i.e. mode 1777.
-
- If the recovery directory does not exist, eexx/vvii will
-attempt to create it. This can result in the recovery
-directory being owned by a normal user, which means that
-that user will be able to remove other user's recovery and
-backup files. This is annoying, but is not a security issue
-as the user cannot otherwise access or modify the files.
-
- The recovery file has all of the necessary information
-in it to enable the user to recover the edit session. In
-addition, it has all of the necessary email headers for
-_s_e_n_d_m_a_i_l(8). When the system is rebooted, all of the files
-in //vvaarr//ttmmpp//vvii..rreeccoovveerr named "rreeccoovveerr..XXXXXXXXXXXX" should be sent
-to their owners, by email, using the --tt option of sseennddmmaaiill
-(or a similar mechanism in other mailers). If eexx/vvii
-receives a hangup (SIGHUP) signal, or the user executes the
-eexx pprreesseerrvvee command, eexx/vvii will automatically email the
-recovery information to the user.
-
- If your system does not have the sseennddmmaaiill utility (or a
-mailer program which supports its interface) the source file
-nnvvii//ccoommmmoonn//rreeccoovveerr..cc will have to be modified to use your
-local mail delivery programs. Note, if nneexx/nnvvii is changed
-to use another mailer, it is important to remember that the
-owner of the file given to the mailer is the nneexx/nnvvii user,
-so nothing in the file should be trusted as it may have been
-modified in an effort to compromise the system.
-
-
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--66 NNvvii//NNeexx RReeffeerreennccee
-
-
- Finally, the owner execute bit is set on backup files
-when they are created, and unset when they are first modi-
-fied, e.g. backup files that have no associated email recov-
-ery file will have this bit set. (There is also a small
-window where empty files can be created and not yet have
-this bit set. This is due to the method in which the files
-are created.) Such files should be deleted when the system
-reboots.
-
- A simple way to do this cleanup is to insert the fol-
-lowing Bourne shell script into your //eettcc//rrcc..llooccaall (or other
-startup) file. The script should work with the historic
-Bourne shell, a POSIX 1003.2 shell or the Korn shell. (A
-copy of this script is included as
-nnvvii//iinnssttaallll//rreeccoovveerr..ssccrriipptt in the nneexx/nnvvii distribution.)
-
-
- ## @@((##))rreeccoovveerr..ssccrriipptt 88..44 ((BBeerrkkeelleeyy)) 88//1133//9944
- ##
- ## RReeccoovveerr nnvvii eeddiittoorr ffiilleess::
- RREECCDDIIRR==//vvaarr//ttmmpp//vvii..rreeccoovveerr
- SSEENNDDMMAAIILL==//uussrr//lliibb//sseennddmmaaiill
- eecchhoo ''RReeccoovveerriinngg nnvvii eeddiittoorr sseessssiioonnss..''
-
- ## UUnnmmooddiiffiieedd nnvvii eeddiittoorr bbaacckkuupp ffiilleess aarree eeiitthheerr zzeerroo lleennggtthh oorr
- ## hhaavvee tthhee eexxeeccuuttee bbiitt sseett.. DDeelleettee bbootthh ccaasseess..
- vviibbaacckkuupp==``eecchhoo $$RREECCDDIIRR//vvii..**``
- iiff [[ ""$$vviibbaacckkuupp"" !!== ""$$RREECCDDIIRR//vvii..**"" ]];; tthheenn
- ffoorr ii iinn $$vviibbaacckkuupp;; ddoo
- iiff tteesstt --xx $$ii --oo !! --ss $$ii;; tthheenn
- rrmm $$ii
- ffii
- ddoonnee
- ffii
-
- ## IItt iiss ppoossssiibbllee ttoo ggeett iinnccoommpplleettee rreeccoovveerryy ffiilleess,, iiff tthhee eeddiittoorr
- ## ccrraasshheess aatt tthhee rriigghhtt ttiimmee.. DDeelleettee aannyy rreeccoovveerryy ffiilleess wwiitthhoouutt
- ## ccoorrrreessppoonnddiinngg bbaacckkuupp ffiilleess,, ootthheerrwwiissee sseenndd mmaaiill ttoo tthhee uusseerr..
- vviirreeccoovveerryy==``eecchhoo $$RREECCDDIIRR//rreeccoovveerr..**``
- iiff [[ ""$$vviirreeccoovveerryy"" !!== ""$$RREECCDDIIRR//rreeccoovveerr..**"" ]];; tthheenn
- ffoorr ii iinn $$vviirreeccoovveerryy;; ddoo
- rreeccffiillee==``aawwkk ''//^^XX--vvii--rreeccoovveerr--ppaatthh:://{{pprriinntt $$22}}'' << $$ii``
- iiff tteesstt !! --nn $$rreeccffiillee --aa --ss $$rreeccffiillee;; tthheenn
- $$SSEENNDDMMAAIILL --tt << $$ii
- eellssee
- rrmm $$ii
- ffii
- ddoonnee
- ffii
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee UUSSDD::1133--77
-
-
- If you are not using the default value for the rreeccddiirr
-option, be sure to substitute the value you're using for the
-RREECCDDIIRR value in the recovery script.
-
- If the path of your system's sseennddmmaaiill program (or what-
-ever mailer you're using) is not //uussrr//lliibb//sseennddmmaaiill, be sure
-to substitute the correct pathname for the SSEENNDDMMAAIILL value in
-the recovery script. Consult the manual page for details on
-recovering preserved or aborted editing sessions.
-
-44.. SSiizziinngg tthhee SSccrreeeenn
-
- The size of the screen can be set in a number of ways.
-EExx/vvii takes the following steps until values are obtained
-for both the number of rows and number of columns in the
-screen.
-
- (1) If the environmental variable LLIINNEESS exists, it is
- used to specify the number of rows in the screen.
-
- (2) If the environmental variable CCOOLLUUMMNNSS exists, it is
- used to specify the number of columns in the screen.
-
- (3) The TIOCGWINSZ _i_o_c_t_l(2) is attempted on the standard
- error file descriptor.
-
- (4) The termcap entry (or terminfo entry on System V
- machines) is checked for the "li" entry (rows) and
- the "co" entry (columns).
-
- (5) The number of rows is set to 24, and the number of
- columns is set to 80.
-
- If a window change size signal (SIGWINCH) is received,
-the new window size is retrieved using the TIOCGWINSZ
-_i_o_c_t_l(2) call, and all other information is ignored.
-
-55.. CChhaarraacctteerr DDiissppllaayy
-
- In both eexx and vvii printable characters as defined by
-_i_s_p_r_i_n_t(3) are displayed using the local character set.
-
- Non-printable characters, for which _i_s_c_n_t_r_l(3) returns
-true, and which are less than octal \076, are displayed as
-the string "^^<<cchhaarraacctteerr>>", where <<cchhaarraacctteerr>> is the charac-
-ter that is the original character's value offset from the
-"@@" character. For example, the octal character \001 is
-displayed as "^^AA". If _i_s_c_n_t_r_l(3) returns true for the octal
-character \177, it is displayed as the string "^^??". All
-other characters are displayed as either hexadecimal values,
-in the form "00xx<<hhiigghh--hhaallffbbyyttee>> ...... 00xx<<llooww--hhaallffbbyyttee>>", or as
-octal values, in the form "\\<<hhiigghh--oonnee--oorr--ttwwoo--bbiittss>> ......
-\\<<llooww--tthhrreeee--bbiittss>>". The display of unknown characters is
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--88 NNvvii//NNeexx RReeffeerreennccee
-
-
-based on the value of the ooccttaall option.
-
- In vvii command mode, the cursor is always positioned on
-the last column of characters which take up more than one
-column on the screen. In vvii text input mode, the cursor is
-positioned on the first column of characters which take up
-more than one column on the screen.
-
-66.. MMuullttiippllee SSccrreeeennss
-
- NNvvii supports multiple screens by dividing the window
-into regions. It also supports stacks of screens by permit-
-ting the user to change the set of screens that are cur-
-rently displayed.
-
- The command sspplliitt divides the current screen into two
-regions of approximately equal size. If a list of files are
-specified as arguments to the sspplliitt command, the list of
-files to be edited is initialized as if the nneexxtt command had
-been used. If no files are specified, the new screen will
-begin by editing the same file as the previous screen.
-
- When more than one screen is editing a file, changes in
-any screen are reflected in all other screens editing the
-same file. Exiting any screen without saving any changes
-(or explicitly discarding them) is permitted until the last
-screen editing the file is exited.
-
- The rreessiizzee command permits resizing of individual
-screens. Screens may be grown, shrunk or set to an absolute
-number of rows.
-
- The ^^WW command is used to switch between screens. Each
-^^WW moves to the next lower screen in the window, or to the
-first screen in the window if there are no lower screens.
-
- The bbgg command "backgrounds" the current screen. The
-screen disappears from the window, and the rows it occupied
-are taken over by a neighboring screen. It is an error to
-attempt to background the only screen in the window.
-
- The ddiissppllaayy ssccrreeeennss command displays the names of the
-files associated with the current backgrounded screens in
-the window.
-
- The ffgg [[ffiillee]] command "foregrounds" the first screen in
-the list of backgrounded screens that is associated with its
-argument. If no file argument is specified, the first
-screen on the list is foregrounded. Foregrounding consists
-of backgrounding the current screen, and replacing its space
-in the window with the foregrounded screen.
-
-
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee UUSSDD::1133--99
-
-
- If the last screen in the window is exited, and there
-are backgrounded screens, the first screen on the list of
-backgrounded screens takes over the window.
-
-77.. RReegguullaarr EExxpprreessssiioonnss aanndd RReeppllaacceemmeenntt SSttrriinnggss
-
- Regular expressions are used in line addresses, as the
-first part of the eexx ssuubbssttiittuuttee, gglloobbaall, and vvgglloobbaall com-
-mands, and in search patterns.
-
- The regular expressions supported by eexx/vvii are, by
-default, the Basic Regular Expressions (BRE's) described in
-the IEEE POSIX Standard 1003.2. The eexxtteennddeedd option causes
-all regular expressions to be interpreted as the Extended
-Regular Expressions (ERE's) described by the same standard.
-(See _r_e___f_o_r_m_a_t(7) for more information.) Generally speak-
-ing, BRE's are the Regular Expressions found in _e_d(1) and
-_g_r_e_p(1), and ERE's are the Regular Expressions found in
-_e_g_r_e_p(1).
-
- The following is not intended to provide a description
-of Regular Expressions. The information here only describes
-strings and characters which have special meanings in the
-eexx/vvii version of RE's, or options which change the meanings
-of characters that normally have special meanings in RE's.
-
- (1) An empty RE (e.g. "////" or "????" is equivalent to the
- last RE used.
-
- (2) The construct "\\<<" matches the beginning of a word.
-
- (3) The construct "\\>>" matches the end of a word.
-
- (4) The character "~~" matches the replacement part of the
- last ssuubbssttiittuuttee command.
-
- When the mmaaggiicc option is _n_o_t set, the only characters
-with special meanings are a "^^" character at the beginning
-of an RE, a "$$" character at the end of an RE, and the
-escaping character "\\". The characters "..", "**", "[[" and
-"~~" are treated as ordinary characters unless preceded by a
-"\\"; when preceded by a "\\" they regain their special mean-
-ing.
-
- Replacement strings are the second part of a ssuubbssttiittuuttee
-command.
-
- The character "&&" (or "\\&&" if the mmaaggiicc option is _n_o_t
-set) in the replacement string stands for the text matched
-by the RE that is being replaced. The character "~~" (or
-"\\~~" if the mmaaggiicc option is _n_o_t set) stands for the replace-
-ment part of the previous ssuubbssttiittuuttee command. It is only
-valid after a ssuubbssttiittuuttee command has been performed.
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--1100 NNvvii//NNeexx RReeffeerreennccee
-
-
- The string "\\##", where "##" is an integer value from 1
-to 9, stands for the text matched by the portion of the RE
-enclosed in the "##"'th set of escaped parentheses, e.g.
-"\\((" and "\\))". For example, "ss//aabbcc\\((..**\\))ddeeff//\\11//" deletes
-the strings "aabbcc" and "ddeeff" from the matched pattern.
-
- The strings "\\ll", "\\uu", "\\LL" and "\\UU" can be used to
-modify the case of elements in the replacement string. The
-string "\\ll" causes the next character to be converted to
-lowercase; the string "\\uu" behaves similarly, but converts
-to uppercase (e.g. ss//aabbcc//\\UU&&// replaces the string aabbcc with
-AABBCC). The strings "\\LL" causes characters up to the end of
-the string or the next occurrence of the strings "\\ee" or
-"\\EE" to be converted to lowercase; the string "\\UU" behaves
-similarly, but converts to uppercase.
-
- If the entire replacement pattern is "%%", then the last
-replacement pattern is used again.
-
- In vvii, inserting a <<ccoonnttrrooll--MM>> into the replacement
-string will cause the matched line to be split into two
-lines at that point. (The <<ccoonnttrrooll--MM>> will be discarded.)
-
-88.. GGeenneerraall EEddiittoorr DDeessccrriippttiioonn
-
- When eexx or vvii are executed, the text of a file is read
-(or a temporary file is created), and then all editing
-changes happen within the context of the copy of the file.
-_N_o _c_h_a_n_g_e_s _a_f_f_e_c_t _t_h_e _a_c_t_u_a_l _f_i_l_e _u_n_t_i_l _t_h_e _f_i_l_e _i_s _w_r_i_t_t_e_n
-_o_u_t, either using a write command or another command which
-is affected by the aauuttoowwrriittee option.
-
- All files are locked (using the _f_l_o_c_k(2) or _f_c_n_t_l(2)
-interfaces) during the edit session, to avoid inadvertently
-making modifications to multiple copies of the file. If a
-lock cannot be obtained for a file because it is locked by
-another process, the edit session is read-only (as if the
-rreeaaddoonnllyy option or the --RR flag had been specified). If a
-lock cannot be obtained for other reasons, the edit session
-will continue, but the file status information (see the
-<<ccoonnttrrooll--GG>> command) will reflect this fact.
-
- Both eexx and vvii are modeful editors, i.e. they have two
-modes, "command" mode and "text input" mode. The former is
-intended to permit you to enter commands which modifies
-already existing text. The latter is intended to permit you
-to enter new text. When eexx first starts running, it is in
-command mode, and usually displays a prompt (see the pprroommpptt
-option for more information). The prompt is a single colon
-("::") character. There are three commands that switch eexx
-into text input mode: aappppeenndd, cchhaannggee and iinnsseerrtt. Once in
-input mode, entering a line containing only a single period
-("..") terminates text input mode and returns to command
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee UUSSDD::1133--1111
-
-
-mode, where the prompt is redisplayed.
-
- When vvii first starts running, it is in command mode as
-well. There are eleven commands that switch vvii into text
-input mode: AA, aa, CC, cc, II, ii, OO, oo, RR, SS and ss. Once in
-input mode, entering an <<eessccaappee>> character terminates text
-input mode and returns to command mode.
-
- The following words have special meanings in both the
-eexx and vvii command descriptions:
-
-<<iinntteerrrruupptt>>
- The interrupt character is used to interrupt the cur-
- rent operation. Normally <<ccoonnttrrooll--CC>>, whatever charac-
- ter is set for the current terminal is used.
-
-<<lliitteerraall nneexxtt>>
- The literal next character is used to escape the subse-
- quent character from any special meaning. This charac-
- ter is always <<ccoonnttrrooll--VV>>. If the terminal is not set
- up to do XON/XOFF flow control, then <<ccoonnttrrooll--QQ>> is
- used to mean literal next as well.
-
-ccuurrrreenntt ppaatthhnnaammee
- The pathname of the file currently being edited by vi.
- When the percent character ("%%") appears in a file name
- entered as part of an eexx command argument, it is
- replaced by the current pathname. (The "%%" character
- can be escaped by preceding it with a backslash.)
-
-aalltteerrnnaattee ppaatthhnnaammee
- The name of the last file name mentioned in an eexx com-
- mand, or, the previous current pathname if the last
- file mentioned becomes the current file. When the hash
- mark character ("##") appears in a file name entered as
- part of an eexx command argument, it is replaced by the
- alternate pathname. (The "##" character can be escaped
- by preceding it with a backslash.)
-
-bbuuffffeerr
- One of a number of named areas for saving copies of
- text. Commands that change or delete text can save the
- changed or deleted text into a specific buffer, for
- later use, if the command allows it (i.e. the eexx cchhaannggee
- command cannot save the changed text in a named
- buffer). Buffers are named with a single character,
- preceded by a double quote, e.g. ""<<cchhaarraacctteerr>>. His-
- toric implementations of eexx/vvii limited <<cchhaarraacctteerr>> to
- the alphanumeric characters; nneexx/nnvvii permits the use of
- any character.
-
- Buffers named by uppercase characters are the same as
- buffers named by lowercase characters, e.g. the buffer
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--1122 NNvvii//NNeexx RReeffeerreennccee
-
-
- named by the English character "AA" is the same as the
- buffer named by the character "aa", with the exception
- that, if the buffer contents are being changed (as with
- a text deletion or vvii cchhaannggee command), the text is
- _a_p_p_e_n_d_e_d to the buffer, instead of replacing the cur-
- rent contents.
-
- The buffers named by the numeric characters (in
- English, "11" through "99"), are special, in that if at
- least one line is changed or deleted in the file, (or a
- command changes or deletes a region that crosses a line
- boundary) a copy of the text is placed into the numeric
- buffer "11", regardless of the user specifying another
- buffer in which to save it. Before this copy is done,
- the previous contents of buffer "11" are moved into
- buffer "22", "22" into buffer "33", and so on. The con-
- tents of buffer "99" are discarded. In vvii, text may be
- explicitly stored into the numeric buffers. In this
- case, the buffer rotation described above occurs before
- the replacement of the buffer's contents. (Text cannot
- be explicitly stored into the numeric buffers in eexx
- because of ambiguities that this would cause in the eexx
- command syntax.)
-
- When a vvii command synopsis shows both a [[bbuuffffeerr]] and a
- [[ccoouunntt]], they may be presented in any order.
-
- Finally, all buffers are either "line" or "character"
- oriented. All eexx commands which store text into
- buffers are line oriented. Some vvii commands which
- store text into buffers are line oriented, and some are
- character oriented; the description for each applicable
- vvii command notes whether text copied into buffers using
- the command is line or character oriented. In addi-
- tion, the vvii command ddiissppllaayy bbuuffffeerrss displays the cur-
- rent orientation for each buffer. Generally, the only
- importance attached to this orientation is that if the
- buffer is subsequently inserted into the text, line
- oriented buffers create new lines for each of the lines
- they contain, and character oriented buffers create new
- lines for any lines _o_t_h_e_r than the first and last lines
- they contain. The first and last lines are inserted
- into the text at the current cursor position, becoming
- part of the current line. If there is more than one
- line in the buffer, however, the current line itself
- will be split.
-
-uunnnnaammeedd bbuuffffeerr
- The unnamed buffer is a text storage area which is used
- by commands that take a buffer as an argument, when no
- buffer is specified by the user. There is no way to
- explicitly reference this buffer.
-
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--1133
-
-
-99.. VVii DDeessccrriippttiioonn
-
- VVii takes up the entire screen to display the edited
-file, except for the bottom line of the screen. The bottom
-line of the screen is used to enter eexx commands, and for vvii
-error and informational messages. If no other information
-is being displayed, the default display can show the current
-cursor row and cursor column, an indication of whether the
-file has been modified, and the current mode of the editor.
-See the rruulleerr, sshhoowwddiirrttyy and sshhoowwmmooddee options for more
-information.
-
- Empty lines do not have any special representation on
-the screen, but lines on the screen that would logically
-come after the end of the file are displayed as a single
-tilde ("~~") character. To differentiate between empty lines
-and lines consisting of only whitespace characters, use the
-lliisstt option. Historically, implementations of vvii have also
-displayed some lines as single asterisk ("@@") characters.
-These were lines that were not correctly displayed, i.e.
-lines on the screen that did not correspond to lines in the
-file, or lines that did not fit on the current screen. NNvvii
-never displays lines in this fashion.
-
- VVii is a modeful editor, i.e. it has two modes, "com-
-mand" mode and "text input" mode. When vvii first starts, it
-is in command mode. There are several commands that change
-vvii into text input mode. The <<eessccaappee>> character is used to
-resolve the text input into the file, and exit back into
-command mode. In vvii command mode, the cursor is always
-positioned on the last column of characters which take up
-more than one column on the screen. In vvii text insert mode,
-the cursor is positioned on the first column of characters
-which take up more than one column on the screen.
-
- Generally, if the cursor line and cursor column are not
-on the screen, then the screen is scrolled (if the target
-cursor is close) or repainted (if the target cursor is far
-away) so that the cursor is on the screen. If the screen is
-scrolled, it is moved a minimal amount, and the cursor line
-will usually appear at the top or bottom of the screen. In
-the screen is repainted, the cursor line will appear in the
-center of the screen, unless the cursor is sufficiently
-close to the beginning or end of the file that this is not
-possible. If the lleeffttrriigghhtt option is set, the screen may be
-scrolled or repainted in a horizontal direction as well as
-in a vertical one.
-
- A major difference between the historical vvii presenta-
-tion and nnvvii is in the scrolling and screen oriented posi-
-tion commands, <<ccoonnttrrooll--BB>>, <<ccoonnttrrooll--DD>>, <<ccoonnttrrooll--EE>>, <<ccoonn--
-ttrrooll--FF>>, <<ccoonnttrrooll--UU>>, <<ccoonnttrrooll--YY>>, HH, LL and MM. In histori-
-cal implementations of vvii, these commands acted on physical
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--1144 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
-(as opposed to logical, or screen) lines. For lines that
-were sufficiently long in relation to the size of the
-screen, this meant that single line scroll commands might
-repaint the entire screen, scrolling or screen positioning
-command might not change the screen or move the cursor at
-all, and some lines simply could not be displayed, even
-though vvii would edit the file that contained them. In nnvvii,
-these commands act on logical, i.e. screen lines. You are
-unlikely to notice any difference unless you are editing
-files with lines significantly longer than a screen width.
-
- VVii keeps track of the currently "most attractive" cur-
-sor position. Each command description (for commands that
-can change the current cursor position), specifies if the
-cursor is set to a specific location in the line, or if it
-is moved to the "most attractive cursor position". The lat-
-ter means that the cursor is moved to the cursor position
-that is vertically as close as possible to the current cur-
-sor position. If the current line is shorter than the cur-
-sor position vvii would select, the cursor is positioned on
-the last character in the line. (If the line is empty, the
-cursor is positioned on the first column of the line.) If a
-command moves the cursor to the most attractive position, it
-does not alter the current cursor position, and a subsequent
-movement will again attempt to move the cursor to that posi-
-tion. Therefore, although a movement to a line shorter than
-the currently most attractive position will cause the cursor
-to move to the end of that line, a subsequent movement to a
-longer line will cause the cursor to move back to the most
-attractive position.
-
- In addition, the $$ command makes the end of each line
-the most attractive cursor position rather than a specific
-column.
-
- Each vvii command described below notes where the cursor
-ends up after it is executed. This position is described in
-terms of characters on the line, i.e. "the previous charac-
-ter", or, "the last character in the line". This is to
-avoid needing to continually refer to on what part of the
-character the cursor rests.
-
- The following words have special meaning for vvii com-
-mands.
-
-pprreevviioouuss ccoonntteexxtt
- The position of the cursor before the command which
- caused the last absolute movement was executed. Each
- vvii command described in the next section that is con-
- sidered an absolute movement is so noted. In addition,
- specifying _a_n_y address to an eexx command is considered
- an absolute movement.
-
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--1155
-
-
-mmoottiioonn
- A second vvii command can be used as an optional trailing
- argument to the vvii !!, <<, >>, cc, dd, yy, and (depending on
- the ttiillddeeoopp option) ~~ commands. This command indicates
- the end of the region of text that's affected by the
- command. The motion command may be either the command
- character repeated (in which case it means the current
- line) or a cursor movement command. In the latter
- case, the region affected by the command is from the
- starting or stopping cursor position which comes first
- in the file, to immediately before the starting or
- stopping cursor position which comes later in the file.
- Commands that operate on lines instead of using begin-
- ning and ending cursor positions operate on all of the
- lines that are wholly or partially in the region. In
- addition, some other commands become line oriented
- depending on where in the text they are used. The com-
- mand descriptions below note these special cases.
-
- The following commands may all be used as motion compo-
- nents for vvii commands:
-
-
- <<ccoonnttrrooll--AA>> <<ccoonnttrrooll--HH>> <<ccoonnttrrooll--JJ>> <<ccoonnttrrooll--MM>>
- <<ccoonnttrrooll--NN>> <<ccoonnttrrooll--PP>> <<ssppaaccee>> $$
- %% ''<<cchhaarraacctteerr>> (( ))
- ++ ,, -- //
- 00 ;; ?? BB
- EE FF GG HH
- LL MM NN TT
- WW [[[[ ]]]] ^^
- __ ``<<cchhaarraacctteerr>> bb ee
- ff hh jj kk
- ll nn tt ww
- {{ || }}
-
-
- The optional count prefix available for some of the vvii
- commands that take motion commands, or the count prefix
- available for the vvii commands that are used as motion
- components, may be included and is _a_l_w_a_y_s considered
- part of the motion argument. For example, the commands
- "cc22ww" and "22ccww" are equivalent, and the region affected
- by the cc command is two words of text. In addition, if
- the optional count prefix is specified for both the vvii
- command and its motion component, the effect is multi-
- plicative and is considered part of the motion argu-
- ment. For example, the commands "44ccww" and "22cc22ww" are
- equivalent, and the region affected by the cc command is
- four words of text.
-
-
-
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--1166 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
-ccoouunntt
- A positive number used as an optional argument to most
- commands, either to give a size or a position (for dis-
- play or movement commands), or as a repeat count (for
- commands that modify text). The count argument is
- always optional and defaults to 1 unless otherwise
- noted in the command description.
-
- When a vvii command synopsis shows both a [[bbuuffffeerr]] and
- [[ccoouunntt]], they may be presented in any order.
-
-bbiiggwwoorrdd
- A set of non-whitespace characters preceded and fol-
- lowed by whitespace characters or the beginning or end
- of the file or line.
-
- Groups of empty lines (or lines containing only whites-
- pace characters) are treated as a single bigword.
-
-wwoorrdd
- Generally, in languages where it is applicable, vvii rec-
- ognizes two kinds of words. First, a sequence of let-
- ters, digits and underscores, delimited at both ends
- by: characters other than letters, digits, or under-
- scores; the beginning or end of a line; the beginning
- or end of the file. Second, a sequence of characters
- other than letters, digits, underscores, or whitespace
- characters, delimited at both ends by: a letter, digit,
- underscore, or whitespace character; the beginning or
- end of a line; the beginning or end of the file.
-
- Groups of empty lines (or lines containing only whites-
- pace characters) are treated as a single word.
-
-ppaarraaggrraapphh
- An area of text that begins with either the beginning
- of a file, an empty line, or a section boundary, and
- continues until either an empty line, section boundary,
- or the end of the file.
-
- Groups of empty lines (or lines containing only whites-
- pace characters) are treated as a single paragraph.
-
- Additional paragraph boundaries can be defined using
- the ppaarraaggrraapphh option.
-
-sseeccttiioonn
- An area of text that starts with the beginning of the
- file or a line whose first character is an open brace
- ("{{") and continues until the next section or the end
- of the file.
-
- Additional section boundaries can be defined using the
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--1177
-
-
- sseeccttiioonnss option.
-
-sseenntteennccee
- An area of text that begins with either the beginning
- of the file or the first nonblank character following
- the previous sentence, paragraph, or section boundary
- and continues until the end of the file or a or a
- period ("..") exclamation point ("!!") or question mark
- ("??") character, followed by either an end-of-line or
- two whitespace characters. Any number of closing
- parentheses ("))"), brackets ("]]") or double-quote ("""")
- characters can appear between the period, exclamation
- point, or question mark and the whitespace characters
- or end-of-line.
-
- Groups of empty lines (or lines containing only whites-
- pace characters) are treated as a single sentence.
-
-1100.. VVii CCoommmmaannddss
-
- The following section describes the commands available
-in the command mode of the vvii editor. In each entry below,
-the tag line is a usage synopsis for the command character.
-In addition, the final line and column the cursor rests
-upon, and any options which affect the command are noted.
-
-[[ccoouunntt]] <<ccoonnttrrooll--AA>>
- Search forward ccoouunntt times for the current word. The
- current word begins at the first non-whitespace charac-
- ter on or after the current cursor position, and
- extends up to the next non-word character or the end of
- the line. The search is literal, i.e. no characters in
- the word have any special meaning in terms of Regular
- Expressions. It is an error if no matching pattern is
- found between the starting position and the end of the
- file.
-
- The <<ccoonnttrrooll--AA>> command is an absolute movement. The
- <<ccoonnttrrooll--AA>> command may be used as the motion component
- of other vvii commands, in which case any text copied
- into a buffer is character oriented.
-
- Line: Set to the line where the word is found.
- Column: Set to the first character of the word.
- Options: Affected by the eexxtteennddeedd, iiggnnoorreeccaassee and wwrraapp--
- ssccaann options.
-
-[[ccoouunntt]] <<ccoonnttrrooll--BB>>
- Page backward ccoouunntt screens. Two lines of overlap are
- maintained by displaying the window starting at line
- ((ttoopp__lliinnee -- ccoouunntt ** wwiinnddooww__ssiizzee)) ++ 22, where wwiinnddooww__ssiizzee
- is the value of the wwiinnddooww option. (In the case of
- split screens, this size is corrected to the current
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--1188 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
- screen size.) This is an error if the movement is past
- the beginning of the file.
-
- The <<ccoonnttrrooll--BB>> command is an absolute movement.
-
- Line: Set to the last line of text displayed on the
- screen.
- Column: Set to the first nonblank character of the
- line.
- Options: None.
-
-[[ccoouunntt]] <<ccoonnttrrooll--DD>>
- Scroll forward ccoouunntt lines. If ccoouunntt is not specified,
- scroll forward the number of lines specified by the
- last <<ccoonnttrrooll--DD>> or <<ccoonnttrrooll--UU>> command. If this is
- the first <<ccoonnttrrooll--DD>> or <<ccoonnttrrooll--UU>> command, scroll
- forward half the number of lines in the screen. (In
- the case of split screens, the default scrolling dis-
- tance is corrected to half the current screen size.)
- This is an error if the movement is past the end of the
- file.
-
- The <<ccoonnttrrooll--DD>> command is an absolute movement.
-
- Line: Set to the current line plus the number of
- lines scrolled.
- Column: Set to the first nonblank character of the
- line.
- Options: None.
-
-[[ccoouunntt]] <<ccoonnttrrooll--EE>>
- Scroll forward ccoouunntt lines, leaving the cursor on the
- current line and column, if possible. This is an error
- if the movement is past the end of the file.
-
- Line: Unchanged unless the current line scrolls off
- the screen, in which case it is set to the
- first line on the screen.
- Column: Unchanged unless the current line scrolls off
- the screen, in which case it is set to the
- most attractive cursor position.
- Options: None.
-
-[[ccoouunntt]] <<ccoonnttrrooll--FF>>
- Page forward ccoouunntt screens. Two lines of overlap are
- maintained by displaying the window starting at line
- ttoopp__lliinnee ++ ccoouunntt ** wwiinnddooww__ssiizzee -- 22, where wwiinnddooww__ssiizzee
- is the value of the wwiinnddooww option. (In the case of
- split screens, this size is corrected to the current
- screen size.) This is an error if the movement is past
- the end of the file.
-
- The <<ccoonnttrrooll--FF>> command is an absolute movement.
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--1199
-
-
- Line: Set to the first line on the screen.
- Column: Set to the first nonblank character of the
- current line.
- Options: None.
-
-<<ccoonnttrrooll--GG>>
- Display the file information. The information includes
- the current pathname, the current line, the number of
- total lines in the file, the current line as a percent-
- age of the total lines in the file, if the file has
- been modified, was able to be locked, if the file's
- name has been changed, and if the edit session is read-
- only.
-
- Line: Unchanged.
- Column: Unchanged.
- Options: None.
-
-<<ccoonnttrrooll--HH>>
-[[ccoouunntt]] hh
- Move the cursor back ccoouunntt characters in the current
- line. This is an error if the cursor is on the first
- character in the line.
-
- The <<ccoonnttrrooll--HH>> and hh commands may be used as the
- motion component of other vvii commands, in which case
- any text copied into a buffer is character oriented.
-
- Line: Unchanged.
- Column: Set to the ccuurrrreenntt -- ccoouunntt character, or, the
- first character in the line if ccoouunntt is
- greater than or equal to the number of charac-
- ters in the line before the cursor.
- Options: None.
-
-[[ccoouunntt]] <<ccoonnttrrooll--JJ>>
-[[ccoouunntt]] <<ccoonnttrrooll--NN>>
-[[ccoouunntt]] jj
- Move the cursor down ccoouunntt lines without changing the
- current column. This is an error if the movement is
- past the end of the file.
-
- The <<ccoonnttrrooll--JJ>>, <<ccoonnttrrooll--NN>> and jj commands may be used
- as the motion component of other vvii commands, in which
- case any text copied into a buffer is line oriented.
-
- Line: Set to the current line plus ccoouunntt.
- Column: The most attractive cursor position.
- Options: None.
-
-<<ccoonnttrrooll--LL>>
-<<ccoonnttrrooll--RR>>
- Repaint the screen.
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--2200 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
- Line: Unchanged.
- Column: Unchanged.
- Options: None.
-
-[[ccoouunntt]] <<ccoonnttrrooll--MM>>
-[[ccoouunntt]] ++
- Move the cursor down ccoouunntt lines to the first nonblank
- character of that line. This is an error if the move-
- ment is past the end of the file.
-
- The <<ccoonnttrrooll--MM>> and ++ commands may be used as the
- motion component of other vvii commands, in which case
- any text copied into a buffer is line oriented.
-
- Line: Set to the current line plus ccoouunntt.
- Column: Set to the first nonblank character in the
- line.
- Options: None.
-
-[[ccoouunntt]] <<ccoonnttrrooll--PP>>
-[[ccoouunntt]] kk
- Move the cursor up ccoouunntt lines, without changing the
- current column. This is an error if the movement is
- past the beginning of the file.
-
- The <<ccoonnttrrooll--PP>> and kk commands may be used as the
- motion component of other vvii commands, in which case
- any text copied into a buffer is line oriented.
-
- Line: Set to the current line minus count.
- Column: The most attractive cursor position.
- Options: None.
-
-<<ccoonnttrrooll--TT>>
- Return to the most recent tag context. The <<ccoonnttrrooll--TT>>
- command is an absolute movement.
-
- Line: Set to the context of the previous tag com-
- mand.
- Column: Set to the context of the previous tag com-
- mand.
- Options: None.
-
-<<ccoonnttrrooll--UU>>
- Scroll backward ccoouunntt lines. If ccoouunntt is not speci-
- fied, scroll backward the number of lines specified by
- the last <<ccoonnttrrooll--DD>> or <<ccoonnttrrooll--UU>> command. If this
- is the first <<ccoonnttrrooll--DD>> or <<ccoonnttrrooll--UU>> command, scroll
- backward half the number of lines in the screen. (In
- the case of split screens, the default scrolling dis-
- tance is corrected to half the current screen size.)
- This is an error if the movement is past the beginning
- of the file.
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--2211
-
-
- The <<ccoonnttrrooll--UU>> command is an absolute movement.
-
- Line: Set to the current line minus the amount
- scrolled.
- Column: Set to the first nonblank character in the
- line.
- Options: None.
-
-<<ccoonnttrrooll--WW>>
- Switch to the next lower screen in the window, or, to
- the first screen if there are no lower screens in the
- window.
-
- Line: Set to the previous cursor position in the
- window.
- Column: Set to the previous cursor position in the
- window.
- Options: None.
-
-<<ccoonnttrrooll--YY>>
- Scroll backward ccoouunntt lines, leaving the current line
- and column as is, if possible. This is an error if the
- movement is past the beginning of the file.
-
- Line: Unchanged unless the current line scrolls off
- the screen, in which case it is set to the
- last line of text displayed on the screen.
- Column: Unchanged unless the current line scrolls off
- the screen, in which case it is the most
- attractive cursor position.
- Options: None.
-
-<<ccoonnttrrooll--ZZ>>
- Suspend the current editor session. If the file has
- been modified since it was last completely written, and
- the aauuttoowwrriittee option is set, the file is written before
- the editor session is suspended. If this write fails,
- the editor session is not suspended.
-
- Line: Unchanged.
- Column: Unchanged.
- Options: Affected by the aauuttoowwrriittee option.
-
-<<eessccaappee>>
- Execute eexx commands or cancel partial commands. If an
- eexx command is being entered (e.g. //, ??, :: or !!), the
- command is executed. If a partial command has been
- entered, e.g. or the command is cancelled. Otherwise,
- it is an error.
-
- Line: When an eexx command is being executed, the cur-
- rent line is set as described for that com-
- mand. Otherwise, unchanged.
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--2222 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
- Column: When an eexx command is being executed, the cur-
- rent column is set as described for that com-
- mand. Otherwise, unchanged.
- Options: None.
-
-<<ccoonnttrrooll--]]>>
- Push a tag reference onto the tag stack. The tags
- files (see the ttaaggss option for more information) are
- searched for a tag matching the current word. The cur-
- rent word begins at the first non-whitespace character
- on or after the current cursor position, and extends up
- to the next non-word character or the end of the line.
- If a matching tag is found, the current file is dis-
- carded and the file containing the tag reference is
- edited.
-
- If the current file has been modified since it was last
- completely written, the command will fail. The <<ccoonn--
- ttrrooll--]]>> command is an absolute movement.
-
- Line: Set to the line containing the matching tag
- string.
- Column: Set to the start of the matching tag string.
- Options: Affected by the ttaaggss and ttaagglleennggtthh options.
-
-<<ccoonnttrrooll--^^>>
- Switch to the most recently edited file.
-
- If the file has been modified since it was last com-
- pletely written, and the aauuttoowwrriittee option is set, the
- file is written out. If this write fails, the command
- will fail. Otherwise, if the current file has been
- modified since it was last completely written, the com-
- mand will fail.
-
- Line: Set to the line the cursor was on when the
- file was last edited.
- Column: Set to the column the cursor was on when the
- file was last edited.
- Options: Affected by the aauuttoowwrriittee option.
-
-[[ccoouunntt]] <<ssppaaccee>>
-[[ccoouunntt]] ll
- Move the cursor forward ccoouunntt characters without chang-
- ing the current line. This is an error if the cursor
- is on the last character in the line.
-
- The <<ssppaaccee>> and ll commands may be used as the motion
- component of other vvii commands, in which case any text
- copied into a buffer is character oriented. In addi-
- tion, these commands may be used as the motion compo-
- nents of other commands when the cursor is on the last
- character in the line, without error.
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--2233
-
-
- Line: Unchanged.
- Column: Set to the current character plus the next
- ccoouunntt characters, or to the last character on
- the line if ccoouunntt is greater than the number
- of characters in the line after the current
- character.
- Options: None.
-
-[[ccoouunntt]] !! mmoottiioonn sshheellll--aarrgguummeenntt((ss))
- Replace text with results from a shell command. Pass
- the lines specified by the ccoouunntt and mmoottiioonn arguments
- as standard input to the program named by the sshheellll
- option, and replace those lines with the output (both
- standard error and standard output) of that command.
-
- After the motion is entered, vvii prompts for arguments
- to the shell command.
-
- Within those arguments, "%%" and "##" characters are
- expanded to the current and alternate pathnames,
- respectively. The "!!" character is expanded with the
- command text of the previous !! or ::!! commands.
- (Therefore, the command !!!! repeats the previous !!
- command.) The special meanings of "%%", "##" and "!!"
- can be overridden by escaping them with a backslash.
- If no !! or ::!! command has yet been executed, it is an
- error to use an unescaped "!!" character. The !! com-
- mand does _n_o_t do shell expansion on the strings pro-
- vided as arguments. If any of the above expansions
- change the arguments the user entered, the command is
- redisplayed at the bottom of the screen.
-
- VVii then executes the program named by the sshheellll option,
- with a --cc flag followed by the arguments (which are
- bundled into a single argument).
-
- The !! command is permitted in an empty file.
-
- If the file has been modified since it was last com-
- pletely written, the !! command will warn you.
-
- Line: The first line of the replaced text.
- Column: The first column of the replaced text.
- Options: Affected by the sshheellll option.
-
-[[ccoouunntt]] ## ++||--||##
- Increment or decrement the current number. The current
- number begins at the first non-number character on or
- before the current cursor position, or the beginning of
- the line, and extends up to the first non-number char-
- acter on or after the current cursor position or the
- end of the line. If the trailing character is a ++, the
- number is incremented by ccoouunntt. If the trailing
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--2244 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
- character is a --, the number is decremented by ccoouunntt.
- If the trailing character is a ##, the previous incre-
- ment or decrement is repeated.
-
- The format of the number (decimal, hexadecimal, and
- octal, and leading 0's) is retained unless the new
- value cannot be represented in the previous format.
-
- Line: Unchanged.
- Column: Set to the first character in the cursor word.
- Options: None.
-
-[[ccoouunntt]] $$
- Move the cursor to the end of a line. If ccoouunntt is
- specified, the cursor moves down ccoouunntt -- 11 lines.
-
- It is not an error to use the $$ command when the cursor
- is on the last character in the line or when the line
- is empty.
-
- The $$ command may be used as the motion component of
- other vvii commands, in which case any text copied into a
- buffer is character oriented, unless the cursor is at,
- or before the first nonblank character in the line, in
- which case it is line oriented. It is not an error to
- use the $$ command as a motion component when the cursor
- is on the last character in the line, although it is an
- error when the line is empty.
-
- Line: Set to the current line plus ccoouunntt minus 1.
- Column: Set to the last character in the line.
- Options: None.
-
-%%
- Move to the matching character. The cursor moves to
- the parenthesis or curly brace which _m_a_t_c_h_e_s the paren-
- thesis or curly brace found at the current cursor posi-
- tion or which is the closest one to the right of the
- cursor on the line. It is an error to execute the %%
- command on a line without a parenthesis or curly brace.
- Historically, any ccoouunntt specified to the %% command was
- ignored.
-
- The %% command is an absolute movement. The %% command
- may be used as the motion component of other vvii com-
- mands, in which case any text copied into a buffer is
- character oriented, unless the starting point of the
- region is at or before the first nonblank character on
- its line, and the ending point is at or after the last
- nonblank character on its line, in which case it is
- line oriented.
-
-
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--2255
-
-
- Line: Set to the line containing the matching char-
- acter.
- Column: Set to the matching character.
- Options: None.
-
-&&
- Repeat the previous substitution command on the current
- line.
-
- Historically, any ccoouunntt specified to the && command was
- ignored.
-
- Line: Unchanged.
- Column: Unchanged if the cursor was on the last char-
- acter in the line, otherwise, set to the first
- nonblank character in the line.
- Options: Affected by the eeddccoommppaattiibbllee, eexxtteennddeedd,
- iiggnnoorreeccaassee and mmaaggiicc options.
-
-''<<cchhaarraacctteerr>>
-``<<cchhaarraacctteerr>>
- Return to a context marked by the character <<cchhaarraacc--
- tteerr>>. If <<cchhaarraacctteerr>> is the "''" or "``" character,
- return to the previous context. If <<cchhaarraacctteerr>> is any
- other character, return to the context marked by that
- character (see the mm command for more information). If
- the command is the '' command, only the line value is
- restored, and the cursor is placed on the first non-
- blank character of that line. If the command is the ``
- command, both the line and column values are restored.
-
- It is an error if the context no longer exists because
- of line deletion. (Contexts follow lines that are
- moved, or which are deleted and then restored.)
-
- The '' and `` commands are both absolute movements. They
- may be used as a motion component for other vvii com-
- mands. For the '' command, any text copied into a
- buffer is line oriented. For the `` command, any text
- copied into a buffer is character oriented, unless it
- both starts and stops at the first character in the
- line, in which case it is line oriented. In addition,
- when using the `` command as a motion component, com-
- mands which move backward and started at the first
- character in the line, or move forward and ended at the
- first character in the line, are corrected to the last
- character of the starting and ending lines, respec-
- tively.
-
- Line: Set to the line from the context.
- Column: Set to the first nonblank character in the
- line, for the '' command, and set to the con-
- text's column for the `` command.
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--2266 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
- Options: None.
-
-[[ccoouunntt]] ((
- Back up ccoouunntt sentences.
-
- The (( command is an absolute movement. The (( command
- may be used as the motion component of other vvii com-
- mands, in which case any text copied into a buffer is
- character oriented, unless the starting and stopping
- points of the region are the first character in the
- line, in which case it is line oriented. In the latter
- case, the stopping point of the region is adjusted to
- be the end of the line immediately before it, and not
- the original cursor position.
-
- Line: Set to the line containing the beginning of
- the sentence.
- Column: Set to the first nonblank character of the
- sentence.
- Options: None.
-
-[[ccoouunntt]] ))
- Move forward ccoouunntt sentences.
-
- The )) command is an absolute movement. The )) command
- may be used as the motion component of other vvii com-
- mands, in which case any text copied into a buffer is
- character oriented, unless the starting point of the
- region is the first character in the line, in which
- case it is line oriented. In the latter case, if the
- stopping point of the region is also the first charac-
- ter in the line, it is adjusted to be the end of the
- line immediately before it.
-
- Line: Set to the line containing the beginning of
- the sentence.
- Column: Set to the first nonblank character of the
- sentence.
- Options: None.
-
-[[ccoouunntt]] ,,
- Reverse find character ccoouunntt times. Reverse the last
- FF, ff, TT or tt command, searching the other way in the
- line, ccoouunntt times.
-
- The ,, command may be used as the motion component of
- other vvii commands, in which case any text copied into a
- buffer is character oriented.
-
- Line: Unchanged.
- Column: Set to the searched-for character.
- Options: None.
-
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--2277
-
-
-[[ccoouunntt]] --
- Move to first nonblank of the previous line, ccoouunntt
- times.
-
- This is an error if the movement is past the beginning
- of the file.
-
- The -- command may be used as the motion component of
- other vvii commands, in which case any text copied into a
- buffer is line oriented.
-
- Line: Set to the current line minus ccoouunntt.
- Column: Set to the first nonblank character in the
- line.
- Options: None.
-
-[[ccoouunntt]] ..
- Repeat the last vvii command that modified text. The
- repeated command may be a command and motion component
- combination. If ccoouunntt is specified, it replaces _b_o_t_h
- the count specified for the repeated command, and, if
- applicable, for the repeated motion component. If
- ccoouunntt is not specified, the counts originally specified
- to the command being repeated are used again.
-
- As a special case, if the .. command is executed imme-
- diately after the uu command, the change log is rolled
- forward or backward, depending on the action of the uu
- command.
-
- Line: Set as described for the repeated command.
- Column: Set as described for the repeated command.
- Options: None.
-
-//RREE<<ccaarrrriiaaggee--rreettuurrnn>>
-//RREE// [[ooffffsseett]]<<ccaarrrriiaaggee--rreettuurrnn>>
-??RREE<<ccaarrrriiaaggee--rreettuurrnn>>
-??RREE?? [[ooffffsseett]]<<ccaarrrriiaaggee--rreettuurrnn>>
-NN
-nn
- Search forward or backward for a regular expression.
- The commands beginning with a slash ("//") character are
- forward searches, the commands beginning with a ques-
- tion mark ("??") are backward searches. VVii prompts
- with the leading character on the last line of the
- screen for a string. It then searches forward or back-
- ward in the file for the next occurrence of the string,
- which is interpreted as a Basic Regular Expression.
-
- The // and ?? commands are absolute movements. They may
- be used as the motion components of other vvii commands,
- in which case any text copied into a buffer is charac-
- ter oriented, unless the search started and ended on
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--2288 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
- the first column of a line, in which case it is line
- oriented. In addition, forward searches ending at the
- first character of a line, and backward searches begin-
- ning at the first character in the line, are corrected
- to begin or end at the last character of the previous
- line. (Note, forward and backward searches can occur
- for both // and ?? commands, if the wwrraappssccaann option is
- set.)
-
- If an offset from the matched line is specified (i.e. a
- trailing "//" or "??" character is followed by a signed
- offset), the buffer will always be line oriented (e.g.
- "//ssttrriinngg//++00" will always guarantee a line orientation).
-
- The nn command repeats the previous search.
-
- The NN command repeats the previous search, but in the
- reverse direction.
-
- Missing RE's (e.g. "////<<ccaarrrriiaaggee--rreettuurrnn>>", "//<<ccaarrrriiaaggee--
- rreettuurrnn>>", "????<<ccaarrrriiaaggee--rreettuurrnn>>", or "??<<ccaarrrriiaaggee--
- rreettuurrnn>>" search for the last search RE, in the indi-
- cated direction.
-
- Searches may be interrupted using the <<iinntteerrrruupptt>> char-
- acter.
-
- Line: Set to the line in which the match occurred.
- Column: Set to the first character of the matched
- string.
- Options: Affected by the eeddccoommppaattiibbllee, eexxtteennddeedd,
- iiggnnoorreeccaassee, mmaaggiicc, and wwrraappssccaann options.
-
-00
- Move to the first character in the current line. It is
- not an error to use the 00 command when the cursor is on
- the first character in the line,
-
- The 00 command may be used as the motion component of
- other vvii commands, in which case it is an error if the
- cursor is on the first character in the line.
-
- Line: Unchanged.
- Column: Set to the first character in the line.
- Options: None.
-
-::
- Execute an ex command. VVii prompts for an eexx command on
- the last line of the screen, using a colon ("::") char-
- acter. The command is terminated by a <<ccaarrrriiaaggee--
- rreettuurrnn>>, <<nneewwlliinnee>> or <<eessccaappee>> character; all of these
- characters may be escaped by using a <<lliitteerraall nneexxtt>>
- character. The command is then executed.
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--2299
-
-
- If the eexx command writes to the screen, vvii will prompt
- the user for a <<ccaarrrriiaaggee--rreettuurrnn>> before continuing when
- the eexx command finishes. Large amounts of output from
- the eexx command will be paged for the user, and the user
- prompted for a <<ccaarrrriiaaggee--rreettuurrnn>> or <<ssppaaccee>> key to con-
- tinue. In some cases, a quit (normally a "q" charac-
- ter) or <<iinntteerrrruupptt>> may be entered to interrupt the eexx
- command.
-
- When the eexx command finishes, and the user is prompted
- to resume visual mode, it is also possible to enter
- another "::" character followed by another eexx command.
-
- Line: The current line is set as described for the
- eexx command.
- Column: The current column is set as described for the
- eexx command.
- Options: None.
-
-[[ccoouunntt]] ;;
- Repeat the last character find ccoouunntt times. The last
- character find is one of the FF, ff, TT or tt commands.
-
- The ;; command may be used as the motion component of
- other vvii commands, in which case any text copied into a
- buffer is character oriented.
-
- Line: Unchanged.
- Column: Set to the searched-for character.
- Options: None.
-
-[[ccoouunntt]] << mmoottiioonn
-[[ccoouunntt]] >> mmoottiioonn
- Shift lines left or right. Shift the number of lines
- in the region specified by the motion component, times
- ccoouunntt, left (for the << command) or right (for the >>
- command) by the number of columns specified by the
- sshhiiffttwwiiddtthh option. Only whitespace characters are
- deleted when shifting left; once the first character in
- the line contains a nonblank character, the sshhiifftt will
- succeed, but the line will not be modified.
-
- Line: Unchanged.
- Column: Set to the first nonblank character in the
- line.
- Options: Affected by the sshhiiffttwwiiddtthh option.
-
-@@ bbuuffffeerr
- Execute a named buffer. Execute the named buffer as vvii
- commands. The buffer may include eexx commands, too, but
- they must be expressed as a :: command. If the buffer
- is line oriented, <<nneewwlliinnee>> characters are logically
- appended to each line of the buffer. If the buffer is
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--3300 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
- character oriented, <<nneewwlliinnee>> characters are logically
- appended to all but the last line in the buffer.
-
- If the buffer name is "@@", or "**", then the last buffer
- executed shall be used. It is an error to specify "@@@@"
- or "****" if there were no buffer previous executions.
- The text of a macro may contain an @@ command, and it is
- possible to create infinite loops in this manner. (The
- <<iinntteerrrruupptt>> character may be used to interrupt the
- loop.)
-
- Line: The current line is set as described for the
- command(s).
- Column: The current column is set as described for the
- command(s).
- Options: None.
-
-[[ccoouunntt]] AA
- Enter input mode, appending the text after the end of
- the line. If ccoouunntt is specified, the text is repeat-
- edly input ccoouunntt -- 11 more times after input mode is
- exited.
-
- Line: Set to the last line upon which characters
- were entered.
- Column: Set to the last character entered.
- Options: Affected by the aallttwweerraassee, aauuttooiinnddeenntt, bbeeaauu--
- ttiiffyy, sshhoowwmmaattcchh, ttttyywweerraassee and wwrraappmmaarrggiinn
- options.
-
-[[ccoouunntt]] BB
- Move backward ccoouunntt bigwords. Move the cursor backward
- to the beginning of a bigword by repeating the follow-
- ing algorithm: if the current position is at the begin-
- ning of a bigword or the character at the current posi-
- tion cannot be part of a bigword, move to the first
- character of the preceding bigword. Otherwise, move to
- the first character of the bigword at the current posi-
- tion. If no preceding bigword exists on the current
- line, move to the first character of the last bigword
- on the first preceding line that contains a bigword.
-
- The BB command may be used as the motion component of
- other vvii commands, in which case any text copied into a
- buffer is character oriented.
-
- Line: Set to the line containing the word selected.
- Column: Set to the first character of the word
- selected.
- Options: None.
-
-[[bbuuffffeerr]] [[ccoouunntt]] CC
- Change text from the current position to the end-of-
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--3311
-
-
- line. If ccoouunntt is specified, the input text replaces
- from the current position to the end-of-line, plus
- ccoouunntt -- 11 subsequent lines.
-
- Line: Set to the last line upon which characters
- were entered.
- Column: Set to the last character entered.
- Options: Affected by the aallttwweerraassee, aauuttooiinnddeenntt, bbeeaauu--
- ttiiffyy, sshhoowwmmaattcchh, ttttyywweerraassee and wwrraappmmaarrggiinn
- options.
-
-[[bbuuffffeerr]] DD
- Delete text from the current position to the end-of-
- line.
-
- It is not an error to execute the DD command on an empty
- line.
-
- Line: Unchanged.
- Column: Set to the character before the current char-
- acter, or, column 1 if the cursor was on col-
- umn 1.
- Options: None.
-
-[[ccoouunntt]] EE
- Move forward ccoouunntt end-of-bigwords. Move the cursor
- forward to the end of a bigword by repeating the fol-
- lowing algorithm: if the current position is the end of
- a bigword or the character at that position cannot be
- part of a bigword, move to the last character of the
- following bigword. Otherwise, move to the last charac-
- ter of the bigword at the current position. If no suc-
- ceeding bigword exists on the current line, move to the
- last character of the first bigword on the next follow-
- ing line that contains a bigword.
-
- The EE command may be used as the motion component of
- other vvii commands, in which case any text copied into a
- buffer is character oriented.
-
- Line: Set to the line containing the word selected.
- Column: Set to the last character of the word
- selected.
- Options: None.
-
-[[ccoouunntt]] FF <<cchhaarraacctteerr>>
- Search ccoouunntt times backward through the current line
- for <<cchhaarraacctteerr>>.
-
- The FF command may be used as the motion component of
- other vvii commands, in which case any text copied into a
- buffer is character oriented.
-
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--3322 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
- Line: Unchanged.
- Column: Set to the searched-for character.
- Options: None.
-
-[[ccoouunntt]] GG
- Move to line ccoouunntt, or the last line of the file if
- ccoouunntt not specified.
-
- The GG command is an absolute movement. The GG command
- may be used as the motion component of other vvii com-
- mands, in which case any text copied into a buffer is
- line oriented.
-
- Line: Set to ccoouunntt, if specified, otherwise, the
- last line.
- Column: Set to the first nonblank character in the
- line.
- Options: None.
-
-[[ccoouunntt]] HH
- Move to the screen line ccoouunntt -- 11 lines below the top
- of the screen.
-
- The HH command is an absolute movement. The HH command
- may be used as the motion component of other vvii com-
- mands, in which case any text copied into a buffer is
- line oriented.
-
- Line: Set to the line ccoouunntt -- 11 lines below the top
- of the screen.
- Column: Set to the first nonblank character of the
- _s_c_r_e_e_n line.
- Options: None.
-
-[[ccoouunntt]] II
- Enter input mode, inserting the text at the beginning
- of the line. If ccoouunntt is specified, the text input is
- repeatedly input ccoouunntt -- 11 more times.
-
- Line: Set to the last line upon which characters
- were entered.
- Column: Set to the last character entered.
- Options: None.
-
-[[ccoouunntt]] JJ
- Join lines. If ccoouunntt is specified, ccoouunntt lines are
- joined; a minimum of two lines are always joined,
- regardless of the value of ccoouunntt.
-
- If the current line ends with a whitespace character,
- all whitespace is stripped from the next line. Other-
- wise, if the next line starts with a open parenthesis
- ("((") do nothing. Otherwise, if the current line ends
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--3333
-
-
- with a question mark ("??"), period ("..") or exclama-
- tion point ("!!"), insert two spaces. Otherwise, insert
- a single space.
-
- It is not an error to join lines past the end of the
- file, i.e. lines that do not exist.
-
- Line: Unchanged.
- Column: Set to the character after the last character
- of the next-to-last joined line.
- Options: None.
-
-[[ccoouunntt]] LL
- Move to the screen line ccoouunntt -- 11 lines above the bot-
- tom of the screen.
-
- The LL command is an absolute movement. The LL command
- may be used as the motion component of other vvii com-
- mands, in which case any text copied into a buffer is
- line oriented.
-
- Line: Set to the line ccoouunntt -- 11 lines above the bot-
- tom of the screen.
- Column: Set to the first nonblank character of the
- _s_c_r_e_e_n line.
- Options: None.
-
- MM
- Move to the screen line in the middle of the screen.
-
- The MM command is an absolute movement. The MM command
- may be used as the motion component of other vvii com-
- mands, in which case any text copied into a buffer is
- line oriented.
-
- Historically, any ccoouunntt specified to the MM command was
- ignored.
-
- Line: Set to the line in the middle of the screen.
- Column: Set to the first nonblank character of the
- _s_c_r_e_e_n line.
- Options: None.
-
-[[ccoouunntt]] OO
- Enter input mode, appending text in a new line above
- the current line. If ccoouunntt is specified, the text
- input is repeatedly input ccoouunntt -- 11 more times.
-
- Historically, any ccoouunntt specified to the OO command was
- ignored.
-
- Line: Set to the last line upon which characters
- were entered.
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--3344 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
- Column: Set to the last character entered.
- Options: Affected by the aallttwweerraassee, aauuttooiinnddeenntt, bbeeaauu--
- ttiiffyy, sshhoowwmmaattcchh, ttttyywweerraassee and wwrraappmmaarrggiinn
- options.
-
-[[bbuuffffeerr]] PP
- Insert text from a buffer. Text from the buffer (the
- unnamed buffer by default) is inserted before the cur-
- rent column or, if the buffer is line oriented, before
- the current line.
-
- Line: Set to the lowest numbered line insert, if the
- buffer is line oriented, otherwise unchanged.
- Column: Set to the first nonblank character of the
- appended text, if the buffer is line oriented,
- otherwise, the last character of the appended
- text.
- Options: None.
-
-QQ
- Exit vvii (or visual) mode and switch to eexx mode.
-
- Line: Unchanged.
- Column: No longer relevant.
- Options: None.
-
-[[ccoouunntt]] RR
- Enter input mode, replacing the characters in the cur-
- rent line. If ccoouunntt is specified, the text input is
- repeatedly input ccoouunntt -- 11 more times.
-
- If the end of the current line is reached, no more
- characters are replaced and any further characters
- input are appended to the line.
-
- Line: Set to the last line upon which characters
- were entered.
- Column: Set to the last character entered.
- Options: Affected by the aallttwweerraassee, aauuttooiinnddeenntt, bbeeaauu--
- ttiiffyy, sshhoowwmmaattcchh, ttttyywweerraassee and wwrraappmmaarrggiinn
- options.
-
-[[bbuuffffeerr]] [[ccoouunntt]] SS
- Substitute ccoouunntt lines.
-
- Line: Set to the last line upon which characters
- were entered.
- Column: Set to the last character entered.
- Options: Affected by the aallttwweerraassee, aauuttooiinnddeenntt, bbeeaauu--
- ttiiffyy, sshhoowwmmaattcchh, ttttyywweerraassee and wwrraappmmaarrggiinn
- options.
-
-
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--3355
-
-
-[[ccoouunntt]] TT <<cchhaarraacctteerr>>
- Search backward, ccoouunntt times, through the current line
- for the character _a_f_t_e_r the specified <<cchhaarraacctteerr>>.
-
- The TT command may be used as the motion component of
- other vvii commands, in which case any text copied into a
- buffer is character oriented.
-
- Line: Unchanged.
- Column: Set to the character _a_f_t_e_r the searched-for
- character.
- Options: None.
-
-UU
- Restore the current line to its state before the cursor
- last moved to it.
-
- Line: Unchanged.
- Column: The first character in the line.
- Options: None.
-
-[[ccoouunntt]] WW
- Move forward ccoouunntt bigwords. Move the cursor forward
- to the beginning of a bigword by repeating the follow-
- ing algorithm: if the current position is within a big-
- word or the character at that position cannot be part
- of a bigword, move to the first character of the next
- bigword. If no subsequent bigword exists on the cur-
- rent line, move to the first character of the first
- bigword on the first following line that contains a
- bigword.
-
- The WW command may be used as the motion component of
- other vvii commands, in which case any text copied into a
- buffer is character oriented.
-
- Line: The line containing the word selected.
- Column: The first character of the word selected.
- Options: None.
-
-[[bbuuffffeerr]] [[ccoouunntt]] XX
- Delete ccoouunntt characters before the cursor. If the num-
- ber of characters to be deleted is greater than or
- equal to the number of characters to the beginning of
- the line, all of the characters before the current cur-
- sor position, to the beginning of the line, are
- deleted.
-
- Line: Unchanged.
- Column: Set to the current character minus ccoouunntt, or
- the first character if count is greater than
- the number of characters in the line before
- the cursor.
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--3366 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
- Options: None.
-
-[[bbuuffffeerr]] [[ccoouunntt]] YY
- Copy (or "yank") ccoouunntt lines into the specified buffer.
-
- Line: Unchanged.
- Column: Unchanged.
- Options: None.
-
-ZZZZ
- Write the file and exit vvii. The file is only written
- if it has been modified since the last complete write
- of the file to any file.
-
- The ZZZZ command will exit the editor after writing the
- file, if there are no further files to edit. Entering
- two "quit" commands (i.e. wwqq, qquuiitt, xxiitt or ZZZZ) in a
- row will override this check and the editor will exit,
- ignoring any files that have not yet been edited.
-
- Line: Unchanged.
- Column: Unchanged.
- Options: None.
-
-[[ccoouunntt]] [[[[
- Back up ccoouunntt section boundaries.
-
- The [[[[ command is an absolute movement. The [[[[ command
- may be used as the motion component of other vvii com-
- mands, in which case any text copied into a buffer is
- character oriented, unless the starting position is
- column 0, in which case it is line oriented.
-
- This is an error if the movement is past the beginning
- of the file.
-
- Line: Set to the previous line that is ccoouunntt section
- boundaries back, or the first line of the file
- if no more section boundaries exist preceding
- the current line.
- Column: Set to the first nonblank character in the
- line.
- Options: Affected by the sseeccttiioonnss option.
-
-[[ccoouunntt]] ]]]]
- Move forward ccoouunntt section boundaries.
-
- The ]]]] command is an absolute movement. The ]]]] command
- may be used as the motion component of other vvii com-
- mands, in which case any text copied into a buffer is
- character oriented, unless the starting position is
- column 0, in which case it is line oriented.
-
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--3377
-
-
- This is an error if the movement is past the end of the
- file.
-
- Line: Set to the line that is ccoouunntt section bound-
- aries forward, or to the last line of the file
- if no more section boundaries exist following
- the current line.
- Column: Set to the first nonblank character in the
- line.
- Options: Affected by the sseeccttiioonnss option.
-
-^^
- Move to first nonblank character on the current line.
-
- The ^^ command may be used as the motion component of
- other vvii commands, in which case any text copied into a
- buffer is character oriented.
-
- Line: Unchanged.
- Column: Set to the first nonblank character of the
- current line.
- Options: None.
-
-[[ccoouunntt]] __
- Move down ccoouunntt -- 11 lines, to the first nonblank char-
- acter. The __ command may be used as the motion compo-
- nent of other vvii commands, in which case any text
- copied into a buffer is line oriented.
-
- It is not an error to execute the __ command when the
- cursor is on the first character in the line.
-
- Line: The current line plus ccoouunntt -- 11.
- Column: The first nonblank character in the line.
- Options: None.
-
-[[ccoouunntt]] aa
- Enter input mode, appending the text after the cursor.
- If ccoouunntt is specified, the text input is repeatedly
- input ccoouunntt -- 11 more times.
-
- Line: Set to the last line upon which characters
- were entered.
- Column: Set to the last character entered.
- Options: Affected by the aallttwweerraassee, aauuttooiinnddeenntt, bbeeaauu--
- ttiiffyy, sshhoowwmmaattcchh, ttttyywweerraassee and wwrraappmmaarrggiinn
- options.
-
-[[ccoouunntt]] bb
- Move backward ccoouunntt words. Move the cursor backward to
- the beginning of a word by repeating the following
- algorithm: if the current position is at the beginning
- of a word, move to the first character of the preceding
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--3388 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
- word. Otherwise, the current position moves to the
- first character of the word at the current position.
- If no preceding word exists on the current line, move
- to the first character of the last word on the first
- preceding line that contains a word.
-
- The bb command may be used as the motion component of
- other vvii commands, in which case any text copied into a
- buffer is character oriented.
-
- Line: Set to the line containing the word selected.
- Column: Set to the first character of the word
- selected.
- Options: None.
-
-[[bbuuffffeerr]] [[ccoouunntt]] cc mmoottiioonn
- Change a region of text. If only part of a single line
- is affected, then the last character being changed is
- marked with a "$$". Otherwise, the region of text is
- deleted, and input mode is entered.
-
- If ccoouunntt is specified, it is applied to the mmoottiioonn.
-
- Line: Set to the last line upon which characters
- were entered.
- Column: Set to the last character entered.
- Options: Affected by the aallttwweerraassee, aauuttooiinnddeenntt, bbeeaauu--
- ttiiffyy, sshhoowwmmaattcchh, ttttyywweerraassee and wwrraappmmaarrggiinn
- options.
-
-[[bbuuffffeerr]] [[ccoouunntt]] dd mmoottiioonn
- Delete a region of text. If ccoouunntt is specified, it is
- applied to the mmoottiioonn.
-
- Line: Set to the line where the region starts.
- Column: Set to the first character in the line after
- the last character in the region. If no such
- character exists, set to the last character
- before the region.
- Options: None.
-
-[[ccoouunntt]] ee
- Move forward ccoouunntt end-of-words. Move the cursor for-
- ward to the end of a word by repeating the following
- algorithm: if the current position is the end of a
- word, move to the last character of the following word.
- Otherwise, move to the last character of the word at
- the current position. If no succeeding word exists on
- the current line, move to the last character of the
- first word on the next following line that contains a
- word.
-
- The ee command may be used as the motion component of
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--3399
-
-
- other vvii commands, in which case any text copied into a
- buffer is character oriented.
-
- Line: Set to the line containing the word selected.
- Column: Set to the last character of the word
- selected.
- Options: None.
-
-[[ccoouunntt]] ff <<cchhaarraacctteerr>>
- Search forward, ccoouunntt times, through the rest of the
- current line for <<cchhaarraacctteerr>>.
-
- The ff command may be used as the motion component of
- other vvii commands, in which case any text copied into a
- buffer is character oriented.
-
- Line: Unchanged.
- Column: Set to the searched-for character.
- Options: None.
-
-[[ccoouunntt]] ii
- Enter input mode, inserting the text before the cursor.
- If ccoouunntt is specified, the text input is repeatedly
- input ccoouunntt -- 11 more times.
-
- Line: Set to the last line upon which characters
- were entered.
- Column: Set to the last character entered.
- Options: Affected by the aallttwweerraassee, aauuttooiinnddeenntt, bbeeaauu--
- ttiiffyy, sshhoowwmmaattcchh, ttttyywweerraassee and wwrraappmmaarrggiinn
- options.
-
-mm <<cchhaarraacctteerr>>
- Save the current context (line and column) as <<cchhaarraacc--
- tteerr>>. The exact position is referred to by "``<<cchhaarraacc--
- tteerr>>". The line is referred to by "''<<cchhaarraacctteerr>>".
-
- Historically, <<cchhaarraacctteerr>> was restricted to lower-case
- letters only, nnvvii permits the use of any character.
-
- Line: Unchanged.
- Column: Unchanged.
- Options: None.
-
-[[ccoouunntt]] oo
- Enter input mode, appending text in a new line under
- the current line. If ccoouunntt is specified, the text
- input is repeatedly input ccoouunntt -- 11 more times.
-
- Historically, any ccoouunntt specified to the oo command was
- ignored.
-
-
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--4400 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
- Line: Set to the last line upon which characters
- were entered.
- Column: Set to the last character entered.
- Options: Affected by the aallttwweerraassee, aauuttooiinnddeenntt, bbeeaauu--
- ttiiffyy, sshhoowwmmaattcchh, ttttyywweerraassee and wwrraappmmaarrggiinn
- options.
-
-[[bbuuffffeerr]] pp
- Append text from a buffer. Text from the buffer (the
- unnamed buffer by default) is appended after the cur-
- rent column or, if the buffer is line oriented, after
- the current line.
-
- Line: Set to the first line appended, if the buffer
- is line oriented, otherwise unchanged.
- Column: Set to the first nonblank character of the
- appended text if the buffer is line oriented,
- otherwise, the last character of the appended
- text.
- Options: None.
-
-[[ccoouunntt]] rr <<cchhaarraacctteerr>>
- Replace characters. The next ccoouunntt characters in the
- line are replaced with <<cchhaarraacctteerr>>. Replacing charac-
- ters with <<nneewwlliinnee>> characters results in creating new,
- empty lines into the file.
-
- If <<cchhaarraacctteerr>> is <<eessccaappee>>, the command is cancelled.
-
- Line: Unchanged unless the replacement character is
- a <<nneewwlliinnee>>, in which case it is set to the
- current line plus ccoouunntt -- 11.
- Column: Set to the last character replaced, unless the
- replacement character is a <<nneewwlliinnee>>, in which
- case the cursor is in column 1 of the last
- line inserted.
- Options: None.
-
-[[bbuuffffeerr]] [[ccoouunntt]] ss
- Substitute ccoouunntt characters in the current line start-
- ing with the current character.
-
- Line: Set to the last line upon which characters
- were entered.
- Column: Set to the last character entered.
- Options: Affected by the aallttwweerraassee, aauuttooiinnddeenntt, bbeeaauu--
- ttiiffyy, sshhoowwmmaattcchh, ttttyywweerraassee and wwrraappmmaarrggiinn
- options.
-
-[[ccoouunntt]] tt <<cchhaarraacctteerr>>
- Search forward, ccoouunntt times, through the current line
- for the character immediately _b_e_f_o_r_e <<cchhaarraacctteerr>>.
-
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--4411
-
-
- The tt command may be used as the motion component of
- other vvii commands, in which case any text copied into a
- buffer is character oriented.
-
- Line: Unchanged.
- Column: Set to the character _b_e_f_o_r_e the searched-for
- character.
- Options: None.
-
-uu
- Undo the last change made to the file. If repeated,
- the uu command alternates between these two states, and
- is its own inverse. When used after an insert that
- inserted text on more than one line, the lines are
- saved in the numeric buffers.
-
- The .. command, when used immediately after the uu com-
- mand, causes the change log to be rolled forward or
- backward, depending on the action of the uu command.
-
- Line: Set to the position of the first line changed,
- if the reversal affects only one line or rep-
- resents an addition or change; otherwise, the
- line preceding the deleted text.
- Column: Set to the cursor position before the change
- was made.
- Options: None.
-
-[[ccoouunntt]] ww
- Move forward ccoouunntt words. Move the cursor forward to
- the beginning of a word by repeating the following
- algorithm: if the current position is at the beginning
- of a word, move to the first character of the next
- word. If no subsequent word exists on the current
- line, move to the first character of the first word on
- the first following line that contains a word.
-
- The ww command may be used as the motion component of
- other vvii commands, in which case any text copied into a
- buffer is character oriented.
-
- Line: Set to the line containing the word selected.
- Column: Set to the first character of the word
- selected.
- Options: None.
-
-[[bbuuffffeerr]] [[ccoouunntt]] xx
- Delete ccoouunntt characters. The deletion is at the cur-
- rent character position. If the number of characters
- to be deleted is greater than or equal to the number of
- characters to the end of the line, all of the charac-
- ters from the current cursor position to the end of the
- line are deleted.
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--4422 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
- Line: Unchanged.
- Column: Unchanged unless the last character in the
- line is deleted and the cursor is not already
- on the first character in the line, in which
- case it is set to the previous character.
- Options: None.
-
-[[bbuuffffeerr]] [[ccoouunntt]] yy mmoottiioonn
- Copy (or "yank") a text region specified by the ccoouunntt
- and motion into a buffer. If ccoouunntt is specified, it is
- applied to the mmoottiioonn.
-
- Line: Unchanged, unless the region covers more than
- a single line, in which case it is set to the
- line where the region starts.
- Column: Unchanged, unless the region covers more than
- a single line, in which case it is set to the
- character were the region starts.
- Options: None.
-
-[[ccoouunntt11]] zz [[ccoouunntt22]] ttyyppee
- Redraw the screen with a window ccoouunntt22 lines long, with
- line ccoouunntt11 placed as specified by the ttyyppee character.
- If ccoouunntt11 is not specified, it defaults to the current
- line. If ccoouunntt22 is not specified, it defaults to the
- current window size.
-
- The following ttyyppee characters may be used:
-
- + If ccoouunntt11 is specified, place the line ccoouunntt11
- at the top of the screen. Otherwise, display
- the screen after the current screen, similarly
- to the <<ccoonnttrrooll--FF>> command.
- <carriage-return>
- Place the line ccoouunntt11 at the top of the
- screen.
- . Place the line ccoouunntt11 in the center of the
- screen.
- - Place the line ccoouunntt11 at the bottom of the
- screen.
- ^ If ccoouunntt11 is specified, place the line that is
- at the top of the screen when ccoouunntt11 is at the
- bottom of the screen, at the bottom of the
- screen, i.e. display the screen before the
- screen before ccoouunntt11. Otherwise, display the
- screen before the current screen, similarly to
- the <<ccoonnttrrooll--BB>> command.
-
- Line: Set to ccoouunntt11 unless ccoouunntt11 is not specified
- and the ttyyppee character was either "^^" or "++",
- in which case it is set to the line before the
- first line on the previous screen or the line
- after the last line on the previous screen,
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--4433
-
-
- respectively.
- Column: Set to the first nonblank character in the
- line.
- Options: None.
-
-[[ccoouunntt]] {{
- Move backward ccoouunntt paragraphs.
-
- The {{ command is an absolute movement. The {{ command
- may be used as the motion component of other vvii com-
- mands, in which case any text copied into a buffer is
- character oriented, unless the starting character is
- the first character on its line, in which case it is
- line oriented.
-
- Line: Set to the line containing the beginning of
- the previous paragraph.
- Column: Set to the first nonblank character in the
- line.
- Options: Affected by the ppaarraaggrraapphh option.
-
-[[ccoouunntt]] ||
- Move to a specific _c_o_l_u_m_n position on the current line.
-
- The || command may be used as the motion component of
- other vvii commands, in which case any text copied into a
- buffer is character oriented. It is an error to use
- the || command as a motion component and for the cursor
- not to move.
-
- Line: Unchanged.
- Column: Set to the character occupying the column
- position identified by ccoouunntt, if the position
- exists in the line. If the column length of
- the current line is less than ccoouunntt, the cur-
- sor is moved to the last character in the
- line.
- Options: None.
-
-[[ccoouunntt]] }}
- Move forward ccoouunntt paragraphs.
-
- The }} command is an absolute movement. The }} command
- may be used as the motion component of other vvii com-
- mands, in which case any text copied into a buffer is
- character oriented, unless the starting character is at
- or before any nonblank characters in its line, in which
- case it is line oriented.
-
- Line: Set to the line containing the beginning of
- the next paragraph.
- Column: Set to the first nonblank character in the
- line.
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--4444 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
- Options: Affected by the ppaarraaggrraapphh option.
-
-[[ccoouunntt]] ~~
- Reverse the case of the next ccoouunntt character(s). This
- is the historic semantic for the ~~ command and it is
- only in effect if the ttiillddeeoopp option is not set.
-
- Lowercase alphabetic characters are changed to upper-
- case, and uppercase characters are changed to lower-
- case. No other characters are affected.
-
- Historically, the ~~ command did not take an associated
- count, nor did it move past the end of the current
- line. As it had no associated motion it was difficult
- to change the case of large blocks of text. In nnvvii, if
- the cursor is on the last character of a line, and
- there are more lines in the file, the cursor moves to
- the next line.
-
- It is not an error to specify a count larger than the
- number of characters between the cursor and the end of
- the file.
-
- Line: Set to the line of the character after ccoouunntt
- characters, or, end of file.
- Column: Set to the character after ccoouunntt characters,
- or, end-of-file.
- Options: Affected by the ttiillddeeoopp option.
-
-[[ccoouunntt]] ~~ mmoottiioonn
- Reverse the case of the characters in a text region
- specified by the ccoouunntt and mmoottiioonn. Only in effect if
- the ttiillddeeoopp option is set.
-
- Lowercase characters are changed to uppercase, and
- uppercase characters are changed to lowercase. No
- other characters are affected.
-
- Line: Set to the line of the character after the
- last character in the region.
- Column: Set to the character after the last character
- in the region.
- Options: Affected by the ttiillddeeoopp option.
-
-<<iinntteerrrruupptt>>
- Interrupt the current operation. Many of the poten-
- tially long-running vvii commands may be interrupted
- using the terminal interrupt character. These opera-
- tions include searches, file reading and writing, fil-
- ter operations and map character expansion. Interrupts
- are also enabled when running commands outside of vvii.
-
- If the <<iinntteerrrruupptt>> character is used to interrupt while
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--4455
-
-
- entering an eexx command, the command is aborted, the
- cursor returns to its previous position, and vvii remains
- in command mode.
-
- Generally, if the <<iinntteerrrruupptt>> character is used to
- interrupt any operation, any changes made before the
- interrupt are left in place.
-
- Line: Dependent on the operation being interrupted.
- Column: Dependent on the operation being interrupted.
- Options: None.
-
- 1111.. VVii TTeexxtt IInnppuutt CCoommmmaannddss
-
- The following section describes the commands
- available in the text input mode of the vvii editor.
-
- Historically, vvii implementations only permitted
- the characters inserted on the current line to be
- erased. In addition, only the <<ccoonnttrrooll--DD>> erase char-
- acter and the "00<<ccoonnttrrooll--DD>>" and "^^<<ccoonnttrrooll--DD>>" erase
- strings could erase autoindent characters. This imple-
- mentation permits erasure to continue past the begin-
- ning of the current line, and back to where text input
- mode was entered. In addition, autoindent characters
- may be erased using the standard erase characters. For
- the line and word erase characters, reaching the
- autoindent characters forms a "soft" boundary, denoting
- the end of the current word or line erase. Repeating
- the word or line erase key will erase the autoindent
- characters.
-
- Historically, vvii always used <<ccoonnttrrooll--HH>> and <<ccoonn--
- ttrrooll--WW>> as character and word erase characters, respec-
- tively, regardless of the current terminal settings.
- This implementation accepts, in addition to these two
- characters, the current terminal characters for those
- operations.
-
- <<nnuull>>
- If the first character of the input is a <<nnuull>>,
- the previous input is replayed, as if just
- entered.
-
- <<ccoonnttrrooll--DD>>
- If the previous character on the line was an
- autoindent character, erase it. Otherwise, if the
- user is entering the first character in the line,
- <<ccoonnttrrooll--DD>> is ignored. Otherwise, a literal
- <<ccoonnttrrooll--DD>> character is entered.
-
- ^^<<ccoonnttrrooll--DD>>
- If the previous character on the line was an
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--4466 NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss))
-
-
- autoindent character, erase all of the autoindent
- characters on the line. In addition, the autoin-
- dent level is reset to 0.
-
- 00<<ccoonnttrrooll--DD>>
- If the previous character on the line was an
- autoindent character, erase all of the autoindent
- characters on the line.
-
- <<ccoonnttrrooll--TT>>
- Insert sufficient <<ttaabb>> and <<ssppaaccee>> characters to
- move the cursor forward to a column immediately
- after the next column which is an even multiple of
- the sshhiiffttwwiiddtthh option.
-
- Historically, vvii did not permit the <<ccoonnttrrooll--TT>>
- command to be used unless the cursor was at the
- first column of a new line or it was preceded only
- by autoindent characters. NNvvii permits it to be
- used at any time during insert mode.
-
- <<eerraassee>>
- <<ccoonnttrrooll--HH>>
- Erase the last character.
-
- <<lliitteerraall nneexxtt>>
- Quote the next character. The next character will
- not be mapped (see the mmaapp command for more infor-
- mation) or interpreted specially. A carat ("^^")
- character will be displayed immediately as a
- placeholder, but will be replaced by the next
- character.
-
- <<eessccaappee>>
- Resolve all text input into the file, and return
- to command mode.
-
- <<lliinnee eerraassee>>
- Erase the current line.
-
- <<ccoonnttrrooll--WW>>
- <<wwoorrdd eerraassee>>
- Erase the last word. The definition of word is
- dependent on the aallttwweerraassee and ttttyywweerraassee options.
-
- <<ccoonnttrrooll--XX>>[[00--99AA--FFaa--ff]]**
- Insert a character with the specified hexadecimal
- value into the text.
-
- <<iinntteerrrruupptt>>
- Interrupt text input mode, returning to command
- mode. If the <<iinntteerrrruupptt>> character is used to
- interrupt inserting text into the file, it is as
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((VVii CCoommmmaannddss)) UUSSDD::1133--4477
-
-
- if the <<eessccaappee>> character was used; all text input
- up to the interruption is resolved into the file.
-
- 1122.. EExx AAddddrreessssiinngg
-
- Addressing in eexx (and when eexx commands are exe-
- cuted from vvii) relates to the current line. In gen-
- eral, the current line is the last line affected by a
- command. The exact effect on the current line is dis-
- cussed under the description of each command. When the
- file contains no lines, the current line is zero.
-
- Addresses are constructed by one or more of the
- following methods:
-
- (1) The address ".." refers to the current line.
-
- (2) The address "$$" refers to the last line of the
- file.
-
- (3) The address "NN", where NN is a positive number,
- refers to the N-th line of the file.
-
- (4) The address "''<<cchhaarraacctteerr>>" or "``<<cchhaarraacctteerr>>"
- refers to the line marked with the name <<cchhaarraacc--
- tteerr>>. (See the kk or mm commands for more infor-
- mation on how to mark lines.)
-
- (5) A regular expression (RE) enclosed by slashes
- ("//") is an address, and it refers to the first
- line found by searching forward from the line
- _a_f_t_e_r the current line toward the end of the
- file, and stopping at the first line containing
- a string matching the RE. (The trailing slash
- can be omitted at the end of the command line.)
-
- If no RE is specified, i.e. the pattern is "////",
- the last RE used in any command is used in the
- search.
-
- If the eexxtteennddeedd option is set, the RE is handled
- as an extended RE, not a basic RE. If the wwrraapp--
- ssccaann option is set, the search wraps around to
- the beginning of the file and continues up to
- and including the current line, so that the
- entire file is searched.
-
- The form "\\//" is accepted for historic reasons,
- and is identical to "////".
-
- (6) An RE enclosed in question marks ("??")
- addresses the first line found by searching
- backward from the line _p_r_e_c_e_d_i_n_g the current
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--4488 NNvvii//NNeexx RReeffeerreennccee
-
-
- line, toward the beginning of the file and stop-
- ping at the first line containing a string
- matching the RE. (The trailing question mark
- can be omitted at the end of a command line.)
-
- If no RE is specified, i.e. the pattern is "????",
- the last RE used in any command is used in the
- search.
-
- If the eexxtteennddeedd option is set, the RE is handled
- as an extended RE, not a basic RE. If the wwrraapp--
- ssccaann option is set, the search wraps around
- from the beginning of the file to the end of the
- file and continues up to and including the cur-
- rent line, so that the entire file is searched.
-
- The form "\\??" is accepted for historic reasons,
- and is identical to "????".
-
- (7) An address followed by a plus sign ("++") or a
- minus sign ("--") followed by a number is an off-
- set address and refers to the address plus (or
- minus) the indicated number of lines. If the
- address is omitted, the addition or subtraction
- is done with respect to the current line.
-
- (8) An address of "++" or "--" followed by a number is
- an offset from the current line. For example,
- "--55" is the same as "..--55".
-
- (9) An address ending with "++" or "--" has 1 added to
- or subtracted from the address, respectively.
- As a consequence of this rule and of the previ-
- ous rule, the address "--" refers to the line
- preceding the current line. Moreover, trailing
- "++" and "--" characters have a cumulative effect.
- For example, "++++--++++" refers to the current line
- plus 3.
-
- (10) A percent sign ("%%") is equivalent to the
- address range "11,,$$".
-
- EExx commands require zero, one, or two addresses.
- It is an error to specify an address to a command which
- requires zero addresses.
-
- If the user provides more than the expected number
- of addresses to any eexx command, the first addresses
- specified are discarded. For example, "11,,22,,33,,55"print
- prints lines 3 through 5, because the pprriinntt command
- only takes two addresses.
-
-
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee UUSSDD::1133--4499
-
-
- The addresses in a range are separated from each
- other by a comma (",,") or a semicolon (";;"). In the
- latter case, the current line ("..") is set to the
- first address, and only then is the second address cal-
- culated. This feature can be used to determine the
- starting line for forward and backward searches (see
- rules (5) and (6) above). The second address of any
- two-address sequence corresponds to a line that fol-
- lows, in the file, the line corresponding to the first
- address. The first address must be less than or equal
- to the second address. The first address must be
- greater than or equal to the first line of the file,
- and the last address must be less than or equal to the
- last line of the file.
-
- 1133.. EExx DDeessccrriippttiioonn
-
- The following words have special meanings for eexx
- commands.
-
- <<eeooff>>
- The end-of-file character is used to scroll the
- screen in the eexx editor. This character is nor-
- mally <<ccoonnttrrooll--DD>>, however, whatever character is
- set for the current terminal is used.
-
- lliinnee
- A single-line address, given in any of the forms
- described in the section entitled "EExx AAddddrreessssiinngg".
- The default for lliinnee is the current line.
-
- rraannggee
- A line, or a pair of line addresses, separated by
- a comma or semicolon. (See the section entitled
- "EExx AAddddrreessssiinngg" for more information.) The
- default for range is the current line _o_n_l_y, i.e.
- "..,,..". A percent sign ("%%") stands for the range
- "11,,$$". The starting address must be less than, or
- equal to, the ending address.
-
- ccoouunntt
- A positive integer, specifying the number of lines
- to be affected by the command; the default is 1.
- Generally, a count past the end-of-file may be
- specified, e.g. the command "pp 33000000" in a 10 line
- file is acceptable, and will print from the cur-
- rent line through the last line in the file.
-
- ffllaaggss
- One or more of the characters "#", "p", and "l".
- When a command that accepts these flags completes,
- the addressed line(s) are written out as if by the
- corresponding ##, ll or pp commands. In addition,
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--5500 NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss))
-
-
- any number of "++" or "--" characters can be speci-
- fied before, after, or during the flags, in which
- case the line written is not necessarily the one
- affected by the command, but rather the line
- addressed by the offset address specified. The
- default for ffllaaggss is none.
-
- ffiillee
- A pattern used to derive a pathname; the default
- is the current file. File names are subjected to
- normal _s_h(1) word expansions.
-
- Anywhere a file name is specified, it is also pos-
- sible to use the special string "//ttmmpp". This will be
- replaced with a temporary file name which can be used
- for temporary work, e.g. "::ee //ttmmpp" creates and edits a
- new file.
-
- If both a count and a range are specified for com-
- mands that use either, the starting line for the com-
- mand is the _l_a_s_t line addressed by the range, and
- ccoouunntt- subsequent lines are affected by the command,
- e.g. the command "22,,33pp44" prints out lines 3, 4, 5 and
- 6.
-
- When only a line or range is specified, with no
- command, the implied command is either a lliisstt, nnuummbbeerr
- or pprriinntt command. The command used is the most recent
- of the three commands to have been used (including any
- use as a flag). If none of these commands have been
- used before, the pprriinntt command is the implied command.
- When no range or count is specified and the command
- line is a blank line, the current line is incremented
- by 1 and then the current line is displayed.
-
- Zero or more whitespace characters may precede or
- follow the addresses, count, flags, or command name.
- Any object following a command name (such as buffer,
- file, etc.), that begins with an alphabetic character,
- should be separated from the command name by at least
- one whitespace character.
-
- Any character, including <<ccaarrrriiaaggee--rreettuurrnn>>, "%%"
- and "##" retain their literal value when preceded by a
- backslash.
-
- 1144.. EExx CCoommmmaannddss
-
- The following section describes the commands
- available in the eexx editor. In each entry below, the
- tag line is a usage synopsis for the command.
-
-
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss)) UUSSDD::1133--5511
-
-
- Each command can be entered as the abbreviation
- (those characters in the synopsis command word preced-
- ing the "[" character), the full command (all charac-
- ters shown for the command word, omitting the "[" and
- "]" characters), or any leading subset of the full com-
- mand down to the abbreviation. For example, the args
- command (shown as "aarr[[ggss]]" in the synopsis) can be
- entered as "aarr", "aarrgg" or "aarrggss".
-
- Each eexx command described below notes the new cur-
- rent line after it is executed, as well as any options
- that affect the command.
-
- ""
- A comment. Command lines beginning with the dou-
- ble-quote character ("""") are ignored. This per-
- mits comments in editor scripts and startup files.
-
- <<eenndd--ooff--ffiillee>>
- Scroll the screen. Write the next N lines, where
- N is the value of the ssccrroollll option. The command
- is the end-of-file terminal character, which may
- be different on different terminals. Tradition-
- ally, it is the <<ccoonnttrrooll--DD>> key.
-
- Historically, the eeooff command ignored any preced-
- ing count, and the <<eenndd--ooff--ffiillee>> character was
- ignored unless it was entered as the first charac-
- ter of the command. This implementation treats it
- as a command _o_n_l_y if entered as the first charac-
- ter of the command line, and otherwise treats it
- as any other character.
-
- Line: Set to the last line written.
- Options: None.
-
- !! aarrgguummeenntt((ss))
- [[rraannggee]]!! aarrgguummeenntt((ss))
- Execute a shell command, or filter lines through a
- shell command. In the first synopsis, the remain-
- der of the line after the "!!" character is passed
- to the program named by the sshheellll option, as a
- single argument.
-
- Within the rest of the line, "%%" and "##" are
- expanded into the current and alternate pathnames,
- respectively. The character "!!" is expanded with
- the command text of the previous !! command.
- (Therefore, the command !!!! repeats the previous !!
- command.) The special meanings of "%%", "##", and
- "!!" can be overridden by escaping them with a
- backslash. If no !! or ::!! command has yet been
- executed, it is an error to use an unescaped "!!"
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--5522 NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss))
-
-
- character. The !! command does _n_o_t do shell
- expansion on the strings provided as arguments.
- If any of the above expansions change the command
- the user entered, the command is redisplayed at
- the bottom of the screen.
-
- EExx then executes the program named by the sshheellll
- option, with a --cc flag followed by the arguments
- (which are bundled into a single argument).
-
- The !! command is permitted in an empty file.
-
- If the file has been modified since it was last
- completely written, the command will warn you.
-
- A single "!!" character is displayed when the com-
- mand completes.
-
- In the second form of the !! command, the remain-
- der of the line after the "!!" is passed to the
- program named by the sshheellll option, as described
- above. The specified lines are passed to the pro-
- gram as standard input, and the standard and stan-
- dard error output of the program replace the orig-
- inal lines.
-
- Line: Unchanged if no range was specified, oth-
- erwise set to the first line of the
- range.
- Options: Affected by the aauuttoowwrriittee and wwrriitteeaannyy
- options.
-
- [[rraannggee]] nnuu[[mmbbeerr]] [[ccoouunntt]] [[ffllaaggss]]
- [[rraannggee]] ## [[ccoouunntt]] [[ffllaaggss]]
- Display the selected lines, each preceded with its
- line number.
-
- The line number format is "%6d", followed by two
- spaces.
-
- Line: Set to the last line displayed.
- Options: None.
-
- @@ bbuuffffeerr
- ** bbuuffffeerr
- Execute a buffer. Each line in the named buffer
- is executed as an eexx command. If no buffer is
- specified, or if the specified buffer is "@@" or
- "**", the last buffer executed is used.
-
- [[rraannggee]] <<[[<< ......]] [[ccoouunntt]] [[ffllaaggss]]
- Shift lines left or right. The specified lines
- are shifted to the left (for the << command) or
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss)) UUSSDD::1133--5533
-
-
- right (for the >> command), by the number of
- columns specified by the sshhiiffttwwiiddtthh option. Only
- leading whitespace characters are deleted when
- shifting left; once the first column of the line
- contains a nonblank character, the sshhiifftt command
- will succeed, but the line will not be modified.
-
- If the command character << or >> is repeated more
- than once, the command is repeated once for each
- additional command character.
-
- Line: If the current line is set to one of the
- lines that are affected by the command,
- it is unchanged. Otherwise, it is set to
- the first nonblank character of the low-
- est numbered line shifted.
- Options: Affected by the sshhiiffttwwiiddtthh option.
-
- [[lliinnee]] == [[ffllaaggss]]
- Display the line number. Display the line number
- of lliinnee (which defaults to the last line in the
- file).
-
- Line: Unchanged.
- Options: None.
-
- [[rraannggee]] >>[[>> ......]] [[ccoouunntt]] [[ffllaaggss]]
- Shift right. The specified lines are shifted to
- the right by the number of columns specified by
- the sshhiiffttwwiiddtthh option, by inserting tab and space
- characters. Empty lines are not changed.
-
- If the command character ">>" is repeated more than
- once, the command is repeated once for each addi-
- tional command character.
-
- Line: Set to the last line modified by the com-
- mand.
- Options: None.
-
- aabb[[bbrreevv]] llhhss rrhhss
- Add an abbreviation to the current abbreviation
- list. In vvii, if llhhss is entered such that it is
- preceded and followed by characters that cannot be
- part of a word, it is replaced by the string rrhhss.
-
- Line: Unchanged.
- Options: None.
-
- [[lliinnee]] aa[[ppppeenndd]][[!!]]
- The input text is appended to the specified line.
- If line 0 is specified, the text is inserted at
- the beginning of the file. Set to the last line
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--5544 NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss))
-
-
- input. If no lines are input, then set to lliinnee,
- or to the first line of the file if a lliinnee of 0
- was specified. Following the command name with a
- "!!" character causes the aauuttooiinnddeenntt option to be
- toggled for the duration of the command.
-
- Line: Unchanged.
- Options: Affected by the aallttwweerraassee, aauuttooiinnddeenntt,
- bbeeaauuttiiffyy, sshhoowwmmaattcchh, ttttyywweerraassee and wwrraapp--
- mmaarrggiinn options.
-
- aarr[[ggss]]
- Display the argument list. The current argument
- is displayed inside of "[[" and "]]" characters.
- The argument list is the list of operands speci-
- fied on startup, which can be replaced using the
- nneexxtt command.
-
- Line: Unchanged.
- Options: None.
-
- bbgg
- VVii mode only. Background the current screen.
-
- Line: Set to the current line when the screen
- was last edited.
- Options: None.
-
- [[rraannggee]] cc[[hhaannggee]][[!!]] [[ccoouunntt]]
- Replace the lines with input text. Following the
- command name with a "!!" character causes the
- aauuttooiinnddeenntt option to be toggled for the duration
- of the command.
-
- Line: Set to the last line input, or, if no
- lines were input, set to the line before
- the target line, or to the first line of
- the file if there are no lines preceding
- the target line.
- Options: Affected by the aallttwweerraassee, aauuttooiinnddeenntt,
- bbeeaauuttiiffyy, sshhoowwmmaattcchh, ttttyywweerraassee and wwrraapp--
- mmaarrggiinn options.
-
- cchhdd[[iirr]][[!!]] [[ddiirreeccttoorryy]]
- ccdd[[!!]] [[ddiirreeccttoorryy]]
- Change the current working directory. The ddiirreecc--
- ttoorryy argument is subjected to _s_h(1) word expan-
- sions. When invoked with no directory argument
- and the HHOOMMEE environment variable is set, the
- directory named by the HHOOMMEE environment variable
- becomes the new current directory. Otherwise, the
- new current directory becomes the directory
- returned by the _g_e_t_p_w_e_n_t(3) routine.
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss)) UUSSDD::1133--5555
-
-
- The cchhddiirr command will fail if the file has been
- modified since the last complete write of the
- file. You can override this check by appending a
- "!!" character to the command.
-
- Line: Unchanged.
- Options: Affected by the ccddppaatthh option.
-
- [[rraannggee]] ccoo[[ppyy]] lliinnee [[ffllaaggss]]
- [[rraannggee]] tt lliinnee [[ffllaaggss]]
- Copy the specified lines (range) after the desti-
- nation line. Line 0 may be specified to insert
- the lines at the beginning of the file.
-
- Line: Unchanged.
- Options: None.
-
- [[rraannggee]] dd[[eelleettee]] [[bbuuffffeerr]] [[ccoouunntt]] [[ffllaaggss]]
- Delete the lines from the file. The deleted text
- is saved in the specified buffer, or, if no buffer
- is specified, in the unnamed buffer. If the com-
- mand name is followed by a letter that could be
- interpreted as either a buffer name or a flag
- value (because neither a ccoouunntt or ffllaaggss values
- were given), eexx treats the letter as a ffllaaggss value
- if the letter immediately follows the command
- name, without any whitespace separation. If the
- letter is preceded by whitespace characters, it
- treats it as a buffer name.
-
- Line: Set to the line following the deleted
- lines, or to the last line if the deleted
- lines were at the end.
- Options: None.
-
- ddii[[ssppllaayy]] bb[[uuffffeerrss]] || ss[[ccrreeeennss]] || tt[[aaggss]]
- Display buffers, screens or tags. The ddiissppllaayy
- command takes one of three additional arguments,
- which are as follows:
-
- b[uffers]
- Display all buffers (including named,
- unnamed, and numeric) that contain text.
- s[creens]
- Display the file names of all background
- screens.
- t[ags] Display the tags stack.
-
- Line: Unchanged.
- Options: None.
-
- ee[[ddiitt]][[!!]] [[++ccmmdd]] [[ffiillee]]
-
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--5566 NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss))
-
-
- eexx[[!!]] [[++ccmmdd]] [[ffiillee]]
- Edit a different file. If the current buffer has
- been modified since the last complete write, the
- command will fail. You can override this by
- appending a "!!" character to the command name.
-
- If the "++ccmmdd" option is specified, that eexx command
- will be executed in the new file. Any eexx command
- may be used, although the most common use of this
- feature is to specify a line number or search pat-
- tern to set the initial location in the new file.
-
- Line: If you have previously edited the file,
- the current line will be set to your last
- position in the file. If that position
- does not exist, or you have not previ-
- ously edited the file, the current line
- will be set to the first line of the file
- if you are in vvii mode, and the last line
- of the file if you are in eexx.
- Options: Affected by the aauuttoowwrriittee and wwrriitteeaannyy
- options.
-
- eexxuu[[ssaaggee]] [[ccoommmmaanndd]]
- Display usage for an eexx command. If ccoommmmaanndd is
- specified, a usage statement for that command is
- displayed. Otherwise, usage statements for all eexx
- commands are displayed.
-
- Line: Unchanged.
- Options: None.
-
- ff[[iillee]] [[ffiillee]]
- Display and optionally change the file name. If a
- file name is specified, the current pathname is
- changed to the specified name. The current path-
- name, the number of lines, and the current posi-
- tion in the file are displayed.
-
- Line: Unchanged.
- Options: None.
-
- ffgg [[nnaammee]]
- VVii mode only. Foreground the specified screen.
- Swap the current screen with the specified back-
- grounded screen. If no screen is specified, the
- first background screen is foregrounded.
-
- Line: Set to the current line when the screen
- was last edited.
- Options: None.
-
-
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss)) UUSSDD::1133--5577
-
-
- [[rraannggee]] gg[[lloobbaall]] //ppaatttteerrnn// [[ccoommmmaannddss]]
- [[rraannggee]] vv //ppaatttteerrnn// [[ccoommmmaannddss]]
- Apply commands to lines matching (or not matching)
- a pattern. The lines within the given range that
- match ("gg[[lloobbaall]]"), or do not match ("vv") the
- given pattern are selected. Then, the specified
- eexx command(s) are executed with the current line
- ("..") set to each selected line. If no range is
- specified, the entire file is searched for match-
- ing, or not matching, lines.
-
- Multiple commands can be specified, one per line,
- by escaping each <<nneewwlliinnee>> character with a back-
- slash, or by separating commands with a "||" char-
- acter. If no commands are specified, the command
- defaults to the pprriinntt command.
-
- For the aappppeenndd, cchhaannggee and iinnsseerrtt commands, the
- input text must be part of the global command
- line. In this case, the terminating period can be
- omitted if it ends the commands.
-
- The vviissuuaall command may also be specified as one of
- the eexx commands. In this mode, input is taken
- from the terminal. Entering a QQ command in vvii
- mode causes the next line matching the pattern to
- be selected and vvii to be reentered, until the list
- is exhausted.
-
- The gglloobbaall, vv and uunnddoo commands cannot be used as
- part of these commands.
-
- The editor options aauuttoopprriinntt, aauuttooiinnddeenntt, and
- rreeppoorrtt are turned off for the duration of the
- gglloobbaall and vv commands.
-
- Line: The last line modified.
- Options: None.
-
- hhee[[llpp]]
- Display a help message.
-
- Line: Unchanged.
- Options: None.
-
- [[lliinnee]] ii[[nnsseerrtt]][[!!]]
- The input text is inserted before the specified
- line. Following the command name with a "!!"
- character causes the aauuttooiinnddeenntt option setting to
- be toggled for the duration of this command.
-
- Line: Set to the last line input; if no lines
- were input, set to the line before the
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--5588 NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss))
-
-
- target line, or to the first line of the
- file if there are no lines preceding the
- target line.
- Options: Affected by the aallttwweerraassee, aauuttooiinnddeenntt,
- bbeeaauuttiiffyy, sshhoowwmmaattcchh, ttttyywweerraassee and wwrraapp--
- mmaarrggiinn options.
-
- [[rraannggee]] jj[[ooiinn]][[!!]] [[ccoouunntt]] [[ffllaaggss]]
- Join lines of text together.
-
- A ccoouunntt specified to the command specifies that
- the last line of the rraannggee plus ccoouunntt subsequent
- lines will be joined. (Note, this differs by one
- from the general rule where only ccoouunntt- subsequent
- lines are affected.)
-
- If the current line ends with a whitespace charac-
- ter, all whitespace is stripped from the next
- line. Otherwise, if the next line starts with a
- open parenthesis ("(("), do nothing. Otherwise, if
- the current line ends with a question mark ("??"),
- period ("..") or exclamation point ("!!"), insert
- two spaces. Otherwise, insert a single space.
-
- Appending a "!!" character to the command name
- causes a simpler join with no white-space process-
- ing.
-
- Line: Unchanged.
- Options: None.
-
- [[rraannggee]] ll[[iisstt]] [[ccoouunntt]] [[ffllaaggss]]
- Display the lines unambiguously. Tabs are dis-
- played as "^^II", and the end of the line is marked
- with a "$$" character.
-
- Line: Set to the last line displayed.
- Options: None.
-
- mmaapp[[!!]] [[llhhss rrhhss]]
- Define or display maps (for vvii only).
-
- If "llhhss" and "rrhhss" are not specified, the current
- set of command mode maps are displayed. If a "!!"
- character is appended to to the command, the text
- input mode maps are displayed.
-
- Otherwise, when the "llhhss" character sequence is
- entered in vvii, the action is as if the correspond-
- ing "rrhhss" had been entered. If a "!!" character
- is appended to the command name, the mapping is
- effective during text input mode, otherwise, it is
- effective during command mode. This allows "llhhss"
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss)) UUSSDD::1133--5599
-
-
- to have two different macro definitions at the
- same time: one for command mode and one for input
- mode.
-
- Whitespace characters require escaping with a
- <<lliitteerraallnext> character to be entered in the llhhss
- string in visual mode.
-
- Normally, keys in the rrhhss string are remapped (see
- the rreemmaapp option), and it is possible to create
- infinite loops. However, keys which map to them-
- selves are not further remapped, regardless of the
- setting of the rreemmaapp option. For example, the
- command "::mmaapp nn nnzz.." maps the "nn" key to the nn
- and zz commands.
-
- To exit an infinitely looping map, use the termi-
- nal <<iinntteerrrruupptt>> character.
-
- Line: Unchanged.
- Options: None.
-
- [[lliinnee]] mmaa[[rrkk]] <<cchhaarraacctteerr>>
- [[lliinnee]] kk <<cchhaarraacctteerr>>
- Mark the line with the mark <<cchhaarraacctteerr>>. The
- expressions "''<<cchhaarraacctteerr>>" and "``<<cchhaarraacctteerr>>" can
- then be used as an address in any command that
- uses one.
-
- Line: Unchanged.
- Options: None.
-
- [[rraannggee]] mm[[oovvee]] lliinnee
- Move the specified lines after the target line. A
- target line of 0 places the lines at the beginning
- of the file.
-
- Line: Set to the first of the moved lines.
- Options: None.
-
- mmkk[[eexxrrcc]][[!!]] ffiillee
- Write the abbreviations, editor options and maps
- to the specified file. Information is written in
- a form which can later be read back in using the
- eexx ssoouurrccee command. If ffiillee already exists, the
- mmkkeexxrrcc command will fail. This check can be over-
- ridden by appending a "!!" character to the com-
- mand.
-
- Line: Unchanged.
- Options: None.
-
-
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--6600 NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss))
-
-
- nn[[eexxtt]][[!!]] [[ffiillee ......]]
- Edit the next file from the argument list. The
- nneexxtt command will fail if the file has been modi-
- fied since the last complete write. This check
- can be overridden by appending the "!!" character
- to the command name. The argument list can
- optionally be replaced by specifying a new one as
- arguments to this command. In this case, editing
- starts with the first file on the new list.
-
- Line: Set as described for the eeddiitt command.
- Options: Affected by the options aauuttoowwrriittee and
- wwrriitteeaannyy.
-
- [[lliinnee]] oo[[ppeenn]] //ppaatttteerrnn// [[ffllaaggss]]
- Enter open mode. Open mode is the same as being
- in vvii, but with a one-line window. All the stan-
- dard vvii commands are available. If a match is
- found for the optional RE argument, the cursor is
- set to the start of the matching pattern.
-
- _T_h_i_s _c_o_m_m_a_n_d _i_s _n_o_t _y_e_t _i_m_p_l_e_m_e_n_t_e_d_.
-
- Line: Unchanged, unless the optional RE is
- specified, in which case it is set to the
- line where the matching pattern is found.
- Options: Affected by the ooppeenn option.
-
- pprree[[sseerrvvee]]
- Save the file in a form that can later be recov-
- ered using the eexx --rr option. When the file is
- preserved, an email message is sent to the user.
-
- Line: Unchanged.
- Options: None.
-
- pprreevv[[iioouuss]][[!!]]
- Edit the previous file from the argument list.
- The pprreevviioouuss command will fail if the file has
- been modified since the last complete write. This
- check can be overridden by appending the "!!"
- character to the command name.
-
- Line: Set as described for the eeddiitt command.
- Options: Affected by the options aauuttoowwrriittee and
- wwrriitteeaannyy. None.
-
- [[rraannggee]] pp[[rriinntt]] [[ccoouunntt]] [[ffllaaggss]]
- Display the specified lines.
-
- Line: Set to the last line displayed.
- Options: None.
-
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss)) UUSSDD::1133--6611
-
-
- [[lliinnee]] ppuu[[tt]] [[bbuuffffeerr]]
- Append buffer contents to the current line. If a
- buffer is specified, its contents are appended to
- the line, otherwise, the contents of the unnamed
- buffer are used.
-
- Line: Set to the line after the current line.
- Options: None.
-
- qq[[uuiitt]][[!!]]
- End the editing session. If the file has been
- modified since the last complete write, the qquuiitt
- command will fail. This check may be overridden
- by appending a "!!" character to the command.
-
- If there are more files to edit, the qquuiitt command
- will fail. Appending a "!!" character to the com-
- mand name or entering two qquuiitt commands (i.e. wwqq,
- qquuiitt, xxiitt or ZZZZ) in a row) will override this
- check and the editor will exit.
-
- Line: Unchanged.
- Options: None.
-
- [[lliinnee]] rr[[eeaadd]][[!!]] [[ffiillee]]
- Read a file. A copy of the specified file is
- appended to the line. If lliinnee is 0, the copy is
- inserted at the beginning of the file. If no file
- is specified, the current file is read; if there
- is no current file, then ffiillee becomes the current
- file. If there is no current file and no ffiillee is
- specified, then the rreeaadd command will fail.
-
- If ffiillee is preceded by a "!!" character, ffiillee is
- treated as if it were a shell command, and passed
- to the program named by the SSHHEELLLL environment
- variable. The standard and standard error outputs
- of that command are read into the file after the
- specified line. The special meaning of the "!!"
- character can be overridden by escaping it with a
- backslash ("\\") character.
-
- Line: When executed from eexx, the current line
- is set to the last line read. When exe-
- cuted from vvii, the current line is set to
- the first line read.
- Options: None.
-
- rreecc[[oovveerr]] ffiillee
- Recover ffiillee if it was previously saved. If no
- saved file by that name exists, the rreeccoovveerr com-
- mand behaves similarly to the eeddiitt command.
-
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--6622 NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss))
-
-
- Line: Set as described for the eeddiitt command.
- Options: None.
-
- rreess[[iizzee]] [[++||--]]ssiizzee
- VVii mode only. Grow or shrink the current screen.
- If ssiizzee is a positive, signed number, the current
- screen is grown by that many lines. If ssiizzee is a
- negative, signed number, the current screen is
- shrunk by that many lines. If ssiizzee is not signed,
- the current screen is set to the specified ssiizzee.
- Applicable only to split screens.
-
- Line: Unchanged.
- Options: None.
-
- rreeww[[iinndd]][[!!]]
- Rewind the argument list. If the current file has
- been modified since the last complete write, the
- rreewwiinndd command will fail. This check may be over-
- ridden by appending the "!!" character to the com-
- mand.
-
- Otherwise, the current file is set to the first
- file in the argument list.
-
- Line: Set as described for the eeddiitt command.
- Options: Affected by the aauuttoowwrriittee and wwrriitteeaannyy
- options.
-
- ssee[[tt]] [[ooppttiioonn[[==[[vvaalluuee]]]] ......]] [[nnooooppttiioonn ......]] [[ooppttiioonn??
- ......]] [[aallll]]
- Display or set editor options. When no arguments
- are specified, the editor option tteerrmm, and any
- editor options whose values have been changed from
- the default settings are displayed. If the argu-
- ment aallll is specified, the values of all of editor
- options are displayed.
-
- Specifying an option name followed by the charac-
- ter "??" causes the current value of that option
- to be displayed. The "??" can be separated from
- the option name by whitespace characters. The "??"
- is necessary only for Boolean valued options.
- Boolean options can be given values by the form
- "sseett ooppttiioonn" to turn them on, or "sseett nnooooppttiioonn" to
- turn them off. String and numeric options can be
- assigned by the form "sseett ooppttiioonn==vvaalluuee". Any
- whitespace characters in strings can be included
- literally by preceding each with a backslash.
- More than one option can be set or listed by a
- single set command, by specifying multiple argu-
- ments, each separated from the next by whitespace
- characters.
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss)) UUSSDD::1133--6633
-
-
- Line: Unchanged.
- Options: None.
-
- sshh[[eellll]]
- Run a shell program. The program named by the
- sshheellll option is run with a --ii (for interactive)
- flag. Editing is resumed when that program exits.
-
- Line: Unchanged.
- Options: None.
-
- ssoo[[uurrccee]] ffiillee
- Read and execute eexx commands from a file. SSoouurrccee
- commands may be nested.
-
- Line: Unchanged.
- Options: None.
-
- sspp[[lliitt]] [[ffiillee ......]]
- VVii mode only. Split the screen. The current
- screen is split into two screens, of approximately
- equal size. If the cursor is in the lower half of
- the screen, the screen will split up, i.e. the new
- screen will be above the old one. If the cursor
- is in the upper half of the screen, the new screen
- will be below the old one.
-
- If ffiillee is specified, the new screen is editing
- that file, otherwise, both screens are editing the
- same file, and changes in each will be be
- reflected in the other. The argument list for the
- new screen consists of the list of files specified
- as arguments to this command, or, the current
- pathname if no files are specified.
-
- Line: If ffiillee is specified, set as for the eeddiitt
- command, otherwise unchanged.
- Options: None.
-
- [[rraannggee]] ss[[uubbssttiittuuttee]] [[//ppaatttteerrnn//rreeppllaaccee//]] [[ooppttiioonnss]]
- [[ccoouunntt]] [[ffllaaggss]]
- [[rraannggee]] && [[ooppttiioonnss]] [[ccoouunntt]] [[ffllaaggss]]
- [[rraannggee]] ~~ [[ooppttiioonnss]] [[ccoouunntt]] [[ffllaaggss]]
- Make substitutions. Replace the first instance of
- ppaatttteerrnn with the string rreeppllaaccee on the specified
- line(s). If the "//ppaatttteerrnn//rreeppll//" argument is not
- specified, the "//ppaatttteerrnn//rreeppll//" from the previous
- ssuubbssttiittuuttee command is used.
-
- If ooppttiioonnss includes the letter "cc" (confirm), you
- will be prompted for confirmation before each
- replacement is done. An affirmative response (in
- English, a "yy" character) causes the replacement
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--6644 NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss))
-
-
- to be made. A quit response (in English, a "qq"
- character) causes the ssuubbssttiittuuttee command to be
- terminated. Any other response causes the
- replacement not to be made, and the ssuubbssttiittuuttee
- command continues. If ooppttiioonnss includes the letter
- "gg" (global), all nonoverlapping instances of ppaatt--
- tteerrnn in the line are replaced.
-
- The && version of the command is the same as not
- specifying a pattern or replacement string to the
- ssuubbssttiittuuttee command, and the "&&" is replaced by the
- pattern and replacement information from the pre-
- vious substitute command.
-
- The ~~ version of the command is the same as && and
- ss, except that the search pattern used is the last
- RE used in _a_n_y command, not necessarily the one
- used in the last ssuubbssttiittuuttee command.
-
- For example, in the sequence
-
- ss//rreedd//bblluuee//
- //ggrreeeenn
- ~~
-
- the "~~" is equivalent to "ss//ggrreeeenn//bblluuee//".
-
- The ssuubbssttiittuuttee command may be interrupted, using
- the terminal interrupt character. All substitu-
- tions completed before the interrupt are retained.
-
- Line: Set to the last line upon which a substi-
- tution was made.
- Options: None.
-
- ssuu[[ssppeenndd]][[!!]]
- sstt[[oopp]][[!!]]
- <<ccoonnttrrooll--ZZ>>
- Suspend the edit session. Appending a "!!" char-
- acter to these commands turns off the aauuttoowwrriittee
- option for the command.
-
- Line: Unchanged.
- Options: Affected by the aauuttoowwrriittee option.
-
- ttaa[[gg]][[!!]] ttaaggssttrriinngg
- Edit the file containing the specified tag.
- Search for the tagstring, which can be in a dif-
- ferent file. If the tag is in a different file,
- then the new file is edited. If the current file
- has been modified since the last complete write,
- the ttaagg command will fail. This check can be
- overridden by appending the "!!" character to the
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss)) UUSSDD::1133--6655
-
-
- command name.
-
- The ttaagg command searches for ttaaggssttrriinngg in the tags
- file(s) specified by the option. (See _c_t_a_g_s(1)
- for more information on tags files.)
-
- Line: Set to the line indicated by the tag.
- Options: Affected by the aauuttoowwrriittee, ttaagglleennggtthh,
- ttaaggss and wwrriitteeaannyy options.
-
- ttaaggpp[[oopp]][[!!]] [[ffiillee || nnuummbbeerr]]
- Pop to the specified tag in the tags stack. If
- neither ffiillee or nnuummbbeerr is specified, the ttaaggppoopp
- command pops to the most recent entry on the tags
- stack. If ffiillee or nnuummbbeerr is specified, the ttaaggppoopp
- command pops to the most recent entry in the tags
- stack for that file, or numbered entry in the tags
- stack, respectively. (See the ddiissppllaayy command for
- information on displaying the tags stack.)
-
- If the file has been modified since the last com-
- plete write, the ttaaggppoopp command will fail. This
- check may be overridden by appending a "!!" char-
- acter to the command name.
-
- Line: Set to the line indicated by the tag.
- Options: Affected by the aauuttoowwrriittee, and wwrriitteeaannyy
- options.
-
- ttaaggtt[[oopp]][[!!]]
- Pop to the least recent tag on the tags stack,
- clearing the tags stack.
-
- If the file has been modified since the last com-
- plete write, the ttaaggppoopp command will fail. This
- check may be overridden by appending a "!!" char-
- acter to the command name.
-
- Line: Set to the line indicated by the tag.
- Options: Affected by the aauuttoowwrriittee, and wwrriitteeaannyy
- options.
-
- uunnaa[[bbbbrreevv]] llhhss
- Delete an abbreviation. Delete llhhss from the cur-
- rent list of abbreviations.
-
- Line: Unchanged.
- Options: None.
-
- uu[[nnddoo]]
- Undo the last change made to the file. Changes
- made by gglloobbaall, vv, vviissuuaall and map sequences are
- considered a single command. If repeated, the uu
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--6666 NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss))
-
-
- command alternates between these two states, and
- is its own inverse.
-
- Line: Set to the last line modified by the com-
- mand.
- Options: None.
-
- uunnmm[[aapp]][[!!]] llhhss
- Unmap a mapped string. Delete the command mode
- map definition for llhhss. If a "!!" character is
- appended to the command name, delete the text
- input mode map definition instead.
-
- Line: Unchanged.
- Options: None.
-
- vvee[[rrssiioonn]]
- Display the version of the eexx//vvii editor.
-
- [[lliinnee]] vvii[[ssuuaall]] [[ttyyppee]] [[ccoouunntt]] [[ffllaaggss]]
- EExx mode only. Enter vvii. The ttyyppee is optional,
- and can be "--", "++" or "^^", as in the eexx zz com-
- mand, to specify the the position of the specified
- line in the screen window. (The default is to
- place the line at the top of the screen window.)
- A ccoouunntt specifies the number of lines that will
- initially be displayed. (The default is the value
- of the wwiinnddooww editor option.)
-
- Line: Unchanged unless lliinnee is specified, in
- which case it is set to that line.
- Options: None.
-
- vvii[[ssuuaall]][[!!]] [[++ccmmdd]] [[ffiillee]]
- VVii mode only. Edit a new file. Identical to the
- "eeddiitt[[!!]] [[++ccmmdd]] [[ffiillee]]" command.
-
- vviiuu[[ssaaggee]] [[ccoommmmaanndd]]
- Display usage for a vvii command. If ccoommmmaanndd is
- specified, a usage statement for that command is
- displayed. Otherwise, usage statements for all vvii
- commands are displayed.
-
- Line: Unchanged.
- Options: None.
-
- [[rraannggee]] ww[[rriittee]][[!!]] [[>>>>]] [[ffiillee]]
- [[rraannggee]] ww[[rriittee]] [[!!]] [[ffiillee]]
- [[rraannggee]] wwnn[[!!]] [[>>>>]] [[ffiillee]]
- [[rraannggee]] wwqq[[!!]] [[>>>>]] [[ffiillee]]
- Write the file. The specified lines (the entire
- file, if no range is given) is written to ffiillee.
- If ffiillee is not specified, the current pathname is
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss)) UUSSDD::1133--6677
-
-
- used. If ffiillee is specified, and it exists, or if
- the current pathname was set using the ffiillee com-
- mand, and the file already exists, these commands
- will fail. Appending a "!!" character to the com-
- mand name will override this check and the write
- will be attempted, regardless.
-
- Specifying the optional ">>>>" string will cause the
- write to be appended to the file, in which case no
- tests are made for the file already existing.
-
- If the file is preceded by a "!!" character, the
- program named in the SHELL environment variable is
- invoked with file as its second argument, and the
- specified lines are passed as standard input to
- that command. The "!!" in this usage must be sep-
- arated from command name by at least one whites-
- pace character. The special meaning of the "!!"
- may be overridden by escaping it with a backslash
- ("\\") character.
-
- The wwqq version of the write command will exit the
- editor after writing the file, if there are no
- further files to edit. Appending a "!!" character
- to the command name or entering two "quit" com-
- mands (i.e. wwqq, qquuiitt, xxiitt or ZZZZ) in a row) will
- override this check and the editor will exit,
- ignoring any files that have not yet been edited.
-
- The wwnn version of the write command will move to
- the next file after writing the file, unless the
- write fails.
-
- Line: Unchanged.
- Options: Affected by the rreeaaddoonnllyy and wwrriitteeaannyy
- options.
-
- [[rraannggee]] xx[[iitt]][[!!]] [[ffiillee]]
- Write the file if it has been modified. The spec-
- ified lines are written to ffiillee, if the file has
- been modified since the last complete write to any
- file. If no rraannggee is specified, the entire file
- is written.
-
- The xxiitt command will exit the editor after writing
- the file, if there are no further files to edit.
- Appending a "!!" character to the command name or
- entering two "quit" commands (i.e. wwqq, qquuiitt, xxiitt
- or ZZZZ) in a row) will override this check and the
- editor will exit, ignoring any files that have not
- yet been edited.
-
-
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--6688 NNvvii//NNeexx RReeffeerreennccee ((EExx CCoommmmaannddss))
-
-
- Line: Unchanged.
- Options: Affected by the rreeaaddoonnllyy and wwrriitteeaannyy
- options.
-
- [[rraannggee]] yyaa[[nnkk]] [[bbuuffffeerr]] [[ccoouunntt]]
- Copy the specified lines to a buffer. If no
- buffer is specified, the unnamed buffer is used.
-
- Line: Unchanged.
- Options: None.
-
- [[lliinnee]] zz [[ttyyppee]] [[ccoouunntt]] [[ffllaaggss]]
- Adjust the window. If no ttyyppee is specified, then
- ccoouunntt lines following the specified line are dis-
- played. The default ccoouunntt is the value of the
- wwiinnddooww option. The ttyyppee argument changes the
- position at which lliinnee is displayed on the screen
- by changing the number of lines displayed before
- and after lliinnee. The following ttyyppee characters may
- be used:
-
- - Place the line at the bottom of the
- screen.
- + Place the line at the top of the screen.
- . Place the line in the middle of the
- screen.
- ^ Write out count lines starting ccoouunntt ** 22
- lines before lliinnee; the net effect of this
- is that a "zz^^" command following a zz com-
- mand writes the previous page.
- = Center lliinnee on the screen with a line of
- hyphens displayed immediately before and
- after it. The number of preceding and
- following lines of text displayed are
- reduced to account for those lines.
-
- Line: Set to the last line displayed, with the
- exception of the ttyyppee, where the current
- line is set to the line specified by the
- command.
- Options: Affected by the option.
-
- 1155.. SSeett OOppttiioonnss
-
- There are a large number of options that may be
- set (or unset) to change the editor's behavior. This
- section describes the options, their abbreviations and
- their default values.
-
- In each entry below, the first part of the tag
- line is the full name of the option, followed by any
- equivalent abbreviations. (Regardless of the abbrevia-
- tions, it is only necessary to use the minimum number
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee UUSSDD::1133--6699
-
-
- of characters necessary to distinguish an abbreviation
- from all other commands for it to be accepted, in
- nneexx/nnvvii. Historically, only the full name and the
- official abbreviations were accepted by eexx/vvii. Using
- full names in your startup files and environmental
- variables will probably make them more portable.) The
- part in square brackets is the default value of the
- option. Most of the options are boolean, i.e. they are
- either on or off, and do not have an associated value.
-
- Options apply to both eexx and vvii modes, unless oth-
- erwise specified.
-
- For information on modifying the options or to
- display the options and their current values, see the
- "set" command in the section entitled "EExx CCoommmmaannddss".
-
- aallttwweerraassee [[ooffff]]
- VVii only. Change how vvii does word erase during
- text input. When this option is set, text is bro-
- ken up into three classes: alphabetic, numeric and
- underscore characters, other nonblank characters,
- and blank characters. Changing from one class to
- another marks the end of a word. In addition, the
- class of the first character erased is ignored
- (which is exactly what you want when erasing path-
- name components).
-
- aauuttooiinnddeenntt,, aaii [[ooffff]]
- If this option is set, whenever you create a new
- line (using the vvii AA, aa, CC, cc, II, ii, OO, oo, RR, rr,
- SS, and ss commands, or the eexx aappppeenndd, cchhaannggee, and
- iinnsseerrtt commands) the new line is automatically
- indented to align the cursor with the first non-
- blank character of the line from which you created
- it. Lines are indented using tab characters to
- the extent possible (based on the value of the
- ttaabbssttoopp option) and then using space characters as
- necessary. For commands inserting text into the
- middle of a line, any blank characters to the
- right of the cursor are discarded, and the first
- nonblank character to the right of the cursor is
- aligned as described above.
-
- The indent characters are themselves somewhat spe-
- cial. If you do not enter more characters on the
- new line before moving to another line, or enter-
- ing <<eessccaappee>>, the indent character will be deleted
- and the line will be empty. For example, if you
- enter <<ccaarrrriiaaggee--rreettuurrnn>> twice in succession, the
- line created by the first <<ccaarrrriiaaggee--rreettuurrnn>> will
- not have any characters in it, regardless of the
- indentation of the previous or subsequent line.
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--7700 NNvvii//NNeexx RReeffeerreennccee
-
-
- Indent characters also require that you enter
- additional erase characters to delete them. For
- example, if you have an indented line, containing
- only blanks, the first <<wwoorrdd--eerraassee>> character you
- enter will erase up to end of the indent charac-
- ters, and the second will erase back to the begin-
- ning of the line. (Historically, only the <<ccoonn--
- ttrrooll--DD>> key would erase the indent characters.
- Both the <<ccoonnttrrooll--DD>> key and the usual erase keys
- work in nnvvii.) In addition, if the cursor is posi-
- tioned at the end of the indent characters, the
- keys "00<<ccoonnttrrooll--DD>>" will erase all of the indent
- characters for the current line, resetting the
- indentation level to 0. Similarly, the keys
- "^^<<ccoonnttrrooll--DD>>" will erase all of the indent char-
- acters for the current line, leaving the indenta-
- tion level for future created lines unaffected.
-
- Finally, if the aauuttooiinnddeenntt option is set, the SS
- and cccc commands change from the first nonblank of
- the line to the end of the line, instead of from
- the beginning of the line to the end of the line.
-
- aauuttoopprriinntt,, aapp [[ooffff]]
- EExx only. Cause the current line to be automati-
- cally displayed after the eexx commands <<, >>, ccooppyy,
- ddeelleettee, jjooiinn, mmoovvee, ppuutt, tt, UUnnddoo, and uunnddoo. This
- automatic display is suppressed during gglloobbaall and
- vvgglloobbaall commands, and for any command where
- optional flags are used to explicitly display the
- line.
-
- aauuttoowwrriittee,, aaww [[ooffff]]
- If this option is set, the vvii !!, ^^^^, ^^]] and <<ccoonn--
- ttrrooll--ZZ>> commands, and the eexx eeddiitt, nneexxtt, rreewwiinndd,
- ssttoopp, ssuussppeenndd, ttaagg, ttaaggppoopp, and ttaaggttoopp commands
- automatically write the current file back to the
- current file name if it has been modified since it
- was last written. If the write fails, the command
- fails and goes no further.
-
- Appending the optional force flag character "!!"
- to the eexx commands nneexxtt, rreewwiinndd, ssttoopp, ssuussppeenndd,
- ttaagg, ttaaggppoopp, and ttaaggttoopp stops the automatic write
- from being attempted.
-
- (Historically, the nneexxtt command ignored the
- optional force flag.) Note, the eexx commands eeddiitt,
- qquuiitt, sshheellll, and xxiitt are _n_o_t affected by the
- aauuttoowwrriittee option.
-
- bbeeaauuttiiffyy,, bbff [[ooffff]]
- If this option is set, all control characters that
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee UUSSDD::1133--7711
-
-
- are not currently being specially interpreted,
- other than <<ttaabb>>, <<nneewwlliinnee>>, and <<ffoorrmm--ffeeeedd>>, are
- discarded from commands read in by eexx from command
- files, and from input text entered to vvii (either
- into the file or to the colon command line). Text
- files read by eexx/vvii are _n_o_t affected by the bbeeaauu--
- ttiiffyy option.
-
- ccddppaatthh [[eennvviirroonnmmeenntt vvaarriiaabbllee CCDDPPAATTHH,, oorr ccuurrrreenntt ddiirreecc--
- ttoorryy]]
- This option is used to specify a colon separated
- list of directories which are used as path pre-
- fixes for any relative path names used as argu-
- ments for the ccdd command. The value of this
- option defaults to the value of the environmental
- variable CCDDPPAATTHH if it is set, otherwise to the
- current directory. For compatibility with the
- POSIX 1003.2 shell, the ccdd command does _n_o_t check
- the current directory as a path prefix for rela-
- tive path names unless it is explicitly specified.
- It may be so specified by entering an empty string
- or a ".." character into the CCDDPPAATTHH variable or
- the option value.
-
- ccoolluummnnss,, ccoo [[8800]]
- The number of columns in the screen. Setting this
- option causes eexx/vvii to set (or reset) the environ-
- mental variable CCOOLLUUMMNNSS. See the section entitled
- "SSiizziinngg tthhee SSccrreeeenn" more information.
-
- ccoommmmeenntt [[ooffff]]
- VVii only. If the first non-empty line of the file
- begins with the string "//**", this option causes vvii
- to skip to the end of that C-language comment
- (probably a terribly boring legal notice) before
- displaying the file.
-
- ddiirreeccttoorryy,, ddiirr [[eennvviirroonnmmeenntt vvaarriiaabbllee TTMMPPDDIIRR,, oorr //ttmmpp]]
- The directory where temporary files are created.
- The environmental variable TTMMPPDDIIRR is used as the
- default value if it exists, otherwise //ttmmpp is
- used.
-
- eeddccoommppaattiibbllee,, eedd [[ooffff]]
- Remember the values of the "c" and "g" suffices to
- the ssuubbssttiittuuttee commands, instead of initializing
- them as unset for each new command. Specifying
- pattern and replacement strings to the ssuubbssttiittuuttee
- command unsets the "c" and "g" suffices as well.
-
- eerrrroorrbbeellllss,, eebb [[ooffff]]
- EExx only. EExx error messages are normally presented
- in inverse video. If that is not possible for the
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--7722 NNvvii//NNeexx RReeffeerreennccee
-
-
- terminal, setting this option causes error mes-
- sages to be announced by ringing the terminal
- bell.
-
- eexxrrcc,, eexx [[ooffff]]
- If this option is turned off in the system or
- $HOME startup files, the local startup files are
- never read (unless they are the same as the system
- or $HOME startup files). Turning it on has no
- effect, i.e. the normal checks for local startup
- files are performed, regardless. See the section
- entitled "SSttaarrttuupp IInnffoorrmmaattiioonn" for more informa-
- tion.
-
- eexxtteennddeedd [[ooffff]]
- This option causes all regular expressions to be
- treated as POSIX 1003.2 Extended Regular Expres-
- sions (which are similar to historic _e_g_r_e_p(1)
- style expressions).
-
- ffllaasshh [[oonn]]
- This option causes the screen to flash instead of
- beeping the keyboard, on error, if the terminal
- has the capability.
-
- hhaarrddttaabbss,, hhtt [[88]]
- This option defines the spacing between hardware
- tab settings, i.e. the tab expansion done by the
- operating system and/or the terminal itself. As
- nneexx/nnvvii never writes <<ttaabb>> characters to the ter-
- minal, unlike historic versions of eexx/vvii, this
- option does not currently have any affect.
-
- iiggnnoorreeccaassee,, iicc [[ooffff]]
- This option causes regular expressions, both in eexx
- commands and in searches, to be evaluated in a
- case-insensitive manner.
-
- kkeeyyttiimmee [[66]]
- The 10th's of a second eexx/vvii waits for a subse-
- quent key to complete a key mapping.
-
- lleeffttrriigghhtt [[ooffff]]
- VVii only. This option causes the screen to be
- scrolled left-right to view lines longer than the
- screen, instead of the traditional vvii screen
- interface which folds long lines at the right-hand
- margin of the terminal.
-
- lliinneess,, llii [[2244]]
- VVii only. The number of lines in the screen. Set-
- ting this option causes eexx/vvii to set (or reset)
- the environmental variable LLIINNEESS. See the section
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee UUSSDD::1133--7733
-
-
- entitled "SSiizziinngg tthhee SSccrreeeenn" for more information.
-
- lliisspp [[ooffff]]
- VVii only. This option changes the behavior of the
- vvii ((, )), {{, }}, [[[[ and ]]]] commands to match the
- Lisp language. Also, the aauuttooiinnddeenntt option's
- behavior is changed to be appropriate for Lisp.
-
- _T_h_i_s _o_p_t_i_o_n _i_s _n_o_t _y_e_t _i_m_p_l_e_m_e_n_t_e_d_.
-
- lliisstt [[ooffff]]
- This option causes lines to be displayed in an
- unambiguous fashion. Specifically, tabs are dis-
- played as control characters, i.e. "^^II", and the
- ends of lines are marked with a "$$" character.
-
- mmaaggiicc [[oonn]]
- This option is on by default. Turning the mmaaggiicc
- option off causes all regular expression charac-
- ters except for "^^" and "$$", to be treated as
- ordinary characters. To re-enable characters
- individually, when the mmaaggiicc option is off, pre-
- cede them with a backslash "\\" character. See the
- section entitled "RReegguullaarr EExxpprreessssiioonnss aanndd RReeppllaaccee--
- mmeenntt SSttrriinnggss" for more information.
-
- mmaattcchhttiimmee [[77]]
- VVii only. The 10th's of a second eexx/vvii pauses on
- the matching character when the sshhoowwmmaattcchh option
- is set.
-
- mmeessgg [[oonn]]
- This option allows other users to contact you
- using the _t_a_l_k(1) and _w_r_i_t_e(1) utilities, while
- you are editing. EExx/vvii does not turn message on,
- i.e. if messages were turned off when the editor
- was invoked, they will stay turned off. This
- option only permits you to disallow messages for
- the edit session. See the _m_e_s_g(1) utility for
- more information.
-
- mmooddeelliinneess,, mmooddeelliinnee [[ooffff]]
- If the mmooddeelliinneess option is set, eexx/vvii has histori-
- cally scanned the first and last five lines of
- each file as it is read for editing, looking for
- any eexx commands that have been placed in those
- lines. After the startup information has been
- processed, and before the user starts editing the
- file, any commands embedded in the file are exe-
- cuted.
-
- Commands were recognized by the letters "e" or "v"
- followed by "x" or "i", at the beginning of a line
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--7744 NNvvii//NNeexx RReeffeerreennccee
-
-
- or following a tab or space character, and fol-
- lowed by a ":", an eexx command, and another ":".
-
- This option is a security problem of immense pro-
- portions, and should not be used under any circum-
- stances.
-
- _T_h_i_s _o_p_t_i_o_n _w_i_l_l _n_e_v_e_r _b_e _i_m_p_l_e_m_e_n_t_e_d_.
-
- nnuummbbeerr,, nnuu [[ooffff]]
- Precede each line displayed with its current line
- number.
-
- ooccttaall [[ooffff]]
- Display unknown characters as octal numbers,
- instead of the default hexadecimal.
-
- ooppeenn [[oonn]]
- EExx only. If this option is not set, the ooppeenn and
- vviissuuaall commands are disallowed.
-
- ooppttiimmiizzee,, oopptt [[oonn]]
- VVii only. Throughput of text is expedited by set-
- ting the terminal not to do automatic carriage
- returns when printing more than one (logical) line
- of output, greatly speeding output on terminals
- without addressable cursors when text with leading
- white space is printed.
-
- _T_h_i_s _o_p_t_i_o_n _i_s _n_o_t _y_e_t _i_m_p_l_e_m_e_n_t_e_d_.
-
- ppaarraaggrraapphhss,, ppaarraa [[IIPPLLPPPPPPQQPPPP LLIIppppllppiippbbpp]]
- VVii only. Define additional paragraph boundaries
- for the {{ and }} commands. The value of this
- option must be a character string consisting of
- zero or more character pairs.
-
- In the text to be edited, the character string
- <<nneewwlliinnee>>..<<cchhaarr--ppaaiirr>>, (where <<cchhaarr--ppaaiirr>> is one
- of the character pairs in the option's value)
- defines a paragraph boundary. For example, if the
- option were set to LLaaAA<<ssppaaccee>>####, then all of the
- following additional paragraph boundaries would be
- recognized:
-
-
- <newline>.La
- <newline>.A<space>
- <newline>.##
-
-
- pprroommpptt [[oonn]]
- EExx only. This option causes eexx to prompt for
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee UUSSDD::1133--7755
-
-
- command input with a "::" character; when it is not
- set, no prompt is displayed.
-
- rreeaaddoonnllyy,, rroo [[ooffff]]
- This option causes a force flag to be required to
- attempt to write the file back to the original
- file name. Setting this option is equivalent to
- using the --RR command line option, or editing a
- file which lacks write permission.
-
- rreeccddiirr [[//vvaarr//ttmmpp//vvii..rreeccoovveerr]]
- The directory where recovery files are stored.
-
- If you change the value of rreeccddiirr, be careful to
- choose a directory whose contents are not regu-
- larly deleted. Bad choices include directories in
- memory based filesystems, or //ttmmpp, on most sys-
- tems, as their contents are removed when the
- machine is rebooted.
-
- Public directories like //uussrr//ttmmpp and //vvaarr//ttmmpp are
- usually safe, although some sites periodically
- prune old files from them. There is no require-
- ment that you use a public directory, e.g. a sub-
- directory of your home directory will work fine.
-
- Finally, if you change the value of rreeccddiirr, you
- must modify the recovery script to operate in your
- chosen recovery area.
-
- See the section entitled "RReeccoovveerryy" for further
- information.
-
- rreeddrraaww,, rree [[ooffff]]
- VVii only. The editor simulates (using great
- amounts of output), an intelligent terminal on a
- dumb terminal (e.g. during insertions in vvii the
- characters to the right of the cursor are
- refreshed as each input character is typed).
-
- _T_h_i_s _o_p_t_i_o_n _i_s _n_o_t _y_e_t _i_m_p_l_e_m_e_n_t_e_d_.
-
- rreemmaapp [[oonn]]
- If this option is set, it is possible to define
- macros in terms of other macros. Otherwise, each
- key is only remapped up to one time. For example,
- if "AA" is mapped to "BB", and "BB" is mapped to "CC",
- The keystroke "AA" will be mapped to "CC" if the
- rreemmaapp option is set, and to "BB" if it is not set.
-
- rreeppoorrtt [[55]]
- Set the threshold of the number of lines that need
- to be changed or yanked before a message will be
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--7766 NNvvii//NNeexx RReeffeerreennccee
-
-
- displayed to the user. For everything but the
- yank command, the value is the largest value about
- which the editor is silent, i.e. by default, 6
- lines must be deleted before the user is notified.
- However, if the number of lines yanked is greater
- than _o_r _e_q_u_a_l _t_o the set value, it is reported to
- the user.
-
- rruulleerr [[ooffff]]
- VVii only. Display a row/column ruler on the colon
- command line.
-
- ssccrroollll,, ssccrr [[wwiinnddooww // 22]]
- Set the number of lines scrolled by the vvii <<ccoonn--
- ttrrooll--DD>> and <<ccoonnttrrooll--UU>> commands.
-
- Historically, the eexx zz command, when specified
- without a count, used two times the size of the
- scroll value; the POSIX 1003.2 standard specified
- the window size, which is a better choice.
-
- sseeccttiioonnss,, sseecctt [[NNHHSSHHHH HHUUnnhhsshh]]
- VVii only. Define additional section boundaries for
- the [[[[ and ]]]] commands. The sseeccttiioonnss option
- should be set to a character string consisting of
- zero or more character pairs. In the text to be
- edited, the character string <<nneewwlliinnee>>..<<cchhaarr--
- ppaaiirr>>, (where <<cchhaarr--ppaaiirr>> is one of the character
- pairs in the option's value), defines a section
- boundary in the same manner that ppaarraaggrraapphh option
- boundaries are defined.
-
- sshheellll,, sshh [[eennvviirroonnmmeenntt vvaarriiaabbllee SSHHEELLLL,, oorr //bbiinn//sshh]]
- Select the shell used by the editor. The speci-
- fied path is the pathname of the shell invoked by
- the vvii !! shell escape command and by the eexx sshheellll
- command. This program is also used to resolve any
- shell meta-characters in eexx commands.
-
- sshhiiffttwwiiddtthh,, ssww [[88]]
- Set the autoindent and shift command indentation
- width. This width is used by the aauuttooiinnddeenntt
- option and by the <<, >>, and sshhiifftt commands.
-
- sshhoowwddiirrttyy [[ooffff]]
- VVii only. Display an asterisk on the colon command
- line if the file has been modified.
-
- sshhoowwmmaattcchh,, ssmm [[ooffff]]
- VVii only. This option causes vvii, when a "}}" or "))"
- is entered, to briefly move the cursor the match-
- ing "{{" or "((". See the mmaattcchhttiimmee option for more
- information.
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee UUSSDD::1133--7777
-
-
- sshhoowwmmooddee [[ooffff]]
- VVii only. This option causes vvii to display a
- string identifying the current editor mode on the
- colon command line.
-
- ssiiddeessccrroollll [[1166]]
- VVii only. Sets the number of columns that are
- shifted to the left or right, when vvii is doing
- left-right scrolling and the left or right margin
- is crossed. See the lleeffttrriigghhtt option for more
- information.
-
- sslloowwooppeenn,, ssllooww [[ooffff]]
- This option affects the display algorithm used by
- vvii, holding off display updating during input of
- new text to improve throughput when the terminal
- in use is slow and unintelligent.
-
- _T_h_i_s _o_p_t_i_o_n _i_s _n_o_t _y_e_t _i_m_p_l_e_m_e_n_t_e_d_.
-
- ssoouurrcceeaannyy [[ooffff]]
- If this option is turned on, vvii historically read
- startup files that were owned by someone other
- than the editor user. See the section entitled
- "SSttaarrttuupp IInnffoorrmmaattiioonn" for more information. This
- option is a security problem of immense propor-
- tions, and should not be used under any circum-
- stances.
-
- _T_h_i_s _o_p_t_i_o_n _w_i_l_l _n_e_v_e_r _b_e _i_m_p_l_e_m_e_n_t_e_d_.
-
- ttaabbssttoopp,, ttss [[88]]
- This option sets tab widths for the editor dis-
- play.
-
- ttaagglleennggtthh,, ttll [[00]]
- This option sets the maximum number of characters
- that are considered significant in a tag name.
- Setting the value to 0 makes all of the characters
- in the tag name significant.
-
- ttaaggss,, ttaagg [[ttaaggss //vvaarr//ddbb//lliibbcc..ttaaggss //ssyyss//kkeerrnn//ttaaggss]]
- Sets the list of tags files, in search order,
- which are used when the editor searches for a tag.
-
- tteerrmm,, ttttyyttyyppee,, ttttyy [[eennvviirroonnmmeenntt vvaarriiaabbllee TTEERRMM]]
- Set the terminal type. Setting this option causes
- eexx/vvii to set (or reset) the environmental variable
- TTEERRMM.
-
- tteerrssee [[ooffff]]
- This option has historically made editor messages
- less verbose. It has no effect in this
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--7788 NNvvii//NNeexx RReeffeerreennccee
-
-
- implementation. See the vveerrbboossee option for more
- information.
-
- ttiillddeeoopp
- Modify the ~~ command to take an associated motion.
-
- ttiimmeeoouutt,, ttoo [[oonn]]
- If this option is set, eexx/vvii waits for a specific
- period for a subsequent key to complete a key map-
- ping (see the kkeeyyttiimmee option). If the option is
- not set, the editor waits until enough keys are
- entered to resolve the ambiguity, regardless of
- how long it takes.
-
- ttttyywweerraassee [[ooffff]]
- VVii only. This option changes how vvii does word
- erase during text input. If this option is set,
- text is broken up into two classes, blank charac-
- ters and nonblank characters. Changing from one
- class to another marks the end of a word.
-
- vveerrbboossee [[ooffff]]
- VVii only. VVii historically bells the terminal for
- many obvious mistakes, e.g. trying to move past
- the left-hand margin, or past the end of the file.
- If this option is set, an error message is dis-
- played for all errors.
-
- ww330000 [[nnoo ddeeffaauulltt]]
- VVii only. Set the window size if the baud rate is
- less than 1200 baud. See the wwiinnddooww option for
- more information.
-
- ww11220000 [[nnoo ddeeffaauulltt]]
- VVii only. Set the window size if the baud rate is
- equal to 1200 baud. See the wwiinnddooww option for
- more information.
-
- ww99660000 [[nnoo ddeeffaauulltt]]
- VVii only. Set the window size if the baud rate is
- greater than 1200 baud. See the wwiinnddooww option for
- more information.
-
- wwaarrnn [[oonn]]
- EExx only. This option causes a warning message to
- the terminal if the file has been modified, since
- it was last written, before a !! command.
-
- wwiinnddooww,, ww,, wwii [[eennvviirroonnmmeenntt vvaarriiaabbllee LLIINNEESS]]
- This option determines the default number of lines
- in a screenful, as written by the zz command. It
- also determines the number of lines scrolled by
- the vvii commands <<ccoonnttrrooll--FF>> and <<ccoonnttrrooll--BB>>. The
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee UUSSDD::1133--7799
-
-
- value of window can be unrelated to the real
- screen size, although it starts out as the number
- of lines on the screen (see the section entitled
- "SSiizziinngg tthhee SSccrreeeenn" for more information). Set-
- ting the value of the wwiinnddooww option is the same as
- using the --ww command line option.
-
- If the value of the wwiinnddooww option (as set by the
- wwiinnddooww, ww330000, ww11220000 or ww99660000 options) is smaller
- than the actual size of the screen, large screen
- movements will result in displaying only that
- smaller number of lines on the screen. (Further
- movements in that same area will result in the
- screen being filled.) This can provide a perfor-
- mance improvement when viewing different places in
- one or more files over a slow link.
-
- wwrraappmmaarrggiinn,, wwmm [[00]]
- VVii only. If the value of the wwrraappmmaarrggiinn option is
- non-zero, vvii will split lines so that they end at
- least that number of characters before the right-
- hand margin of the screen. (Note, the value of
- wwrraappmmaarrggiinn is _n_o_t a text length. In a screen that
- is 80 columns wide, the command "::sseett wwrraappmmaarr--
- ggiinn==88" attempts to keep the lines less than or
- equal to 72 columns wide.)
-
- Lines are split at the previous whitespace charac-
- ter closest to the number. Any trailing whites-
- pace characters before that character are deleted.
- If the line is split because of an inserted
- <<ssppaaccee>> or <<ttaabb>> character, and you then enter
- another <<ssppaaccee>> character, it is discarded.
-
- If wrapmargin is set to 0, or if there is no blank
- character upon which to split the line, the line
- is not broken.
-
- wwrraappssccaann,, wwss [[oonn]]
- This option causes searches to wrap around the end
- or the beginning of the file, and back to the
- starting point. Otherwise, the end or beginning
- of the file terminates the search.
-
- wwrriitteeaannyy,, wwaa [[ooffff]]
- If this option is set, file-overwriting checks
- that would usually be made before the wwrriittee and
- xxiitt commands, or before an automatic write (see
- the aauuttoowwrriittee option), are not made. This allows
- a write to any file, provided the file permissions
- allow it.
-
-
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--8800 NNvvii//NNeexx RReeffeerreennccee
-
-
- 1166.. AAddddiittiioonnaall FFeeaattuurreess iinn NNeexx//NNvvii
-
- There are a few features in nneexx/nnvvii that are not
- found in historic versions of eexx/vvii. Some of the more
- interesting of those features are as follows:
-
- 88--bbiitt cclleeaann ddaattaa,, llaarrggee lliinneess,, ffiilleess
- NNeexx/nnvvii will edit any format file. Line lengths
- are limited by available memory, and file sizes
- are limited by available disk space. The vvii text
- input mode command <<ccoonnttrrooll--XX>> can insert any pos-
- sible character value into the text.
-
- SSpplliitt ssccrreeeennss
- The sspplliitt command divides the screen into multiple
- editing regions. The <<ccoonnttrrooll--WW>> command rotates
- between the foreground screens. The rreessiizzee com-
- mand can be used to grow or shrink a particular
- screen.
-
- BBaacckkggrroouunndd aanndd ffoorreeggrroouunndd ssccrreeeennss
- The bbgg command backgrounds the current screen, and
- the ffgg command foregrounds backgrounded screens.
- The ddiissppllaayy command can be used to list the back-
- ground screens.
-
- TTaagg ssttaacckkss
- Tags are now maintained in a stack. The <<ccoonnttrrooll--
- TT>> command returns to the previous tag location.
- The ttaaggppoopp command returns to the most recent tag
- location by default, or, optionally to a specific
- tag number in the tag stack, or the most recent
- tag from a specified file. The ddiissppllaayy command
- can be used to list the tags stack. The ttaaggttoopp
- command returns to the top of the tag stack.
-
- NNeeww ddiissppllaayyss
- The ddiissppllaayy command can be used to display the
- current buffers, the backgrounded screens, and the
- tags stack.
-
- IInnffiinniittee uunnddoo
- Changes made during an edit session may be rolled
- backward and forward. A .. command immediately
- after a uu command continues either forward or
- backward depending on whether the uu command was an
- undo or a redo.
-
- UUssaaggee iinnffoorrmmaattiioonn
- The eexxuussaaggee and vviiuussaaggee commands provide usage
- information for all of the eexx and vvii commands by
- default, or, optionally, for a specific command or
- key.
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee UUSSDD::1133--8811
-
-
- EExxtteennddeedd RReegguullaarr EExxpprreessssiioonnss
- The eexxtteennddeedd option causes Regular Expressions to
- be interpreted as as Extended Regular Expressions,
- (i.e. _e_g_r_e_p(1) style Regular Expressions).
-
- WWoorrdd sseeaarrcchh
- The <<ccoonnttrrooll--AA>> command searches for the word ref-
- erenced by the cursor.
-
- NNuummbbeerr iinnccrreemmeenntt
- The ## command increments or decrements the number
- referenced by the cursor.
-
- PPrreevviioouuss ffiillee
- The pprreevviioouuss command edits the previous file from
- the argument list.
-
- LLeefftt--rriigghhtt ssccrroolllliinngg
- The lleeffttrriigghhtt option causes nnvvii to do left-right
- screen scrolling, instead of the traditional vvii
- line wrapping.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--8822 NNvvii//NNeexx RReeffeerreennccee
-
-
- 1177.. IInnddeexx
-
- ! 15, 34 @ 20, 35 columns 47
- "" 34 A 20 comment 47
- # 16, 35 B 20 copy 36
- $ 16 C 21 count 10, 33
- % 16 D 21 current pathname 8
- & 17, 42 E 21 d 26
- ( 17 F 21 delete 37
- ) 17 G 21 directory 47
- * 35 H 21 display 37
- + 13 I 22 e 26
- , 18 J 22 edcompatible47
- /RE/ 18 L 22 edit 37
- 0 19 M 22 errorbells 47
- 0<control-D>31 N 18 exrc 47
- : 19 O 22 extended 48
- ; 19 P 23 exusage 37
- < 20, 35 Q 23 f 26
- <control-A> 11 R 23 fg 37
- <control-B> 11 S 23 file 33, 37
- <control-1D2>, 31 T 23 flags 33
- <control-E> 12 U 23 flash 48
- <control-F> 12 W 24 global 38
- <control-G> 12 X 24 hardtabs 48
- <control-1H2>, 31 Y 24 help 38
- <control-J> 13 ZZ 24 i 26
- <control-L> 13 [[ 24 ignorecase 48
- <control-M> 13 - 18 insert 38
- <control-N> 13 ]] 25 j 13
- <control-P> 13 ^ 25 join 38
- <control-R> 13 ^<control-D>31 k 13, 39
- <control-1T4>, 31 _ 25 keytime 48
- <control-U> 14 `<character>17 l 15
- <control-1W4>, 31 a 25 leftright 48
- <control-X> 31 abbrev 35 line 33
- <control-Y> 14 alternate pathname 8 lines 48
- <control-1Z4>, 43 altwerase 46 lisp 48
- <control-]> 15 append 36 list 39, 48
- <control-^> 15 args 36 m 27
- <end-of-file> 34 autoindent 46 magic 48
- <eof> 33 autoprint 46 map 39
- <erase> 31 autowrite 47 mark 39
- <escape>14, 31 b 25 matchtime 48
- <inter7r,up3t0>, 31 beautify 47 mesg 48
- <line erase>31 bg 36 mkexrc 39
- <literal next> 7, 31 bigword 10 modelines 49
- <nul> 30 buffer 8 motion 10
- <space> 15 c 26 move 39
- <word erase>31 cd 36 n 18
- = 35 cdpath 47 next 40
- > 20, 35 change 36 number 35, 49
- ?RE? 18 chdir 36 o 27
-
-
-
-
-
-
-
-
-
-
-NNvvii//NNeexx RReeffeerreennccee UUSSDD::1133--8833
-
-
- octal 49 tildeop 51
- open 40, 49 timeout 51
- optimize 49 ttywerase 52
- p 27 u 28
- paragraph 11 unabbrev 44
- paragraphs 49 undo 44
- preserve 40 unmap 44
- previous 40 unnamed buffer 8
- previous context 9 v 38
- print 40 verbose 52
- prompt 49 version 44
- put 40 visual 44
- quit 41 viusage 44
- r 27 w 28
- range 33 w1200 52
- read 41 w300 52
- readonly 49 w9600 52
- recdir 49 warn 52
- recover 41 window 52
- redraw 50 wn 44
- remap 50 word 10
- report 50 wq 44
- resize 41 wrapmargin 52
- rewind 41 wrapscan 52
- ruler 50 write 44
- s 27 writeany 53
- scroll 50 x 28
- section 11 xit 45
- sections 50 y 28
- sentence 11 yank 45
- set 41 z 28, 45
- shell 42, 50 { 29
- shiftwidth 50 | 29
- showdirty 51 } 29
- showmatch 51 ~ 29, 30, 42
- showmode 51
- sidescroll 51
- slowopen 51
- source 42
- sourceany 51
- split 42
- stop 43
- substitute 42
- suspend 43
- t 27, 36
- tabstop 51
- tag 43
- taglength 51
- tagpop 43
- tags 51
- tagtop 43
- term 51
- terse 51
-
-
-
-
-
-
-
-
-
-
-UUSSDD::1133--22 NNvvii//NNeexx RReeffeerreennccee
-
-
- TTaabbllee ooff CCoonntteennttss
-
- Description ...................................... 3
- Startup Information .............................. 3
- Recovery ......................................... 4
- Sizing the Screen ................................ 7
- Character Display ................................ 7
- Multiple Screens ................................. 8
- Regular Expressions and Replacement Strings ...... 9
- General Editor Description ....................... 10
- Vi Description ................................... 12
- Vi Commands ...................................... 17
- Vi Text Input Commands ........................... 45
- Ex Addressing .................................... 47
- Ex Description ................................... 49
- Ex Commands ...................................... 50
- Set Options ...................................... 68
- Additional Features in Nex/Nvi ................... 79
- Index ............................................ 82
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/usr.bin/vi/USD.doc/vitut/Makefile b/usr.bin/vi/USD.doc/vitut/Makefile
deleted file mode 100644
index bfb29bff32e8..000000000000
--- a/usr.bin/vi/USD.doc/vitut/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# @(#)Makefile 8.1 (Berkeley) 8/14/93
-
-DIR= usd/12.vi
-SRCS= vi.in vi.chars
-MACROS= -msU
-CLEANFILES+=summary.* viapwh.*
-
-paper.ps: ${SRCS} summary.ps viapwh.ps
- ${TBL} ${SRCS} | ${ROFF} > ${.TARGET}
-
-summary.ps: vi.summary
- ${TBL} vi.summary | ${ROFF} > ${.TARGET}
-
-viapwh.ps: vi.apwh.ms
- ${ROFF} vi.apwh.ms > ${.TARGET}
-
-.include <bsd.doc.mk>
diff --git a/usr.bin/vi/common/Makefile b/usr.bin/vi/common/Makefile
deleted file mode 100644
index 67d88e7ae4b9..000000000000
--- a/usr.bin/vi/common/Makefile
+++ /dev/null
@@ -1,108 +0,0 @@
-# @(#)Makefile 8.51 (Berkeley) 8/17/94
-
-VI= nvi
-EX= nex
-VIEW= nview
-PROG= nvi
-LINKS= ${BINDIR}/${VI} ${BINDIR}/${EX} ${BINDIR}/${VI} ${BINDIR}/${VIEW}
-LINKS+= ${BINDIR}/${VI} ${BINDIR}/vi ${BINDIR}/${EX} ${BINDIR}/ex
-LINKS+= ${BINDIR}/${VI} ${BINDIR}/view
-MAN1= ${.CURDIR}/../USD.doc/vi.man/vi.1
-MLINKS+=vi.1 ex.1 vi.1 view.1
-MLINKS+=vi.1 nex.1 vi.1 nview.1 vi.1 nvi.1
-
-
-CFLAGS+=-I. -I${.CURDIR}
-DPADD+= ${LIBCURSES} ${LIBTERMCAP} ${LIBUTIL}
-LDADD+= -lcurses -ltermcap -lutil
-
-.PATH: ${.CURDIR}/../common ${.CURDIR}/../ex ${.CURDIR}/../sex \
- ${.CURDIR}/../vi ${.CURDIR}/../svi ${.CURDIR}/../xaw
-
-SPECHDR=compat.h excmd.h options.h
-
-CLEANFILES+=${SPECHDR} ${EX}
-
-# General sources.
-SRCS= cut.c delete.c exf.c line.c log.c main.c mark.c msg.c options.c \
- options_f.c put.c screen.c search.c seq.c signal.c recover.c \
- term.c trace.c util.c ${SPECHDR}
-
-# Ex source.
-SRCS+= ex.c ex_abbrev.c ex_append.c ex_args.c ex_argv.c ex_at.c ex_bang.c \
- ex_cd.c ex_delete.c ex_digraph.c ex_display.c ex_edit.c ex_equal.c \
- ex_exit.c ex_file.c ex_global.c ex_init.c ex_join.c ex_map.c \
- ex_mark.c ex_mkexrc.c ex_move.c ex_open.c ex_preserve.c ex_print.c \
- ex_put.c ex_read.c ex_screen.c ex_script.c ex_set.c ex_shell.c \
- ex_shift.c ex_source.c ex_stop.c ex_subst.c ex_tag.c ex_undo.c \
- ex_usage.c ex_util.c ex_version.c ex_visual.c ex_write.c ex_yank.c \
- ex_z.c excmd.c filter.c
-
-# Ex screen source.
-SRCS+= sex_confirm.c sex_get.c sex_refresh.c sex_screen.c sex_term.c \
- sex_util.c sex_window.c
-
-# Vi source.
-SRCS+= getc.c v_ch.c v_delete.c v_ex.c v_increment.c v_init.c v_left.c \
- v_mark.c v_match.c v_ntext.c v_paragraph.c v_put.c v_redraw.c \
- v_replace.c v_right.c v_screen.c v_scroll.c v_search.c v_section.c \
- v_sentence.c v_status.c v_stop.c v_text.c v_ulcase.c v_undo.c \
- v_util.c v_word.c v_xchar.c v_yank.c v_z.c v_zexit.c vcmd.c vi.c
-
-# Vi curses screen source.
-SRCS+= svi_confirm.c svi_curses.c svi_ex.c svi_get.c svi_line.c \
- svi_refresh.c svi_relative.c svi_screen.c svi_smap.c svi_split.c \
- svi_term.c svi_util.c
-
-# Athena widget set screen source.
-SRCS+= xaw_screen.c
-
-all: ${VI} ${EX}
-
-all: nvi nex
-nex: nvi
- rm -f nex
- ln nvi nex
-
-${EX}: ${VI}
- rm -f ${EX}
- ln ${VI} ${EX}
-
-compat.h:
- :> compat.h
-
-excmd.h: excmd.h.stub excmd.c excmd.awk
- rm -f excmd.h
- cat ${.CURDIR}/../ex/excmd.h.stub > excmd.h
- awk -f ${.CURDIR}/../ex/excmd.awk ${.CURDIR}/../ex/excmd.c >> excmd.h
-
-options.h: options.h.stub options.c options.awk
- rm -f options.h
- cat ${.CURDIR}/options.h.stub > options.h
- awk -f ${.CURDIR}/options.awk ${.CURDIR}/options.c >> options.h
-
-excmd.h: excmd.h.stub excmd.c excmd.awk
- rm -f excmd.h
- cat ${.CURDIR}/../ex/excmd.h.stub > excmd.h
- awk -f ${.CURDIR}/../ex/excmd.awk ${.CURDIR}/../ex/excmd.c >> excmd.h
-
-tags::
- -(cd ${.CURDIR} && rm -f tags && \
- ctags ../common/*.[ch] ../common/*.stub ../ex/*.[ch] ../ex/*.stub \
- ../vi/*.[ch] ../sex/*.[ch] ../svi/*.[ch] ../xaw/*.[ch])
-
-warn:: ${SRCS}
- -(cd ${.CURDIR} && gcc -Wall -O4 -DDEBUG \
- -Iobj -I. ${.ALLSRC} -lcurses -ltermcap 2>&1 | \
- sed -e "/warning: .*sccsid.*defined but not used/d" \
- -e "/warning: suggest parentheses around/d" \
- -e "/In function /d" \
- -e "/At top level:/d" \
- -e "/warning: .*inline call to/d" \
- -e "/warning: comparison is always 1 due /d") > \
- ${.CURDIR}/WARN.OUT
-
-.include "../../Makefile.inc"
-.include <bsd.prog.mk>
-
-.depend: ${SPECHDR}
diff --git a/usr.bin/vi/common/args.h b/usr.bin/vi/common/args.h
deleted file mode 100644
index 5e127dec9b34..000000000000
--- a/usr.bin/vi/common/args.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)args.h 8.5 (Berkeley) 7/17/94
- */
-
-/*
- * Structure for building "argc/argv" vector of arguments.
- *
- * !!!
- * All arguments are nul terminated as well as having an associated length.
- * The argument vector is NOT necessarily NULL terminated. The proper way
- * to check the number of arguments is to use the argc value in the EXCMDARG
- * structure or to walk the array until an ARGS structure with a length of 0
- * is found.
- */
-typedef struct _args {
- CHAR_T *bp; /* Argument. */
- size_t blen; /* Buffer length. */
- size_t len; /* Argument length. */
-
-#define A_ALLOCATED 0x01 /* If allocated space. */
- u_int8_t flags;
-} ARGS;
diff --git a/usr.bin/vi/common/cut.h b/usr.bin/vi/common/cut.h
deleted file mode 100644
index 3113411a5242..000000000000
--- a/usr.bin/vi/common/cut.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)cut.h 8.19 (Berkeley) 7/28/94
- */
-
-typedef struct _texth TEXTH; /* TEXT list head structure. */
-CIRCLEQ_HEAD(_texth, _text);
-
-/* Cut buffers. */
-struct _cb {
- LIST_ENTRY(_cb) q; /* Linked list of cut buffers. */
- TEXTH textq; /* Linked list of TEXT structures. */
- CHAR_T name; /* Cut buffer name. */
- size_t len; /* Total length of cut text. */
-
-#define CB_LMODE 0x01 /* Cut was in line mode. */
- u_int8_t flags;
-};
-
-/* Lines/blocks of text. */
-struct _text { /* Text: a linked list of lines. */
- CIRCLEQ_ENTRY(_text) q; /* Linked list of text structures. */
- char *lb; /* Line buffer. */
- size_t lb_len; /* Line buffer length. */
- size_t len; /* Line length. */
-
- /* These fields are used by the vi text input routine. */
- recno_t lno; /* 1-N: line number. */
- size_t ai; /* 0-N: autoindent bytes. */
- size_t insert; /* 0-N: bytes to insert (push). */
- size_t offset; /* 0-N: initial, unerasable chars. */
- size_t owrite; /* 0-N: chars to overwrite. */
- size_t R_erase; /* 0-N: 'R' erase count. */
- size_t sv_cno; /* 0-N: Saved line cursor. */
- size_t sv_len; /* 0-N: Saved line length. */
-
- /* These fields are used by the ex text input routine. */
- u_char *wd; /* Width buffer. */
- size_t wd_len; /* Width buffer length. */
-};
-
-/*
- * Get named buffer 'name'.
- * Translate upper-case buffer names to lower-case buffer names.
- */
-#define CBNAME(sp, cbp, nch) { \
- CHAR_T __name; \
- __name = isupper(nch) ? tolower(nch) : (nch); \
- for (cbp = sp->gp->cutq.lh_first; \
- cbp != NULL; cbp = cbp->q.le_next) \
- if (cbp->name == __name) \
- break; \
-}
-
-#define CUT_LINEMODE 0x01 /* Cut in line mode. */
-#define CUT_NUMOPT 0x02 /* Numeric buffer: optional. */
-#define CUT_NUMREQ 0x04 /* Numeric buffer: required. */
-int cut __P((SCR *, EXF *, CHAR_T *, MARK *, MARK *, int));
-
-int cut_line __P((SCR *, EXF *, recno_t, size_t, size_t, CB *));
-int delete __P((SCR *, EXF *, MARK *, MARK *, int));
-int put __P((SCR *, EXF *, CB *, CHAR_T *, MARK *, MARK *, int));
-
-void text_free __P((TEXT *));
-TEXT *text_init __P((SCR *, const char *, size_t, size_t));
-void text_lfree __P((TEXTH *));
diff --git a/usr.bin/vi/common/delete.c b/usr.bin/vi/common/delete.c
deleted file mode 100644
index 4edd008e6f09..000000000000
--- a/usr.bin/vi/common/delete.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)delete.c 8.10 (Berkeley) 4/26/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-
-/*
- * delete --
- * Delete a range of text.
- */
-int
-delete(sp, ep, fm, tm, lmode)
- SCR *sp;
- EXF *ep;
- MARK *fm, *tm;
- int lmode;
-{
- recno_t lno;
- size_t blen, len, nlen, tlen;
- char *bp, *p;
- int eof;
-
- bp = NULL;
-
- /* Case 1 -- delete in line mode. */
- if (lmode) {
- for (lno = tm->lno; lno >= fm->lno; --lno)
- if (file_dline(sp, ep, lno))
- return (1);
- goto vdone;
- }
-
- /*
- * Case 2 -- delete to EOF. This is a special case because it's
- * easier to pick it off than try and find it in the other cases.
- */
- if (file_lline(sp, ep, &lno))
- return (1);
- if (tm->lno >= lno) {
- if (tm->lno == lno) {
- if ((p = file_gline(sp, ep, lno, &len)) == NULL) {
- GETLINE_ERR(sp, lno);
- return (1);
- }
- eof = tm->cno >= len ? 1 : 0;
- } else
- eof = 1;
- if (eof) {
- for (lno = tm->lno; lno > fm->lno; --lno) {
- if (file_dline(sp, ep, lno))
- return (1);
- ++sp->rptlines[L_DELETED];
- }
- if ((p = file_gline(sp, ep, fm->lno, &len)) == NULL) {
- GETLINE_ERR(sp, fm->lno);
- return (1);
- }
- GET_SPACE_RET(sp, bp, blen, fm->cno);
- memmove(bp, p, fm->cno);
- if (file_sline(sp, ep, fm->lno, bp, fm->cno))
- return (1);
- goto done;
- }
- }
-
- /* Case 3 -- delete within a single line. */
- if (tm->lno == fm->lno) {
- if ((p = file_gline(sp, ep, fm->lno, &len)) == NULL) {
- GETLINE_ERR(sp, fm->lno);
- return (1);
- }
- GET_SPACE_RET(sp, bp, blen, len);
- if (fm->cno != 0)
- memmove(bp, p, fm->cno);
- memmove(bp + fm->cno, p + (tm->cno + 1), len - (tm->cno + 1));
- if (file_sline(sp, ep, fm->lno,
- bp, len - ((tm->cno - fm->cno) + 1)))
- goto err;
- goto done;
- }
-
- /*
- * Case 4 -- delete over multiple lines.
- *
- * Copy the start partial line into place.
- */
- if ((tlen = fm->cno) != 0) {
- if ((p = file_gline(sp, ep, fm->lno, NULL)) == NULL) {
- GETLINE_ERR(sp, fm->lno);
- return (1);
- }
- GET_SPACE_RET(sp, bp, blen, tlen + 256);
- memmove(bp, p, tlen);
- }
-
- /* Copy the end partial line into place. */
- if ((p = file_gline(sp, ep, tm->lno, &len)) == NULL) {
- GETLINE_ERR(sp, tm->lno);
- goto err;
- }
- if (len != 0 && tm->cno != len - 1) {
- /*
- * XXX
- * We can overflow memory here, if the total length is greater
- * than SIZE_T_MAX. The only portable way I've found to test
- * is depending on the overflow being less than the value.
- */
- nlen = (len - (tm->cno + 1)) + tlen;
- if (tlen > nlen) {
- msgq(sp, M_ERR, "Error: line length overflow");
- goto err;
- }
- if (tlen == 0) {
- GET_SPACE_RET(sp, bp, blen, nlen);
- } else
- ADD_SPACE_RET(sp, bp, blen, nlen);
-
- memmove(bp + tlen, p + (tm->cno + 1), len - (tm->cno + 1));
- tlen += len - (tm->cno + 1);
- }
-
- /* Set the current line. */
- if (file_sline(sp, ep, fm->lno, bp, tlen))
- goto err;
-
- /* Delete the last and intermediate lines. */
- for (lno = tm->lno; lno > fm->lno; --lno)
- if (file_dline(sp, ep, lno))
- goto err;
-
- /* Reporting. */
-vdone: sp->rptlines[L_DELETED] += tm->lno - fm->lno + 1;
-
-done: if (bp != NULL)
- FREE_SPACE(sp, bp, blen);
-
- return (0);
-
- /* Free memory. */
-err: if (bp != NULL)
- FREE_SPACE(sp, bp, blen);
- return (1);
-}
diff --git a/usr.bin/vi/common/exf.c b/usr.bin/vi/common/exf.c
deleted file mode 100644
index b18565e2d0a0..000000000000
--- a/usr.bin/vi/common/exf.c
+++ /dev/null
@@ -1,830 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)exf.c 8.94 (Berkeley) 8/7/94";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-/*
- * We include <sys/file.h>, because the flock(2) and open(2) #defines
- * were found there on historical systems. We also include <fcntl.h>
- * because the open(2) #defines are found there on newer systems.
- */
-#include <sys/file.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-#include <pathnames.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * file_add --
- * Insert a file name into the FREF list, if it doesn't already
- * appear in it.
- *
- * !!!
- * The "if it doesn't already appear" changes vi's semantics slightly. If
- * you do a "vi foo bar", and then execute "next bar baz", the edit of bar
- * will reflect the line/column of the previous edit session. Historic nvi
- * did not do this. The change is a logical extension of the change where
- * vi now remembers the last location in any file that it has ever edited,
- * not just the previously edited file.
- */
-FREF *
-file_add(sp, name)
- SCR *sp;
- CHAR_T *name;
-{
- FREF *frp;
-
- /*
- * Return it if it already exists. Note that we test against the
- * user's name, whatever that happens to be, including if it's a
- * temporary file.
- */
- if (name != NULL)
- for (frp = sp->frefq.cqh_first;
- frp != (FREF *)&sp->frefq; frp = frp->q.cqe_next)
- if (!strcmp(frp->name, name))
- return (frp);
-
- /* Allocate and initialize the FREF structure. */
- CALLOC(sp, frp, FREF *, 1, sizeof(FREF));
- if (frp == NULL)
- return (NULL);
-
- /*
- * If no file name specified, or if the file name is a request
- * for something temporary, file_init() will allocate the file
- * name. Temporary files are always ignored.
- */
- if (name != NULL && strcmp(name, TEMPORARY_FILE_STRING) &&
- (frp->name = strdup(name)) == NULL) {
- FREE(frp, sizeof(FREF));
- msgq(sp, M_SYSERR, NULL);
- return (NULL);
- }
-
- /* Append into the chain of file names. */
- CIRCLEQ_INSERT_TAIL(&sp->frefq, frp, q);
-
- return (frp);
-}
-
-/*
- * file_init --
- * Start editing a file, based on the FREF structure. If successsful,
- * let go of any previous file. Don't release the previous file until
- * absolutely sure we have the new one.
- */
-int
-file_init(sp, frp, rcv_name, force)
- SCR *sp;
- FREF *frp;
- char *rcv_name;
- int force;
-{
- EXF *ep;
- RECNOINFO oinfo;
- struct stat sb;
- size_t psize;
- int fd;
- char *oname, tname[MAXPATHLEN];
-
- /*
- * If the file is a recovery file, let the recovery code handle it.
- * Clear the FR_RECOVER flag first -- the recovery code does set up,
- * and then calls us! If the recovery call fails, it's probably
- * because the named file doesn't exist. So, move boldly forward,
- * presuming that there's an error message the user will get to see.
- */
- if (F_ISSET(frp, FR_RECOVER)) {
- F_CLR(frp, FR_RECOVER);
- return (rcv_read(sp, frp));
- }
-
- /*
- * Required FRP initialization; the only flag we keep is the
- * cursor information.
- */
- F_CLR(frp, ~FR_CURSORSET);
-
- /*
- * Required EXF initialization:
- * Flush the line caches.
- * Default recover mail file fd to -1.
- * Set initial EXF flag bits.
- */
- CALLOC_RET(sp, ep, EXF *, 1, sizeof(EXF));
- ep->c_lno = ep->c_nlines = OOBLNO;
- ep->rcv_fd = ep->fcntl_fd = -1;
- LIST_INIT(&ep->marks);
- F_SET(ep, F_FIRSTMODIFY);
-
- /*
- * If no name or backing file, create a backing temporary file, saving
- * the temp file name so we can later unlink it. If the user never
- * named this file, copy the temporary file name to the real name (we
- * display that until the user renames it).
- */
- if ((oname = frp->name) == NULL || stat(oname, &sb)) {
- (void)snprintf(tname,
- sizeof(tname), "%s/vi.XXXXXX", O_STR(sp, O_DIRECTORY));
- if ((fd = mkstemp(tname)) == -1) {
- msgq(sp, M_SYSERR, "Temporary file");
- goto err;
- }
- (void)close(fd);
-
- if (frp->name == NULL)
- F_SET(frp, FR_TMPFILE);
- if ((frp->tname = strdup(tname)) == NULL ||
- frp->name == NULL && (frp->name = strdup(tname)) == NULL) {
- if (frp->tname != NULL)
- free(frp->tname);
- msgq(sp, M_SYSERR, NULL);
- (void)unlink(tname);
- goto err;
- }
- oname = frp->tname;
- psize = 4 * 1024;
- F_SET(frp, FR_NEWFILE);
- } else {
- /*
- * Try to keep it at 10 pages or less per file. This
- * isn't friendly on a loaded machine, btw.
- */
- if (sb.st_size < 40 * 1024)
- psize = 4 * 1024;
- else if (sb.st_size < 320 * 1024)
- psize = 32 * 1024;
- else
- psize = 64 * 1024;
-
- ep->mtime = sb.st_mtime;
-
- if (!S_ISREG(sb.st_mode))
- msgq(sp, M_ERR,
- "Warning: %s is not a regular file", oname);
- }
-
- /* Set up recovery. */
- memset(&oinfo, 0, sizeof(RECNOINFO));
- oinfo.bval = '\n'; /* Always set. */
- oinfo.psize = psize;
- oinfo.flags = F_ISSET(sp->gp, G_SNAPSHOT) ? R_SNAPSHOT : 0;
- if (rcv_name == NULL) {
- if (!rcv_tmp(sp, ep, frp->name))
- oinfo.bfname = ep->rcv_path;
- } else {
- if ((ep->rcv_path = strdup(rcv_name)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- goto err;
- }
- oinfo.bfname = ep->rcv_path;
- F_SET(ep, F_MODIFIED);
- }
-
- /* Open a db structure. */
- if ((ep->db = dbopen(rcv_name == NULL ? oname : NULL,
- O_NONBLOCK | O_RDONLY, DEFFILEMODE, DB_RECNO, &oinfo)) == NULL) {
- msgq(sp, M_SYSERR, rcv_name == NULL ? oname : rcv_name);
- goto err;
- }
-
- /*
- * Do the remaining things that can cause failure of the new file,
- * mark and logging initialization.
- */
- if (mark_init(sp, ep) || log_init(sp, ep))
- goto err;
-
- /*
- * Close the previous file; if that fails, close the new one and
- * run for the border.
- *
- * !!!
- * There's a nasty special case. If the user edits a temporary file,
- * and then does an ":e! %", we need to re-initialize the backing
- * file, but we can't change the name. (It's worse -- we're dealing
- * with *names* here, we can't even detect that it happened.) Set a
- * flag so that the file_end routine ignores the backing information
- * of the old file if it happens to be the same as the new one.
- *
- * !!!
- * Side-effect: after the call to file_end(), sp->frp may be NULL.
- */
- F_SET(frp, FR_DONTDELETE);
- if (sp->ep != NULL && file_end(sp, sp->ep, force)) {
- (void)file_end(sp, ep, 1);
- goto err;
- }
- F_CLR(frp, FR_DONTDELETE);
-
- /*
- * Lock the file; if it's a recovery file, it should already be
- * locked. Note, we acquire the lock after the previous file
- * has been ended, so that we don't get an "already locked" error
- * for ":edit!".
- *
- * XXX
- * While the user can't interrupt us between the open and here,
- * there's a race between the dbopen() and the lock. Not much
- * we can do about it.
- *
- * XXX
- * We don't make a big deal of not being able to lock the file. As
- * locking rarely works over NFS, and often fails if the file was
- * mmap(2)'d, it's far too common to do anything like print an error
- * message, let alone make the file readonly. At some future time,
- * when locking is a little more reliable, this should change to be
- * an error.
- */
- if (rcv_name == NULL)
- switch (file_lock(oname,
- &ep->fcntl_fd, ep->db->fd(ep->db), 0)) {
- case LOCK_FAILED:
- F_SET(frp, FR_UNLOCKED);
- break;
- case LOCK_UNAVAIL:
- msgq(sp, M_INFO,
- "%s already locked, session is read-only", oname);
- F_SET(frp, FR_RDONLY);
- break;
- case LOCK_SUCCESS:
- break;
- }
-
- /*
- * The -R flag, or doing a "set readonly" during a session causes
- * all files edited during the session (using an edit command, or
- * even using tags) to be marked read-only. Changing the file name
- * (see ex/ex_file.c), clears this flag.
- *
- * Otherwise, try and figure out if a file is readonly. This is a
- * dangerous thing to do. The kernel is the only arbiter of whether
- * or not a file is writeable, and the best that a user program can
- * do is guess. Obvious loopholes are files that are on a file system
- * mounted readonly (access catches this one on a few systems), or
- * alternate protection mechanisms, ACL's for example, that we can't
- * portably check. Lots of fun, and only here because users whined.
- *
- * !!!
- * Historic vi displayed the readonly message if none of the file
- * write bits were set, or if an an access(2) call on the path
- * failed. This seems reasonable. If the file is mode 444, root
- * users may want to know that the owner of the file did not expect
- * it to be written.
- *
- * Historic vi set the readonly bit if no write bits were set for
- * a file, even if the access call would have succeeded. This makes
- * the superuser force the write even when vi expects that it will
- * succeed. I'm less supportive of this semantic, but it's historic
- * practice and the conservative approach to vi'ing files as root.
- *
- * It would be nice if there was some way to update this when the user
- * does a "^Z; chmod ...". The problem is that we'd first have to
- * distinguish between readonly bits set because of file permissions
- * and those set for other reasons. That's not too hard, but deciding
- * when to reevaluate the permissions is trickier. An alternative
- * might be to turn off the readonly bit if the user forces a write
- * and it succeeds.
- *
- * XXX
- * Access(2) doesn't consider the effective uid/gid values. This
- * probably isn't a problem for vi when it's running standalone.
- */
- if (O_ISSET(sp, O_READONLY) || !F_ISSET(frp, FR_NEWFILE) &&
- (!(sb.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) ||
- access(frp->name, W_OK)))
- F_SET(frp, FR_RDONLY);
-
- /*
- * Set the alternate file name to be the file we've just discarded.
- *
- * !!!
- * If the current file was a temporary file, the call to file_end()
- * unlinked it and free'd the name. So, there is no previous file,
- * and there is no alternate file name. This matches historical
- * practice, although in historical vi it could only happen as the
- * result of the initial command, i.e. if vi was executed without a
- * file name.
- */
- set_alt_name(sp, sp->frp == NULL ? NULL : sp->frp->name);
-
- /* Switch... */
- ++ep->refcnt;
- sp->ep = ep;
- sp->frp = frp;
- return (0);
-
-err: if (frp->name != NULL) {
- free(frp->name);
- frp->name = NULL;
- }
- if (frp->tname != NULL) {
- (void)unlink(frp->tname);
- free(frp->tname);
- frp->tname = NULL;
- }
- if (ep->rcv_path != NULL) {
- free(ep->rcv_path);
- ep->rcv_path = NULL;
- }
- if (ep->db != NULL)
- (void)ep->db->close(ep->db);
- FREE(ep, sizeof(EXF));
- return (1);
-}
-
-/*
- * file_end --
- * Stop editing a file.
- */
-int
-file_end(sp, ep, force)
- SCR *sp;
- EXF *ep;
- int force;
-{
- FREF *frp;
-
- /*
- * Clean up the FREF structure.
- *
- * Save the cursor location.
- *
- * XXX
- * It would be cleaner to do this somewhere else, but by the time
- * ex or vi knows that we're changing files it's already happened.
- */
- frp = sp->frp;
- frp->lno = sp->lno;
- frp->cno = sp->cno;
- F_SET(frp, FR_CURSORSET);
-
- /*
- * We may no longer need the temporary backing file, so clean it
- * up. We don't need the FREF structure either, if the file was
- * never named, so lose it.
- *
- * !!!
- * Re: FR_DONTDELETE, see the comment above in file_init().
- */
- if (!F_ISSET(frp, FR_DONTDELETE) && frp->tname != NULL) {
- if (unlink(frp->tname))
- msgq(sp, M_SYSERR, "%s: remove", frp->tname);
- free(frp->tname);
- frp->tname = NULL;
- if (F_ISSET(frp, FR_TMPFILE)) {
- CIRCLEQ_REMOVE(&sp->frefq, frp, q);
- free(frp->name);
- free(frp);
- }
- sp->frp = NULL;
- }
-
- /*
- * Clean up the EXF structure.
- *
- * sp->ep MAY NOT BE THE SAME AS THE ARGUMENT ep, SO DON'T USE IT!
- *
- * If multiply referenced, just decrement the count and return.
- */
- if (--ep->refcnt != 0)
- return (0);
-
- /* Close the db structure. */
- if (ep->db->close != NULL && ep->db->close(ep->db) && !force) {
- msgq(sp, M_ERR, "%s: close: %s", frp->name, strerror(errno));
- ++ep->refcnt;
- return (1);
- }
-
- /* COMMITTED TO THE CLOSE. THERE'S NO GOING BACK... */
-
- /* Stop logging. */
- (void)log_end(sp, ep);
-
- /* Free up any marks. */
- (void)mark_end(sp, ep);
-
- /*
- * Delete recovery files, close the open descriptor, free recovery
- * memory. See recover.c for a description of the protocol.
- *
- * XXX
- * Unlink backup file first, we can detect that the recovery file
- * doesn't reference anything when the user tries to recover it.
- * There's a race, here, obviously, but it's fairly small.
- */
- if (!F_ISSET(ep, F_RCV_NORM)) {
- if (ep->rcv_path != NULL && unlink(ep->rcv_path))
- msgq(sp, M_ERR,
- "%s: remove: %s", ep->rcv_path, strerror(errno));
- if (ep->rcv_mpath != NULL && unlink(ep->rcv_mpath))
- msgq(sp, M_ERR,
- "%s: remove: %s", ep->rcv_mpath, strerror(errno));
- }
- if (ep->fcntl_fd != -1)
- (void)close(ep->fcntl_fd);
- if (ep->rcv_fd != -1)
- (void)close(ep->rcv_fd);
- if (ep->rcv_path != NULL)
- free(ep->rcv_path);
- if (ep->rcv_mpath != NULL)
- free(ep->rcv_mpath);
-
- FREE(ep, sizeof(EXF));
- return (0);
-}
-
-/*
- * file_write --
- * Write the file to disk. Historic vi had fairly convoluted
- * semantics for whether or not writes would happen. That's
- * why all the flags.
- */
-int
-file_write(sp, ep, fm, tm, name, flags)
- SCR *sp;
- EXF *ep;
- MARK *fm, *tm;
- char *name;
- int flags;
-{
- struct stat sb;
- FILE *fp;
- FREF *frp;
- MARK from, to;
- u_long nlno, nch;
- int btear, fd, noname, oflags, rval;
- char *msg;
-
- frp = sp->frp;
- if (name == NULL) {
- noname = 1;
- name = frp->name;
- } else
- noname = 0;
-
- /* Can't write files marked read-only, unless forced. */
- if (!LF_ISSET(FS_FORCE) && noname && F_ISSET(frp, FR_RDONLY)) {
- if (LF_ISSET(FS_POSSIBLE))
- msgq(sp, M_ERR,
- "Read-only file, not written; use ! to override");
- else
- msgq(sp, M_ERR, "Read-only file, not written");
- return (1);
- }
-
- /* If not forced, not appending, and "writeany" not set ... */
- if (!LF_ISSET(FS_FORCE | FS_APPEND) && !O_ISSET(sp, O_WRITEANY)) {
- /* Don't overwrite anything but the original file. */
- if ((!noname || F_ISSET(frp, FR_NAMECHANGE)) &&
- !stat(name, &sb)) {
- if (LF_ISSET(FS_POSSIBLE))
- msgq(sp, M_ERR,
- "%s exists, not written; use ! to override", name);
- else
- msgq(sp, M_ERR, "%s exists, not written", name);
- return (1);
- }
-
- /*
- * Don't write part of any existing file. Only test for the
- * original file, the previous test catches anything else.
- */
- if (!LF_ISSET(FS_ALL) && noname && !stat(name, &sb)) {
- if (LF_ISSET(FS_POSSIBLE))
- msgq(sp, M_ERR,
- "Use ! to write a partial file");
- else
- msgq(sp, M_ERR, "Partial file, not written");
- return (1);
- }
- }
-
- /*
- * Figure out if the file already exists -- if it doesn't, we display
- * the "new file" message. The stat might not be necessary, but we
- * just repeat it because it's easier than hacking the previous tests.
- * The information is only used for the user message and modification
- * time test, so we can ignore the obvious race condition.
- *
- * If the user is overwriting a file other than the original file, and
- * O_WRITEANY was what got us here (neither force nor append was set),
- * display the "existing file" messsage. Since the FR_NAMECHANGE flag
- * is cleared on a successful write, the message only appears once when
- * the user changes a file name. This is historic practice.
- *
- * One final test. If we're not forcing or appending, and we have a
- * saved modification time, stop the user if it's been written since
- * we last edited or wrote it, and make them force it.
- */
- if (stat(name, &sb))
- msg = ": new file";
- else {
- msg = "";
- if (!LF_ISSET(FS_FORCE | FS_APPEND)) {
- if (ep->mtime && sb.st_mtime > ep->mtime) {
- msgq(sp, M_ERR,
- "%s: file modified more recently than this copy%s",
- name, LF_ISSET(FS_POSSIBLE) ?
- "; use ! to override" : "");
- return (1);
- }
- if (!noname || F_ISSET(frp, FR_NAMECHANGE))
- msg = ": existing file";
- }
- }
-
- /* Set flags to either append or truncate. */
- oflags = O_CREAT | O_WRONLY;
- if (LF_ISSET(FS_APPEND))
- oflags |= O_APPEND;
- else
- oflags |= O_TRUNC;
-
- /* Open the file. */
- if ((fd = open(name, oflags, DEFFILEMODE)) < 0) {
- msgq(sp, M_SYSERR, name);
- return (1);
- }
-
- /* Use stdio for buffering. */
- if ((fp = fdopen(fd, "w")) == NULL) {
- (void)close(fd);
- msgq(sp, M_SYSERR, name);
- return (1);
- }
-
- /* Build fake addresses, if necessary. */
- if (fm == NULL) {
- from.lno = 1;
- from.cno = 0;
- fm = &from;
- if (file_lline(sp, ep, &to.lno))
- return (1);
- to.cno = 0;
- tm = &to;
- }
-
- /* Turn on the busy message. */
- btear = F_ISSET(sp, S_EXSILENT) ? 0 : !busy_on(sp, "Writing...");
- rval = ex_writefp(sp, ep, name, fp, fm, tm, &nlno, &nch);
- if (btear)
- busy_off(sp);
-
- /*
- * Save the new last modification time -- even if the write fails
- * we re-init the time. That way the user can clean up the disk
- * and rewrite without having to force it.
- */
- ep->mtime = stat(name, &sb) ? 0 : sb.st_mtime;
-
- /* If the write failed, complain loudly. */
- if (rval) {
- if (!LF_ISSET(FS_APPEND))
- msgq(sp, M_ERR, "%s: WARNING: file truncated!", name);
- return (1);
- }
-
- /*
- * Once we've actually written the file, it doesn't matter that the
- * file name was changed -- if it was, we've already whacked it.
- */
- F_CLR(frp, FR_NAMECHANGE);
-
- /*
- * If wrote the entire file clear the modified bit. If the file was
- * written back to the original file name and the file is a temporary,
- * set the "no exit" bit. This permits the user to write the file and
- * use it in the context of the file system, but still keeps them from
- * losing their changes by exiting.
- */
- if (LF_ISSET(FS_ALL)) {
- F_CLR(ep, F_MODIFIED);
- if (F_ISSET(frp, FR_TMPFILE))
- if (noname)
- F_SET(frp, FR_TMPEXIT);
- else
- F_CLR(frp, FR_TMPEXIT);
- }
-
- msgq(sp, M_INFO, "%s%s%s: %lu line%s, %lu characters",
- INTERRUPTED(sp) ? "Interrupted write: " : "",
- name, msg, nlno, nlno == 1 ? "" : "s", nch);
-
- return (0);
-}
-
-/*
- * file_m1 --
- * First modification check routine. The :next, :prev, :rewind, :tag,
- * :tagpush, :tagpop, ^^ modifications check.
- */
-int
-file_m1(sp, ep, force, flags)
- SCR *sp;
- EXF *ep;
- int force, flags;
-{
- /*
- * If the file has been modified, we'll want to write it back or
- * fail. If autowrite is set, we'll write it back automatically,
- * unless force is also set. Otherwise, we fail unless forced or
- * there's another open screen on this file.
- */
- if (F_ISSET(ep, F_MODIFIED))
- if (O_ISSET(sp, O_AUTOWRITE)) {
- if (!force &&
- file_write(sp, ep, NULL, NULL, NULL, flags))
- return (1);
- } else if (ep->refcnt <= 1 && !force) {
- msgq(sp, M_ERR,
- "File modified since last complete write; write or use %s to override",
- LF_ISSET(FS_POSSIBLE) ? "!" : ":edit!");
- return (1);
- }
-
- return (file_m3(sp, ep, force));
-}
-
-/*
- * file_m2 --
- * Second modification check routine. The :edit, :quit, :recover
- * modifications check.
- */
-int
-file_m2(sp, ep, force)
- SCR *sp;
- EXF *ep;
- int force;
-{
- /*
- * If the file has been modified, we'll want to fail, unless forced
- * or there's another open screen on this file.
- */
- if (F_ISSET(ep, F_MODIFIED) && ep->refcnt <= 1 && !force) {
- msgq(sp, M_ERR,
- "File modified since last complete write; write or use ! to override");
- return (1);
- }
-
- return (file_m3(sp, ep, force));
-}
-
-/*
- * file_m3 --
- * Third modification check routine.
- */
-int
-file_m3(sp, ep, force)
- SCR *sp;
- EXF *ep;
- int force;
-{
- /*
- * Don't exit while in a temporary files if the file was ever modified.
- * The problem is that if the user does a ":wq", we write and quit,
- * unlinking the temporary file. Not what the user had in mind at all.
- * We permit writing to temporary files, so that user maps using file
- * system names work with temporary files.
- */
- if (F_ISSET(sp->frp, FR_TMPEXIT) && ep->refcnt <= 1 && !force) {
- msgq(sp, M_ERR,
- "File is a temporary; exit will discard modifications");
- return (1);
- }
- return (0);
-}
-
-/*
- * file_lock --
- * Get an exclusive lock on a file.
- *
- * XXX
- * The default locking is flock(2) style, not fcntl(2). The latter is
- * known to fail badly on some systems, and its only advantage is that
- * it occasionally works over NFS.
- *
- * Furthermore, the semantics of fcntl(2) are wrong. The problems are
- * two-fold: you can't close any file descriptor associated with the file
- * without losing all of the locks, and you can't get an exclusive lock
- * unless you have the file open for writing. Someone ought to be shot,
- * but it's probably too late, they may already have reproduced. To get
- * around these problems, nvi opens the files for writing when it can and
- * acquires a second file descriptor when it can't. The recovery files
- * are examples of the former, they're always opened for writing. The DB
- * files can't be opened for writing because the semantics of DB are that
- * files opened for writing are flushed back to disk when the DB session
- * is ended. So, in that case we have to acquire an extra file descriptor.
- */
-enum lockt
-file_lock(name, fdp, fd, iswrite)
- char *name;
- int fd, *fdp, iswrite;
-{
-#if !defined(USE_FCNTL) && defined(LOCK_EX)
- /* Hurrah! We've got flock(2). */
- /*
- * !!!
- * We need to distinguish a lock not being available for the file
- * from the file system not supporting locking. Flock is documented
- * as returning EWOULDBLOCK; add EAGAIN for good measure, and assume
- * they are the former. There's no portable way to do this.
- */
- errno = 0;
- return (flock(fd, LOCK_EX | LOCK_NB) ?
- errno == EAGAIN || errno == EWOULDBLOCK ?
- LOCK_UNAVAIL : LOCK_FAILED : LOCK_SUCCESS);
-
-#else /* Gag me. We've got fcntl(2). */
- struct flock arg;
- int didopen, sverrno;
-
- arg.l_type = F_WRLCK;
- arg.l_whence = 0; /* SEEK_SET */
- arg.l_start = arg.l_len = 0;
- arg.l_pid = 0;
-
- /* If the file descriptor isn't opened for writing, it must fail. */
- if (!iswrite) {
- if (name == NULL || fdp == NULL)
- return (LOCK_FAILED);
- if ((fd = open(name, O_RDWR, 0)) == -1)
- return (LOCK_FAILED);
- *fdp = fd;
- didopen = 1;
- }
-
- errno = 0;
- if (!fcntl(fd, F_SETLK, &arg))
- return (LOCK_SUCCESS);
- if (didopen) {
- sverrno = errno;
- (void)close(fd);
- errno = sverrno;
- }
-
- /*
- * !!!
- * We need to distinguish a lock not being available for the file
- * from the file system not supporting locking. Fcntl is documented
- * as returning EACCESS and EAGAIN; add EWOULDBLOCK for good measure,
- * and assume they are the former. There's no portable way to do this.
- */
- return (errno == EACCES || errno == EAGAIN || errno == EWOULDBLOCK ?
- LOCK_UNAVAIL : LOCK_FAILED);
-#endif
-}
diff --git a/usr.bin/vi/common/exf.h b/usr.bin/vi/common/exf.h
deleted file mode 100644
index 1b06649384fb..000000000000
--- a/usr.bin/vi/common/exf.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)exf.h 8.35 (Berkeley) 8/4/94
- */
- /* Undo direction. */
-/*
- * exf --
- * The file structure.
- */
-struct _exf {
- int refcnt; /* Reference count. */
-
- /* Underlying database state. */
- DB *db; /* File db structure. */
- char *c_lp; /* Cached line. */
- size_t c_len; /* Cached line length. */
- recno_t c_lno; /* Cached line number. */
- recno_t c_nlines; /* Cached lines in the file. */
-
- DB *log; /* Log db structure. */
- char *l_lp; /* Log buffer. */
- size_t l_len; /* Log buffer length. */
- recno_t l_high; /* Log last + 1 record number. */
- recno_t l_cur; /* Log current record number. */
- MARK l_cursor; /* Log cursor position. */
- enum direction lundo; /* Last undo direction. */
-
- LIST_HEAD(_markh, _lmark) marks;/* Linked list of file MARK's. */
-
- time_t mtime; /* Last modification time. */
-
- int fcntl_fd; /* Fcntl locking fd; see exf.c. */
-
- /*
- * Recovery in general, and these fields specifically, are described
- * in recover.c.
- */
-#define RCV_PERIOD 120 /* Sync every two minutes. */
- char *rcv_path; /* Recover file name. */
- char *rcv_mpath; /* Recover mail file name. */
- int rcv_fd; /* Locked mail file descriptor. */
- struct timeval rcv_tod; /* ITIMER_REAL: recovery time-of-day. */
-
-#define F_FIRSTMODIFY 0x001 /* File not yet modified. */
-#define F_MODIFIED 0x002 /* File is currently dirty. */
-#define F_MULTILOCK 0x004 /* Multiple processes running, lock. */
-#define F_NOLOG 0x008 /* Logging turned off. */
-#define F_RCV_NORM 0x010 /* Don't delete recovery files. */
-#define F_RCV_ON 0x020 /* Recovery is possible. */
-#define F_UNDO 0x040 /* No change since last undo. */
- u_int8_t flags;
-};
-
-#define GETLINE_ERR(sp, lno) { \
- msgq(sp, M_ERR, \
- "Error: %s/%d: unable to retrieve line %u", \
- tail(__FILE__), __LINE__, lno); \
-}
-
-/* EXF routines. */
-FREF *file_add __P((SCR *, CHAR_T *));
-int file_end __P((SCR *, EXF *, int));
-int file_init __P((SCR *, FREF *, char *, int));
-int file_m1 __P((SCR *, EXF *, int, int));
-int file_m2 __P((SCR *, EXF *, int));
-int file_m3 __P((SCR *, EXF *, int));
-
-enum lockt { LOCK_FAILED, LOCK_SUCCESS, LOCK_UNAVAIL };
-enum lockt
- file_lock __P((char *, int *, int, int));
-
-#define FS_ALL 0x01 /* Write the entire file. */
-#define FS_APPEND 0x02 /* Append to the file. */
-#define FS_FORCE 0x04 /* Force is set. */
-#define FS_POSSIBLE 0x08 /* Force could be set. */
-int file_write __P((SCR *, EXF *, MARK *, MARK *, char *, int));
-
-/* Recovery routines. */
-int rcv_init __P((SCR *, EXF *));
-int rcv_list __P((SCR *));
-int rcv_on __P((SCR *, EXF *));
-int rcv_read __P((SCR *, FREF *));
-
-#define RCV_EMAIL 0x01 /* Send the user email, IFF file modified. */
-#define RCV_ENDSESSION 0x02 /* End the file session. */
-#define RCV_PRESERVE 0x04 /* Preserve backup file, IFF file modified. */
-#define RCV_SNAPSHOT 0x08 /* Snapshot the recovery, and send email. */
-int rcv_sync __P((SCR *, EXF *, u_int));
-int rcv_tmp __P((SCR *, EXF *, char *));
-
-/* DB interface routines */
-int file_aline __P((SCR *, EXF *, int, recno_t, char *, size_t));
-int file_dline __P((SCR *, EXF *, recno_t));
-char *file_gline __P((SCR *, EXF *, recno_t, size_t *));
-int file_iline __P((SCR *, EXF *, recno_t, char *, size_t));
-int file_lline __P((SCR *, EXF *, recno_t *));
-char *file_rline __P((SCR *, EXF *, recno_t, size_t *));
-int file_sline __P((SCR *, EXF *, recno_t, char *, size_t));
diff --git a/usr.bin/vi/common/gs.h b/usr.bin/vi/common/gs.h
deleted file mode 100644
index 36343f4c404e..000000000000
--- a/usr.bin/vi/common/gs.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)gs.h 8.39 (Berkeley) 7/23/94
- */
-
-struct _gs {
- CIRCLEQ_HEAD(_dqh, _scr) dq; /* Displayed screens. */
- CIRCLEQ_HEAD(_hqh, _scr) hq; /* Hidden screens. */
-
- mode_t origmode; /* Original terminal mode. */
- struct termios
- original_termios; /* Original terminal values. */
-
- MSGH msgq; /* User message list. */
-
- char *tmp_bp; /* Temporary buffer. */
- size_t tmp_blen; /* Size of temporary buffer. */
-
- sigset_t blockset; /* Signal mask. */
-
-#ifdef DEBUG
- FILE *tracefp; /* Trace file pointer. */
-#endif
-
-/* INFORMATION SHARED BY ALL SCREENS. */
- IBUF *tty; /* Key input buffer. */
-
- CB *dcbp; /* Default cut buffer pointer. */
- CB dcb_store; /* Default cut buffer storage. */
- LIST_HEAD(_cuth, _cb) cutq; /* Linked list of cut buffers. */
-
-#define MAX_BIT_SEQ 128 /* Max + 1 fast check character. */
- LIST_HEAD(_seqh, _seq) seqq; /* Linked list of maps, abbrevs. */
- bitstr_t bit_decl(seqb, MAX_BIT_SEQ);
-
-#define MAX_FAST_KEY 254 /* Max fast check character.*/
-#define KEY_LEN(sp, ch) \
- ((ch) <= MAX_FAST_KEY ? \
- sp->gp->cname[ch].len : __key_len(sp, ch))
-#define KEY_NAME(sp, ch) \
- ((ch) <= MAX_FAST_KEY ? \
- sp->gp->cname[ch].name : __key_name(sp, ch))
- struct {
- CHAR_T name[MAX_CHARACTER_COLUMNS + 1];
- u_int8_t len;
- } cname[MAX_FAST_KEY + 1]; /* Fast lookup table. */
-
-#define KEY_VAL(sp, ch) \
- ((ch) <= MAX_FAST_KEY ? sp->gp->special_key[ch] : \
- (ch) > sp->gp->max_special ? 0 : __key_val(sp, ch))
- CHAR_T max_special; /* Max special character. */
- u_char /* Fast lookup table. */
- special_key[MAX_FAST_KEY + 1];
-
-/* Interrupt macros. */
-#define INTERRUPTED(sp) \
- (F_ISSET((sp), S_INTERRUPTED) || F_ISSET((sp)->gp, G_SIGINT))
-#define CLR_INTERRUPT(sp) { \
- F_CLR((sp), S_INTERRUPTED | S_INTERRUPTIBLE); \
- F_CLR((sp)->gp, G_SIGINT); \
-}
-
-#define G_ABBREV 0x0001 /* If have abbreviations. */
-#define G_BELLSCHED 0x0002 /* Bell scheduled. */
-#define G_RECOVER_SET 0x0004 /* Recover system initialized. */
-#define G_SETMODE 0x0008 /* Tty mode changed. */
-#define G_SIGALRM 0x0010 /* SIGALRM arrived. */
-#define G_SIGINT 0x0020 /* SIGINT arrived. */
-#define G_SIGWINCH 0x0040 /* SIGWINCH arrived. */
-#define G_SNAPSHOT 0x0080 /* Always snapshot files. */
-#define G_STDIN_TTY 0x0100 /* Standard input is a tty. */
-#define G_TERMIOS_SET 0x0200 /* Termios structure is valid. */
-#define G_TMP_INUSE 0x0400 /* Temporary buffer in use. */
- u_int16_t flags;
-};
-
-extern GS *__global_list; /* List of screens. */
diff --git a/usr.bin/vi/common/line.c b/usr.bin/vi/common/line.c
deleted file mode 100644
index 12d22e481dd7..000000000000
--- a/usr.bin/vi/common/line.c
+++ /dev/null
@@ -1,492 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)line.c 8.30 (Berkeley) 6/30/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-static __inline int scr_update
- __P((SCR *, EXF *, recno_t, enum operation, int));
-
-/*
- * file_gline --
- * Look in the text buffers for a line; if it's not there
- * call file_rline to retrieve it from the database.
- */
-char *
-file_gline(sp, ep, lno, lenp)
- SCR *sp;
- EXF *ep;
- recno_t lno; /* Line number. */
- size_t *lenp; /* Length store. */
-{
- TEXT *tp;
- recno_t l1, l2;
-
- /*
- * The underlying recno stuff handles zero by returning NULL, but
- * have to have an oob condition for the look-aside into the input
- * buffer anyway.
- */
- if (lno == 0)
- return (NULL);
-
- /*
- * Look-aside into the TEXT buffers and see if the line we want
- * is there.
- */
- if (F_ISSET(sp, S_INPUT)) {
- l1 = ((TEXT *)sp->tiqp->cqh_first)->lno;
- l2 = ((TEXT *)sp->tiqp->cqh_last)->lno;
- if (l1 <= lno && l2 >= lno) {
- for (tp = sp->tiqp->cqh_first;
- tp->lno != lno; tp = tp->q.cqe_next);
- if (lenp)
- *lenp = tp->len;
- return (tp->lb);
- }
- /*
- * Adjust the line number for the number of lines used
- * by the text input buffers.
- */
- if (lno > l2)
- lno -= l2 - l1;
- }
- return (file_rline(sp, ep, lno, lenp));
-}
-
-/*
- * file_rline --
- * Look in the cache for a line; if it's not there retrieve
- * it from the file.
- */
-char *
-file_rline(sp, ep, lno, lenp)
- SCR *sp;
- EXF *ep;
- recno_t lno; /* Line number. */
- size_t *lenp; /* Length store. */
-{
- DBT data, key;
-
- /* Check the cache. */
- if (lno == ep->c_lno) {
- if (lenp)
- *lenp = ep->c_len;
- return (ep->c_lp);
- }
- ep->c_lno = OOBLNO;
-
- /* Get the line from the underlying database. */
- key.data = &lno;
- key.size = sizeof(lno);
- switch (ep->db->get(ep->db, &key, &data, 0)) {
- case -1:
- msgq(sp, M_ERR,
- "Error: %s/%d: unable to get line %u: %s",
- tail(__FILE__), __LINE__, lno, strerror(errno));
- /* FALLTHROUGH */
- case 1:
- return (NULL);
- /* NOTREACHED */
- }
- if (lenp)
- *lenp = data.size;
-
- /* Fill the cache. */
- ep->c_lno = lno;
- ep->c_len = data.size;
- ep->c_lp = data.data;
-
- return (data.data);
-}
-
-/*
- * file_dline --
- * Delete a line from the file.
- */
-int
-file_dline(sp, ep, lno)
- SCR *sp;
- EXF *ep;
- recno_t lno;
-{
- DBT key;
-
-#if defined(DEBUG) && 0
- TRACE(sp, "delete line %lu\n", lno);
-#endif
- /*
- * XXX
- * Marks and global commands have to know when lines are
- * inserted or deleted.
- */
- mark_insdel(sp, ep, LINE_DELETE, lno);
- global_insdel(sp, ep, LINE_DELETE, lno);
-
- /* Log change. */
- log_line(sp, ep, lno, LOG_LINE_DELETE);
-
- /* Update file. */
- key.data = &lno;
- key.size = sizeof(lno);
- SIGBLOCK(sp->gp);
- if (ep->db->del(ep->db, &key, 0) == 1) {
- msgq(sp, M_ERR,
- "Error: %s/%d: unable to delete line %u: %s",
- tail(__FILE__), __LINE__, lno, strerror(errno));
- return (1);
- }
- SIGUNBLOCK(sp->gp);
-
- /* Flush the cache, update line count, before screen update. */
- if (lno <= ep->c_lno)
- ep->c_lno = OOBLNO;
- if (ep->c_nlines != OOBLNO)
- --ep->c_nlines;
-
- /* File now dirty. */
- if (F_ISSET(ep, F_FIRSTMODIFY))
- (void)rcv_init(sp, ep);
- F_SET(ep, F_MODIFIED);
-
- /* Update screen. */
- return (scr_update(sp, ep, lno, LINE_DELETE, 1));
-}
-
-/*
- * file_aline --
- * Append a line into the file.
- */
-int
-file_aline(sp, ep, update, lno, p, len)
- SCR *sp;
- EXF *ep;
- int update;
- recno_t lno;
- char *p;
- size_t len;
-{
- DBT data, key;
- recno_t lline;
-
-#if defined(DEBUG) && 0
- TRACE(sp, "append to %lu: len %u {%.*s}\n", lno, len, MIN(len, 20), p);
-#endif
- /*
- * XXX
- * Very nasty special case. The historic vi code displays a single
- * space (or a '$' if the list option is set) for the first line in
- * an "empty" file. If we "insert" a line, that line gets scrolled
- * down, not repainted, so it's incorrect when we refresh the the
- * screen. This is really hard to find and fix in the vi code -- the
- * text input functions detect it explicitly and don't insert a new
- * line. The hack here is to repaint the screen if we're appending
- * to an empty file. The reason that the test is in file_aline, and
- * not in file_iline or file_sline, is that all of the ex commands
- * that work in empty files end up here.
- */
- if (lno == 0) {
- if (file_lline(sp, ep, &lline))
- return (1);
- if (lline == 0)
- F_SET(sp, S_REDRAW);
- }
-
- /* Update file. */
- key.data = &lno;
- key.size = sizeof(lno);
- data.data = p;
- data.size = len;
- SIGBLOCK(sp->gp);
- if (ep->db->put(ep->db, &key, &data, R_IAFTER) == -1) {
- msgq(sp, M_ERR,
- "Error: %s/%d: unable to append to line %u: %s",
- tail(__FILE__), __LINE__, lno, strerror(errno));
- return (1);
- }
- SIGUNBLOCK(sp->gp);
-
- /* Flush the cache, update line count, before screen update. */
- if (lno < ep->c_lno)
- ep->c_lno = OOBLNO;
- if (ep->c_nlines != OOBLNO)
- ++ep->c_nlines;
-
- /* File now dirty. */
- if (F_ISSET(ep, F_FIRSTMODIFY))
- (void)rcv_init(sp, ep);
- F_SET(ep, F_MODIFIED);
-
- /* Log change. */
- log_line(sp, ep, lno + 1, LOG_LINE_APPEND);
-
- /*
- * XXX
- * Marks and global commands have to know when lines are
- * inserted or deleted.
- *
- * XXX
- * See comment above about empty files. If the file was empty,
- * then we're adding the first line, which is a replacement, not
- * an append. So, we shouldn't whack the marks.
- */
- if (lno != 0) {
- mark_insdel(sp, ep, LINE_INSERT, lno + 1);
- global_insdel(sp, ep, LINE_INSERT, lno + 1);
- }
-
- /*
- * Update screen.
- *
- * XXX
- * Nasty hack. If multiple lines are input by the user, they aren't
- * committed until an <ESC> is entered. The problem is the screen was
- * updated/scrolled as each line was entered. So, when this routine
- * is called to copy the new lines from the cut buffer into the file,
- * it has to know not to update the screen again.
- */
- return (scr_update(sp, ep, lno, LINE_APPEND, update));
-}
-
-/*
- * file_iline --
- * Insert a line into the file.
- */
-int
-file_iline(sp, ep, lno, p, len)
- SCR *sp;
- EXF *ep;
- recno_t lno;
- char *p;
- size_t len;
-{
- DBT data, key;
- recno_t lline;
-
-#if defined(DEBUG) && 0
- TRACE(sp,
- "insert before %lu: len %u {%.*s}\n", lno, len, MIN(len, 20), p);
-#endif
-
- /* Very nasty special case. See comment in file_aline(). */
- if (lno == 1) {
- if (file_lline(sp, ep, &lline))
- return (1);
- if (lline == 0)
- F_SET(sp, S_REDRAW);
- }
-
- /* Update file. */
- key.data = &lno;
- key.size = sizeof(lno);
- data.data = p;
- data.size = len;
- SIGBLOCK(sp->gp);
- if (ep->db->put(ep->db, &key, &data, R_IBEFORE) == -1) {
- msgq(sp, M_ERR,
- "Error: %s/%d: unable to insert at line %u: %s",
- tail(__FILE__), __LINE__, lno, strerror(errno));
- return (1);
- }
- SIGUNBLOCK(sp->gp);
-
- /* Flush the cache, update line count, before screen update. */
- if (lno >= ep->c_lno)
- ep->c_lno = OOBLNO;
- if (ep->c_nlines != OOBLNO)
- ++ep->c_nlines;
-
- /* File now dirty. */
- if (F_ISSET(ep, F_FIRSTMODIFY))
- (void)rcv_init(sp, ep);
- F_SET(ep, F_MODIFIED);
-
- /* Log change. */
- log_line(sp, ep, lno, LOG_LINE_INSERT);
-
- /*
- * XXX
- * Marks and global commands have to know when lines are
- * inserted or deleted.
- */
- mark_insdel(sp, ep, LINE_INSERT, lno);
- global_insdel(sp, ep, LINE_INSERT, lno);
-
- /* Update screen. */
- return (scr_update(sp, ep, lno, LINE_INSERT, 1));
-}
-
-/*
- * file_sline --
- * Store a line in the file.
- */
-int
-file_sline(sp, ep, lno, p, len)
- SCR *sp;
- EXF *ep;
- recno_t lno;
- char *p;
- size_t len;
-{
- DBT data, key;
-
-#if defined(DEBUG) && 0
- TRACE(sp,
- "replace line %lu: len %u {%.*s}\n", lno, len, MIN(len, 20), p);
-#endif
- /* Log before change. */
- log_line(sp, ep, lno, LOG_LINE_RESET_B);
-
- /* Update file. */
- key.data = &lno;
- key.size = sizeof(lno);
- data.data = p;
- data.size = len;
- SIGBLOCK(sp->gp);
- if (ep->db->put(ep->db, &key, &data, 0) == -1) {
- msgq(sp, M_ERR,
- "Error: %s/%d: unable to store line %u: %s",
- tail(__FILE__), __LINE__, lno, strerror(errno));
- return (1);
- }
- SIGUNBLOCK(sp->gp);
-
- /* Flush the cache, before logging or screen update. */
- if (lno == ep->c_lno)
- ep->c_lno = OOBLNO;
-
- /* File now dirty. */
- if (F_ISSET(ep, F_FIRSTMODIFY))
- (void)rcv_init(sp, ep);
- F_SET(ep, F_MODIFIED);
-
- /* Log after change. */
- log_line(sp, ep, lno, LOG_LINE_RESET_F);
-
- /* Update screen. */
- return (scr_update(sp, ep, lno, LINE_RESET, 1));
-}
-
-/*
- * file_lline --
- * Return the number of lines in the file.
- */
-int
-file_lline(sp, ep, lnop)
- SCR *sp;
- EXF *ep;
- recno_t *lnop;
-{
- DBT data, key;
- recno_t lno;
-
- /* Check the cache. */
- if (ep->c_nlines != OOBLNO) {
- *lnop = (F_ISSET(sp, S_INPUT) &&
- ((TEXT *)sp->tiqp->cqh_last)->lno > ep->c_nlines ?
- ((TEXT *)sp->tiqp->cqh_last)->lno : ep->c_nlines);
- return (0);
- }
-
- key.data = &lno;
- key.size = sizeof(lno);
-
- switch (ep->db->seq(ep->db, &key, &data, R_LAST)) {
- case -1:
- msgq(sp, M_ERR,
- "Error: %s/%d: unable to get last line: %s",
- tail(__FILE__), __LINE__, strerror(errno));
- *lnop = 0;
- return (1);
- case 1:
- *lnop = 0;
- return (0);
- default:
- break;
- }
-
- /* Fill the cache. */
- memmove(&lno, key.data, sizeof(lno));
- ep->c_nlines = ep->c_lno = lno;
- ep->c_len = data.size;
- ep->c_lp = data.data;
-
- /* Return the value. */
- *lnop = (F_ISSET(sp, S_INPUT) &&
- ((TEXT *)sp->tiqp->cqh_last)->lno > lno ?
- ((TEXT *)sp->tiqp->cqh_last)->lno : lno);
- return (0);
-}
-
-/*
- * scr_update --
- * Update all of the screens that are backed by the file that
- * just changed.
- */
-static __inline int
-scr_update(sp, ep, lno, op, current)
- SCR *sp;
- EXF *ep;
- recno_t lno;
- enum operation op;
- int current;
-{
- SCR *tsp;
-
- if (ep->refcnt != 1)
- for (tsp = sp->gp->dq.cqh_first;
- tsp != (void *)&sp->gp->dq; tsp = tsp->q.cqe_next)
- if (sp != tsp && tsp->ep == ep)
- (void)sp->s_change(tsp, ep, lno, op);
- return (current && sp->s_change(sp, ep, lno, op));
-}
diff --git a/usr.bin/vi/common/log.h b/usr.bin/vi/common/log.h
deleted file mode 100644
index 2974df4d14b6..000000000000
--- a/usr.bin/vi/common/log.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)log.h 8.5 (Berkeley) 3/16/94
- */
-
-#define LOG_NOTYPE 0
-#define LOG_CURSOR_INIT 1
-#define LOG_CURSOR_END 2
-#define LOG_LINE_APPEND 3
-#define LOG_LINE_DELETE 4
-#define LOG_LINE_INSERT 5
-#define LOG_LINE_RESET_F 6
-#define LOG_LINE_RESET_B 7
-#define LOG_MARK 8
-
-int log_backward __P((SCR *, EXF *, MARK *));
-int log_cursor __P((SCR *, EXF *));
-int log_end __P((SCR *, EXF *));
-int log_forward __P((SCR *, EXF *, MARK *));
-int log_init __P((SCR *, EXF *));
-int log_line __P((SCR *, EXF *, recno_t, u_int));
-int log_mark __P((SCR *, EXF *, LMARK *));
-int log_setline __P((SCR *, EXF *));
diff --git a/usr.bin/vi/common/main.c b/usr.bin/vi/common/main.c
deleted file mode 100644
index 5e4593e57034..000000000000
--- a/usr.bin/vi/common/main.c
+++ /dev/null
@@ -1,711 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright (c) 1992, 1993, 1994\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)main.c 8.103 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-#include <pathnames.h>
-
-#include "vi.h"
-#include "excmd.h"
-#include "../ex/tag.h"
-
-enum rc { NOEXIST, NOPERM, OK };
-
-static enum rc exrc_isok __P((SCR *, struct stat *, char *, int, int));
-static void gs_end __P((GS *));
-static GS *gs_init __P((void));
-static void obsolete __P((char *[]));
-static void usage __P((int));
-
-GS *__global_list; /* GLOBAL: List of screens. */
-
-int
-main(argc, argv)
- int argc;
- char *argv[];
-{
- extern int optind;
- extern char *optarg;
- static int reenter; /* STATIC: Re-entrancy check. */
- struct stat hsb, lsb;
- GS *gp;
- FREF *frp;
- SCR *sp;
- u_int flags, saved_vi_mode;
- int ch, eval, flagchk, readonly, silent, snapshot;
- char *excmdarg, *myname, *p, *tag_f, *trace_f, *wsizearg;
- char path[MAXPATHLEN];
-
- /* Stop if indirecting through a NULL pointer. */
- if (reenter++)
- abort();
-
-#ifdef GDBATTACH
- (void)printf("%u waiting...\n", getpid());
- (void)read(0, &eval, 1);
-#endif
-
- /* Set screen type and mode based on the program name. */
- readonly = 0;
- if ((myname = strrchr(*argv, '/')) == NULL)
- myname = *argv;
- else
- ++myname;
- if (!strcmp(myname, "ex") || !strcmp(myname, "nex"))
- LF_INIT(S_EX);
- else {
- /* View is readonly. */
- if (!strcmp(myname, "view"))
- readonly = 1;
- LF_INIT(S_VI_CURSES);
- }
- saved_vi_mode = S_VI_CURSES;
-
- /* Convert old-style arguments into new-style ones. */
- obsolete(argv);
-
- /* Parse the arguments. */
- flagchk = '\0';
- excmdarg = tag_f = trace_f = wsizearg = NULL;
- silent = 0;
- snapshot = 1;
- while ((ch = getopt(argc, argv, "c:eFRrsT:t:vw:X:")) != EOF)
- switch (ch) {
- case 'c': /* Run the command. */
- excmdarg = optarg;
- break;
- case 'e': /* Ex mode. */
- LF_CLR(S_SCREENS);
- LF_SET(S_EX);
- break;
- case 'F': /* No snapshot. */
- snapshot = 0;
- break;
- case 'R': /* Readonly. */
- readonly = 1;
- break;
- case 'r': /* Recover. */
- if (flagchk == 't')
- errx(1,
- "only one of -r and -t may be specified.");
- flagchk = 'r';
- break;
- case 's':
- silent = 1;
- break;
- case 'T': /* Trace. */
- trace_f = optarg;
- break;
- case 't': /* Tag. */
- if (flagchk == 'r')
- errx(1,
- "only one of -r and -t may be specified.");
- if (flagchk == 't')
- errx(1,
- "only one tag file may be specified.");
- flagchk = 't';
- tag_f = optarg;
- break;
- case 'v': /* Vi mode. */
- LF_CLR(S_SCREENS);
- LF_SET(S_VI_CURSES);
- break;
- case 'w':
- wsizearg = optarg;
- break;
- case 'X':
- if (!strcmp(optarg, "aw")) {
- LF_CLR(S_SCREENS);
- LF_SET(S_VI_XAW);
- saved_vi_mode = S_VI_XAW;
- break;
- }
- /* FALLTHROUGH */
- case '?':
- default:
- usage(LF_ISSET(S_EX));
- }
- argc -= optind;
- argv += optind;
-
- /* Silent is only applicable to ex. */
- if (silent && !LF_ISSET(S_EX))
- errx(1, "-s only applicable to ex.");
-
- /* Build and initialize the GS structure. */
- __global_list = gp = gs_init();
-
- /*
- * If not reading from a terminal, it's like -s was specified.
- * Vi always reads from the terminal, so fail if it's not a
- * terminal.
- */
- if (!F_ISSET(gp, G_STDIN_TTY)) {
- silent = 1;
- if (!LF_ISSET(S_EX)) {
- msgq(NULL, M_ERR,
- "Vi's standard input must be a terminal");
- goto err;
- }
- }
-
- /*
- * Build and initialize the first/current screen. This is a bit
- * tricky. If an error is returned, we may or may not have a
- * screen structure. If we have a screen structure, put it on a
- * display queue so that the error messages get displayed.
- */
- if (screen_init(NULL, &sp, flags)) {
- if (sp != NULL)
- CIRCLEQ_INSERT_HEAD(&__global_list->dq, sp, q);
- goto err;
- }
- sp->saved_vi_mode = saved_vi_mode;
- CIRCLEQ_INSERT_HEAD(&__global_list->dq, sp, q);
-
- if (trace_f != NULL) {
-#ifdef DEBUG
- if ((gp->tracefp = fopen(trace_f, "w")) == NULL)
- err(1, "%s", trace_f);
- (void)fprintf(gp->tracefp, "\n===\ntrace: open %s\n", trace_f);
-#else
- msgq(sp, M_ERR, "-T support not compiled into this version");
-#endif
- }
-
- if (opts_init(sp)) /* Options initialization. */
- goto err;
- if (readonly) /* Global read-only bit. */
- O_SET(sp, O_READONLY);
- if (silent) { /* Ex batch mode. */
- O_CLR(sp, O_AUTOPRINT);
- O_CLR(sp, O_PROMPT);
- O_CLR(sp, O_VERBOSE);
- O_CLR(sp, O_WARN);
- F_SET(sp, S_EXSILENT);
- }
- if (wsizearg != NULL) {
- ARGS *av[2], a, b;
- errno = 0;
- if (strtol(wsizearg, &p, 10) < 0 || errno || *p)
- errx(1, "illegal window size -- %s.", wsizearg);
- (void)snprintf(path, sizeof(path), "window=%s", wsizearg);
- a.bp = (CHAR_T *)path;
- a.len = strlen(path);
- b.bp = NULL;
- b.len = 0;
- av[0] = &a;
- av[1] = &b;
- if (opts_set(sp, NULL, av))
- msgq(sp, M_ERR,
- "Unable to set command line window size option");
- }
-
- /* Keymaps, special keys, must follow option initializations. */
- if (term_init(sp))
- goto err;
-
-#ifdef DIGRAPHS
- if (digraph_init(sp)) /* Digraph initialization. */
- goto err;
-#endif
-
- /*
- * Source the system, environment, $HOME and local .exrc values.
- * Vi historically didn't check $HOME/.exrc if the environment
- * variable EXINIT was set. This is all done before the file is
- * read in, because things in the .exrc information can set, for
- * example, the recovery directory.
- *
- * !!!
- * While nvi can handle any of the options settings of historic vi,
- * the converse is not true. Since users are going to have to have
- * files and environmental variables that work with both, we use nvi
- * versions of both the $HOME and local startup files if they exist,
- * otherwise the historic ones.
- *
- * !!!
- * For a discussion of permissions and when what .exrc files are
- * read, see the the comment above the exrc_isok() function below.
- *
- * !!!
- * If the user started the historic of vi in $HOME, vi read the user's
- * .exrc file twice, as $HOME/.exrc and as ./.exrc. We avoid this, as
- * it's going to make some commands behave oddly, and I can't imagine
- * anyone depending on it.
- */
- if (!silent) {
- switch (exrc_isok(sp, &hsb, _PATH_SYSEXRC, 1, 0)) {
- case NOEXIST:
- case NOPERM:
- break;
- case OK:
- (void)ex_cfile(sp, NULL, _PATH_SYSEXRC, 0);
- break;
- }
-
- if ((p = getenv("NEXINIT")) != NULL ||
- (p = getenv("EXINIT")) != NULL)
- if ((p = strdup(p)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- goto err;
- } else {
- F_SET(sp, S_VLITONLY);
- (void)ex_icmd(sp, NULL, p, strlen(p), 0);
- F_CLR(sp, S_VLITONLY);
- free(p);
- }
- else if ((p = getenv("HOME")) != NULL && *p) {
- (void)snprintf(path,
- sizeof(path), "%s/%s", p, _PATH_NEXRC);
- switch (exrc_isok(sp, &hsb, path, 0, 1)) {
- case NOEXIST:
- (void)snprintf(path,
- sizeof(path), "%s/%s", p, _PATH_EXRC);
- if (exrc_isok(sp, &hsb, path, 0, 1) == OK)
- (void)ex_cfile(sp, NULL, path, 0);
- break;
- case NOPERM:
- break;
- case OK:
- (void)ex_cfile(sp, NULL, path, 0);
- break;
- }
- }
-
- if (O_ISSET(sp, O_EXRC))
- switch (exrc_isok(sp, &lsb, _PATH_NEXRC, 0, 0)) {
- case NOEXIST:
- if (exrc_isok(sp,
- &lsb, _PATH_EXRC, 0, 0) == OK &&
- (lsb.st_dev != hsb.st_dev ||
- lsb.st_ino != hsb.st_ino))
- (void)ex_cfile(sp, NULL, _PATH_EXRC, 0);
- break;
- case NOPERM:
- break;
- case OK:
- if (lsb.st_dev != hsb.st_dev ||
- lsb.st_ino != hsb.st_ino)
- (void)ex_cfile(sp,
- NULL, _PATH_NEXRC, 0);
- break;
- }
- }
-
- /* List recovery files if -r specified without file arguments. */
- if (flagchk == 'r' && argv[0] == NULL)
- exit(rcv_list(sp));
-
- /* Set the file snapshot flag. */
- if (snapshot)
- F_SET(gp, G_SNAPSHOT);
-
- /* Use a tag file if specified. */
- if (tag_f != NULL && ex_tagfirst(sp, tag_f))
- goto err;
-
- /*
- * Append any remaining arguments as file names. Files are
- * recovery files if -r specified.
- */
- if (*argv != NULL) {
- sp->argv = sp->cargv = argv;
- F_SET(sp, S_ARGNOFREE);
- if (flagchk == 'r')
- F_SET(sp, S_ARGRECOVER);
- }
-
- /*
- * If the tag option hasn't already created a file, create one.
- * If no files as arguments, use a temporary file.
- */
- if (tag_f == NULL) {
- if ((frp = file_add(sp,
- sp->argv == NULL ? NULL : (CHAR_T *)(sp->argv[0]))) == NULL)
- goto err;
- if (F_ISSET(sp, S_ARGRECOVER))
- F_SET(frp, FR_RECOVER);
- if (file_init(sp, frp, NULL, 0))
- goto err;
- }
-
- /*
- * If there's an initial command, push it on the command stack.
- * Historically, it was always an ex command, not vi in vi mode
- * or ex in ex mode. So, make it look like an ex command to vi.
- *
- * !!!
- * Historically, all such commands were executed with the last
- * line of the file as the current line, and not the first, so
- * set up vi to be at the end of the file.
- */
- if (excmdarg != NULL)
- if (IN_EX_MODE(sp)) {
- if (term_push(sp, "\n", 1, 0))
- goto err;
- if (term_push(sp, excmdarg, strlen(excmdarg), 0))
- goto err;
- } else if (IN_VI_MODE(sp)) {
- if (term_push(sp, "\n", 1, 0))
- goto err;
- if (term_push(sp, excmdarg, strlen(excmdarg), 0))
- goto err;
- if (term_push(sp, ":", 1, 0))
- goto err;
- if (file_lline(sp, sp->ep, &sp->frp->lno))
- goto err;
- F_SET(sp->frp, FR_CURSORSET);
- }
-
- /* Set up signals. */
- if (sig_init(sp))
- goto err;
-
- for (;;) {
- /* Ignore errors -- other screens may succeed. */
- (void)sp->s_edit(sp, sp->ep);
-
- /*
- * Edit the next screen on the display queue, or, move
- * a screen from the hidden queue to the display queue.
- */
- if ((sp = __global_list->dq.cqh_first) ==
- (void *)&__global_list->dq)
- if ((sp = __global_list->hq.cqh_first) !=
- (void *)&__global_list->hq) {
- CIRCLEQ_REMOVE(&sp->gp->hq, sp, q);
- CIRCLEQ_INSERT_TAIL(&sp->gp->dq, sp, q);
- } else
- break;
-
- /*
- * The screen type may have changed -- reinitialize the
- * functions in case it has.
- */
- switch (F_ISSET(sp, S_SCREENS)) {
- case S_EX:
- if (sex_screen_init(sp))
- goto err;
- break;
- case S_VI_CURSES:
- if (svi_screen_init(sp))
- goto err;
- break;
- case S_VI_XAW:
- if (xaw_screen_init(sp))
- goto err;
- break;
- default:
- abort();
- }
- }
-
- eval = 0;
- if (0)
-err: eval = 1;
-
- /*
- * NOTE: sp may be GONE when the screen returns, so only
- * the gp can be trusted.
- */
- gs_end(gp);
-
- exit(eval);
-}
-
-/*
- * gs_init --
- * Build and initialize the GS structure.
- */
-static GS *
-gs_init()
-{
- GS *gp;
- int fd;
-
- CALLOC_NOMSG(NULL, gp, GS *, 1, sizeof(GS));
- if (gp == NULL)
- err(1, NULL);
-
- CIRCLEQ_INIT(&gp->dq);
- CIRCLEQ_INIT(&gp->hq);
- LIST_INIT(&gp->msgq);
-
- /* Structures shared by screens so stored in the GS structure. */
- CALLOC_NOMSG(NULL, gp->tty, IBUF *, 1, sizeof(IBUF));
- if (gp->tty == NULL)
- err(1, NULL);
-
- CIRCLEQ_INIT(&gp->dcb_store.textq);
- LIST_INIT(&gp->cutq);
- LIST_INIT(&gp->seqq);
-
- /* Set a flag if we're reading from the tty. */
- if (isatty(STDIN_FILENO))
- F_SET(gp, G_STDIN_TTY);
-
- /*
- * Set the G_STDIN_TTY flag. It's purpose is to avoid setting and
- * resetting the tty if the input isn't from there.
- *
- * Set the G_TERMIOS_SET flag. It's purpose is to avoid using the
- * original_termios information (mostly special character values)
- * if it's not valid. We expect that if we've lost our controlling
- * terminal that the open() (but not the tcgetattr()) will fail.
- */
- if (F_ISSET(gp, G_STDIN_TTY)) {
- if (tcgetattr(STDIN_FILENO, &gp->original_termios) == -1)
- err(1, "tcgetattr");
- F_SET(gp, G_TERMIOS_SET);
- } else if ((fd = open(_PATH_TTY, O_RDONLY, 0)) != -1) {
- if (tcgetattr(fd, &gp->original_termios) == -1)
- err(1, "tcgetattr");
- F_SET(gp, G_TERMIOS_SET);
- (void)close(fd);
- }
- return (gp);
-}
-
-
-/*
- * gs_end --
- * End the GS structure.
- */
-static void
-gs_end(gp)
- GS *gp;
-{
- MSG *mp;
- SCR *sp;
- char *tty;
-
- /* Default buffer storage. */
- (void)text_lfree(&gp->dcb_store.textq);
-
- /* Reset anything that needs resetting. */
- if (gp->flags & G_SETMODE) /* O_MESG */
- if ((tty = ttyname(STDERR_FILENO)) == NULL)
- warn("ttyname");
- else if (chmod(tty, gp->origmode) < 0)
- warn("%s", tty);
-
- /* Ring the bell if scheduled. */
- if (F_ISSET(gp, G_BELLSCHED))
- (void)fprintf(stderr, "\07"); /* \a */
-
- /* If there are any remaining screens, flush their messages. */
- for (sp = __global_list->dq.cqh_first;
- sp != (void *)&__global_list->dq; sp = sp->q.cqe_next)
- for (mp = sp->msgq.lh_first;
- mp != NULL && !(F_ISSET(mp, M_EMPTY)); mp = mp->q.le_next)
- (void)fprintf(stderr,
- "%.*s.\n", (int)mp->len, mp->mbuf);
- for (sp = __global_list->hq.cqh_first;
- sp != (void *)&__global_list->hq; sp = sp->q.cqe_next)
- for (mp = sp->msgq.lh_first;
- mp != NULL && !(F_ISSET(mp, M_EMPTY)); mp = mp->q.le_next)
- (void)fprintf(stderr,
- "%.*s.\n", (int)mp->len, mp->mbuf);
- /* Flush messages on the global queue. */
- for (mp = gp->msgq.lh_first;
- mp != NULL && !(F_ISSET(mp, M_EMPTY)); mp = mp->q.le_next)
- (void)fprintf(stderr, "%.*s.\n", (int)mp->len, mp->mbuf);
-
- /*
- * DON'T FREE THE GLOBAL STRUCTURE -- WE DIDN'T TURN
- * OFF SIGNALS/TIMERS, SO IT MAY STILL BE REFERENCED.
- */
-}
-
-/*
- * exrc_isok --
- * Check a .exrc file for source-ability.
- *
- * !!!
- * Historically, vi read the $HOME and local .exrc files if they were owned
- * by the user's real ID, or the "sourceany" option was set, regardless of
- * any other considerations. We no longer support the sourceany option as
- * it's a security problem of mammoth proportions. We require the system
- * .exrc file to be owned by root, the $HOME .exrc file to be owned by the
- * user's effective ID (or that the user's effective ID be root) and the
- * local .exrc files to be owned by the user's effective ID. In all cases,
- * the file cannot be writeable by anyone other than its owner.
- *
- * In O'Reilly ("Learning the VI Editor", Fifth Ed., May 1992, page 106),
- * it notes that System V release 3.2 and later has an option "[no]exrc".
- * The behavior is that local .exrc files are read only if the exrc option
- * is set. The default for the exrc option was off, so, by default, local
- * .exrc files were not read. The problem this was intended to solve was
- * that System V permitted users to give away files, so there's no possible
- * ownership or writeability test to ensure that the file is safe.
- *
- * POSIX 1003.2-1992 standardized exrc as an option. It required the exrc
- * option to be off by default, thus local .exrc files are not to be read
- * by default. The Rationale noted (incorrectly) that this was a change
- * to historic practice, but correctly noted that a default of off improves
- * system security. POSIX also required that vi check the effective user
- * ID instead of the real user ID, which is why we've switched from historic
- * practice.
- *
- * We initialize the exrc variable to off. If it's turned on by the system
- * or $HOME .exrc files, and the local .exrc file passes the ownership and
- * writeability tests, then we read it. This breaks historic 4BSD practice,
- * but it gives us a measure of security on systems where users can give away
- * files.
- */
-static enum rc
-exrc_isok(sp, sbp, path, rootown, rootid)
- SCR *sp;
- struct stat *sbp;
- char *path;
- int rootown, rootid;
-{
- uid_t euid;
- char *emsg, buf[MAXPATHLEN];
-
- /* Check for the file's existence. */
- if (stat(path, sbp))
- return (NOEXIST);
-
- /* Check ownership permissions. */
- euid = geteuid();
- if (!(rootown && sbp->st_uid == 0) &&
- !(rootid && euid == 0) && sbp->st_uid != euid) {
- emsg = rootown ?
- "not owned by you or root" : "not owned by you";
- goto denied;
- }
-
- /* Check writeability. */
- if (sbp->st_mode & (S_IWGRP | S_IWOTH)) {
- emsg = "writeable by a user other than the owner";
-denied: if (strchr(path, '/') == NULL &&
- getcwd(buf, sizeof(buf)) != NULL)
- msgq(sp, M_ERR,
- "%s/%s: not sourced: %s", buf, path, emsg);
- else
- msgq(sp, M_ERR,
- "%s: not sourced: %s", path, emsg);
- return (NOPERM);
- }
- return (OK);
-}
-
-static void
-obsolete(argv)
- char *argv[];
-{
- size_t len;
- char *p;
-
- /*
- * Translate old style arguments into something getopt will like.
- * Make sure it's not text space memory, because ex changes the
- * strings.
- * Change "+" into "-c$".
- * Change "+<anything else>" into "-c<anything else>".
- * Change "-" into "-s"
- */
- while (*++argv)
- if (argv[0][0] == '+') {
- if (argv[0][1] == '\0') {
- MALLOC_NOMSG(NULL, argv[0], char *, 4);
- if (argv[0] == NULL)
- err(1, NULL);
- (void)strcpy(argv[0], "-c$");
- } else {
- p = argv[0];
- len = strlen(argv[0]);
- MALLOC_NOMSG(NULL, argv[0], char *, len + 2);
- if (argv[0] == NULL)
- err(1, NULL);
- argv[0][0] = '-';
- argv[0][1] = 'c';
- (void)strcpy(argv[0] + 2, p + 1);
- }
- } else if (argv[0][0] == '-' && argv[0][1] == '\0') {
- MALLOC_NOMSG(NULL, argv[0], char *, 3);
- if (argv[0] == NULL)
- err(1, NULL);
- (void)strcpy(argv[0], "-s");
- }
-}
-
-static void
-usage(is_ex)
- int is_ex;
-{
-#define EX_USAGE \
- "ex [-eFRrsv] [-c command] [-t tag] [-w size] [files ...]"
-#define VI_USAGE \
- "vi [-eFRrv] [-c command] [-t tag] [-w size] [files ...]"
-
- (void)fprintf(stderr, "usage: %s\n", is_ex ? EX_USAGE : VI_USAGE);
- exit(1);
-}
diff --git a/usr.bin/vi/common/mark.h b/usr.bin/vi/common/mark.h
deleted file mode 100644
index 2c42e50372b7..000000000000
--- a/usr.bin/vi/common/mark.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)mark.h 8.9 (Berkeley) 7/17/94
- */
-
-/*
- * The MARK and LMARK structures define positions in the file. There are
- * two structures because the mark subroutines are the only places where
- * anything cares about something other than line and column.
- *
- * Because of the different interfaces used by the db(3) package, curses,
- * and users, the line number is 1 based and the column number is 0 based.
- * Additionally, it is known that the out-of-band line number is less than
- * any legal line number. The line number is of type recno_t, as that's
- * the underlying type of the database. The column number is of type size_t,
- * guaranteeing that we can malloc a line.
- */
-struct _mark {
-#define OOBLNO 0 /* Out-of-band line number. */
- recno_t lno; /* Line number. */
- size_t cno; /* Column number. */
-};
-
-struct _lmark {
- LIST_ENTRY(_lmark) q; /* Linked list of marks. */
- recno_t lno; /* Line number. */
- size_t cno; /* Column number. */
- CHAR_T name; /* Mark name. */
-
-#define MARK_DELETED 0x01 /* Mark was deleted. */
-#define MARK_USERSET 0x02 /* User set this mark. */
- u_int8_t flags;
-};
-
-#define ABSMARK1 '\'' /* Absolute mark name. */
-#define ABSMARK2 '`' /* Absolute mark name. */
-
-/* Mark routines. */
-int mark_end __P((SCR *, EXF *));
-int mark_get __P((SCR *, EXF *, ARG_CHAR_T, MARK *));
-int mark_init __P((SCR *, EXF *));
-void mark_insdel __P((SCR *, EXF *, enum operation, recno_t));
-int mark_set __P((SCR *, EXF *, ARG_CHAR_T, MARK *, int));
diff --git a/usr.bin/vi/common/mem.h b/usr.bin/vi/common/mem.h
deleted file mode 100644
index e61f7ffb6430..000000000000
--- a/usr.bin/vi/common/mem.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)mem.h 8.6 (Berkeley) 6/20/94
- */
-
-/* Increase the size of a malloc'd buffer. Two versions, one that
- * returns, one that jumps to an error label.
- */
-#define BINC_GOTO(sp, lp, llen, nlen) { \
- if ((nlen) > llen && binc(sp, &(lp), &(llen), nlen)) \
- goto binc_err; \
-}
-#define BINC_RET(sp, lp, llen, nlen) { \
- if ((nlen) > llen && binc(sp, &(lp), &(llen), nlen)) \
- return (1); \
-}
-
-/*
- * Get some temporary space, preferably from the global temporary buffer,
- * from a malloc'd buffer otherwise. Two versions, one that returns, one
- * that jumps to an error label.
- */
-#define GET_SPACE_GOTO(sp, bp, blen, nlen) { \
- GS *__gp = (sp)->gp; \
- if (F_ISSET(__gp, G_TMP_INUSE)) { \
- bp = NULL; \
- blen = 0; \
- BINC_GOTO(sp, bp, blen, nlen); \
- } else { \
- BINC_GOTO(sp, __gp->tmp_bp, __gp->tmp_blen, nlen); \
- bp = __gp->tmp_bp; \
- blen = __gp->tmp_blen; \
- F_SET(__gp, G_TMP_INUSE); \
- } \
-}
-#define GET_SPACE_RET(sp, bp, blen, nlen) { \
- GS *__gp = (sp)->gp; \
- if (F_ISSET(__gp, G_TMP_INUSE)) { \
- bp = NULL; \
- blen = 0; \
- BINC_RET(sp, bp, blen, nlen); \
- } else { \
- BINC_RET(sp, __gp->tmp_bp, __gp->tmp_blen, nlen); \
- bp = __gp->tmp_bp; \
- blen = __gp->tmp_blen; \
- F_SET(__gp, G_TMP_INUSE); \
- } \
-}
-
-/*
- * Add space to a GET_SPACE returned buffer. Two versions, one that
- * returns, one that jumps to an error label.
- */
-#define ADD_SPACE_GOTO(sp, bp, blen, nlen) { \
- GS *__gp = (sp)->gp; \
- if (bp == __gp->tmp_bp) { \
- F_CLR(__gp, G_TMP_INUSE); \
- BINC_GOTO(sp, __gp->tmp_bp, __gp->tmp_blen, nlen); \
- bp = __gp->tmp_bp; \
- blen = __gp->tmp_blen; \
- F_SET(__gp, G_TMP_INUSE); \
- } else \
- BINC_GOTO(sp, bp, blen, nlen); \
-}
-#define ADD_SPACE_RET(sp, bp, blen, nlen) { \
- GS *__gp = (sp)->gp; \
- if (bp == __gp->tmp_bp) { \
- F_CLR(__gp, G_TMP_INUSE); \
- BINC_RET(sp, __gp->tmp_bp, __gp->tmp_blen, nlen); \
- bp = __gp->tmp_bp; \
- blen = __gp->tmp_blen; \
- F_SET(__gp, G_TMP_INUSE); \
- } else \
- BINC_RET(sp, bp, blen, nlen); \
-}
-
-/* Free memory, optionally making pointers unusable. */
-#ifdef DEBUG
-#define FREE(p, sz) { \
- memset(p, 0xff, sz); \
- free(p); \
-}
-#else
-#define FREE(p, sz) free(p);
-#endif
-
-/* Free a GET_SPACE returned buffer. */
-#define FREE_SPACE(sp, bp, blen) { \
- if (bp == sp->gp->tmp_bp) \
- F_CLR(sp->gp, G_TMP_INUSE); \
- else \
- FREE(bp, blen); \
-}
-
-/*
- * Malloc a buffer, casting the return pointer. Various versions.
- *
- * !!!
- * The cast should be unnecessary, malloc(3) and friends return void *'s,
- * which is all we need. However, some systems that nvi needs to run on
- * don't do it right yet, resulting in the compiler printing out roughly
- * a million warnings. After awhile, it seemed easier to put the casts
- * in instead of explaining it all the time.
- */
-#define CALLOC_NOMSG(sp, p, cast, nmemb, size) { \
- p = (cast)calloc(nmemb, size); \
-}
-#define CALLOC(sp, p, cast, nmemb, size) { \
- if ((p = (cast)calloc(nmemb, size)) == NULL) \
- msgq(sp, M_SYSERR, NULL); \
-}
-#define CALLOC_RET(sp, p, cast, nmemb, size) { \
- if ((p = (cast)calloc(nmemb, size)) == NULL) { \
- msgq(sp, M_SYSERR, NULL); \
- return (1); \
- } \
-}
-#define MALLOC_NOMSG(sp, p, cast, size) { \
- p = (cast)malloc(size); \
-}
-#define MALLOC(sp, p, cast, size) { \
- if ((p = (cast)malloc(size)) == NULL) \
- msgq(sp, M_SYSERR, NULL); \
-}
-#define MALLOC_RET(sp, p, cast, size) { \
- if ((p = (cast)malloc(size)) == NULL) { \
- msgq(sp, M_SYSERR, NULL); \
- return (1); \
- } \
-}
-/*
- * XXX
- * Don't depend on realloc(NULL, size) working.
- */
-#define REALLOC(sp, p, cast, size) { \
- if ((p = (cast)(p == NULL ? \
- malloc(size) : realloc(p, size))) == NULL) \
- msgq(sp, M_SYSERR, NULL); \
-}
-
-/*
- * Versions of memmove(3) and memset(3) that use the size of the
- * initial pointer to figure out how much memory to manipulate.
- */
-#define MEMMOVE(p, t, len) memmove(p, t, (len) * sizeof(*(p)))
-#define MEMSET(p, value, len) memset(p, value, (len) * sizeof(*(p)))
-
-int binc __P((SCR *, void *, size_t *, size_t));
diff --git a/usr.bin/vi/common/msg.c b/usr.bin/vi/common/msg.c
deleted file mode 100644
index f5fe595f44bd..000000000000
--- a/usr.bin/vi/common/msg.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)msg.c 8.9 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-
-/*
- * msgq --
- * Display a message.
- */
-void
-#ifdef __STDC__
-msgq(SCR *sp, enum msgtype mt, const char *fmt, ...)
-#else
-msgq(sp, mt, fmt, va_alist)
- SCR *sp;
- enum msgtype mt;
- char *fmt;
- va_dcl
-#endif
-{
- va_list ap;
- size_t len;
- char msgbuf[1024];
-
-#ifdef __STDC__
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
- /*
- * It's possible to enter msg when there's no screen to hold
- * the message. If sp is NULL, ignore the special cases and
- * just build the message, using __global_list.
- */
- if (sp == NULL)
- goto nullsp;
-
- switch (mt) {
- case M_BERR:
- if (!F_ISSET(sp, S_EXSILENT) &&
- F_ISSET(sp->gp, G_STDIN_TTY) && !O_ISSET(sp, O_VERBOSE)) {
- F_SET(sp, S_BELLSCHED);
- return;
- }
- mt = M_ERR;
- break;
- case M_VINFO:
- if (!O_ISSET(sp, O_VERBOSE))
- return;
- mt = M_INFO;
- /* FALLTHROUGH */
- case M_INFO:
- if (F_ISSET(sp, S_EXSILENT))
- return;
- break;
- case M_ERR:
- case M_SYSERR:
- break;
- default:
- abort();
- }
-
-nullsp: len = 0;
-
-#define EPREFIX "Error: "
- if (mt == M_SYSERR) {
- memmove(msgbuf, EPREFIX, sizeof(EPREFIX) - 1);
- len += sizeof(EPREFIX) - 1;
- }
-
- if (sp != NULL && sp->if_name != NULL) {
- len += snprintf(msgbuf + len, sizeof(msgbuf) - len,
- "%s, %d: ", sp->if_name, sp->if_lno);
- if (len >= sizeof(msgbuf))
- goto err;
- }
-
- if (fmt != NULL) {
- len += vsnprintf(msgbuf + len, sizeof(msgbuf) - len, fmt, ap);
- if (len >= sizeof(msgbuf))
- goto err;
- }
-
- if (mt == M_SYSERR) {
- len += snprintf(msgbuf + len,
- sizeof(msgbuf) - len, ": %s", strerror(errno));
- if (len >= sizeof(msgbuf))
- goto err;
- }
-
- /*
- * If len >= the size, some characters were discarded.
- * Ignore trailing nul.
- */
-err: if (len >= sizeof(msgbuf))
- len = sizeof(msgbuf) - 1;
-
-#ifdef DEBUG
- if (sp != NULL)
- TRACE(sp, "%.*s\n", len, msgbuf);
-#endif
- msg_app(__global_list, sp, mt == M_ERR ? 1 : 0, msgbuf, len);
-}
-
-/*
- * msg_app --
- * Append a message into the queue. This can fail, but there's
- * nothing we can do if it does.
- */
-void
-msg_app(gp, sp, inv_video, p, len)
- GS *gp;
- SCR *sp;
- int inv_video;
- char *p;
- size_t len;
-{
- static int reenter; /* STATIC: Re-entrancy check. */
- MSG *mp, *nmp;
-
- /*
- * It's possible to reenter msg when it allocates space.
- * We're probably dead anyway, but no reason to drop core.
- */
- if (reenter)
- return;
- reenter = 1;
-
- /*
- * We can be entered as the result of a signal arriving, trying
- * to sync the file and failing. This shouldn't be a hot spot,
- * block the signals.
- */
- SIGBLOCK(gp);
-
- /*
- * Find an empty structure, or allocate a new one. Use the
- * screen structure if it exists, otherwise the global one.
- */
- if (sp != NULL) {
- if ((mp = sp->msgq.lh_first) == NULL) {
- CALLOC(sp, mp, MSG *, 1, sizeof(MSG));
- if (mp == NULL)
- goto ret;
- LIST_INSERT_HEAD(&sp->msgq, mp, q);
- goto store;
- }
- } else if ((mp = gp->msgq.lh_first) == NULL) {
- CALLOC(sp, mp, MSG *, 1, sizeof(MSG));
- if (mp == NULL)
- goto ret;
- LIST_INSERT_HEAD(&gp->msgq, mp, q);
- goto store;
- }
- while (!F_ISSET(mp, M_EMPTY) && mp->q.le_next != NULL)
- mp = mp->q.le_next;
- if (!F_ISSET(mp, M_EMPTY)) {
- CALLOC(sp, nmp, MSG *, 1, sizeof(MSG));
- if (nmp == NULL)
- goto ret;
- LIST_INSERT_AFTER(mp, nmp, q);
- mp = nmp;
- }
-
- /* Get enough memory for the message. */
-store: if (len > mp->blen && binc(sp, &mp->mbuf, &mp->blen, len))
- goto ret;
-
- /* Store the message. */
- memmove(mp->mbuf, p, len);
- mp->len = len;
- mp->flags = inv_video ? M_INV_VIDEO : 0;
-
-ret: reenter = 0;
- SIGUNBLOCK(gp);
-}
-
-/*
- * msg_rpt --
- * Report on the lines that changed.
- *
- * !!!
- * Historic vi documentation (USD:15-8) claimed that "The editor will also
- * always tell you when a change you make affects text which you cannot see."
- * This isn't true -- edit a large file and do "100d|1". We don't implement
- * this semantic as it would require that we track each line that changes
- * during a command instead of just keeping count.
- *
- * Line counts weren't right in historic vi, either. For example, given the
- * file:
- * abc
- * def
- * the command 2d}, from the 'b' would report that two lines were deleted,
- * not one.
- */
-int
-msg_rpt(sp, is_message)
- SCR *sp;
- int is_message;
-{
- static char * const action[] = {
- "added", "changed", "deleted", "joined", "moved",
- "left shifted", "right shifted", "yanked",
- NULL,
- };
- recno_t total;
- u_long rptval;
- int first, cnt;
- size_t blen, len;
- char * const *ap;
- char *bp, *p, number[40];
-
- if (F_ISSET(sp, S_EXSILENT))
- return (0);
-
- if ((rptval = O_VAL(sp, O_REPORT)) == 0)
- goto norpt;
-
- GET_SPACE_RET(sp, bp, blen, 512);
- p = bp;
-
- total = 0;
- for (ap = action, cnt = 0, first = 1; *ap != NULL; ++ap, ++cnt)
- if (sp->rptlines[cnt] != 0) {
- total += sp->rptlines[cnt];
- len = snprintf(number, sizeof(number),
- "%s%lu lines %s",
- first ? "" : "; ", sp->rptlines[cnt], *ap);
- memmove(p, number, len);
- p += len;
- first = 0;
- }
-
- /*
- * If nothing to report, return.
- *
- * !!!
- * And now, a special vi clone test. Historically, vi reported if
- * the number of changed lines was > than the value, not >=. Which
- * means that users can't report on single line changes, btw.) In
- * any case, if it was a yank command, it was >=, not >. No lie. I
- * got complaints, so we do it right.
- */
- if (total > rptval || sp->rptlines[L_YANKED] >= rptval) {
- *p = '\0';
- if (is_message)
- msgq(sp, M_INFO, "%s", bp);
- else
- ex_printf(EXCOOKIE, "%s\n", bp);
- }
-
- FREE_SPACE(sp, bp, blen);
-
- /* Clear after each report. */
-norpt: sp->rptlchange = OOBLNO;
- memset(sp->rptlines, 0, sizeof(sp->rptlines));
- return (0);
-}
-
-/*
- * msg_status --
- * Report on the file's status.
- */
-int
-msg_status(sp, ep, lno, showlast)
- SCR *sp;
- EXF *ep;
- recno_t lno;
- int showlast;
-{
- recno_t last;
- char *mo, *nc, *nf, *pid, *ro, *ul;
-#ifdef DEBUG
- char pbuf[50];
-
- (void)snprintf(pbuf, sizeof(pbuf), " (pid %u)", getpid());
- pid = pbuf;
-#else
- pid = "";
-#endif
- /*
- * See nvi/exf.c:file_init() for a description of how and
- * when the read-only bit is set.
- *
- * !!!
- * The historic display for "name changed" was "[Not edited]".
- */
- if (F_ISSET(sp->frp, FR_NEWFILE)) {
- F_CLR(sp->frp, FR_NEWFILE);
- nf = "new file";
- mo = nc = "";
- } else {
- nf = "";
- if (F_ISSET(sp->frp, FR_NAMECHANGE)) {
- nc = "name changed";
- mo = F_ISSET(ep, F_MODIFIED) ?
- ", modified" : ", unmodified";
- } else {
- nc = "";
- mo = F_ISSET(ep, F_MODIFIED) ?
- "modified" : "unmodified";
- }
- }
- ro = F_ISSET(sp->frp, FR_RDONLY) ? ", readonly" : "";
- ul = F_ISSET(sp->frp, FR_UNLOCKED) ? ", UNLOCKED" : "";
- if (showlast) {
- if (file_lline(sp, ep, &last))
- return (1);
- if (last >= 1)
- msgq(sp, M_INFO,
- "%s: %s%s%s%s%s: line %lu of %lu [%ld%%]%s",
- sp->frp->name, nf, nc, mo, ul, ro, lno,
- last, (lno * 100) / last, pid);
- else
- msgq(sp, M_INFO, "%s: %s%s%s%s%s: empty file%s",
- sp->frp->name, nf, nc, mo, ul, ro, pid);
- } else
- msgq(sp, M_INFO, "%s: %s%s%s%s%s: line %lu%s",
- sp->frp->name, nf, nc, mo, ul, ro, lno, pid);
- return (0);
-}
-
-#ifdef MSG_CATALOG
-/*
- * get_msg --
- * Return a format based on a message number.
- */
-char *
-get_msg(sp, msgno)
- SCR *sp;
- char *s_msgno;
-{
- DBT data, key;
- GS *gp;
- recno_t msgno;
- char *msg, *p;
-
- gp = sp == NULL ? __global_list : sp->gp;
- if (gp->msgdb == NULL) {
- p = sp == NULL ? _PATH_MSGDEF : O_STR(sp, O_CATALOG);
- if ((gp->msgdb = dbopen(p,
- O_NONBLOCK | O_RDONLY, 444, DB_RECNO, NULL)) == NULL) {
- if ((fmt = malloc(256)) == NULL)
- return ("");
- (void)snprintf(fmt,
- "unable to open %s: %s", p, strerror(errno));
- return (fmt);
- }
- }
- msgno = atoi(s_msgno);
- key.data = &msgno;
- key.size = sizeof(recno_t);
- switch (gp->msgdb->get(gp->msgdb, &key, &data, 0)) {
- case 0:
- return (data.data);
- case 1:
- p = "no catalog record %ls";
- break;
- case -1:
- p = "catalog record %s: %s";
- break;
- }
- if ((fmt = malloc(256)) == NULL)
- return ("");
- (void)snprintf(fmt, p, msgno, strerror(errno));
- return (fmt);
-}
-#endif
diff --git a/usr.bin/vi/common/msg.h b/usr.bin/vi/common/msg.h
deleted file mode 100644
index fc6e365087eb..000000000000
--- a/usr.bin/vi/common/msg.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)msg.h 8.13 (Berkeley) 8/8/94
- */
-
-/*
- * Message types.
- *
- * !!!
- * In historical vi, O_VERBOSE didn't exist, and O_TERSE made the error
- * messages shorter. In this implementation, O_TERSE has no effect and
- * O_VERBOSE results in informational displays about common errors for
- * naive users.
- *
- * M_BERR Error: M_ERR if O_VERBOSE, else bell.
- * M_ERR Error: Display in inverse video.
- * M_INFO Info: Display in normal video.
- * M_SYSERR Error: M_ERR, using strerror(3) message.
- * M_VINFO Info: M_INFO if O_VERBOSE, else ignore.
- */
-enum msgtype { M_BERR, M_ERR, M_INFO, M_SYSERR, M_VINFO };
-
-typedef struct _msgh MSGH; /* MESG list head structure. */
-LIST_HEAD(_msgh, _msg);
-
-struct _msg {
- LIST_ENTRY(_msg) q; /* Linked list of messages. */
- char *mbuf; /* Message buffer. */
- size_t blen; /* Message buffer length. */
- size_t len; /* Message length. */
-
-#define M_EMPTY 0x01 /* No message. */
-#define M_INV_VIDEO 0x02 /* Inverse video. */
- u_int8_t flags;
-};
-
-/*
- * Define MSG_CATALOG for the Makefile compile command
- * line to enable message catalogs.
- */
-#ifdef MSG_CATALOG
-#define M(number, fmt) number
-char *get_msg __P((SCR *, char *));
-#else
-#define M(number, fmt) fmt
-#endif
-
-/* Messages. */
-void msg_app __P((GS *, SCR *, int, char *, size_t));
-int msg_rpt __P((SCR *, int));
-int msg_status __P((SCR *, EXF *, recno_t, int));
-void msgq __P((SCR *, enum msgtype, const char *, ...));
diff --git a/usr.bin/vi/common/options.c b/usr.bin/vi/common/options.c
deleted file mode 100644
index 1c8496d1d01d..000000000000
--- a/usr.bin/vi/common/options.c
+++ /dev/null
@@ -1,890 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)options.c 8.64 (Berkeley) 7/27/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-#include <pathnames.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-static int opts_abbcmp __P((const void *, const void *));
-static int opts_cmp __P((const void *, const void *));
-static OPTLIST const *opts_prefix __P((char *));
-static int opts_print __P((SCR *, OPTLIST const *));
-
-/*
- * O'Reilly noted options and abbreviations are from "Learning the VI Editor",
- * Fifth Edition, May 1992. There's no way of knowing what systems they are
- * actually from.
- *
- * HPUX noted options and abbreviations are from "The Ultimate Guide to the
- * VI and EX Text Editors", 1990.
- */
-static OPTLIST const optlist[] = {
-/* O_ALTWERASE 4.4BSD */
- {"altwerase", f_altwerase, OPT_0BOOL, 0},
-/* O_AUTOINDENT 4BSD */
- {"autoindent", NULL, OPT_0BOOL, 0},
-/* O_AUTOPRINT 4BSD */
- {"autoprint", NULL, OPT_1BOOL, 0},
-/* O_AUTOWRITE 4BSD */
- {"autowrite", NULL, OPT_0BOOL, 0},
-/* O_BEAUTIFY 4BSD */
- {"beautify", NULL, OPT_0BOOL, 0},
-/* O_CDPATH 4.4BSD */
- {"cdpath", f_cdpath, OPT_STR, 0},
-/* O_COLUMNS 4.4BSD */
- {"columns", f_columns, OPT_NUM, OPT_NOSAVE},
-/* O_COMMENT 4.4BSD */
- {"comment", NULL, OPT_0BOOL, 0},
-/* O_DIGRAPH XXX: Elvis */
- {"digraph", NULL, OPT_0BOOL, 0},
-/* O_DIRECTORY 4BSD */
- {"directory", NULL, OPT_STR, 0},
-/* O_EDCOMPATIBLE 4BSD */
- {"edcompatible",NULL, OPT_0BOOL, 0},
-/* O_ERRORBELLS 4BSD */
- {"errorbells", NULL, OPT_0BOOL, 0},
-/* O_EXRC System V (undocumented) */
- {"exrc", NULL, OPT_0BOOL, 0},
-/* O_EXTENDED 4.4BSD */
- {"extended", NULL, OPT_0BOOL, 0},
-/* O_FLASH HPUX */
- {"flash", NULL, OPT_1BOOL, 0},
-/* O_HARDTABS 4BSD */
- {"hardtabs", NULL, OPT_NUM, 0},
-/* O_IGNORECASE 4BSD */
- {"ignorecase", NULL, OPT_0BOOL, 0},
-/* O_KEYTIME 4.4BSD */
- {"keytime", NULL, OPT_NUM, 0},
-/* O_LEFTRIGHT 4.4BSD */
- {"leftright", f_leftright, OPT_0BOOL, 0},
-/* O_LINES 4.4BSD */
- {"lines", f_lines, OPT_NUM, OPT_NOSAVE},
-/* O_LISP 4BSD */
-/*
- * XXX
- * When the lisp option is implemented, delete
- * the OPT_NOSAVE flag, so that :mkexrc dumps it.
- */
- {"lisp", f_lisp, OPT_0BOOL, OPT_NOSAVE},
-/* O_LIST 4BSD */
- {"list", f_list, OPT_0BOOL, 0},
-/* O_MAGIC 4BSD */
- {"magic", NULL, OPT_1BOOL, 0},
-/* O_MATCHTIME 4.4BSD */
- {"matchtime", NULL, OPT_NUM, 0},
-/* O_MESG 4BSD */
- {"mesg", f_mesg, OPT_1BOOL, 0},
-/* O_META 4.4BSD */
- {"meta", NULL, OPT_STR, 0},
-/* O_MODELINE 4BSD */
- {"modeline", f_modeline, OPT_0BOOL, 0},
-/* O_NUMBER 4BSD */
- {"number", f_number, OPT_0BOOL, 0},
-/* O_OCTAL 4.4BSD */
- {"octal", f_octal, OPT_0BOOL, 0},
-/* O_OPEN 4BSD */
- {"open", NULL, OPT_1BOOL, 0},
-/* O_OPTIMIZE 4BSD */
- {"optimize", NULL, OPT_1BOOL, 0},
-/* O_PARAGRAPHS 4BSD */
- {"paragraphs", f_paragraph, OPT_STR, 0},
-/* O_PROMPT 4BSD */
- {"prompt", NULL, OPT_1BOOL, 0},
-/* O_READONLY 4BSD (undocumented) */
- {"readonly", f_readonly, OPT_0BOOL, 0},
-/* O_RECDIR 4.4BSD */
- {"recdir", NULL, OPT_STR, 0},
-/* O_REDRAW 4BSD */
- {"redraw", NULL, OPT_0BOOL, 0},
-/* O_REMAP 4BSD */
- {"remap", NULL, OPT_1BOOL, 0},
-/* O_REPORT 4BSD */
- {"report", NULL, OPT_NUM, OPT_NOSTR},
-/* O_RULER 4.4BSD */
- {"ruler", NULL, OPT_0BOOL, 0},
-/* O_SCROLL 4BSD */
- {"scroll", NULL, OPT_NUM, 0},
-/* O_SECTIONS 4BSD */
- {"sections", f_section, OPT_STR, 0},
-/* O_SHELL 4BSD */
- {"shell", NULL, OPT_STR, 0},
-/* O_SHIFTWIDTH 4BSD */
- {"shiftwidth", f_shiftwidth, OPT_NUM, 0},
-/* O_SHOWDIRTY 4.4BSD */
- {"showdirty", NULL, OPT_0BOOL, 0},
-/* O_SHOWMATCH 4BSD */
- {"showmatch", NULL, OPT_0BOOL, 0},
-/* O_SHOWMODE 4.4BSD */
- {"showmode", NULL, OPT_0BOOL, 0},
-/* O_SIDESCROLL 4.4BSD */
- {"sidescroll", NULL, OPT_NUM, 0},
-/* O_SLOWOPEN 4BSD */
- {"slowopen", NULL, OPT_0BOOL, 0},
-/* O_SOURCEANY 4BSD (undocumented) */
- {"sourceany", f_sourceany, OPT_0BOOL, 0},
-/* O_TABSTOP 4BSD */
- {"tabstop", f_tabstop, OPT_NUM, 0},
-/* O_TAGLENGTH 4BSD */
- {"taglength", NULL, OPT_NUM, OPT_NOSTR},
-/* O_TAGS 4BSD */
- {"tags", f_tags, OPT_STR, 0},
-/* O_TERM 4BSD */
- {"term", f_term, OPT_STR, OPT_NOSAVE},
-/* O_TERSE 4BSD */
- {"terse", NULL, OPT_0BOOL, 0},
-/* O_TILDEOP 4.4BSD */
- {"tildeop", NULL, OPT_0BOOL, 0},
-/* O_TIMEOUT 4BSD (undocumented) */
- {"timeout", NULL, OPT_1BOOL, 0},
-/* O_TTYWERASE 4.4BSD */
- {"ttywerase", f_ttywerase, OPT_0BOOL, 0},
-/* O_VERBOSE 4.4BSD */
- {"verbose", NULL, OPT_0BOOL, 0},
-/* O_W1200 4BSD */
- {"w1200", f_w1200, OPT_NUM, OPT_NEVER|OPT_NOSAVE},
-/* O_W300 4BSD */
- {"w300", f_w300, OPT_NUM, OPT_NEVER|OPT_NOSAVE},
-/* O_W9600 4BSD */
- {"w9600", f_w9600, OPT_NUM, OPT_NEVER|OPT_NOSAVE},
-/* O_WARN 4BSD */
- {"warn", NULL, OPT_1BOOL, 0},
-/* O_WINDOW 4BSD */
- {"window", f_window, OPT_NUM, 0},
-/* O_WRAPMARGIN 4BSD */
- {"wrapmargin", NULL, OPT_NUM, OPT_NOSTR},
-/* O_WRAPSCAN 4BSD */
- {"wrapscan", NULL, OPT_1BOOL, 0},
-/* O_WRITEANY 4BSD */
- {"writeany", NULL, OPT_0BOOL, 0},
- {NULL},
-};
-
-typedef struct abbrev {
- char *name;
- int offset;
-} OABBREV;
-
-static OABBREV const abbrev[] = {
- {"ai", O_AUTOINDENT}, /* 4BSD */
- {"ap", O_AUTOPRINT}, /* 4BSD */
- {"aw", O_AUTOWRITE}, /* 4BSD */
- {"bf", O_BEAUTIFY}, /* 4BSD */
- {"co", O_COLUMNS}, /* 4.4BSD */
- {"dir", O_DIRECTORY}, /* 4BSD */
- {"eb", O_ERRORBELLS}, /* 4BSD */
- {"ed", O_EDCOMPATIBLE}, /* 4BSD */
- {"ex", O_EXRC}, /* System V (undocumented) */
- {"ht", O_HARDTABS}, /* 4BSD */
- {"ic", O_IGNORECASE}, /* 4BSD */
- {"li", O_LINES}, /* 4.4BSD */
- {"modelines", O_MODELINE}, /* HPUX */
- {"nu", O_NUMBER}, /* 4BSD */
- {"opt", O_OPTIMIZE}, /* 4BSD */
- {"para", O_PARAGRAPHS}, /* 4BSD */
- {"re", O_REDRAW}, /* O'Reilly */
- {"ro", O_READONLY}, /* 4BSD (undocumented) */
- {"scr", O_SCROLL}, /* 4BSD (undocumented) */
- {"sect", O_SECTIONS}, /* O'Reilly */
- {"sh", O_SHELL}, /* 4BSD */
- {"slow", O_SLOWOPEN}, /* 4BSD */
- {"sm", O_SHOWMATCH}, /* 4BSD */
- {"sw", O_SHIFTWIDTH}, /* 4BSD */
- {"tag", O_TAGS}, /* 4BSD (undocumented) */
- {"tl", O_TAGLENGTH}, /* 4BSD */
- {"to", O_TIMEOUT}, /* 4BSD (undocumented) */
- {"ts", O_TABSTOP}, /* 4BSD */
- {"tty", O_TERM}, /* 4BSD (undocumented) */
- {"ttytype", O_TERM}, /* 4BSD (undocumented) */
- {"w", O_WINDOW}, /* O'Reilly */
- {"wa", O_WRITEANY}, /* 4BSD */
- {"wi", O_WINDOW}, /* 4BSD (undocumented) */
- {"wm", O_WRAPMARGIN}, /* 4BSD */
- {"ws", O_WRAPSCAN}, /* 4BSD */
- {NULL},
-};
-
-/*
- * opts_init --
- * Initialize some of the options. Since the user isn't really
- * "setting" these variables, don't set their OPT_SET bits.
- */
-int
-opts_init(sp)
- SCR *sp;
-{
- ARGS *argv[2], a, b;
- OPTLIST const *op;
- u_long v;
- int cnt;
- char *s, b1[1024];
-
- a.bp = b1;
- a.len = 0;
- b.bp = NULL;
- b.len = 0;
- argv[0] = &a;
- argv[1] = &b;
-
-#define SET_DEF(opt, str) { \
- if (str != b1) /* GCC puts strings in text-space. */ \
- (void)strcpy(b1, str); \
- a.len = strlen(b1); \
- if (opts_set(sp, NULL, argv)) { \
- msgq(sp, M_ERR, \
- "Unable to set default %s option", optlist[opt]); \
- return (1); \
- } \
- F_CLR(&sp->opts[opt], OPT_SET); \
-}
- /* Set default values. */
- for (op = optlist, cnt = 0; op->name != NULL; ++op, ++cnt)
- if (op->type == OPT_0BOOL)
- O_CLR(sp, cnt);
- else if (op->type == OPT_1BOOL)
- O_SET(sp, cnt);
-
- (void)snprintf(b1, sizeof(b1), "cdpath=%s",
- (s = getenv("CDPATH")) == NULL ? ":" : s);
- SET_DEF(O_CDPATH, b1);
-
- /*
- * !!!
- * Vi historically stored temporary files in /var/tmp. We store them
- * in /tmp by default, hoping it's a memory based file system. There
- * are two ways to change this -- the user can set either the directory
- * option or the TMPDIR environmental variable.
- */
- (void)snprintf(b1, sizeof(b1), "directory=%s",
- (s = getenv("TMPDIR")) == NULL ? _PATH_TMP : s);
- SET_DEF(O_DIRECTORY, b1);
- SET_DEF(O_KEYTIME, "keytime=6");
- SET_DEF(O_MATCHTIME, "matchtime=7");
- SET_DEF(O_META, "meta=~{[*?$`'\"\\");
- SET_DEF(O_REPORT, "report=5");
- SET_DEF(O_PARAGRAPHS, "paragraphs=IPLPPPQPP LIpplpipbp");
- (void)snprintf(b1, sizeof(b1), "recdir=%s", _PATH_PRESERVE);
- SET_DEF(O_RECDIR, b1);
- SET_DEF(O_SECTIONS, "sections=NHSHH HUnhsh");
- (void)snprintf(b1, sizeof(b1), "shell=%s",
- (s = getenv("SHELL")) == NULL ? _PATH_BSHELL : s);
- SET_DEF(O_SHELL, b1);
- SET_DEF(O_SHIFTWIDTH, "shiftwidth=8");
- SET_DEF(O_SIDESCROLL, "sidescroll=16");
- SET_DEF(O_TABSTOP, "tabstop=8");
- (void)snprintf(b1, sizeof(b1), "tags=%s", _PATH_TAGS);
- SET_DEF(O_TAGS, b1);
- (void)snprintf(b1, sizeof(b1), "term=%s",
- (s = getenv("TERM")) == NULL ? "unknown" : s);
- SET_DEF(O_TERM, b1);
-
- /*
- * XXX
- * Initialize ^D, ^U scrolling value here, after TERM. (We didn't
- * have the options information when the screen was initialized.)
- * Initializing term should have created a LINES/COLUMNS value.
- */
- sp->defscroll = O_VAL(sp, O_LINES) / 2;
- (void)snprintf(b1, sizeof(b1), "scroll=%ld", sp->defscroll);
- SET_DEF(O_SCROLL, b1);
-
- /*
- * The default window option values are:
- * 8 if baud rate <= 600
- * 16 if baud rate <= 1200
- * LINES - 1 if baud rate > 1200
- */
- v = baud_from_bval(sp);
- if (v <= 600)
- v = 8;
- else if (v <= 1200)
- v = 16;
- else
- v = O_VAL(sp, O_LINES) - 1;
- (void)snprintf(b1, sizeof(b1), "window=%lu", v);
- SET_DEF(O_WINDOW, b1);
-
- SET_DEF(O_WRAPMARGIN, "wrapmargin=0");
-
- /*
- * By default, the historic vi always displayed information
- * about two options, redraw and term. Term seems sufficient.
- */
- F_SET(&sp->opts[O_TERM], OPT_SET);
- return (0);
-}
-
-/*
- * opts_set --
- * Change the values of one or more options.
- */
-int
-opts_set(sp, usage, argv)
- SCR *sp;
- char *usage;
- ARGS *argv[];
-{
- enum optdisp disp;
- OABBREV atmp, *ap;
- OPTLIST const *op;
- OPTLIST otmp;
- OPTION *spo;
- u_long value, turnoff;
- int ch, equals, offset, qmark, rval;
- char *endp, *name, *p, *sep;
-
- disp = NO_DISPLAY;
- for (rval = 0; argv[0]->len != 0; ++argv) {
- /*
- * The historic vi dumped the options for each occurrence of
- * "all" in the set list. Puhleeze.
- */
- if (!strcmp(argv[0]->bp, "all")) {
- disp = ALL_DISPLAY;
- continue;
- }
-
- /* Find equals sign or question mark. */
- for (sep = NULL, equals = qmark = 0,
- p = name = argv[0]->bp; (ch = *p) != '\0'; ++p)
- if (ch == '=' || ch == '?') {
- if (p == name) {
- if (usage != NULL)
- msgq(sp,
- M_ERR, "Usage: %s", usage);
- return (1);
- }
- sep = p;
- if (ch == '=')
- equals = 1;
- else
- qmark = 1;
- break;
- }
-
- turnoff = 0;
- op = NULL;
- if (sep != NULL)
- *sep++ = '\0';
-
- /* Check list of abbreviations. */
- atmp.name = name;
- if ((ap = bsearch(&atmp, abbrev,
- sizeof(abbrev) / sizeof(OABBREV) - 1,
- sizeof(OABBREV), opts_abbcmp)) != NULL) {
- op = optlist + ap->offset;
- goto found;
- }
-
- /* Check list of options. */
- otmp.name = name;
- if ((op = bsearch(&otmp, optlist,
- sizeof(optlist) / sizeof(OPTLIST) - 1,
- sizeof(OPTLIST), opts_cmp)) != NULL)
- goto found;
-
- /* Try the name without any leading "no". */
- if (name[0] == 'n' && name[1] == 'o') {
- turnoff = 1;
- name += 2;
- } else
- goto prefix;
-
- /* Check list of abbreviations. */
- atmp.name = name;
- if ((ap = bsearch(&atmp, abbrev,
- sizeof(abbrev) / sizeof(OABBREV) - 1,
- sizeof(OABBREV), opts_abbcmp)) != NULL) {
- op = optlist + ap->offset;
- goto found;
- }
-
- /* Check list of options. */
- otmp.name = name;
- if ((op = bsearch(&otmp, optlist,
- sizeof(optlist) / sizeof(OPTLIST) - 1,
- sizeof(OPTLIST), opts_cmp)) != NULL)
- goto found;
-
- /* Check for prefix match. */
-prefix: op = opts_prefix(name);
-
-found: if (op == NULL) {
- msgq(sp, M_ERR,
- "no %s option: 'set all' gives all option values",
- name);
- continue;
- }
-
- /* Find current option values. */
- offset = op - optlist;
- spo = sp->opts + offset;
-
- /*
- * !!!
- * Historically, the question mark could be a separate
- * argument.
- */
- if (!equals && !qmark &&
- argv[1]->len == 1 && argv[1]->bp[0] == '?') {
- ++argv;
- qmark = 1;
- }
-
- /* Set name, value. */
- switch (op->type) {
- case OPT_0BOOL:
- case OPT_1BOOL:
- if (equals) {
- msgq(sp, M_ERR,
- "set: [no]%s option doesn't take a value",
- name);
- break;
- }
- if (qmark) {
- if (!disp)
- disp = SELECT_DISPLAY;
- F_SET(spo, OPT_SELECTED);
- break;
- }
- if (op->func != NULL) {
- if (op->func(sp, spo, NULL, turnoff)) {
- rval = 1;
- break;
- }
- } else if (turnoff)
- O_CLR(sp, offset);
- else
- O_SET(sp, offset);
- goto change;
- case OPT_NUM:
- /*
- * !!!
- * Extension to historic vi. If the OPT_NOSTR flag is
- * set, a numeric option may be turned off by using a
- * "no" prefix, e.g. "nowrapmargin". (We assume that
- * setting the value to 0 turns a numeric option off.)
- */
- if (turnoff) {
- if (F_ISSET(op, OPT_NOSTR)) {
- value = 0;
- goto nostr;
- }
- msgq(sp, M_ERR,
- "set: %s option isn't a boolean", name);
- break;
- }
- if (qmark || !equals) {
- if (!disp)
- disp = SELECT_DISPLAY;
- F_SET(spo, OPT_SELECTED);
- break;
- }
- value = strtol(sep, &endp, 10);
- if (*endp && !isblank(*endp)) {
- msgq(sp, M_ERR,
- "set %s: illegal number %s", name, sep);
- break;
- }
-nostr: if (op->func != NULL) {
- if (op->func(sp, spo, sep, value)) {
- rval = 1;
- break;
- }
- } else
- O_VAL(sp, offset) = value;
- goto change;
- case OPT_STR:
- if (turnoff) {
- msgq(sp, M_ERR,
- "set: %s option isn't a boolean", name);
- break;
- }
- if (qmark || !equals) {
- if (!disp)
- disp = SELECT_DISPLAY;
- F_SET(spo, OPT_SELECTED);
- break;
- }
- if (op->func != NULL) {
- if (op->func(sp, spo, sep, (u_long)0)) {
- rval = 1;
- break;
- }
- } else {
- if (F_ISSET(&sp->opts[offset], OPT_ALLOCATED))
- free(O_STR(sp, offset));
- if ((O_STR(sp, offset) = strdup(sep)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- rval = 1;
- break;
- } else
- F_SET(&sp->opts[offset], OPT_ALLOCATED);
- }
-change: if (sp->s_optchange != NULL)
- (void)sp->s_optchange(sp, offset);
- F_SET(&sp->opts[offset], OPT_SET);
- break;
- default:
- abort();
- }
- }
- if (disp != NO_DISPLAY)
- opts_dump(sp, disp);
- return (rval);
-}
-
-/*
- * opts_dump --
- * List the current values of selected options.
- */
-void
-opts_dump(sp, type)
- SCR *sp;
- enum optdisp type;
-{
- OPTLIST const *op;
- int base, b_num, cnt, col, colwidth, curlen, s_num;
- int numcols, numrows, row;
- int b_op[O_OPTIONCOUNT], s_op[O_OPTIONCOUNT];
- char nbuf[20];
-
- /*
- * XXX
- * It's possible to get here by putting "set option" in the
- * .exrc file. I can't think of a clean way to layer this,
- * or a reasonable check to make, so we block it here.
- */
- if (sp->stdfp == NULL) {
- msgq(sp, M_ERR,
- "Option display requires that the screen be initialized");
- return;
- }
-
- /*
- * Options are output in two groups -- those that fit in a column and
- * those that don't. Output is done on 6 character "tab" boundaries
- * for no particular reason. (Since we don't output tab characters,
- * we can ignore the terminal's tab settings.) Ignore the user's tab
- * setting because we have no idea how reasonable it is.
- *
- * Find a column width we can live with.
- */
- for (cnt = 6; cnt > 1; --cnt) {
- colwidth = (sp->cols - 1) / cnt & ~(STANDARD_TAB - 1);
- if (colwidth >= 10) {
- colwidth =
- (colwidth + STANDARD_TAB) & ~(STANDARD_TAB - 1);
- break;
- }
- colwidth = 0;
- }
-
- /*
- * Get the set of options to list, entering them into
- * the column list or the overflow list.
- */
- for (b_num = s_num = 0, op = optlist; op->name != NULL; ++op) {
- cnt = op - optlist;
-
- /* If OPT_NEVER set, it's never displayed. */
- if (F_ISSET(op, OPT_NEVER))
- continue;
-
- switch (type) {
- case ALL_DISPLAY: /* Display all. */
- break;
- case CHANGED_DISPLAY: /* Display changed. */
- if (!F_ISSET(&sp->opts[cnt], OPT_SET))
- continue;
- break;
- case SELECT_DISPLAY: /* Display selected. */
- if (!F_ISSET(&sp->opts[cnt], OPT_SELECTED))
- continue;
- break;
- default:
- case NO_DISPLAY:
- abort();
- /* NOTREACHED */
- }
- F_CLR(&sp->opts[cnt], OPT_SELECTED);
-
- curlen = strlen(op->name);
- switch (op->type) {
- case OPT_0BOOL:
- case OPT_1BOOL:
- if (!O_ISSET(sp, cnt))
- curlen += 2;
- break;
- case OPT_NUM:
- (void)snprintf(nbuf,
- sizeof(nbuf), "%ld", O_VAL(sp, cnt));
- curlen += strlen(nbuf);
- break;
- case OPT_STR:
- curlen += strlen(O_STR(sp, cnt)) + 3;
- break;
- }
- /* Offset by two so there's a gap. */
- if (curlen < colwidth - 2)
- s_op[s_num++] = cnt;
- else
- b_op[b_num++] = cnt;
- }
-
- if (s_num > 0) {
- /* Figure out the number of columns. */
- numcols = (sp->cols - 1) / colwidth;
- if (s_num > numcols) {
- numrows = s_num / numcols;
- if (s_num % numcols)
- ++numrows;
- } else
- numrows = 1;
-
- /* Display the options in sorted order. */
- for (row = 0; row < numrows;) {
- for (base = row, col = 0; col < numcols; ++col) {
- cnt = opts_print(sp, &optlist[s_op[base]]);
- if ((base += numrows) >= s_num)
- break;
- (void)ex_printf(EXCOOKIE,
- "%*s", (int)(colwidth - cnt), "");
- }
- if (++row < numrows || b_num)
- (void)ex_printf(EXCOOKIE, "\n");
- }
- }
-
- for (row = 0; row < b_num;) {
- (void)opts_print(sp, &optlist[b_op[row]]);
- if (++row < b_num)
- (void)ex_printf(EXCOOKIE, "\n");
- }
- (void)ex_printf(EXCOOKIE, "\n");
-}
-
-/*
- * opts_print --
- * Print out an option.
- */
-static int
-opts_print(sp, op)
- SCR *sp;
- OPTLIST const *op;
-{
- int curlen, offset;
-
- curlen = 0;
- offset = op - optlist;
- switch (op->type) {
- case OPT_0BOOL:
- case OPT_1BOOL:
- curlen += ex_printf(EXCOOKIE,
- "%s%s", O_ISSET(sp, offset) ? "" : "no", op->name);
- break;
- case OPT_NUM:
- curlen += ex_printf(EXCOOKIE,
- "%s=%ld", op->name, O_VAL(sp, offset));
- break;
- case OPT_STR:
- curlen += ex_printf(EXCOOKIE,
- "%s=\"%s\"", op->name, O_STR(sp, offset));
- break;
- }
- return (curlen);
-}
-
-/*
- * opts_save --
- * Write the current configuration to a file.
- */
-int
-opts_save(sp, fp)
- SCR *sp;
- FILE *fp;
-{
- OPTLIST const *op;
- int ch, cnt;
- char *p;
-
- for (op = optlist; op->name != NULL; ++op) {
- if (F_ISSET(op, OPT_NOSAVE))
- continue;
- cnt = op - optlist;
- switch (op->type) {
- case OPT_0BOOL:
- case OPT_1BOOL:
- if (O_ISSET(sp, cnt))
- (void)fprintf(fp, "set %s\n", op->name);
- else
- (void)fprintf(fp, "set no%s\n", op->name);
- break;
- case OPT_NUM:
- (void)fprintf(fp,
- "set %s=%-3d\n", op->name, O_VAL(sp, cnt));
- break;
- case OPT_STR:
- (void)fprintf(fp, "set ");
- for (p = op->name; (ch = *p) != '\0'; ++p) {
- if (isblank(ch) || ch == '\\')
- (void)putc('\\', fp);
- (void)putc(ch, fp);
- }
- (void)putc('=', fp);
- for (p = O_STR(sp, cnt); (ch = *p) != '\0'; ++p) {
- if (isblank(ch) || ch == '\\')
- (void)putc('\\', fp);
- (void)putc(ch, fp);
- }
- (void)putc('\n', fp);
- break;
- }
- if (ferror(fp)) {
- msgq(sp, M_ERR, "I/O error: %s", strerror(errno));
- return (1);
- }
- }
- return (0);
-}
-
-/*
- * opts_prefix --
- * Check to see if the name is the prefix of one (and only one)
- * option. If so, return the option.
- */
-static OPTLIST const *
-opts_prefix(name)
- char *name;
-{
- OPTLIST const *op, *save_op;
- size_t len;
-
- save_op = NULL;
- len = strlen(name);
- for (op = optlist; op->name != NULL; ++op) {
- if (op->name[0] < name[0])
- continue;
- if (op->name[0] > name[0])
- break;
- if (!memcmp(op->name, name, len)) {
- if (save_op != NULL)
- return (NULL);
- save_op = op;
- }
- }
- return (save_op);
-}
-
-static int
-opts_abbcmp(a, b)
- const void *a, *b;
-{
- return(strcmp(((OABBREV *)a)->name, ((OABBREV *)b)->name));
-}
-
-static int
-opts_cmp(a, b)
- const void *a, *b;
-{
- return(strcmp(((OPTLIST *)a)->name, ((OPTLIST *)b)->name));
-}
-
-/*
- * opts_free --
- * Free all option strings
- */
-void
-opts_free(sp)
- SCR *sp;
-{
- int cnt;
- char *p;
-
- for (cnt = 0; cnt < O_OPTIONCOUNT; ++cnt)
- if (F_ISSET(&sp->opts[cnt], OPT_ALLOCATED)) {
- p = O_STR(sp, cnt);
- FREE(p, strlen(p) + 1);
- }
-}
-
-/*
- * opts_copy --
- * Copy a screen's OPTION array.
- */
-int
-opts_copy(orig, sp)
- SCR *orig, *sp;
-{
- OPTION *op;
- int cnt;
-
- /* Copy most everything without change. */
- memmove(sp->opts, orig->opts, sizeof(orig->opts));
-
- /*
- * Allocate copies of the strings -- keep trying to reallocate
- * after ENOMEM failure, otherwise end up with more than one
- * screen referencing the original memory.
- */
- for (op = sp->opts, cnt = 0; cnt < O_OPTIONCOUNT; ++cnt, ++op)
- if (F_ISSET(&sp->opts[cnt], OPT_ALLOCATED) &&
- (O_STR(sp, cnt) = strdup(O_STR(sp, cnt))) == NULL) {
- msgq(orig, M_SYSERR, NULL);
- return (1);
- }
- return (0);
-}
diff --git a/usr.bin/vi/common/options.h.stub b/usr.bin/vi/common/options.h.stub
deleted file mode 100644
index 0e2051d76117..000000000000
--- a/usr.bin/vi/common/options.h.stub
+++ /dev/null
@@ -1,108 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)options.h.stub 8.22 (Berkeley) 8/8/94
- */
-
-struct _option {
- union {
- u_long val; /* Value or boolean. */
- char *str; /* String. */
- } o_u;
- size_t len; /* String length. */
-
-#define OPT_ALLOCATED 0x01 /* Allocated space. */
-#define OPT_SELECTED 0x02 /* Selected for display. */
-#define OPT_SET 0x04 /* Set (display for the user). */
- u_char flags;
-};
-
-struct _optlist {
- char *name; /* Name. */
- /* Change function. */
- int (*func) __P((SCR *, OPTION *, char *, u_long));
- /* Type of object. */
- enum { OPT_0BOOL, OPT_1BOOL, OPT_NUM, OPT_STR } type;
-
-#define OPT_NEVER 0x01 /* Never display the option. */
-#define OPT_NOSAVE 0x02 /* Mkexrc command doesn't save. */
-#define OPT_NOSTR 0x04 /* String that takes a "no". */
- u_int flags;
-};
-
-/* Clear, set, test boolean options. */
-#define O_SET(sp, o) (sp)->opts[(o)].o_u.val = 1
-#define O_CLR(sp, o) (sp)->opts[(o)].o_u.val = 0
-#define O_ISSET(sp, o) ((sp)->opts[(o)].o_u.val)
-
-/* Get option values. */
-#define O_LEN(sp, o) (sp)->opts[(o)].len
-#define O_STR(sp, o) (sp)->opts[(o)].o_u.str
-#define O_VAL(sp, o) (sp)->opts[(o)].o_u.val
-
-/* Option routines. */
-u_long baud_from_bval __P((SCR *));
-
-int opts_copy __P((SCR *, SCR *));
-void opts_free __P((SCR *));
-int opts_init __P((SCR *));
-int opts_save __P((SCR *, FILE *));
-int opts_set __P((SCR *, char *, ARGS *[]));
-
-enum optdisp { NO_DISPLAY, ALL_DISPLAY, CHANGED_DISPLAY, SELECT_DISPLAY };
-void opts_dump __P((SCR *, enum optdisp));
-
-/* Per-option change routines. */
-int f_altwerase __P((SCR *, OPTION *, char *, u_long));
-int f_cdpath __P((SCR *, OPTION *, char *, u_long));
-int f_columns __P((SCR *, OPTION *, char *, u_long));
-int f_leftright __P((SCR *, OPTION *, char *, u_long));
-int f_lines __P((SCR *, OPTION *, char *, u_long));
-int f_lisp __P((SCR *, OPTION *, char *, u_long));
-int f_list __P((SCR *, OPTION *, char *, u_long));
-int f_mesg __P((SCR *, OPTION *, char *, u_long));
-int f_modeline __P((SCR *, OPTION *, char *, u_long));
-int f_number __P((SCR *, OPTION *, char *, u_long));
-int f_octal __P((SCR *, OPTION *, char *, u_long));
-int f_paragraph __P((SCR *, OPTION *, char *, u_long));
-int f_readonly __P((SCR *, OPTION *, char *, u_long));
-int f_section __P((SCR *, OPTION *, char *, u_long));
-int f_shiftwidth __P((SCR *, OPTION *, char *, u_long));
-int f_sourceany __P((SCR *, OPTION *, char *, u_long));
-int f_tabstop __P((SCR *, OPTION *, char *, u_long));
-int f_tags __P((SCR *, OPTION *, char *, u_long));
-int f_term __P((SCR *, OPTION *, char *, u_long));
-int f_ttywerase __P((SCR *, OPTION *, char *, u_long));
-int f_w1200 __P((SCR *, OPTION *, char *, u_long));
-int f_w300 __P((SCR *, OPTION *, char *, u_long));
-int f_w9600 __P((SCR *, OPTION *, char *, u_long));
-int f_window __P((SCR *, OPTION *, char *, u_long));
diff --git a/usr.bin/vi/common/options_f.c b/usr.bin/vi/common/options_f.c
deleted file mode 100644
index 6e1f060f284e..000000000000
--- a/usr.bin/vi/common/options_f.c
+++ /dev/null
@@ -1,518 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)options_f.c 8.34 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "../ex/tag.h"
-
-static int opt_dup __P((SCR *, int, char *));
-static int opt_putenv __P((char *));
-
-#define DECL(f) \
- int \
- f(sp, op, str, val) \
- SCR *sp; \
- OPTION *op; \
- char *str; \
- u_long val;
-#define CALL(f) \
- f(sp, op, str, val)
-
-#define turnoff val
-
-DECL(f_altwerase)
-{
- if (turnoff)
- O_CLR(sp, O_ALTWERASE);
- else {
- O_SET(sp, O_ALTWERASE);
- O_CLR(sp, O_TTYWERASE);
- }
- return (0);
-}
-
-DECL(f_cdpath)
-{
- return (opt_dup(sp, O_CDPATH, str));
-}
-
-DECL(f_columns)
-{
- char buf[25];
-
- /* Validate the number. */
- if (val < MINIMUM_SCREEN_COLS) {
- msgq(sp, M_ERR, "Screen columns too small, less than %d",
- MINIMUM_SCREEN_COLS);
- return (1);
- }
- /* Set the columns value in the environment for curses. */
- (void)snprintf(buf, sizeof(buf), "COLUMNS=%lu", val);
- if (opt_putenv(buf))
- return (1);
-
- /* This is expensive, don't do it unless it's necessary. */
- if (O_VAL(sp, O_COLUMNS) == val)
- return (0);
-
- /* Set the value. */
- O_VAL(sp, O_COLUMNS) = val;
-
- F_SET(sp, S_RESIZE);
- return (0);
-}
-
-DECL(f_leftright)
-{
- if (turnoff)
- O_CLR(sp, O_LEFTRIGHT);
- else
- O_SET(sp, O_LEFTRIGHT);
- F_SET(sp, S_REFORMAT | S_REDRAW);
- return (0);
-}
-
-DECL(f_lines)
-{
- char buf[25];
-
- /* Validate the number. */
- if (val < MINIMUM_SCREEN_ROWS) {
- msgq(sp, M_ERR, "Screen lines too small, less than %d",
- MINIMUM_SCREEN_ROWS);
- return (1);
- }
-
- /* Set the rows value in the environment for curses. */
- (void)snprintf(buf, sizeof(buf), "ROWS=%lu", val);
- if (opt_putenv(buf))
- return (1);
-
- /* This is expensive, don't do it unless it's necessary. */
- if (O_VAL(sp, O_LINES) == val)
- return (0);
-
- /* Set the value. */
- O_VAL(sp, O_LINES) = val;
-
- /*
- * If no window value set, set a new default window and,
- * optionally, a new scroll value.
- */
- if (!F_ISSET(&sp->opts[O_WINDOW], OPT_SET)) {
- O_VAL(sp, O_WINDOW) = val - 1;
- if (!F_ISSET(&sp->opts[O_SCROLL], OPT_SET))
- O_VAL(sp, O_SCROLL) = val / 2;
- }
-
- F_SET(sp, S_RESIZE);
- return (0);
-}
-
-DECL(f_lisp)
-{
- msgq(sp, M_ERR, "The lisp option is not implemented");
- return (0);
-}
-
-DECL(f_list)
-{
- if (turnoff)
- O_CLR(sp, O_LIST);
- else
- O_SET(sp, O_LIST);
-
- F_SET(sp, S_REFORMAT | S_REDRAW);
- return (0);
-}
-
-DECL(f_mesg)
-{
- struct stat sb;
- char *tty;
-
- /* Find the tty. */
- if ((tty = ttyname(STDERR_FILENO)) == NULL) {
- msgq(sp, M_ERR, "ttyname: %s", strerror(errno));
- return (1);
- }
-
- /* Save the tty mode for later; only save it once. */
- if (!F_ISSET(sp->gp, G_SETMODE)) {
- F_SET(sp->gp, G_SETMODE);
- if (stat(tty, &sb) < 0) {
- msgq(sp, M_ERR, "%s: %s", tty, strerror(errno));
- return (1);
- }
- sp->gp->origmode = sb.st_mode;
- }
-
- if (turnoff) {
- if (chmod(tty, sp->gp->origmode & ~S_IWGRP) < 0) {
- msgq(sp, M_ERR, "messages not turned off: %s: %s",
- tty, strerror(errno));
- return (1);
- }
- O_CLR(sp, O_MESG);
- } else {
- if (chmod(tty, sp->gp->origmode | S_IWGRP) < 0) {
- msgq(sp, M_ERR, "messages not turned on: %s: %s",
- tty, strerror(errno));
- return (1);
- }
- O_SET(sp, O_MESG);
- }
- return (0);
-}
-
-/*
- * f_modeline --
- * This has been documented in historical systems as both "modeline"
- * and as "modelines". Regardless of the name, this option represents
- * a security problem of mammoth proportions, not to mention a stunning
- * example of what your intro CS professor referred to as the perils of
- * mixing code and data. Don't add it, or I will kill you.
- */
-DECL(f_modeline)
-{
- if (!turnoff)
- msgq(sp, M_ERR, "The modeline(s) option may never be set");
- return (0);
-}
-
-DECL(f_number)
-{
- if (turnoff)
- O_CLR(sp, O_NUMBER);
- else
- O_SET(sp, O_NUMBER);
-
- F_SET(sp, S_REFORMAT | S_REDRAW);
- return (0);
-}
-
-DECL(f_octal)
-{
- if (turnoff)
- O_CLR(sp, O_OCTAL);
- else
- O_SET(sp, O_OCTAL);
-
- key_init(sp);
- F_SET(sp, S_REFORMAT | S_REDRAW);
- return (0);
-}
-
-DECL(f_paragraph)
-{
- if (strlen(str) & 1) {
- msgq(sp, M_ERR,
- "Paragraph options must be in sets of two characters");
- return (1);
- }
- return (opt_dup(sp, O_PARAGRAPHS, str));
-}
-
-DECL(f_readonly)
-{
- if (turnoff) {
- O_CLR(sp, O_READONLY);
- if (sp->frp != NULL)
- F_CLR(sp->frp, FR_RDONLY);
- } else {
- O_SET(sp, O_READONLY);
- if (sp->frp != NULL)
- F_SET(sp->frp, FR_RDONLY);
- }
- return (0);
-}
-
-DECL(f_section)
-{
- if (strlen(str) & 1) {
- msgq(sp, M_ERR,
- "Section options must be in sets of two characters");
- return (1);
- }
- return (opt_dup(sp, O_SECTIONS, str));
-}
-
-DECL(f_shiftwidth)
-{
- if (val == 0) {
- msgq(sp, M_ERR, "The shiftwidth can't be set to 0");
- return (1);
- }
- O_VAL(sp, O_SHIFTWIDTH) = val;
- return (0);
-}
-
-/*
- * f_sourceany --
- * Historic vi, on startup, source'd $HOME/.exrc and ./.exrc, if they
- * were owned by the user. The sourceany option was an undocumented
- * feature of historic vi which permitted the startup source'ing of
- * .exrc files the user didn't own. This is an obvious security problem,
- * and we ignore the option.
- */
-DECL(f_sourceany)
-{
- if (!turnoff)
- msgq(sp, M_ERR, "The sourceany option may never be set");
- return (0);
-}
-
-DECL(f_tabstop)
-{
- if (val == 0) {
- msgq(sp, M_ERR, "Tab stops can't be set to 0");
- return (1);
- }
-#define MAXTABSTOP 20
- if (val > MAXTABSTOP) {
- msgq(sp, M_ERR,
- "Tab stops can't be larger than %d", MAXTABSTOP);
- return (1);
- }
- O_VAL(sp, O_TABSTOP) = val;
-
- F_SET(sp, S_REFORMAT | S_REDRAW);
- return (0);
-}
-
-DECL(f_tags)
-{
- return (opt_dup(sp, O_TAGS, str));
-}
-
-DECL(f_term)
-{
- char buf[256];
-
- if (opt_dup(sp, O_TERM, str))
- return (1);
-
- /* Set the terminal value in the environment for curses. */
- (void)snprintf(buf, sizeof(buf), "TERM=%s", str);
- if (opt_putenv(buf))
- return (1);
- return (0);
-}
-
-DECL(f_ttywerase)
-{
- if (turnoff)
- O_CLR(sp, O_TTYWERASE);
- else {
- O_SET(sp, O_TTYWERASE);
- O_CLR(sp, O_ALTWERASE);
- }
- return (0);
-}
-
-DECL(f_w300)
-{
- /* Historical behavior for w300 was < 1200. */
- if (baud_from_bval(sp) >= 1200)
- return (0);
-
- if (CALL(f_window))
- return (1);
-
- if (val > O_VAL(sp, O_LINES) - 1)
- val = O_VAL(sp, O_LINES) - 1;
- O_VAL(sp, O_W300) = val;
- return (0);
-}
-
-DECL(f_w1200)
-{
- u_long v;
-
- /* Historical behavior for w1200 was == 1200. */
- v = baud_from_bval(sp);
- if (v < 1200 || v > 4800)
- return (0);
-
- if (CALL(f_window))
- return (1);
-
- if (val > O_VAL(sp, O_LINES) - 1)
- val = O_VAL(sp, O_LINES) - 1;
- O_VAL(sp, O_W1200) = val;
- return (0);
-}
-
-DECL(f_w9600)
-{
- speed_t v;
-
- /* Historical behavior for w9600 was > 1200. */
- v = baud_from_bval(sp);
- if (v <= 4800)
- return (0);
-
- if (CALL(f_window))
- return (1);
-
- if (val > O_VAL(sp, O_LINES) - 1)
- val = O_VAL(sp, O_LINES) - 1;
- O_VAL(sp, O_W9600) = val;
- return (0);
-}
-
-DECL(f_window)
-{
- if (val < MINIMUM_SCREEN_ROWS) {
- msgq(sp, M_ERR, "Window too small, less than %d",
- MINIMUM_SCREEN_ROWS);
- return (1);
- }
- if (val > O_VAL(sp, O_LINES) - 1)
- val = O_VAL(sp, O_LINES) - 1;
- O_VAL(sp, O_WINDOW) = val;
- O_VAL(sp, O_SCROLL) = val / 2;
-
- return (0);
-}
-
-/*
- * opt_dup --
- * Copy a string value for user display.
- */
-static int
-opt_dup(sp, opt, str)
- SCR *sp;
- int opt;
- char *str;
-{
- char *p;
-
- /* Copy for user display. */
- if ((p = strdup(str)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- return (1);
- }
-
- /* Free the old contents. */
- if (F_ISSET(&sp->opts[opt], OPT_ALLOCATED))
- free(O_STR(sp, opt));
-
- /* Note that it's set and allocated. */
- F_SET(&sp->opts[opt], OPT_ALLOCATED | OPT_SET);
-
- /* Assign new contents. */
- O_STR(sp, opt) = p;
- return (0);
-}
-
-/*
- * opt_putenv --
- * Put a value into the environment. We use putenv(3) because it's
- * more portable. The following hack is because some moron decided
- * to keep a reference to the memory passed to putenv(3), instead of
- * having it allocate its own. Someone clearly needs to get promoted
- * into management.
- */
-static int
-opt_putenv(s)
- char *s;
-{
- char *t;
-
- /*
- * XXX
- * Memory leak.
- */
- if ((t = strdup(s)) == NULL)
- return (1);
- return (putenv(t));
-}
-
-/*
- * baud_from_bval --
- * Return the baud rate using the standard defines.
- */
-u_long
-baud_from_bval(sp)
- SCR *sp;
-{
- if (!F_ISSET(sp->gp, G_TERMIOS_SET))
- return (9600);
-
- /*
- * XXX
- * There's no portable way to get a "baud rate" -- cfgetospeed(3)
- * returns the value associated with some #define, which we may
- * never have heard of, or which may be a purely local speed. Vi
- * only cares if it's SLOW (w300), slow (w1200) or fast (w9600).
- * Try and detect the slow ones, and default to fast.
- */
- switch (cfgetospeed(&sp->gp->original_termios)) {
- case B50:
- case B75:
- case B110:
- case B134:
- case B150:
- case B200:
- case B300:
- case B600:
- return (600);
- case B1200:
- return (1200);
- }
- return (9600);
-}
diff --git a/usr.bin/vi/common/pathnames.h b/usr.bin/vi/common/pathnames.h
deleted file mode 100644
index 6ad165f4bb37..000000000000
--- a/usr.bin/vi/common/pathnames.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)pathnames.h 8.7 (Berkeley) 3/28/94
- */
-
-#define _PATH_BSHELL "/bin/sh"
-#define _PATH_DEVNULL "/dev/null"
-#define _PATH_EXRC ".exrc"
-#define _PATH_NEXRC ".nexrc"
-#define _PATH_PRESERVE "/var/tmp/vi.recover"
-#define _PATH_SENDMAIL "/usr/sbin/sendmail"
-#define _PATH_SYSEXRC "/etc/vi.exrc"
-#define _PATH_TAGS "tags"
-#define _PATH_TMP "/tmp"
-#define _PATH_TTY "/dev/tty"
diff --git a/usr.bin/vi/common/screen.c b/usr.bin/vi/common/screen.c
deleted file mode 100644
index d3e27e7da217..000000000000
--- a/usr.bin/vi/common/screen.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)screen.c 8.64 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "../vi/vcmd.h"
-#include "excmd.h"
-#include "../ex/tag.h"
-
-/*
- * screen_init --
- * Do the default initialization of an SCR structure.
- */
-int
-screen_init(orig, spp, flags)
- SCR *orig, **spp;
- u_int flags;
-{
- SCR *sp;
- size_t len;
-
- *spp = NULL;
- CALLOC_RET(orig, sp, SCR *, 1, sizeof(SCR));
- *spp = sp;
-
-/* INITIALIZED AT SCREEN CREATE. */
- sp->gp = __global_list; /* All ref the GS structure. */
-
- LIST_INIT(&sp->msgq);
- CIRCLEQ_INIT(&sp->frefq);
-
- sp->ccnt = 2; /* Anything > 1 */
-
- FD_ZERO(&sp->rdfd);
-
- /*
- * XXX
- * sp->defscroll is initialized by the opts_init() code because
- * we don't have the option information yet.
- */
-
- sp->tiqp = &sp->__tiq;
- CIRCLEQ_INIT(&sp->__tiq);
-
-/* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */
- if (orig == NULL) {
- sp->searchdir = NOTSET;
-
- switch (flags & S_SCREENS) {
- case S_EX:
- if (sex_screen_init(sp))
- return (1);
- break;
- case S_VI_CURSES:
- if (svi_screen_init(sp))
- return (1);
- break;
- case S_VI_XAW:
- if (xaw_screen_init(sp))
- return (1);
- break;
- default:
- abort();
- }
-
- sp->flags = flags;
- } else {
- if (orig->alt_name != NULL &&
- (sp->alt_name = strdup(orig->alt_name)) == NULL)
- goto mem;
-
- /* Retain all searching/substitution information. */
- if (F_ISSET(orig, S_SRE_SET)) {
- F_SET(sp, S_SRE_SET);
- sp->sre = orig->sre;
- }
- if (F_ISSET(orig, S_SUBRE_SET)) {
- F_SET(sp, S_SUBRE_SET);
- sp->subre = orig->subre;
- }
- sp->searchdir = orig->searchdir == NOTSET ? NOTSET : FORWARD;
-
- if (orig->repl_len) {
- MALLOC(sp, sp->repl, char *, orig->repl_len);
- if (sp->repl == NULL)
- goto mem;
- sp->repl_len = orig->repl_len;
- memmove(sp->repl, orig->repl, orig->repl_len);
- }
- if (orig->newl_len) {
- len = orig->newl_len * sizeof(size_t);
- MALLOC(sp, sp->newl, size_t *, len);
- if (sp->newl == NULL)
- goto mem;
- sp->newl_len = orig->newl_len;
- sp->newl_cnt = orig->newl_cnt;
- memmove(sp->newl, orig->newl, len);
- }
-
- sp->saved_vi_mode = orig->saved_vi_mode;
-
- if (opts_copy(orig, sp)) {
-mem: msgq(orig, M_SYSERR, "new screen attributes");
- (void)screen_end(sp);
- return (1);
- }
-
- sp->s_bell = orig->s_bell;
- sp->s_bg = orig->s_bg;
- sp->s_busy = orig->s_busy;
- sp->s_change = orig->s_change;
- sp->s_clear = orig->s_clear;
- sp->s_colpos = orig->s_colpos;
- sp->s_column = orig->s_column;
- sp->s_confirm = orig->s_confirm;
- sp->s_crel = orig->s_crel;
- sp->s_edit = orig->s_edit;
- sp->s_end = orig->s_end;
- sp->s_ex_cmd = orig->s_ex_cmd;
- sp->s_ex_run = orig->s_ex_run;
- sp->s_ex_write = orig->s_ex_write;
- sp->s_fg = orig->s_fg;
- sp->s_fill = orig->s_fill;
- sp->s_get = orig->s_get;
- sp->s_key_read = orig->s_key_read;
- sp->s_fmap = orig->s_fmap;
- sp->s_optchange = orig->s_optchange;
- sp->s_position = orig->s_position;
- sp->s_rabs = orig->s_rabs;
- sp->s_rcm = orig->s_rcm;
- sp->s_refresh = orig->s_refresh;
- sp->s_scroll = orig->s_scroll;
- sp->s_split = orig->s_split;
- sp->s_suspend = orig->s_suspend;
- sp->s_window = orig->s_window;
-
- F_SET(sp, F_ISSET(orig, S_SCREENS));
- }
-
- if (xaw_screen_copy(orig, sp)) /* Init S_VI_XAW screen. */
- return (1);
- if (svi_screen_copy(orig, sp)) /* Init S_VI_CURSES screen. */
- return (1);
- if (sex_screen_copy(orig, sp)) /* Init S_EX screen. */
- return (1);
- if (v_screen_copy(orig, sp)) /* Init vi. */
- return (1);
- if (ex_screen_copy(orig, sp)) /* Init ex. */
- return (1);
-
- *spp = sp;
- return (0);
-}
-
-/*
- * screen_end --
- * Release a screen.
- */
-int
-screen_end(sp)
- SCR *sp;
-{
- int rval;
-
- rval = 0;
- if (xaw_screen_end(sp)) /* End S_VI_XAW screen. */
- rval = 1;
- if (svi_screen_end(sp)) /* End S_VI_CURSES screen. */
- rval = 1;
- if (sex_screen_end(sp)) /* End S_EX screen. */
- rval = 1;
- if (v_screen_end(sp)) /* End vi. */
- rval = 1;
- if (ex_screen_end(sp)) /* End ex. */
- rval = 1;
-
- /* Free FREF's. */
- { FREF *frp;
- while ((frp = sp->frefq.cqh_first) != (FREF *)&sp->frefq) {
- CIRCLEQ_REMOVE(&sp->frefq, frp, q);
- if (frp->name != NULL)
- free(frp->name);
- if (frp->tname != NULL)
- free(frp->tname);
- FREE(frp, sizeof(FREF));
- }
- }
-
- /* Free file names. */
- { char **ap;
- if (!F_ISSET(sp, S_ARGNOFREE) && sp->argv != NULL) {
- for (ap = sp->argv; *ap != NULL; ++ap)
- free(*ap);
- free(sp->argv);
- }
- }
-
- /* Free any text input. */
- text_lfree(&sp->__tiq);
-
- /* Free any script information. */
- if (F_ISSET(sp, S_SCRIPT))
- sscr_end(sp);
-
- /* Free alternate file name. */
- if (sp->alt_name != NULL)
- free(sp->alt_name);
-
- /* Free up search information. */
- if (sp->repl != NULL)
- FREE(sp->repl, sp->repl_len);
- if (sp->newl != NULL)
- FREE(sp->newl, sp->newl_len);
-
- /* Free all the options */
- opts_free(sp);
-
- /*
- * Free the message chain last, so previous failures have a place
- * to put messages. Copy messages to (in order) a related screen,
- * any screen, the global area.
- */
- { SCR *c_sp; MSG *mp, *next;
- if ((c_sp = sp->q.cqe_prev) != (void *)&sp->gp->dq) {
- if (F_ISSET(sp, S_BELLSCHED))
- F_SET(c_sp, S_BELLSCHED);
- } else if ((c_sp = sp->q.cqe_next) != (void *)&sp->gp->dq) {
- if (F_ISSET(sp, S_BELLSCHED))
- F_SET(c_sp, S_BELLSCHED);
- } else if ((c_sp =
- sp->gp->hq.cqh_first) != (void *)&sp->gp->hq) {
- if (F_ISSET(sp, S_BELLSCHED))
- F_SET(c_sp, S_BELLSCHED);
- } else {
- c_sp = NULL;
- if (F_ISSET(sp, S_BELLSCHED))
- F_SET(sp->gp, G_BELLSCHED);
- }
-
- for (mp = sp->msgq.lh_first; mp != NULL; mp = next) {
- if (!F_ISSET(mp, M_EMPTY))
- msg_app(sp->gp, c_sp,
- mp->flags & M_INV_VIDEO, mp->mbuf, mp->len);
- next = mp->q.le_next;
- if (mp->mbuf != NULL)
- FREE(mp->mbuf, mp->blen);
- FREE(mp, sizeof(MSG));
- }
- }
-
- /* Remove the screen from the displayed queue. */
- CIRCLEQ_REMOVE(&sp->gp->dq, sp, q);
-
- /* Free the screen itself. */
- FREE(sp, sizeof(SCR));
-
- return (rval);
-}
diff --git a/usr.bin/vi/common/screen.h b/usr.bin/vi/common/screen.h
deleted file mode 100644
index 31df988ece3a..000000000000
--- a/usr.bin/vi/common/screen.h
+++ /dev/null
@@ -1,342 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)screen.h 8.127 (Berkeley) 8/8/94
- */
-
-/*
- * There are minimum values that vi has to have to display a screen. The
- * row minimum is fixed at 1 line for the text, and 1 line for any error
- * messages. The column calculation is a lot trickier. For example, you
- * have to have enough columns to display the line number, not to mention
- * guaranteeing that tabstop and shiftwidth values are smaller than the
- * current column value. It's a lot simpler to have a fixed value and not
- * worry about it.
- *
- * XXX
- * MINIMUM_SCREEN_COLS is probably wrong.
- */
-#define MINIMUM_SCREEN_ROWS 2
-#define MINIMUM_SCREEN_COLS 20
-
-enum adjust { /* Screen adjustment operations. */
- A_DECREASE, A_INCREASE, A_SET };
-enum operation { /* Line operations. */
- LINE_APPEND, LINE_DELETE, LINE_INSERT, LINE_RESET };
-enum position { /* Position operations. */
- P_BOTTOM, P_FILL, P_MIDDLE, P_TOP };
-enum sctype { /* Scroll operations. */
- CNTRL_B, CNTRL_D, CNTRL_E, CNTRL_F, CNTRL_U, CNTRL_Y, Z_CARAT, Z_PLUS };
-
-/*
- * Structure for holding file references. Each SCR structure contains a
- * linked list of these. The structure contains the name of the file,
- * along with the information that follows the name.
- *
- * !!!
- * The read-only bit follows the file name, not the file itself.
- *
- * XXX
- * The mtime field should be a struct timespec, but time_t is more portable.
- */
-struct _fref {
- CIRCLEQ_ENTRY(_fref) q; /* Linked list of file references. */
- char *name; /* File name. */
- char *tname; /* Backing temporary file name. */
-
- recno_t lno; /* 1-N: file cursor line. */
- size_t cno; /* 0-N: file cursor column. */
-
-#define FR_CURSORSET 0x001 /* If lno/cno values valid. */
-#define FR_DONTDELETE 0x002 /* Don't delete the temporary file. */
-#define FR_FNONBLANK 0x004 /* Move to the first non-<blank>. */
-#define FR_NAMECHANGE 0x008 /* If the name changed. */
-#define FR_NEWFILE 0x010 /* File doesn't really exist yet. */
-#define FR_RDONLY 0x020 /* File is read-only. */
-#define FR_READNAMED 0x040 /* Read renamed the file. */
-#define FR_RECOVER 0x080 /* File is being recovered. */
-#define FR_TMPEXIT 0x100 /* Modified temporary file, no exit. */
-#define FR_TMPFILE 0x200 /* If file has no name. */
-#define FR_UNLOCKED 0x400 /* File couldn't be locked. */
- u_int16_t flags;
-};
-
-#define TEMPORARY_FILE_STRING "/tmp" /* Default temporary file name. */
-
-/*
- * SCR --
- * The screen structure. To the extent possible, all screen information
- * is stored in the various private areas. The only information here
- * is used by global routines or is shared by too many screens.
- */
-struct _scr {
-/* INITIALIZED AT SCREEN CREATE. */
- CIRCLEQ_ENTRY(_scr) q; /* Screens. */
-
- GS *gp; /* Pointer to global area. */
-
- SCR *nextdisp; /* Next display screen. */
-
- EXF *ep; /* Screen's current EXF structure. */
-
- MSGH msgq; /* Message list. */
- /* FREF list. */
- CIRCLEQ_HEAD(_frefh, _fref) frefq;
- FREF *frp; /* FREF being edited. */
-
- char **argv; /* NULL terminated file name array. */
- char **cargv; /* Current file name. */
-
- u_long ccnt; /* Command count. */
- u_long q_ccnt; /* Quit or ZZ command count. */
-
- /* Screen's: */
- size_t rows; /* 1-N: number of rows. */
- size_t cols; /* 1-N: number of columns. */
- size_t woff; /* 0-N: row offset in screen. */
- size_t t_rows; /* 1-N: cur number of text rows. */
- size_t t_maxrows; /* 1-N: max number of text rows. */
- size_t t_minrows; /* 1-N: min number of text rows. */
-
- /* Cursor's: */
- recno_t lno; /* 1-N: file line. */
- size_t cno; /* 0-N: file character in line. */
-
- size_t rcm; /* Vi: 0-N: Most attractive column. */
- int rcm_last; /* Cursor drawn to the last column. */
-
-#define L_ADDED 0 /* Added lines. */
-#define L_CHANGED 1 /* Changed lines. */
-#define L_DELETED 2 /* Deleted lines. */
-#define L_JOINED 3 /* Joined lines. */
-#define L_MOVED 4 /* Moved lines. */
-#define L_LSHIFT 5 /* Left shift lines. */
-#define L_RSHIFT 6 /* Right shift lines. */
-#define L_YANKED 7 /* Yanked lines. */
- recno_t rptlchange; /* Ex/vi: last L_CHANGED lno. */
- recno_t rptlines[L_YANKED + 1];/* Ex/vi: lines changed by last op. */
-
- FILE *stdfp; /* Ex output file pointer. */
-
- char *if_name; /* Ex input file name, for messages. */
- recno_t if_lno; /* Ex input file line, for messages. */
-
- fd_set rdfd; /* Ex/vi: read fd select mask. */
-
- TEXTH __tiq; /* Ex/vi: text input queue. */
- TEXTH *tiqp; /* Ex/vi: text input queue reference. */
-
- SCRIPT *script; /* Vi: script mode information .*/
-
- recno_t defscroll; /* Vi: ^D, ^U scroll information. */
-
- struct timeval busy_tod; /* ITIMER_REAL: busy time-of-day. */
- char const *busy_msg; /* ITIMER_REAL: busy message. */
-
- /* Display character. */
- CHAR_T cname[MAX_CHARACTER_COLUMNS + 1];
- size_t clen; /* Length of display character. */
-
-#define MAX_MODE_NAME 12
- char *showmode; /* Mode. */
-
- void *ex_private; /* Ex private area. */
- void *sex_private; /* Ex screen private area. */
- void *vi_private; /* Vi private area. */
- void *svi_private; /* Vi curses screen private area. */
- void *xaw_private; /* Vi XAW screen private area. */
-
-/* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */
- char *alt_name; /* Ex/vi: alternate file name. */
-
- /* Ex/vi: search/substitute info. */
- regex_t sre; /* Last search RE. */
- regex_t subre; /* Last substitute RE. */
- enum direction searchdir; /* File search direction. */
- char *repl; /* Substitute replacement. */
- size_t repl_len; /* Substitute replacement length.*/
- size_t *newl; /* Newline offset array. */
- size_t newl_len; /* Newline array size. */
- size_t newl_cnt; /* Newlines in replacement. */
- u_char c_suffix; /* Edcompatible 'c' suffix value. */
- u_char g_suffix; /* Edcompatible 'g' suffix value. */
-
- u_int saved_vi_mode; /* Saved vi display type. */
-
- OPTION opts[O_OPTIONCOUNT]; /* Options. */
-
-/*
- * SCREEN SUPPORT ROUTINES.
- *
- * A SCR * MUST be the first argument to these routines.
- */
- /* Ring the screen bell. */
- void (*s_bell) __P((SCR *));
- /* Background the screen. */
- int (*s_bg) __P((SCR *));
- /* Put up a busy message. */
- int (*s_busy) __P((SCR *, char const *));
- /* Change a screen line. */
- int (*s_change) __P((SCR *, EXF *, recno_t, enum operation));
- /* Clear the screen. */
- int (*s_clear) __P((SCR *));
- /* Return column close to specified. */
- size_t (*s_colpos) __P((SCR *, EXF *, recno_t, size_t));
- /* Return the logical cursor column. */
- int (*s_column) __P((SCR *, EXF *, size_t *));
- enum confirm /* Confirm an action with the user. */
- (*s_confirm) __P((SCR *, EXF *, MARK *, MARK *));
- /* Change the relative screen size. */
- int (*s_crel) __P((SCR *, long));
- /* Edit a file. */
- int (*s_edit) __P((SCR *, EXF *));
- /* End a screen. */
- int (*s_end) __P((SCR *));
- /* Run a single ex command. */
- int (*s_ex_cmd) __P((SCR *, EXF *, EXCMDARG *, MARK *));
- /* Run user's ex commands. */
- int (*s_ex_run) __P((SCR *, EXF *, MARK *));
- /* Screen's ex write function. */
- int (*s_ex_write) __P((void *, const char *, int));
- /* Foreground the screen. */
- int (*s_fg) __P((SCR *, CHAR_T *));
- /* Fill the screen's map. */
- int (*s_fill) __P((SCR *, EXF *, recno_t, enum position));
- enum input /* Get a line from the user. */
- (*s_get) __P((SCR *, EXF *, TEXTH *, ARG_CHAR_T, u_int));
- enum input /* Get a key from the user. */
- (*s_key_read) __P((SCR *, int *, struct timeval *));
- /* Map a function key. */
- int (*s_fmap) __P((SCR *,
- enum seqtype, CHAR_T *, size_t, CHAR_T *, size_t));
- /* Tell the screen an option changed. */
- int (*s_optchange) __P((SCR *, int));
- /* Return column at screen position. */
- int (*s_position) __P((SCR *, EXF *,
- MARK *, u_long, enum position));
- /* Change the absolute screen size. */
- int (*s_rabs) __P((SCR *, long, enum adjust));
- /* Return column close to selection. */
- size_t (*s_rcm) __P((SCR *, EXF *, recno_t));
- /* Refresh the screen. */
- int (*s_refresh) __P((SCR *, EXF *));
- /* Move down the screen. */
- int (*s_scroll) __P((SCR *, EXF *, MARK *, recno_t, enum sctype));
- /* Split the screen. */
- int (*s_split) __P((SCR *, ARGS *[], int));
- /* Suspend the screen. */
- int (*s_suspend) __P((SCR *));
- /* Set the window size. */
- int (*s_window) __P((SCR *, int));
-
-/* Editor screens. */
-#define S_EX 0x0000001 /* Ex screen. */
-#define S_VI_CURSES 0x0000002 /* Vi: curses screen. */
-#define S_VI_XAW 0x0000004 /* Vi: Athena widgets screen. */
-
-#define IN_EX_MODE(sp) /* If in ex mode. */ \
- (F_ISSET(sp, S_EX))
-#define IN_VI_MODE(sp) /* If in vi mode. */ \
- (F_ISSET(sp, S_VI_CURSES | S_VI_XAW))
-#define S_SCREENS /* Screens. */ \
- (S_EX | S_VI_CURSES | S_VI_XAW)
-
-/* Major screen/file changes. */
-#define S_EXIT 0x0000008 /* Exiting (not forced). */
-#define S_EXIT_FORCE 0x0000010 /* Exiting (forced). */
-#define S_FSWITCH 0x0000020 /* Switch files. */
-#define S_SSWITCH 0x0000040 /* Switch screens. */
-#define S_MAJOR_CHANGE /* Screen or file changes. */ \
- (S_EXIT | S_EXIT_FORCE | S_FSWITCH | S_SSWITCH)
-
-#define S_ARGNOFREE 0x0000080 /* Argument list wasn't allocated. */
-#define S_ARGRECOVER 0x0000100 /* Argument list is recovery files. */
-#define S_BELLSCHED 0x0000200 /* Bell scheduled. */
-#define S_CONTINUE 0x0000400 /* Need to ask the user to continue. */
-#define S_EXSILENT 0x0000800 /* Ex batch script. */
-#define S_GLOBAL 0x0001000 /* Doing a global command. */
-#define S_INPUT 0x0002000 /* Doing text input. */
-#define S_INTERRUPTED 0x0004000 /* If have been interrupted. */
-#define S_INTERRUPTIBLE 0x0008000 /* If can be interrupted. */
-#define S_IVIDEO 0x0010000 /* Display in inverse video. */
-#define S_REDRAW 0x0020000 /* Redraw the screen. */
-#define S_REFORMAT 0x0040000 /* Reformat the screen. */
-#define S_REFRESH 0x0080000 /* Refresh the screen. */
-#define S_RENUMBER 0x0100000 /* Renumber the screen. */
-#define S_RESIZE 0x0200000 /* Resize the screen. */
-#define S_SCRIPT 0x0400000 /* Window is a shell script. */
-#define S_SRE_SET 0x0800000 /* The search RE has been set. */
-#define S_SUBRE_SET 0x1000000 /* The substitute RE has been set. */
-#define S_UPDATE_MODE 0x2000000 /* Don't repaint modeline. */
-#define S_VLITONLY 0x4000000 /* ^V literal next only. */
- u_int32_t flags;
-};
-
-/*
- * Signals/timers have no structure, so it's all here.
- *
- * Block all signals that are being handled. Used to keep the underlying DB
- * system calls from being interrupted and not restarted, as it could cause
- * consistency problems. Also used when vi forks child processes, to avoid
- * a signal arriving after the fork and before the exec, causing both parent
- * and child to attempt recovery processing.
- */
-#define SIGBLOCK(gp) \
- (void)sigprocmask(SIG_BLOCK, &(gp)->blockset, NULL);
-#define SIGUNBLOCK(gp) \
- (void)sigprocmask(SIG_UNBLOCK, &(gp)->blockset, NULL);
-
-void busy_off __P((SCR *));
-int busy_on __P((SCR *, char const *));
-void sig_end __P((void));
-int sig_init __P((SCR *));
-
-/* Generic routines to start/stop a screen. */
-int screen_end __P((SCR *));
-int screen_init __P((SCR *, SCR **, u_int));
-
-/* Public interfaces to the underlying screens. */
-int ex_screen_copy __P((SCR *, SCR *));
-int ex_screen_end __P((SCR *));
-int ex_screen_init __P((SCR *));
-int sex_screen_copy __P((SCR *, SCR *));
-int sex_screen_end __P((SCR *));
-int sex_screen_init __P((SCR *));
-int svi_screen_copy __P((SCR *, SCR *));
-int svi_screen_end __P((SCR *));
-int svi_screen_init __P((SCR *));
-int v_screen_copy __P((SCR *, SCR *));
-int v_screen_end __P((SCR *));
-int v_screen_init __P((SCR *));
-int xaw_screen_copy __P((SCR *, SCR *));
-int xaw_screen_end __P((SCR *));
-int xaw_screen_init __P((SCR *));
diff --git a/usr.bin/vi/common/search.c b/usr.bin/vi/common/search.c
deleted file mode 100644
index 72d9e4b2b9de..000000000000
--- a/usr.bin/vi/common/search.c
+++ /dev/null
@@ -1,833 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)search.c 8.46 (Berkeley) 7/2/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-
-static int check_delta __P((SCR *, EXF *, long, recno_t));
-static int ctag_conv __P((SCR *, char **, int *));
-static int get_delta __P((SCR *, char **, long *, u_int *));
-static int resetup __P((SCR *, regex_t **, enum direction,
- char *, char **, long *, u_int *));
-
-/*
- * resetup --
- * Set up a search for a regular expression.
- */
-static int
-resetup(sp, rep, dir, ptrn, epp, deltap, flagp)
- SCR *sp;
- regex_t **rep;
- enum direction dir;
- char *ptrn, **epp;
- long *deltap;
- u_int *flagp;
-{
- u_int flags;
- int delim, eval, re_flags, replaced;
- char *p, *t;
-
- /* Set return information the default. */
- *deltap = 0;
-
- /*
- * Use saved pattern if no pattern supplied, or if only a delimiter
- * character is supplied. Only the pattern was saved, historic vi
- * did not reuse any delta supplied.
- */
- flags = *flagp;
- if (ptrn == NULL)
- goto prev;
- if (ptrn[1] == '\0') {
- if (epp != NULL)
- *epp = ptrn + 1;
- goto prev;
- }
- if (ptrn[0] == ptrn[1] && ptrn[2] == '\0') {
- if (epp != NULL)
- *epp = ptrn + 2;
-prev: if (!F_ISSET(sp, S_SRE_SET)) {
- msgq(sp, M_ERR, "No previous search pattern");
- return (1);
- }
- *rep = &sp->sre;
-
- /* Empty patterns set the direction. */
- if (LF_ISSET(SEARCH_SET)) {
- F_SET(sp, S_SRE_SET);
- sp->searchdir = dir;
- sp->sre = **rep;
- }
- return (0);
- }
-
- re_flags = 0; /* Set RE flags. */
- if (O_ISSET(sp, O_EXTENDED))
- re_flags |= REG_EXTENDED;
- if (O_ISSET(sp, O_IGNORECASE))
- re_flags |= REG_ICASE;
-
- replaced = 0;
- if (LF_ISSET(SEARCH_PARSE)) { /* Parse the string. */
- /* Set delimiter. */
- delim = *ptrn++;
-
- /* Find terminating delimiter, handling escaped delimiters. */
- for (p = t = ptrn;;) {
- if (p[0] == '\0' || p[0] == delim) {
- if (p[0] == delim)
- ++p;
- *t = '\0';
- break;
- }
- if (p[1] == delim && p[0] == '\\')
- ++p;
- *t++ = *p++;
- }
-
- /*
- * If characters after the terminating delimiter, it may
- * be an error, or may be an offset. In either case, we
- * return the end of the string, whatever it may be.
- */
- if (*p) {
- if (get_delta(sp, &p, deltap, flagp))
- return (1);
- if (*p && LF_ISSET(SEARCH_TERM)) {
- msgq(sp, M_ERR,
- "Characters after search string and/or delta");
- return (1);
- }
- }
- if (epp != NULL)
- *epp = p;
-
- /* Check for "/ " or other such silliness. */
- if (*ptrn == '\0')
- goto prev;
-
- if (re_conv(sp, &ptrn, &replaced))
- return (1);
- } else if (LF_ISSET(SEARCH_TAG)) {
- if (ctag_conv(sp, &ptrn, &replaced))
- return (1);
- re_flags &= ~(REG_EXTENDED | REG_ICASE);
- }
-
- /* Compile the RE. */
- if (eval = regcomp(*rep, ptrn, re_flags))
- re_error(sp, eval, *rep);
- else if (LF_ISSET(SEARCH_SET)) {
- F_SET(sp, S_SRE_SET);
- sp->searchdir = dir;
- sp->sre = **rep;
- }
-
- /* Free up any extra memory. */
- if (replaced)
- FREE_SPACE(sp, ptrn, 0);
- return (eval);
-}
-
-/*
- * ctag_conv --
- * Convert a tags search path into something that the POSIX
- * 1003.2 RE functions can handle.
- */
-static int
-ctag_conv(sp, ptrnp, replacedp)
- SCR *sp;
- char **ptrnp;
- int *replacedp;
-{
- size_t blen, len;
- int lastdollar;
- char *bp, *p, *t;
-
- *replacedp = 0;
-
- len = strlen(p = *ptrnp);
-
- /* Max memory usage is 2 times the length of the string. */
- GET_SPACE_RET(sp, bp, blen, len * 2);
-
- t = bp;
-
- /* The last character is a '/' or '?', we just strip it. */
- if (p[len - 1] == '/' || p[len - 1] == '?')
- p[len - 1] = '\0';
-
- /* The next-to-last character is a '$', and it's magic. */
- if (p[len - 2] == '$') {
- lastdollar = 1;
- p[len - 2] = '\0';
- } else
- lastdollar = 0;
-
- /* The first character is a '/' or '?', we just strip it. */
- if (p[0] == '/' || p[0] == '?')
- ++p;
-
- /* The second character is a '^', and it's magic. */
- if (p[0] == '^')
- *t++ = *p++;
-
- /*
- * Escape every other magic character we can find, stripping the
- * backslashes ctags inserts to escape the search delimiter
- * characters.
- */
- while (p[0]) {
- /* Ctags escapes the search delimiter characters. */
- if (p[0] == '\\' && (p[1] == '/' || p[1] == '?'))
- ++p;
- else if (strchr("^.[]$*", p[0]))
- *t++ = '\\';
- *t++ = *p++;
- }
- if (lastdollar)
- *t++ = '$';
- *t++ = '\0';
-
- *ptrnp = bp;
- *replacedp = 1;
- return (0);
-}
-
-#define EMPTYMSG "File empty; nothing to search"
-#define EOFMSG "Reached end-of-file without finding the pattern"
-#define NOTFOUND "Pattern not found"
-#define SOFMSG "Reached top-of-file without finding the pattern"
-#define WRAPMSG "Search wrapped"
-
-int
-f_search(sp, ep, fm, rm, ptrn, eptrn, flagp)
- SCR *sp;
- EXF *ep;
- MARK *fm, *rm;
- char *ptrn, **eptrn;
- u_int *flagp;
-{
- regmatch_t match[1];
- regex_t *re, lre;
- recno_t lno;
- size_t coff, len;
- long delta;
- u_int flags;
- int btear, eval, rval, wrapped;
- char *l;
-
- if (file_lline(sp, ep, &lno))
- return (1);
- flags = *flagp;
- if (lno == 0) {
- if (LF_ISSET(SEARCH_MSG))
- msgq(sp, M_INFO, EMPTYMSG);
- return (1);
- }
-
- re = &lre;
- if (resetup(sp, &re, FORWARD, ptrn, eptrn, &delta, flagp))
- return (1);
-
- /*
- * Start searching immediately after the cursor. If at the end of the
- * line, start searching on the next line. This is incompatible (read
- * bug fix) with the historic vi -- searches for the '$' pattern never
- * moved forward, and "-t foo" didn't work if "foo" was the first thing
- * in the file.
- */
- if (LF_ISSET(SEARCH_FILE)) {
- lno = 1;
- coff = 0;
- } else {
- if ((l = file_gline(sp, ep, fm->lno, &len)) == NULL) {
- GETLINE_ERR(sp, fm->lno);
- return (1);
- }
- if (fm->cno + 1 >= len) {
- if (fm->lno == lno) {
- if (!O_ISSET(sp, O_WRAPSCAN)) {
- if (LF_ISSET(SEARCH_MSG))
- msgq(sp, M_INFO, EOFMSG);
- return (1);
- }
- lno = 1;
- } else
- lno = fm->lno + 1;
- coff = 0;
- } else {
- lno = fm->lno;
- coff = fm->cno + 1;
- }
- }
-
- /* Turn on busy message. */
- btear = F_ISSET(sp, S_EXSILENT) ? 0 : !busy_on(sp, "Searching...");
-
- for (rval = 1, wrapped = 0;; ++lno, coff = 0) {
- if (INTERRUPTED(sp)) {
- msgq(sp, M_INFO, "Interrupted.");
- break;
- }
- if (wrapped && lno > fm->lno ||
- (l = file_gline(sp, ep, lno, &len)) == NULL) {
- if (wrapped) {
- if (LF_ISSET(SEARCH_MSG))
- msgq(sp, M_INFO, NOTFOUND);
- break;
- }
- if (!O_ISSET(sp, O_WRAPSCAN)) {
- if (LF_ISSET(SEARCH_MSG))
- msgq(sp, M_INFO, EOFMSG);
- break;
- }
- lno = 0;
- wrapped = 1;
- continue;
- }
-
- /* If already at EOL, just keep going. */
- if (len && coff == len)
- continue;
-
- /* Set the termination. */
- match[0].rm_so = coff;
- match[0].rm_eo = len;
-
-#if defined(DEBUG) && 0
- TRACE(sp, "F search: %lu from %u to %u\n",
- lno, coff, len ? len - 1 : len);
-#endif
- /* Search the line. */
- eval = regexec(re, l, 1, match,
- (match[0].rm_so == 0 ? 0 : REG_NOTBOL) | REG_STARTEND);
- if (eval == REG_NOMATCH)
- continue;
- if (eval != 0) {
- re_error(sp, eval, re);
- break;
- }
-
- /* Warn if wrapped. */
- if (wrapped && O_ISSET(sp, O_WARN) && LF_ISSET(SEARCH_MSG))
- msgq(sp, M_VINFO, WRAPMSG);
-
- /*
- * If an offset, see if it's legal. It's possible to match
- * past the end of the line with $, so check for that case.
- */
- if (delta) {
- if (check_delta(sp, ep, delta, lno))
- break;
- rm->lno = delta + lno;
- rm->cno = 0;
- } else {
-#if defined(DEBUG) && 0
- TRACE(sp, "found: %qu to %qu\n",
- match[0].rm_so, match[0].rm_eo);
-#endif
- rm->lno = lno;
- rm->cno = match[0].rm_so;
-
- /*
- * If a change command, it's possible to move beyond
- * the end of a line. Historic vi generally got this
- * wrong (try "c?$<cr>"). Not all that sure this gets
- * it right, there are lots of strange cases.
- */
- if (!LF_ISSET(SEARCH_EOL) && rm->cno >= len)
- rm->cno = len ? len - 1 : 0;
- }
- rval = 0;
- break;
- }
-
- /* Turn off busy message, interrupts. */
- if (btear)
- busy_off(sp);
- return (rval);
-}
-
-int
-b_search(sp, ep, fm, rm, ptrn, eptrn, flagp)
- SCR *sp;
- EXF *ep;
- MARK *fm, *rm;
- char *ptrn, **eptrn;
- u_int *flagp;
-{
- regmatch_t match[1];
- regex_t *re, lre;
- recno_t lno;
- size_t coff, len, last;
- long delta;
- u_int flags;
- int btear, eval, rval, wrapped;
- char *l;
-
- if (file_lline(sp, ep, &lno))
- return (1);
- flags = *flagp;
- if (lno == 0) {
- if (LF_ISSET(SEARCH_MSG))
- msgq(sp, M_INFO, EMPTYMSG);
- return (1);
- }
-
- re = &lre;
- if (resetup(sp, &re, BACKWARD, ptrn, eptrn, &delta, flagp))
- return (1);
-
- /* If in the first column, start searching on the previous line. */
- if (fm->cno == 0) {
- if (fm->lno == 1) {
- if (!O_ISSET(sp, O_WRAPSCAN)) {
- if (LF_ISSET(SEARCH_MSG))
- msgq(sp, M_INFO, SOFMSG);
- return (1);
- }
- } else
- lno = fm->lno - 1;
- } else
- lno = fm->lno;
-
- /* Turn on busy message. */
- btear = F_ISSET(sp, S_EXSILENT) ? 0 : !busy_on(sp, "Searching...");
-
- for (rval = 1, wrapped = 0, coff = fm->cno;; --lno, coff = 0) {
- if (INTERRUPTED(sp)) {
- msgq(sp, M_INFO, "Interrupted.");
- break;
- }
- if (wrapped && lno < fm->lno || lno == 0) {
- if (wrapped) {
- if (LF_ISSET(SEARCH_MSG))
- msgq(sp, M_INFO, NOTFOUND);
- break;
- }
- if (!O_ISSET(sp, O_WRAPSCAN)) {
- if (LF_ISSET(SEARCH_MSG))
- msgq(sp, M_INFO, SOFMSG);
- break;
- }
- if (file_lline(sp, ep, &lno))
- goto err;
- if (lno == 0) {
- if (LF_ISSET(SEARCH_MSG))
- msgq(sp, M_INFO, EMPTYMSG);
- break;
- }
- ++lno;
- wrapped = 1;
- continue;
- }
-
- if ((l = file_gline(sp, ep, lno, &len)) == NULL)
- goto err;
-
- /* Set the termination. */
- match[0].rm_so = 0;
- match[0].rm_eo = len;
-
-#if defined(DEBUG) && 0
- TRACE(sp, "B search: %lu from 0 to %qu\n", lno, match[0].rm_eo);
-#endif
- /* Search the line. */
- eval = regexec(re, l, 1, match,
- (match[0].rm_eo == len ? 0 : REG_NOTEOL) | REG_STARTEND);
- if (eval == REG_NOMATCH)
- continue;
- if (eval != 0) {
- re_error(sp, eval, re);
- break;
- }
-
- /* Check for a match starting past the cursor. */
- if (coff != 0 && match[0].rm_so >= coff)
- continue;
-
- /* Warn if wrapped. */
- if (wrapped && O_ISSET(sp, O_WARN) && LF_ISSET(SEARCH_MSG))
- msgq(sp, M_VINFO, WRAPMSG);
-
- if (delta) {
- if (check_delta(sp, ep, delta, lno))
- break;
- rm->lno = delta + lno;
- rm->cno = 0;
- } else {
-#if defined(DEBUG) && 0
- TRACE(sp, "found: %qu to %qu\n",
- match[0].rm_so, match[0].rm_eo);
-#endif
- /*
- * We now have the first match on the line. Step
- * through the line character by character until we
- * find the last acceptable match. This is painful,
- * we need a better interface to regex to make this
- * work.
- */
- for (;;) {
- last = match[0].rm_so++;
- if (match[0].rm_so >= len)
- break;
- match[0].rm_eo = len;
- eval = regexec(re, l, 1, match,
- (match[0].rm_so == 0 ? 0 : REG_NOTBOL) |
- REG_STARTEND);
- if (eval == REG_NOMATCH)
- break;
- if (eval != 0) {
- re_error(sp, eval, re);
- goto err;
- }
- if (coff && match[0].rm_so >= coff)
- break;
- }
- rm->lno = lno;
-
- /* See comment in f_search(). */
- if (!LF_ISSET(SEARCH_EOL) && last >= len)
- rm->cno = len ? len - 1 : 0;
- else
- rm->cno = last;
- }
- rval = 0;
- break;
- }
-
- /* Turn off busy message, interrupts. */
-err: if (btear)
- busy_off(sp);
- return (rval);
-}
-
-/*
- * re_conv --
- * Convert vi's regular expressions into something that the
- * the POSIX 1003.2 RE functions can handle.
- *
- * There are three conversions we make to make vi's RE's (specifically
- * the global, search, and substitute patterns) work with POSIX RE's.
- *
- * 1: If O_MAGIC is not set, strip backslashes from the magic character
- * set (.[]*~) that have them, and add them to the ones that don't.
- * 2: If O_MAGIC is not set, the string "\~" is replaced with the text
- * from the last substitute command's replacement string. If O_MAGIC
- * is set, it's the string "~".
- * 3: The pattern \<ptrn\> does "word" searches, convert it to use the
- * new RE escapes.
- */
-int
-re_conv(sp, ptrnp, replacedp)
- SCR *sp;
- char **ptrnp;
- int *replacedp;
-{
- size_t blen, needlen;
- int magic;
- char *bp, *p, *t;
-
- /*
- * First pass through, we figure out how much space we'll need.
- * We do it in two passes, on the grounds that most of the time
- * the user is doing a search and won't have magic characters.
- * That way we can skip the malloc and memmove's.
- */
- for (p = *ptrnp, magic = 0, needlen = 0; *p != '\0'; ++p)
- switch (*p) {
- case '\\':
- switch (*++p) {
- case '<':
- magic = 1;
- needlen += sizeof(RE_WSTART);
- break;
- case '>':
- magic = 1;
- needlen += sizeof(RE_WSTOP);
- break;
- case '~':
- if (!O_ISSET(sp, O_MAGIC)) {
- magic = 1;
- needlen += sp->repl_len;
- }
- break;
- case '.':
- case '[':
- case ']':
- case '*':
- if (!O_ISSET(sp, O_MAGIC)) {
- magic = 1;
- needlen += 1;
- }
- break;
- default:
- needlen += 2;
- }
- break;
- case '~':
- if (O_ISSET(sp, O_MAGIC)) {
- magic = 1;
- needlen += sp->repl_len;
- }
- break;
- case '.':
- case '[':
- case ']':
- case '*':
- if (!O_ISSET(sp, O_MAGIC)) {
- magic = 1;
- needlen += 2;
- }
- break;
- default:
- needlen += 1;
- break;
- }
-
- if (!magic) {
- *replacedp = 0;
- return (0);
- }
-
- /*
- * Get enough memory to hold the final pattern.
- *
- * XXX
- * It's nul-terminated, for now.
- */
- GET_SPACE_RET(sp, bp, blen, needlen + 1);
-
- for (p = *ptrnp, t = bp; *p != '\0'; ++p)
- switch (*p) {
- case '\\':
- switch (*++p) {
- case '<':
- memmove(t, RE_WSTART, sizeof(RE_WSTART) - 1);
- t += sizeof(RE_WSTART) - 1;
- break;
- case '>':
- memmove(t, RE_WSTOP, sizeof(RE_WSTOP) - 1);
- t += sizeof(RE_WSTOP) - 1;
- break;
- case '~':
- if (O_ISSET(sp, O_MAGIC))
- *t++ = '~';
- else {
- memmove(t, sp->repl, sp->repl_len);
- t += sp->repl_len;
- }
- break;
- case '.':
- case '[':
- case ']':
- case '*':
- if (O_ISSET(sp, O_MAGIC))
- *t++ = '\\';
- *t++ = *p;
- break;
- default:
- *t++ = '\\';
- *t++ = *p;
- }
- break;
- case '~':
- if (O_ISSET(sp, O_MAGIC)) {
- memmove(t, sp->repl, sp->repl_len);
- t += sp->repl_len;
- } else
- *t++ = '~';
- break;
- case '.':
- case '[':
- case ']':
- case '*':
- if (!O_ISSET(sp, O_MAGIC))
- *t++ = '\\';
- *t++ = *p;
- break;
- default:
- *t++ = *p;
- break;
- }
- *t = '\0';
-
- *ptrnp = bp;
- *replacedp = 1;
- return (0);
-}
-
-/*
- * get_delta --
- * Get a line delta. The trickiness is that the delta can be pretty
- * complicated, i.e. "+3-2+3++- ++" is allowed.
- *
- * !!!
- * In historic vi, if you had a delta on a search pattern which was used as
- * a motion command, the command became a line mode command regardless of the
- * cursor positions. A fairly common trick is to use a delta of "+0" to make
- * the command a line mode command. This is the only place that knows about
- * delta's, so we set the return flag information here.
- */
-static int
-get_delta(sp, dp, valp, flagp)
- SCR *sp;
- char **dp;
- long *valp;
- u_int *flagp;
-{
- char *p;
- long val, tval;
-
- for (tval = 0, p = *dp; *p != '\0'; *flagp |= SEARCH_DELTA) {
- if (isblank(*p)) {
- ++p;
- continue;
- }
- if (*p == '+' || *p == '-') {
- if (!isdigit(*(p + 1))) {
- if (*p == '+') {
- if (tval == LONG_MAX)
- goto overflow;
- ++tval;
- } else {
- if (tval == LONG_MIN)
- goto underflow;
- --tval;
- }
- ++p;
- continue;
- }
- } else
- if (!isdigit(*p))
- break;
-
- errno = 0;
- val = strtol(p, &p, 10);
- if (errno == ERANGE) {
- if (val == LONG_MAX)
-overflow: msgq(sp, M_ERR, "Delta value overflow");
- else if (val == LONG_MIN)
-underflow: msgq(sp, M_ERR, "Delta value underflow");
- else
- msgq(sp, M_SYSERR, NULL);
- return (1);
- }
- if (val >= 0) {
- if (LONG_MAX - val < tval)
- goto overflow;
- } else
- if (-(LONG_MIN - tval) > val)
- goto underflow;
- tval += val;
- }
- *dp = p;
- *valp = tval;
- return (0);
-}
-
-/*
- * check_delta --
- * Check a line delta to see if it's legal.
- */
-static int
-check_delta(sp, ep, delta, lno)
- SCR *sp;
- EXF *ep;
- long delta;
- recno_t lno;
-{
- /* A delta can overflow a record number. */
- if (delta < 0) {
- if (lno < LONG_MAX && delta >= (long)lno) {
- msgq(sp, M_ERR, "Search offset before line 1");
- return (1);
- }
- } else {
- if (ULONG_MAX - lno < delta) {
- msgq(sp, M_ERR, "Delta value overflow");
- return (1);
- }
- if (file_gline(sp, ep, lno + delta, NULL) == NULL) {
- msgq(sp, M_ERR, "Search offset past end-of-file");
- return (1);
- }
- }
- return (0);
-}
-
-/*
- * re_error --
- * Report a regular expression error.
- */
-void
-re_error(sp, errcode, preg)
- SCR *sp;
- int errcode;
- regex_t *preg;
-{
- size_t s;
- char *oe;
-
- s = regerror(errcode, preg, "", 0);
- if ((oe = malloc(s)) == NULL)
- msgq(sp, M_SYSERR, NULL);
- else {
- (void)regerror(errcode, preg, oe, s);
- msgq(sp, M_ERR, "RE error: %s", oe);
- }
- free(oe);
-}
diff --git a/usr.bin/vi/common/search.h b/usr.bin/vi/common/search.h
deleted file mode 100644
index 1483a04c7b71..000000000000
--- a/usr.bin/vi/common/search.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)search.h 8.9 (Berkeley) 3/16/94
- */
-
-#define RE_WSTART "[[:<:]]" /* Not-in-word search patterns. */
-#define RE_WSTOP "[[:>:]]"
-
-#define SEARCH_DELTA 0x001 /* A delta part of the search.*/
-#define SEARCH_EOL 0x002 /* Offset past EOL is okay. */
-#define SEARCH_FILE 0x004 /* Search the entire file. */
-#define SEARCH_MSG 0x008 /* Display search warning messages. */
-#define SEARCH_PARSE 0x010 /* Parse the search pattern. */
-#define SEARCH_SET 0x020 /* Set search direction. */
-#define SEARCH_TAG 0x040 /* Search pattern is a tag pattern. */
-#define SEARCH_TERM 0x080 /* Search pattern should terminate. */
-
-enum direction { NOTSET, FORWARD, BACKWARD };
-
-/* Search functions. */
-int b_search __P((SCR *, EXF *, MARK *, MARK *, char *, char **, u_int *));
-int f_search __P((SCR *, EXF *, MARK *, MARK *, char *, char **, u_int *));
-int re_conv __P((SCR *, char **, int *));
-void re_error __P((SCR *, int, regex_t *));
diff --git a/usr.bin/vi/common/seq.h b/usr.bin/vi/common/seq.h
deleted file mode 100644
index 38c197cd7543..000000000000
--- a/usr.bin/vi/common/seq.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)seq.h 8.11 (Berkeley) 7/17/94
- */
-
-/*
- * Map and abbreviation structures.
- *
- * The map structure is doubly linked list, sorted by input string and by
- * input length within the string. (The latter is necessary so that short
- * matches will happen before long matches when the list is searched.)
- * Additionally, there is a bitmap which has bits set if there are entries
- * starting with the corresponding character. This keeps us from walking
- * the list unless it's necessary.
- *
- * The name and the output fields of a SEQ can be empty, i.e. NULL.
- * Only the input field is required.
- *
- * XXX
- * The fast-lookup bits are never turned off -- users don't usually unmap
- * things, though, so it's probably not a big deal.
- */
- /* Sequence type. */
-enum seqtype { SEQ_ABBREV, SEQ_COMMAND, SEQ_INPUT };
-
-struct _seq {
- LIST_ENTRY(_seq) q; /* Linked list of all sequences. */
- enum seqtype stype; /* Sequence type. */
- char *name; /* Sequence name (if any). */
- size_t nlen; /* Name length. */
- char *input; /* Sequence input keys. */
- size_t ilen; /* Input keys length. */
- char *output; /* Sequence output keys. */
- size_t olen; /* Output keys length. */
-
-#define SEQ_FUNCMAP 0x01 /* If unresolved function key.*/
-#define SEQ_SCREEN 0x02 /* If screen specific. */
-#define SEQ_USERDEF 0x04 /* If user defined. */
- u_int8_t flags;
-};
-
-int seq_delete __P((SCR *, char *, size_t, enum seqtype));
-int seq_dump __P((SCR *, enum seqtype, int));
-SEQ *seq_find __P((SCR *, SEQ **, char *, size_t, enum seqtype, int *));
-void seq_init __P((SCR *));
-int seq_mdel __P((SEQ *));
-int seq_save __P((SCR *, FILE *, char *, enum seqtype));
-int seq_set __P((SCR *, char *, size_t,
- char *, size_t, char *, size_t, enum seqtype, int));
diff --git a/usr.bin/vi/common/signal.c b/usr.bin/vi/common/signal.c
deleted file mode 100644
index 68f25891616c..000000000000
--- a/usr.bin/vi/common/signal.c
+++ /dev/null
@@ -1,569 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)signal.c 8.32 (Berkeley) 7/23/94";
-#endif /* not lint */
-
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-
-static void h_alrm __P((int));
-static void h_hup __P((int));
-static void h_int __P((int));
-static void h_term __P((int));
-static void h_winch __P((int));
-static void sig_sync __P((int, u_int));
-
-/*
- * There are seven normally asynchronous actions about which vi cares:
- * SIGALRM, SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGTSTP and SIGWINCH.
- *
- * The assumptions:
- * 1: The DB routines are not reentrant.
- * 2: The curses routines may not be reentrant.
- *
- * SIGALRM, SIGHUP, SIGTERM
- * Used for file recovery. The DB routines can't be reentered, so
- * the vi routines that call DB block all three signals (see line.c).
- * This means that DB routines can be called at interrupt time.
- *
- * SIGALRM
- * Used to paint busy messages on the screen. The curses routines
- * can't be reentered, so this function of SIGALRM can only be used
- * in sections of code that do not use any curses functions (see
- * busy_on, busy_off in signal.c). This means that curses can be
- * called at interrupt time.
- *
- * SIGQUIT
- * Disabled by the signal initialization routines. Historically,
- * ^\ switched vi into ex mode, and we continue that practice.
- *
- * SIGWINCH:
- * The interrupt routine sets a global bit which is checked by the
- * key-read routine, so there are no reentrancy issues. This means
- * that the screen will not resize until vi runs out of keys, but
- * that doesn't seem like a problem.
- *
- * SIGINT and SIGTSTP are a much more difficult issue to resolve. Vi has
- * to permit the user to interrupt long-running operations. Generally, a
- * search, substitution or read/write is done on a large file, or, the user
- * creates a key mapping with an infinite loop. This problem will become
- * worse as more complex semantics are added to vi. There are four major
- * solutions on the table, each of which have minor permutations.
- *
- * 1: Run in raw mode.
- *
- * The up side is that there's no asynchronous behavior to worry about,
- * and obviously no reentrancy problems. The down side is that it's easy
- * to misinterpret characters (e.g. :w big_file^Mi^V^C is going to look
- * like an interrupt) and it's easy to get into places where we won't see
- * interrupt characters (e.g. ":map a ixx^[hxxaXXX" infinitely loops in
- * historic implementations of vi). Periodically reading the terminal
- * input buffer might solve the latter problem, but it's not going to be
- * pretty.
- *
- * Also, we're going to be checking for ^C's and ^Z's both, all over
- * the place -- I hate to litter the source code with that. For example,
- * the historic version of vi didn't permit you to suspend the screen if
- * you were on the colon command line. This isn't right. ^Z isn't a vi
- * command, it's a terminal event. (Dammit.)
- *
- * 2: Run in cbreak mode. There are two problems in this area. First, the
- * current curses implementations (both System V and Berkeley) don't give
- * you clean cbreak modes. For example, the IEXTEN bit is left on, turning
- * on DISCARD and LNEXT. To clarify, what vi WANTS is 8-bit clean, with
- * the exception that flow control and signals are turned on, and curses
- * cbreak mode doesn't give you this.
- *
- * We can either set raw mode and twiddle the tty, or cbreak mode and
- * twiddle the tty. I chose to use raw mode, on the grounds that raw
- * mode is better defined and I'm less likely to be surprised by a curses
- * implementation down the road. The twiddling consists of setting ISIG,
- * IXON/IXOFF, and disabling some of the interrupt characters (see the
- * comments in svi/svi_screen.c). This is all found in historic System
- * V (SVID 3) and POSIX 1003.1-1992, so it should be fairly portable.
- *
- * The second problem is that vi permits you to enter literal signal
- * characters, e.g. ^V^C. There are two possible solutions. First, you
- * can turn off signals when you get a ^V, but that means that a network
- * packet containing ^V and ^C will lose, since the ^C may take effect
- * before vi reads the ^V. (This is particularly problematic if you're
- * talking over a protocol that recognizes signals locally and sends OOB
- * packets when it sees them.) Second, you can turn the ^C into a literal
- * character in vi, but that means that there's a race between entering
- * ^V<character>^C, i.e. the sequence may end up being ^V^C<character>.
- * Also, the second solution doesn't work for flow control characters, as
- * they aren't delivered to the program as signals.
- *
- * Generally, this is what historic vi did. (It didn't have the curses
- * problems because it didn't use curses.) It entered signals following
- * ^V characters into the input stream, (which is why there's no way to
- * enter a literal flow control character).
- *
- * 3: Run in mostly raw mode; turn signals on when doing an operation the
- * user might want to interrupt, but leave them off most of the time.
- *
- * This works well for things like file reads and writes. This doesn't
- * work well for trying to detect infinite maps. The problem is that
- * you can write the code so that you don't have to turn on interrupts
- * per keystroke, but the code isn't pretty and it's hard to make sure
- * that an optimization doesn't cover up an infinite loop. This also
- * requires interaction or state between the vi parser and the key
- * reading routines, as an infinite loop may still be returning keys
- * to the parser.
- *
- * Also, if the user inserts an interrupt into the tty queue while the
- * interrupts are turned off, the key won't be treated as an interrupt,
- * and requiring the user to pound the keyboard to catch an interrupt
- * window is nasty.
- *
- * 4: Run in mostly raw mode, leaving signals on all of the time. Done
- * by setting raw mode, and twiddling the tty's termios ISIG bit.
- *
- * This works well for the interrupt cases, because the code only has
- * to check to see if the interrupt flag has been set, and can otherwise
- * ignore signals. It's also less likely that we'll miss a case, and we
- * don't have to worry about synchronizing between the vi parser and the
- * key read routines.
- *
- * The down side is that we have to turn signals off if the user wants
- * to enter a literal character (e.g. ^V^C). If the user enters the
- * combination fast enough, or as part of a single network packet,
- * the text input routines will treat it as a signal instead of as a
- * literal character. To some extent, we have this problem already,
- * since we turn off flow control so that the user can enter literal
- * XON/XOFF characters.
- *
- * This is probably the easiest to code, and provides the smoothest
- * programming interface.
- *
- * There are a couple of other problems to consider.
- *
- * First, System V's curses doesn't handle SIGTSTP correctly. If you use the
- * newterm() interface, the TSTP signal will leave you in raw mode, and the
- * final endwin() will leave you in the correct shell mode. If you use the
- * initscr() interface, the TSTP signal will return you to the correct shell
- * mode, but the final endwin() will leave you in raw mode. There you have
- * it: proof that drug testing is not making any significant headway in the
- * computer industry. The 4BSD curses is deficient in that it does not have
- * an interface to the terminal keypad. So, regardless, we have to do our
- * own SIGTSTP handling.
- *
- * The problem with this is that if we do our own SIGTSTP handling, in either
- * models #3 or #4, we're going to have to call curses routines at interrupt
- * time, which means that we might be reentering curses, which is something we
- * don't want to do.
- *
- * Second, SIGTSTP has its own little problems. It's broadcast to the entire
- * process group, not sent to a single process. The scenario goes something
- * like this: the shell execs the mail program, which execs vi. The user hits
- * ^Z, and all three programs get the signal, in some random order. The mail
- * program goes to sleep immediately (since it probably didn't have a SIGTSTP
- * handler in place). The shell gets a SIGCHLD, does a wait, and finds out
- * that the only child in its foreground process group (of which it's aware)
- * is asleep. It then optionally resets the terminal (because the modes aren't
- * how it left them), and starts prompting the user for input. The problem is
- * that somewhere in the middle of all of this, vi is resetting the terminal,
- * and getting ready to send a SIGTSTP to the process group in order to put
- * itself to sleep. There's a solution to all of this: when vi starts, it puts
- * itself into its own process group, and then only it (and possible child
- * processes) receive the SIGTSTP. This permits it to clean up the terminal
- * and switch back to the original process group, where it sends that process
- * group a SIGTSTP, putting everyone to sleep and waking the shell.
- *
- * Third, handing SIGTSTP asynchronously is further complicated by the child
- * processes vi may fork off. If vi calls ex, ex resets the terminal and
- * starts running some filter, and SIGTSTP stops them both, vi has to know
- * when it restarts that it can't repaint the screen until ex's child has
- * finished running. This is solveable, but it's annoying.
- *
- * Well, somebody had to make a decision, and this is the way it's going to be
- * (unless I get talked out of it). SIGINT is handled asynchronously, so
- * that we can pretty much guarantee that the user can interrupt any operation
- * at any time. SIGTSTP is handled synchronously, so that we don't have to
- * reenter curses and so that we don't have to play the process group games.
- * ^Z is recognized in the standard text input and command modes. (^Z should
- * also be recognized during operations that may potentially take a long time.
- * The simplest solution is probably to twiddle the tty, install a handler for
- * SIGTSTP, and then restore normal tty modes when the operation is complete.)
- */
-
-/*
- * sig_init --
- * Initialize signals.
- */
-int
-sig_init(sp)
- SCR *sp;
-{
- GS *gp;
- struct sigaction act;
-
- /* Initialize the signals. */
- gp = sp->gp;
- (void)sigemptyset(&gp->blockset);
-
- /*
- * Use sigaction(2), not signal(3), since we don't always want to
- * restart system calls. The example is when waiting for a command
- * mode keystroke and SIGWINCH arrives. Try to set the restart bit
- * (SA_RESTART) on SIGALRM anyway, it should result in a lot fewer
- * interruptions. We also block every other signal that we can block
- * when a signal arrives. This is because the signal functions call
- * other nvi functions, which aren't guaranteed to be reentrant.
- */
-
-#ifndef SA_RESTART
-#define SA_RESTART 0
-#endif
-#define SETSIG(signal, flags, handler) { \
- if (sigaddset(&gp->blockset, signal)) \
- goto err; \
- act.sa_handler = handler; \
- sigfillset(&act.sa_mask); \
- act.sa_flags = flags; \
- if (sigaction(signal, &act, NULL)) \
- goto err; \
-}
- SETSIG(SIGALRM, SA_RESTART, h_alrm);
- SETSIG(SIGHUP, 0, h_hup);
- SETSIG(SIGINT, 0, h_int);
- SETSIG(SIGTERM, 0, h_term);
- SETSIG(SIGWINCH, 0, h_winch);
- return (0);
-
-err: msgq(sp, M_SYSERR, "signal init");
- return (1);
-}
-
-/*
- * sig_end --
- * End signal setup.
- */
-void
-sig_end()
-{
- /*
- * POSIX 1003.1-1990 requires that fork (and, presumably, vfork) clear
- * pending alarms, and that the exec functions clear pending signals.
- * In addition, after an exec, the child continues to ignore signals
- * ignored in the parent, and the child's action for signals caught in
- * the parent is set to the default action. So, as we currently don't
- * ignore any signals, there's no cleanup to be done. This routine is
- * left here as a stub function.
- */
- return;
-}
-
-/*
- * busy_on --
- * Set a busy message timer.
- */
-int
-busy_on(sp, msg)
- SCR *sp;
- char const *msg;
-{
- struct itimerval value;
- struct timeval tod;
-
- /*
- * Give the oldest busy message precedence, since it's
- * the longer running operation.
- */
- if (sp->busy_msg != NULL)
- return (1);
-
- /* Get the current time of day, and create a target time. */
- if (gettimeofday(&tod, NULL))
- return (1);
-#define USER_PATIENCE_USECS (8 * 100000L)
- sp->busy_tod.tv_sec = tod.tv_sec;
- sp->busy_tod.tv_usec = tod.tv_usec + USER_PATIENCE_USECS;
-
- /* We depend on this being an atomic instruction. */
- sp->busy_msg = msg;
-
- /*
- * Busy messages turn around fast. Reset the timer regardless
- * of its current state.
- */
- value.it_value.tv_sec = 0;
- value.it_value.tv_usec = USER_PATIENCE_USECS;
- value.it_interval.tv_sec = 0;
- value.it_interval.tv_usec = 0;
- if (setitimer(ITIMER_REAL, &value, NULL))
- msgq(sp, M_SYSERR, "timer: setitimer");
- return (0);
-}
-
-/*
- * busy_off --
- * Turn off a busy message timer.
- */
-void
-busy_off(sp)
- SCR *sp;
-{
- /* We depend on this being an atomic instruction. */
- sp->busy_msg = NULL;
-}
-
-/*
- * rcv_on --
- * Turn on recovery timer.
- */
-int
-rcv_on(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- struct itimerval value;
- struct timeval tod;
-
- /* Get the current time of day. */
- if (gettimeofday(&tod, NULL))
- return (1);
-
- /* Create target time of day. */
- ep->rcv_tod.tv_sec = tod.tv_sec + RCV_PERIOD;
- ep->rcv_tod.tv_usec = 0;
-
- /*
- * If there's a busy message happening, we're done, the
- * interrupt handler will start our timer as necessary.
- */
- if (sp->busy_msg != NULL)
- return (0);
-
- value.it_value.tv_sec = RCV_PERIOD;
- value.it_value.tv_usec = 0;
- value.it_interval.tv_sec = 0;
- value.it_interval.tv_usec = 0;
- if (setitimer(ITIMER_REAL, &value, NULL)) {
- msgq(sp, M_SYSERR, "timer: setitimer");
- return (1);
- }
- return (0);
-}
-
-/*
- * h_alrm --
- * Handle SIGALRM.
- *
- * There are two uses of the ITIMER_REAL timer (SIGALRM) in nvi. The first
- * is to push the recovery information out to disk at periodic intervals.
- * The second is to display a "busy" message if an operation takes more time
- * that users are willing to wait before seeing something happen. The SCR
- * structure has a wall clock timer structure for each of these. Since the
- * busy timer has a much faster timeout than the recovery timer, most of the
- * code ignores the recovery timer unless it's the only thing running.
- *
- * XXX
- * It would be nice to reimplement this with two timers, a la POSIX 1003.1,
- * but not many systems offer them yet.
- */
-static void
-h_alrm(signo)
- int signo;
-{
- struct itimerval value;
- struct timeval ntod, tod;
- SCR *sp;
- EXF *ep;
- int sverrno;
-
- sverrno = errno;
-
- /* XXX: Get the current time of day; if this fails, we're dead. */
- if (gettimeofday(&tod, NULL))
- goto ret;
-
- /*
- * Fire any timers that are past due, or any that are due
- * in a tenth of a second or less.
- */
- for (ntod.tv_sec = 0, sp = __global_list->dq.cqh_first;
- sp != (void *)&__global_list->dq; sp = sp->q.cqe_next) {
-
- /* Check the busy timer if the msg pointer is set. */
- if (sp->busy_msg == NULL)
- goto skip_busy;
- if (sp->busy_tod.tv_sec > tod.tv_sec ||
- sp->busy_tod.tv_sec == tod.tv_sec &&
- sp->busy_tod.tv_usec > tod.tv_usec &&
- sp->busy_tod.tv_usec - tod.tv_usec > 100000L) {
- if (ntod.tv_sec == 0 ||
- ntod.tv_sec > sp->busy_tod.tv_sec ||
- ntod.tv_sec == sp->busy_tod.tv_sec &&
- ntod.tv_usec > sp->busy_tod.tv_usec)
- ntod = sp->busy_tod;
- } else {
- (void)sp->s_busy(sp, sp->busy_msg);
- sp->busy_msg = NULL;
- }
-
- /*
- * Sync the file if the recovery timer has fired. If
- * the sync fails, we don't reschedule future sync's.
- */
-skip_busy: ep = sp->ep;
- if (ep->rcv_tod.tv_sec < tod.tv_sec ||
- ep->rcv_tod.tv_sec == tod.tv_sec &&
- ep->rcv_tod.tv_usec < tod.tv_usec + 100000L) {
- if (rcv_sync(sp, ep, 0))
- continue;
- ep->rcv_tod = tod;
- ep->rcv_tod.tv_sec += RCV_PERIOD;
- }
- if (ntod.tv_sec == 0 ||
- ntod.tv_sec > ep->rcv_tod.tv_sec ||
- ntod.tv_sec == ep->rcv_tod.tv_sec &&
- ntod.tv_usec > ep->rcv_tod.tv_usec)
- ntod = ep->rcv_tod;
- }
-
- if (ntod.tv_sec == 0)
- goto ret;
-
- /* XXX: Set the timer; if this fails, we're dead. */
- value.it_value.tv_sec = ntod.tv_sec - tod.tv_sec;
- value.it_value.tv_usec = ntod.tv_usec - tod.tv_usec;
- value.it_interval.tv_sec = 0;
- value.it_interval.tv_usec = 0;
- (void)setitimer(ITIMER_REAL, &value, NULL);
-
-ret: errno = sverrno;
-}
-
-/*
- * h_hup --
- * Handle SIGHUP.
- */
-static void
-h_hup(signo)
- int signo;
-{
- sig_sync(SIGHUP, RCV_EMAIL);
- /* NOTREACHED */
-}
-
-/*
- * h_int --
- * Handle SIGINT.
- *
- * XXX
- * This isn't right if windows are independent of each other.
- */
-static void
-h_int(signo)
- int signo;
-{
- F_SET(__global_list, G_SIGINT);
-}
-
-/*
- * h_term --
- * Handle SIGTERM.
- */
-static void
-h_term(signo)
- int signo;
-{
- sig_sync(SIGTERM, 0);
- /* NOTREACHED */
-}
-
-/*
- * h_winch --
- * Handle SIGWINCH.
- *
- * XXX
- * This isn't right if windows are independent of each other.
- */
-static void
-h_winch(signo)
- int signo;
-{
- F_SET(__global_list, G_SIGWINCH);
-}
-
-
-/*
- * sig_sync --
- *
- * Sync the files based on a signal.
- */
-static void
-sig_sync(signo, flags)
- int signo;
- u_int flags;
-{
- SCR *sp;
-
- /*
- * Walk the lists of screens, sync'ing the files; only sync
- * each file once.
- */
- for (sp = __global_list->dq.cqh_first;
- sp != (void *)&__global_list->dq; sp = sp->q.cqe_next)
- rcv_sync(sp, sp->ep, RCV_ENDSESSION | RCV_PRESERVE | flags);
- for (sp = __global_list->hq.cqh_first;
- sp != (void *)&__global_list->hq; sp = sp->q.cqe_next)
- rcv_sync(sp, sp->ep, RCV_ENDSESSION | RCV_PRESERVE | flags);
-
- /*
- * Die with the proper exit status. Don't bother using
- * sigaction(2) 'cause we want the default behavior.
- */
- (void)signal(signo, SIG_DFL);
- (void)kill(getpid(), signo);
- /* NOTREACHED */
-
- exit (1);
-}
diff --git a/usr.bin/vi/common/term.c b/usr.bin/vi/common/term.c
deleted file mode 100644
index 457e368b6831..000000000000
--- a/usr.bin/vi/common/term.c
+++ /dev/null
@@ -1,732 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)term.c 8.79 (Berkeley) 8/2/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <locale.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-/*
- * XXX
- * DON'T INCLUDE <curses.h> HERE, IT BREAKS OSF1 V2.0 WHERE IT
- * CHANGES THE VALUES OF VERASE/VKILL/VWERASE TO INCORRECT ONES.
- */
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-
-static int keycmp __P((const void *, const void *));
-static enum input term_key_queue __P((SCR *));
-static void term_key_set __P((GS *, int, int));
-
-/*
- * If we're reading less than 20 characters, up the size of the tty buffer.
- * This shouldn't ever happen, other than the first time through, but it's
- * possible if a map is large enough.
- */
-#define term_read_grow(sp, tty) \
- (tty)->nelem - ((tty)->cnt + (tty)->next) >= 20 ? \
- 0 : __term_read_grow(sp, tty, 64)
-static int __term_read_grow __P((SCR *, IBUF *, int));
-
-/*
- * !!!
- * Historic vi always used:
- *
- * ^D: autoindent deletion
- * ^H: last character deletion
- * ^W: last word deletion
- * ^Q: quote the next character (if not used in flow control).
- * ^V: quote the next character
- *
- * regardless of the user's choices for these characters. The user's erase
- * and kill characters worked in addition to these characters. Nvi wires
- * down the above characters, but in addition permits the VEOF, VERASE, VKILL
- * and VWERASE characters described by the user's termios structure.
- *
- * Ex was not consistent with this scheme, as it historically ran in tty
- * cooked mode. This meant that the scroll command and autoindent erase
- * characters were mapped to the user's EOF character, and the character
- * and word deletion characters were the user's tty character and word
- * deletion characters. This implementation makes it all consistent, as
- * described above for vi.
- *
- * XXX
- * THIS REQUIRES THAT ALL SCREENS SHARE A SPECIAL KEY SET.
- */
-KEYLIST keylist[] = {
- {K_CARAT, '^'}, /* ^ */
- {K_CNTRLD, '\004'}, /* ^D */
- {K_CNTRLR, '\022'}, /* ^R */
- {K_CNTRLT, '\024'}, /* ^T */
- {K_CNTRLZ, '\032'}, /* ^Z */
- {K_COLON, ':'}, /* : */
- {K_CR, '\r'}, /* \r */
- {K_ESCAPE, '\033'}, /* ^[ */
- {K_FORMFEED, '\f'}, /* \f */
- {K_HEXCHAR, '\030'}, /* ^X */
- {K_NL, '\n'}, /* \n */
- {K_RIGHTBRACE, '}'}, /* } */
- {K_RIGHTPAREN, ')'}, /* ) */
- {K_TAB, '\t'}, /* \t */
- {K_VERASE, '\b'}, /* \b */
- {K_VKILL, '\025'}, /* ^U */
- {K_VLNEXT, '\021'}, /* ^Q */
- {K_VLNEXT, '\026'}, /* ^V */
- {K_VWERASE, '\027'}, /* ^W */
- {K_ZERO, '0'}, /* 0 */
- {K_NOTUSED, 0}, /* VEOF, VERASE, VKILL, VWERASE */
- {K_NOTUSED, 0},
- {K_NOTUSED, 0},
- {K_NOTUSED, 0},
-};
-static int nkeylist = (sizeof(keylist) / sizeof(keylist[0])) - 4;
-
-/*
- * term_init --
- * Initialize the special key lookup table.
- */
-int
-term_init(sp)
- SCR *sp;
-{
- GS *gp;
- KEYLIST *kp;
- int cnt;
-
- /*
- * XXX
- * 8-bit only, for now. Recompilation should get you any
- * 8-bit character set, as long as nul isn't a character.
- */
- (void)setlocale(LC_ALL, "");
- key_init(sp);
-
- gp = sp->gp;
-#ifdef VEOF
- term_key_set(gp, VEOF, K_CNTRLD);
-#endif
-#ifdef VERASE
- term_key_set(gp, VERASE, K_VERASE);
-#endif
-#ifdef VKILL
- term_key_set(gp, VKILL, K_VKILL);
-#endif
-#ifdef VWERASE
- term_key_set(gp, VWERASE, K_VWERASE);
-#endif
-
- /* Sort the special key list. */
- qsort(keylist, nkeylist, sizeof(keylist[0]), keycmp);
-
- /* Initialize the fast lookup table. */
- for (gp->max_special = 0, kp = keylist, cnt = nkeylist; cnt--; ++kp) {
- if (gp->max_special < kp->value)
- gp->max_special = kp->value;
- if (kp->ch <= MAX_FAST_KEY)
- gp->special_key[kp->ch] = kp->value;
- }
- return (0);
-}
-
-/*
- * term_key_set --
- * Set keys found in the termios structure. VERASE and VKILL are required
- * by POSIX 1003.1-1990, VWERASE is a 4.4BSD extension. We've left three
- * open slots in the keylist table, if these values exist, put them into
- * place. Note, they may reset (or duplicate) values already in the table,
- * so we check for that first.
- */
-static void
-term_key_set(gp, name, val)
- GS *gp;
- int name, val;
-{
- KEYLIST *kp;
- cc_t ch;
-
- if (!F_ISSET(gp, G_TERMIOS_SET))
- return;
- if ((ch = gp->original_termios.c_cc[name]) == _POSIX_VDISABLE)
- return;
-
- /* Check for duplication. */
- for (kp = keylist; kp->value != K_NOTUSED; ++kp)
- if (kp->ch == ch) {
- kp->value = val;
- return;
- }
- /* Add a new entry. */
- if (kp->value == K_NOTUSED) {
- keylist[nkeylist].ch = ch;
- keylist[nkeylist].value = val;
- ++nkeylist;
- }
-}
-
-/*
- * key_init --
- * Build the fast-lookup key display array.
- */
-void
-key_init(sp)
- SCR *sp;
-{
- CHAR_T ch;
-
- for (ch = 0; ch <= MAX_FAST_KEY; ++ch) {
- (void)__key_name(sp, ch);
- (void)memmove(sp->gp->cname[ch].name, sp->cname, sp->clen);
- sp->gp->cname[ch].len = sp->clen;
- }
-}
-
-/*
- * __key_len --
- * Return the length of the string that will display the key.
- * This routine is the backup for the KEY_LEN() macro.
- */
-size_t
-__key_len(sp, ch)
- SCR *sp;
- ARG_CHAR_T ch;
-{
- (void)__key_name(sp, ch);
- return (sp->clen);
-}
-
-/*
- * __key_name --
- * Return the string that will display the key. This routine
- * is the backup for the KEY_NAME() macro.
- */
-CHAR_T *
-__key_name(sp, ach)
- SCR *sp;
- ARG_CHAR_T ach;
-{
- static const CHAR_T hexdigit[] = "0123456789abcdef";
- static const CHAR_T octdigit[] = "01234567";
- CHAR_T ch, *chp, mask;
- size_t len;
- int cnt, shift;
-
- /*
- * Historical (ARPA standard) mappings. Printable characters are left
- * alone. Control characters less than '\177' are represented as '^'
- * followed by the character offset from the '@' character in the ASCII
- * map. '\177' is represented as '^' followed by '?'.
- *
- * XXX
- * The following code depends on the current locale being identical to
- * the ASCII map from '\100' to '\076' (\076 since that's the largest
- * character for which we can offset from '@' and get something that's
- * a printable character in ASCII. I'm told that this is a reasonable
- * assumption...
- *
- * XXX
- * This code will only work with CHAR_T's that are multiples of 8-bit
- * bytes.
- *
- * XXX
- * NB: There's an assumption here that all printable characters take
- * up a single column on the screen. This is not always correct.
- */
- ch = ach;
- if (isprint(ch)) {
- sp->cname[0] = ch;
- len = 1;
- } else if (ch <= '\076' && iscntrl(ch)) {
- sp->cname[0] = '^';
- sp->cname[1] = ch == '\177' ? '?' : '@' + ch;
- len = 2;
- } else if (O_ISSET(sp, O_OCTAL)) {
-#define BITS (sizeof(CHAR_T) * 8)
-#define SHIFT (BITS - BITS % 3)
-#define TOPMASK (BITS % 3 == 2 ? 3 : 1) << (BITS - BITS % 3)
- sp->cname[0] = '\\';
- sp->cname[1] = octdigit[(ch & TOPMASK) >> SHIFT];
- shift = SHIFT - 3;
- for (len = 2, mask = 7 << (SHIFT - 3),
- cnt = BITS / 3; cnt-- > 0; mask >>= 3, shift -= 3)
- sp->cname[len++] = octdigit[(ch & mask) >> shift];
- } else {
- sp->cname[0] = '0';
- sp->cname[1] = 'x';
- for (len = 2, chp = (u_int8_t *)&ch,
- cnt = sizeof(CHAR_T); cnt-- > 0; ++chp) {
- sp->cname[len++] = hexdigit[(*chp & 0xf0) >> 4];
- sp->cname[len++] = hexdigit[*chp & 0x0f];
- }
- }
- sp->cname[sp->clen = len] = '\0';
- return (sp->cname);
-}
-
-/*
- * term_push --
- * Push keys onto the front of a buffer.
- *
- * There is a single input buffer in ex/vi. Characters are read onto the
- * end of the buffer by the terminal input routines, and pushed onto the
- * front of the buffer by various other functions in ex/vi. Each key has
- * an associated flag value, which indicates if it has already been quoted,
- * if it is the result of a mapping or an abbreviation, as well as a count
- * of the number of times it has been mapped.
- */
-int
-term_push(sp, s, nchars, flags)
- SCR *sp;
- CHAR_T *s; /* Characters. */
- size_t nchars; /* Number of chars. */
- u_int flags; /* CH_* flags. */
-{
- IBUF *tty;
- size_t total;
-
- /* If we have room, stuff the keys into the buffer. */
- tty = sp->gp->tty;
- if (nchars <= tty->next ||
- (tty->ch != NULL && tty->cnt == 0 && nchars <= tty->nelem)) {
- if (tty->cnt != 0)
- tty->next -= nchars;
- tty->cnt += nchars;
- MEMMOVE(tty->ch + tty->next, s, nchars);
- MEMSET(tty->chf + tty->next, flags, nchars);
- return (0);
- }
-
- /*
- * If there are currently characters in the queue, shift them up,
- * leaving some extra room. Get enough space plus a little extra.
- */
-#define TERM_PUSH_SHIFT 30
- total = tty->cnt + tty->next + nchars + TERM_PUSH_SHIFT;
- if (total >= tty->nelem && __term_read_grow(sp, tty, MAX(total, 64)))
- return (1);
- if (tty->cnt) {
- MEMMOVE(tty->ch + TERM_PUSH_SHIFT + nchars,
- tty->ch + tty->next, tty->cnt);
- MEMMOVE(tty->chf + TERM_PUSH_SHIFT + nchars,
- tty->chf + tty->next, tty->cnt);
- }
-
- /* Put the new characters into the queue. */
- tty->next = TERM_PUSH_SHIFT;
- tty->cnt += nchars;
- MEMMOVE(tty->ch + TERM_PUSH_SHIFT, s, nchars);
- MEMSET(tty->chf + TERM_PUSH_SHIFT, flags, nchars);
- return (0);
-}
-
-/*
- * Remove characters from the queue, simultaneously clearing the flag
- * and map counts.
- */
-#define QREM_HEAD(q, len) { \
- size_t __off = (q)->next; \
- if (len == 1) \
- tty->chf[__off] = 0; \
- else \
- MEMSET(tty->chf + __off, 0, len); \
- if (((q)->cnt -= len) == 0) \
- (q)->next = 0; \
- else \
- (q)->next += len; \
-}
-#define QREM_TAIL(q, len) { \
- size_t __off = (q)->next + (q)->cnt - 1; \
- if (len == 1) \
- tty->chf[__off] = 0; \
- else \
- MEMSET(tty->chf + __off, 0, len); \
- if (((q)->cnt -= len) == 0) \
- (q)->next = 0; \
-}
-
-/*
- * term_key --
- * Get the next key.
- *
- * !!!
- * The flag TXT_MAPNODIGIT probably needs some explanation. First, the idea
- * of mapping keys is that one or more keystrokes act like a function key.
- * What's going on is that vi is reading a number, and the character following
- * the number may or may not be mapped (TXT_MAPCOMMAND). For example, if the
- * user is entering the z command, a valid command is "z40+", and we don't want
- * to map the '+', i.e. if '+' is mapped to "xxx", we don't want to change it
- * into "z40xxx". However, if the user enters "35x", we want to put all of the
- * characters through the mapping code.
- *
- * Historical practice is a bit muddled here. (Surprise!) It always permitted
- * mapping digits as long as they weren't the first character of the map, e.g.
- * ":map ^A1 xxx" was okay. It also permitted the mapping of the digits 1-9
- * (the digit 0 was a special case as it doesn't indicate the start of a count)
- * as the first character of the map, but then ignored those mappings. While
- * it's probably stupid to map digits, vi isn't your mother.
- *
- * The way this works is that the TXT_MAPNODIGIT causes term_key to return the
- * end-of-digit without "looking" at the next character, i.e. leaving it as the
- * user entered it. Presumably, the next term_key call will tell us how the
- * user wants it handled.
- *
- * There is one more complication. Users might map keys to digits, and, as
- * it's described above, the commands "map g 1G|d2g" would return the keys
- * "d2<end-of-digits>1G", when the user probably wanted "d21<end-of-digits>G".
- * So, if a map starts off with a digit we continue as before, otherwise, we
- * pretend that we haven't mapped the character and return <end-of-digits>.
- *
- * Now that that's out of the way, let's talk about Energizer Bunny macros.
- * It's easy to create macros that expand to a loop, e.g. map x 3x. It's
- * fairly easy to detect this example, because it's all internal to term_key.
- * If we're expanding a macro and it gets big enough, at some point we can
- * assume it's looping and kill it. The examples that are tough are the ones
- * where the parser is involved, e.g. map x "ayyx"byy. We do an expansion
- * on 'x', and get "ayyx"byy. We then return the first 4 characters, and then
- * find the looping macro again. There is no way that we can detect this
- * without doing a full parse of the command, because the character that might
- * cause the loop (in this case 'x') may be a literal character, e.g. the map
- * map x "ayy"xyy"byy is perfectly legal and won't cause a loop.
- *
- * Historic vi tried to detect looping macros by disallowing obvious cases in
- * the map command, maps that that ended with the same letter as they started
- * (which wrongly disallowed "map x 'x"), and detecting macros that expanded
- * too many times before keys were returned to the command parser. It didn't
- * get many (most?) of the tricky cases right, however, and it was certainly
- * possible to create macros that ran forever. And, even if it did figure out
- * what was going on, the user was usually tossed into ex mode. Finally, any
- * changes made before vi realized that the macro was recursing were left in
- * place. We recover gracefully, but the only recourse the user has in an
- * infinite macro loop is to interrupt.
- *
- * !!!
- * It is historic practice that mapping characters to themselves as the first
- * part of the mapped string was legal, and did not cause infinite loops, i.e.
- * ":map! { {^M^T" and ":map n nz." were known to work. The initial, matching
- * characters were returned instead of being remapped.
- *
- * XXX
- * The final issue is recovery. It would be possible to undo all of the work
- * that was done by the macro if we entered a record into the log so that we
- * knew when the macro started, and, in fact, this might be worth doing at some
- * point. Given that this might make the log grow unacceptably (consider that
- * cursor keys are done with maps), for now we leave any changes made in place.
- */
-enum input
-term_key(sp, chp, flags)
- SCR *sp;
- CH *chp;
- u_int flags;
-{
- enum input rval;
- struct timeval t, *tp;
- CHAR_T ch;
- GS *gp;
- IBUF *tty;
- SEQ *qp;
- int init_nomap, ispartial, nr;
-
- /* If we've been interrupted, return an error. */
- if (INTERRUPTED(sp))
- return (INP_INTR);
-
- gp = sp->gp;
- tty = gp->tty;
-
- /*
- * If the queue is empty, read more keys in. Since no timeout is
- * requested, s_key_read will either return an error or will read
- * some number of characters.
- */
-loop: if (tty->cnt == 0) {
- if (term_read_grow(sp, tty))
- return (INP_ERR);
- if ((rval = sp->s_key_read(sp, &nr, NULL)) != INP_OK)
- return (rval);
- /*
- * If there's something on the mode line that we wanted
- * the user to see, they just entered a character so we
- * can presume they saw it.
- */
- if (F_ISSET(sp, S_UPDATE_MODE))
- F_CLR(sp, S_UPDATE_MODE);
- }
-
- /* If the key is mappable and should be mapped, look it up. */
- if (!(tty->chf[tty->next] & CH_NOMAP) &&
- LF_ISSET(TXT_MAPCOMMAND | TXT_MAPINPUT)) {
- /* Set up timeout value. */
- if (O_ISSET(sp, O_TIMEOUT)) {
- tp = &t;
- t.tv_sec = O_VAL(sp, O_KEYTIME) / 10;
- t.tv_usec = (O_VAL(sp, O_KEYTIME) % 10) * 100000L;
- } else
- tp = NULL;
-
- /* Get the next key. */
-newmap: ch = tty->ch[tty->next];
- if (ch < MAX_BIT_SEQ && !bit_test(gp->seqb, ch))
- goto nomap;
-
- /* Search the map. */
-remap: qp = seq_find(sp, NULL, &tty->ch[tty->next], tty->cnt,
- LF_ISSET(TXT_MAPCOMMAND) ? SEQ_COMMAND : SEQ_INPUT,
- &ispartial);
-
- /* If we've been interrupted, return an error. */
- if (INTERRUPTED(sp))
- return (INP_INTR);
-
- /*
- * If get a partial match, read more characters and retry
- * the map. If no characters read, return the characters
- * unmapped.
- */
- if (ispartial) {
- if (term_read_grow(sp, tty))
- return (INP_ERR);
- if ((rval = sp->s_key_read(sp, &nr, tp)) != INP_OK)
- return (rval);
- if (nr)
- goto remap;
- goto nomap;
- }
-
- /* If no map, return the character. */
- if (qp == NULL)
- goto nomap;
-
- /*
- * If looking for the end of a digit string, and the first
- * character of the map is it, pretend we haven't seen the
- * character.
- */
- if (LF_ISSET(TXT_MAPNODIGIT) &&
- qp->output != NULL && !isdigit(qp->output[0]))
- goto not_digit_ch;
-
- /* Find out if the initial segments are identical. */
- init_nomap = !memcmp(&tty->ch[tty->next], qp->output, qp->ilen);
-
- /* Delete the mapped characters from the queue. */
- QREM_HEAD(tty, qp->ilen);
-
- /* If keys mapped to nothing, go get more. */
- if (qp->output == NULL)
- goto loop;
-
- /* If remapping characters, push the character on the queue. */
- if (O_ISSET(sp, O_REMAP)) {
- if (init_nomap) {
- if (term_push(sp, qp->output + qp->ilen,
- qp->olen - qp->ilen, CH_MAPPED))
- return (INP_ERR);
- if (term_push(sp,
- qp->output, qp->ilen, CH_NOMAP | CH_MAPPED))
- return (INP_ERR);
- goto nomap;
- } else
- if (term_push(sp,
- qp->output, qp->olen, CH_MAPPED))
- return (INP_ERR);
- goto newmap;
- }
-
- /* Else, push the characters on the queue and return one. */
- if (term_push(sp, qp->output, qp->olen, CH_MAPPED | CH_NOMAP))
- return (INP_ERR);
- }
-
-nomap: ch = tty->ch[tty->next];
- if (LF_ISSET(TXT_MAPNODIGIT) && !isdigit(ch)) {
-not_digit_ch: chp->ch = CH_NOT_DIGIT;
- chp->value = 0;
- chp->flags = 0;
- return (INP_OK);
- }
-
- /* Fill in the return information. */
- chp->ch = ch;
- chp->flags = tty->chf[tty->next];
- chp->value = KEY_VAL(sp, ch);
-
- /* Delete the character from the queue. */
- QREM_HEAD(tty, 1);
- return (INP_OK);
-}
-
-/*
- * term_flush --
- * Flush any flagged keys.
- */
-void
-term_flush(sp, msg, flags)
- SCR *sp;
- char *msg;
- u_int flags;
-{
- IBUF *tty;
-
- tty = sp->gp->tty;
- if (!tty->cnt || !(tty->chf[tty->next] & flags))
- return;
- do {
- QREM_HEAD(tty, 1);
- } while (tty->cnt && tty->chf[tty->next] & flags);
- msgq(sp, M_ERR, "%s: keys flushed", msg);
-}
-
-/*
- * term_user_key --
- * Get the next key, but require the user enter one.
- */
-enum input
-term_user_key(sp, chp)
- SCR *sp;
- CH *chp;
-{
- enum input rval;
- IBUF *tty;
- int nr;
-
- /*
- * Read any keys the user has waiting. Make the race
- * condition as short as possible.
- */
- if ((rval = term_key_queue(sp)) != INP_OK)
- return (rval);
-
- /* Wait and read another key. */
- if ((rval = sp->s_key_read(sp, &nr, NULL)) != INP_OK)
- return (rval);
-
- /* Fill in the return information. */
- tty = sp->gp->tty;
- chp->ch = tty->ch[tty->next + (tty->cnt - 1)];
- chp->flags = 0;
- chp->value = KEY_VAL(sp, chp->ch);
-
- QREM_TAIL(tty, 1);
- return (INP_OK);
-}
-
-/*
- * term_key_queue --
- * Read the keys off of the terminal queue until it's empty.
- */
-static enum input
-term_key_queue(sp)
- SCR *sp;
-{
- enum input rval;
- struct timeval t;
- IBUF *tty;
- int nr;
-
- t.tv_sec = 0;
- t.tv_usec = 0;
- for (tty = sp->gp->tty;;) {
- if (term_read_grow(sp, tty))
- return (INP_ERR);
- if ((rval = sp->s_key_read(sp, &nr, &t)) != INP_OK)
- return (rval);
- if (nr == 0)
- break;
- }
- return (INP_OK);
-}
-
-/*
- * __key_val --
- * Fill in the value for a key. This routine is the backup
- * for the KEY_VAL() macro.
- */
-int
-__key_val(sp, ch)
- SCR *sp;
- ARG_CHAR_T ch;
-{
- KEYLIST k, *kp;
-
- k.ch = ch;
- kp = bsearch(&k, keylist, nkeylist, sizeof(keylist[0]), keycmp);
- return (kp == NULL ? K_NOTUSED : kp->value);
-}
-
-/*
- * __term_read_grow --
- * Grow the terminal queue. This routine is the backup for
- * the term_read_grow() macro.
- */
-static int
-__term_read_grow(sp, tty, add)
- SCR *sp;
- IBUF *tty;
- int add;
-{
- size_t new_nelem, olen;
-
- new_nelem = tty->nelem + add;
- olen = tty->nelem * sizeof(tty->ch[0]);
- BINC_RET(sp, tty->ch, olen, new_nelem * sizeof(tty->ch[0]));
-
- olen = tty->nelem * sizeof(tty->chf[0]);
- BINC_RET(sp, tty->chf, olen, new_nelem * sizeof(tty->chf[0]));
-
- tty->nelem = olen / sizeof(tty->chf[0]);
- return (0);
-}
-
-static int
-keycmp(ap, bp)
- const void *ap, *bp;
-{
- return (((KEYLIST *)ap)->ch - ((KEYLIST *)bp)->ch);
-}
diff --git a/usr.bin/vi/common/term.h b/usr.bin/vi/common/term.h
deleted file mode 100644
index 623a94c8cffd..000000000000
--- a/usr.bin/vi/common/term.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)term.h 8.48 (Berkeley) 7/25/94
- */
-
-/*
- * Fundamental character types.
- *
- * CHAR_T An integral type that can hold any character.
- * ARG_CHAR_T The type of a CHAR_T when passed as an argument using
- * traditional promotion rules. It should also be able
- * to be compared against any CHAR_T for equality without
- * problems.
- * MAX_CHAR_T The maximum value of any character.
- *
- * If no integral type can hold a character, don't even try the port.
- */
-typedef u_char CHAR_T;
-typedef u_int ARG_CHAR_T;
-#define MAX_CHAR_T 0xff
-
-/* The maximum number of columns any character can take up on a screen. */
-#define MAX_CHARACTER_COLUMNS 4
-
-/* Structure to return a character and associated information. */
-struct _ch {
- CHAR_T ch; /* Character. */
-
-#define K_NOTUSED 0
-#define K_CARAT 1
-#define K_CNTRLD 2
-#define K_CNTRLR 3
-#define K_CNTRLT 4
-#define K_CNTRLZ 5
-#define K_COLON 6
-#define K_CR 7
-#define K_ESCAPE 8
-#define K_FORMFEED 9
-#define K_HEXCHAR 10
-#define K_NL 11
-#define K_RIGHTBRACE 12
-#define K_RIGHTPAREN 13
-#define K_TAB 14
-#define K_VERASE 15
-#define K_VKILL 16
-#define K_VLNEXT 17
-#define K_VWERASE 18
-#define K_ZERO 19
- u_int8_t value; /* Special character flag values. */
-
-#define CH_ABBREVIATED 0x01 /* Character from an abbreviation. */
-#define CH_MAPPED 0x02 /* Character from a map. */
-#define CH_NOMAP 0x04 /* Do not map the character. */
-#define CH_QUOTED 0x08 /* Character is already quoted. */
- u_int8_t flags;
-};
-
-typedef struct _keylist {
- u_int8_t value; /* Special value. */
- CHAR_T ch; /* Key. */
-} KEYLIST;
-
-extern KEYLIST keylist[];
-
-/* Structure for the key input buffer. */
-struct _ibuf {
- CHAR_T *ch; /* Array of characters. */
- u_int8_t *chf; /* Array of character flags (CH_*). */
-
- size_t cnt; /* Count of remaining characters. */
- size_t nelem; /* Numer of array elements. */
- size_t next; /* Offset of next array entry. */
-};
- /* Return if more keys in queue. */
-#define KEYS_WAITING(sp) ((sp)->gp->tty->cnt)
-#define MAPPED_KEYS_WAITING(sp) \
- (KEYS_WAITING(sp) && sp->gp->tty->chf[sp->gp->tty->next] & CH_MAPPED)
-
-/*
- * Routines that return a key as a side-effect return:
- *
- * INP_OK Returning a character; must be 0.
- * INP_EOF EOF.
- * INP_ERR Error.
- * INP_INTR Interrupted.
- *
- * The vi structure depends on the key routines being able to return INP_EOF
- * multiple times without failing -- eventually enough things will end due to
- * INP_EOF that vi will reach the command level for the screen, at which point
- * the exit flags will be set and vi will exit.
- */
-enum input { INP_OK=0, INP_EOF, INP_ERR, INP_INTR };
-
-/*
- * Routines that return a confirmation return:
- *
- * CONF_NO User answered no.
- * CONF_QUIT User answered quit, eof or an error.
- * CONF_YES User answered yes.
- */
-enum confirm { CONF_NO, CONF_QUIT, CONF_YES };
-
-/*
- * Ex/vi commands are generally separated by whitespace characters. We
- * can't use the standard isspace(3) macro because it returns true for
- * characters like ^K in the ASCII character set. The 4.4BSD isblank(3)
- * macro does exactly what we want, but it's not portable yet.
- *
- * XXX
- * Note side effect, ch is evaluated multiple times.
- */
-#ifndef isblank
-#define isblank(ch) ((ch) == ' ' || (ch) == '\t')
-#endif
-
-/* The "standard" tab width, for displaying things to users. */
-#define STANDARD_TAB 6
-
-/* Various special characters, messages. */
-#define CH_BSEARCH '?' /* Backward search prompt. */
-#define CH_CURSOR ' ' /* Cursor character. */
-#define CH_ENDMARK '$' /* End of a range. */
-#define CH_EXPROMPT ':' /* Ex prompt. */
-#define CH_FSEARCH '/' /* Forward search prompt. */
-#define CH_HEX '\030' /* Leading hex character. */
-#define CH_LITERAL '\026' /* ASCII ^V. */
-#define CH_NO 'n' /* No. */
-#define CH_NOT_DIGIT 'a' /* A non-isdigit() character. */
-#define CH_QUIT 'q' /* Quit. */
-#define CH_YES 'y' /* Yes. */
-
-#define STR_CONFIRM "confirm? [ynq]"
-#define STR_CMSG "Enter return to continue: "
-#define STR_QMSG "Enter return to continue [q to quit]: "
-
-/* Flags describing how input is handled. */
-#define TXT_AICHARS 0x00000001 /* Leading autoindent chars. */
-#define TXT_ALTWERASE 0x00000002 /* Option: altwerase. */
-#define TXT_APPENDEOL 0x00000004 /* Appending after EOL. */
-#define TXT_AUTOINDENT 0x00000008 /* Autoindent set this line. */
-#define TXT_BACKSLASH 0x00000010 /* Backslashes escape characters. */
-#define TXT_BEAUTIFY 0x00000020 /* Only printable characters. */
-#define TXT_BS 0x00000040 /* Backspace returns the buffer. */
-#define TXT_CNTRLD 0x00000080 /* Control-D is a special command. */
-#define TXT_CNTRLT 0x00000100 /* Control-T is an indent special. */
-#define TXT_CR 0x00000200 /* CR returns the buffer. */
-#define TXT_DOTTERM 0x00000400 /* Leading '.' terminates the input. */
-#define TXT_EMARK 0x00000800 /* End of replacement mark. */
-#define TXT_ESCAPE 0x00001000 /* Escape returns the buffer. */
-#define TXT_EXSUSPEND 0x00002000 /* ^Z should suspend the session. */
-#define TXT_INFOLINE 0x00004000 /* Editing the info line. */
-#define TXT_MAPCOMMAND 0x00008000 /* Apply the command map. */
-#define TXT_MAPINPUT 0x00010000 /* Apply the input map. */
-#define TXT_MAPNODIGIT 0x00020000 /* Return to a digit. */
-#define TXT_NLECHO 0x00040000 /* Echo the newline. */
-#define TXT_OVERWRITE 0x00080000 /* Overwrite characters. */
-#define TXT_PROMPT 0x00100000 /* Display a prompt. */
-#define TXT_RECORD 0x00200000 /* Record for replay. */
-#define TXT_REPLACE 0x00400000 /* Replace; don't delete overwrite. */
-#define TXT_REPLAY 0x00800000 /* Replay the last input. */
-#define TXT_RESOLVE 0x01000000 /* Resolve the text into the file. */
-#define TXT_SHOWMATCH 0x02000000 /* Option: showmatch. */
-#define TXT_TTYWERASE 0x04000000 /* Option: ttywerase. */
-#define TXT_WRAPMARGIN 0x08000000 /* Option: wrapmargin. */
-
-/* Support keyboard routines. */
-size_t __key_len __P((SCR *, ARG_CHAR_T));
-CHAR_T *__key_name __P((SCR *, ARG_CHAR_T));
-int __key_val __P((SCR *, ARG_CHAR_T));
-void key_init __P((SCR *));
-void term_flush __P((SCR *, char *, u_int));
-enum input term_key __P((SCR *, CH *, u_int));
-enum input term_user_key __P((SCR *, CH *));
-int term_init __P((SCR *));
-int term_push __P((SCR *, CHAR_T *, size_t, u_int));
diff --git a/usr.bin/vi/common/trace.c b/usr.bin/vi/common/trace.c
deleted file mode 100644
index 1f63f6628a2e..000000000000
--- a/usr.bin/vi/common/trace.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)trace.c 8.2 (Berkeley) 3/8/94
- */
-
-#ifdef DEBUG
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-void
-#ifdef __STDC__
-TRACE(SCR *sp, const char *fmt, ...)
-#else
-TRACE(sp, fmt, va_alist)
- SCR *sp;
- char *fmt;
- va_dcl
-#endif
-{
- FILE *tfp;
- va_list ap;
-
- if ((tfp = sp->gp->tracefp) == NULL)
- return;
-#ifdef __STDC__
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
- (void)vfprintf(tfp, fmt, ap);
- va_end(ap);
-
- (void)fflush(tfp);
-}
-#endif
diff --git a/usr.bin/vi/common/util.c b/usr.bin/vi/common/util.c
deleted file mode 100644
index 9845e644955e..000000000000
--- a/usr.bin/vi/common/util.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)util.c 8.71 (Berkeley) 8/8/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-
-/*
- * binc --
- * Increase the size of a buffer.
- */
-int
-binc(sp, argp, bsizep, min)
- SCR *sp; /* sp MAY BE NULL!!! */
- void *argp;
- size_t *bsizep, min;
-{
- size_t csize;
- void *bpp;
-
- /* If already larger than the minimum, just return. */
- if (min && *bsizep >= min)
- return (0);
-
- bpp = *(char **)argp;
- csize = *bsizep + MAX(min, 256);
- REALLOC(sp, bpp, void *, csize);
-
- if (bpp == NULL) {
- /*
- * Theoretically, realloc is supposed to leave any already
- * held memory alone if it can't get more. Don't trust it.
- */
- *bsizep = 0;
- return (1);
- }
- /*
- * Memory is guaranteed to be zero-filled, various parts of
- * nvi depend on this.
- */
- memset((char *)bpp + *bsizep, 0, csize - *bsizep);
- *(char **)argp = bpp;
- *bsizep = csize;
- return (0);
-}
-/*
- * nonblank --
- * Set the column number of the first non-blank character
- * including or after the starting column. On error, set
- * the column to 0, it's safest.
- */
-int
-nonblank(sp, ep, lno, cnop)
- SCR *sp;
- EXF *ep;
- recno_t lno;
- size_t *cnop;
-{
- char *p;
- size_t cnt, len, off;
-
- /* Default. */
- off = *cnop;
- *cnop = 0;
-
- /* Get the line. */
- if ((p = file_gline(sp, ep, lno, &len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno == 0)
- return (0);
- GETLINE_ERR(sp, lno);
- return (1);
- }
-
- /* Set the offset. */
- if (len == 0 || off >= len)
- return (0);
-
- for (cnt = off, p = &p[off],
- len -= off; len && isblank(*p); ++cnt, ++p, --len);
-
- /* Set the return. */
- *cnop = len ? cnt : cnt - 1;
- return (0);
-}
-
-/*
- * tail --
- * Return tail of a path.
- */
-char *
-tail(path)
- char *path;
-{
- char *p;
-
- if ((p = strrchr(path, '/')) == NULL)
- return (path);
- return (p + 1);
-}
-
-/*
- * set_alt_name --
- * Set the alternate file name.
- *
- * Swap the alternate file name. It's a routine because I wanted some place
- * to hang this comment. The alternate file name (normally referenced using
- * the special character '#' during file expansion) is set by many
- * operations. In the historic vi, the commands "ex", and "edit" obviously
- * set the alternate file name because they switched the underlying file.
- * Less obviously, the "read", "file", "write" and "wq" commands set it as
- * well. In this implementation, some new commands have been added to the
- * list. Where it gets interesting is that the alternate file name is set
- * multiple times by some commands. If an edit attempt fails (for whatever
- * reason, like the current file is modified but as yet unwritten), it is
- * set to the file name that the user was unable to edit. If the edit
- * succeeds, it is set to the last file name that was edited. Good fun.
- *
- * If the user edits a temporary file, there are time when there isn't an
- * alternative file name. A name argument of NULL turns it off.
- */
-void
-set_alt_name(sp, name)
- SCR *sp;
- char *name;
-{
- if (sp->alt_name != NULL)
- free(sp->alt_name);
- if (name == NULL)
- sp->alt_name = NULL;
- else if ((sp->alt_name = strdup(name)) == NULL)
- msgq(sp, M_SYSERR, NULL);
-}
-
-/*
- * v_strdup --
- * Strdup for wide character strings with an associated length.
- */
-CHAR_T *
-v_strdup(sp, str, len)
- SCR *sp;
- CHAR_T *str;
- size_t len;
-{
- CHAR_T *copy;
-
- MALLOC(sp, copy, CHAR_T *, len + 1);
- if (copy == NULL)
- return (NULL);
- memmove(copy, str, len * sizeof(CHAR_T));
- copy[len] = '\0';
- return (copy);
-}
-
-/*
- * vi_putchar --
- * Functional version of putchar, for tputs.
- */
-void
-vi_putchar(ch)
- int ch;
-{
- (void)putchar(ch);
-}
diff --git a/usr.bin/vi/common/vi.h b/usr.bin/vi/common/vi.h
deleted file mode 100644
index f98b8701edc5..000000000000
--- a/usr.bin/vi/common/vi.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)vi.h 8.46 (Berkeley) 8/8/94
- */
-
-/*
- * Forward structure declarations. Not pretty, but the include files
- * are far too interrelated for a clean solution.
- */
-typedef struct _cb CB;
-typedef struct _ch CH;
-typedef struct _excmdarg EXCMDARG;
-typedef struct _exf EXF;
-typedef struct _fref FREF;
-typedef struct _gs GS;
-typedef struct _ibuf IBUF;
-typedef struct _lmark LMARK;
-typedef struct _mark MARK;
-typedef struct _msg MSG;
-typedef struct _option OPTION;
-typedef struct _optlist OPTLIST;
-typedef struct _scr SCR;
-typedef struct _script SCRIPT;
-typedef struct _seq SEQ;
-typedef struct _tag TAG;
-typedef struct _tagf TAGF;
-typedef struct _text TEXT;
-
-/*
- * Local includes.
- */
-#include "term.h" /* Required by args.h. */
-#include "args.h" /* Required by options.h. */
-#include "options.h" /* Required by screen.h. */
-#include "search.h" /* Required by screen.h. */
-
-#include "msg.h" /* Required by gs.h. */
-#include "cut.h" /* Required by gs.h. */
-#include "seq.h" /* Required by screen.h. */
-#include "gs.h" /* Required by screen.h. */
-#include "screen.h" /* Required by exf.h. */
-#include "mark.h" /* Required by exf.h. */
-#include "exf.h"
-#include "log.h"
-#include "mem.h"
-
-#if FWOPEN_NOT_AVAILABLE /* See PORT/clib/fwopen.c. */
-#define EXCOOKIE sp
-int ex_fflush __P((SCR *));
-int ex_printf __P((SCR *, const char *, ...));
-FILE *fwopen __P((SCR *, void *));
-#else
-#define EXCOOKIE sp->stdfp
-#define ex_fflush fflush
-#define ex_printf fprintf
-#endif
-
-/* Macros to set/clear/test flags. */
-#define F_SET(p, f) (p)->flags |= (f)
-#define F_CLR(p, f) (p)->flags &= ~(f)
-#define F_ISSET(p, f) ((p)->flags & (f))
-
-#define LF_INIT(f) flags = (f)
-#define LF_SET(f) flags |= (f)
-#define LF_CLR(f) flags &= ~(f)
-#define LF_ISSET(f) (flags & (f))
-
-/*
- * XXX
- * MIN/MAX have traditionally been in <sys/param.h>. Don't
- * try to get them from there, it's just not worth the effort.
- */
-#ifndef MAX
-#define MAX(_a,_b) ((_a)<(_b)?(_b):(_a))
-#endif
-#ifndef MIN
-#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b))
-#endif
-
-/* Function prototypes that don't seem to belong anywhere else. */
-int nonblank __P((SCR *, EXF *, recno_t, size_t *));
-void set_alt_name __P((SCR *, char *));
-char *tail __P((char *));
-CHAR_T *v_strdup __P((SCR *, CHAR_T *, size_t));
-void vi_putchar __P((int));
-
-#ifdef DEBUG
-void TRACE __P((SCR *, const char *, ...));
-#endif
-
-/* Digraphs (not currently real). */
-int digraph __P((SCR *, int, int));
-int digraph_init __P((SCR *));
-void digraph_save __P((SCR *, int));
diff --git a/usr.bin/vi/docs/README b/usr.bin/vi/docs/README
deleted file mode 100644
index 5bece9929082..000000000000
--- a/usr.bin/vi/docs/README
+++ /dev/null
@@ -1,200 +0,0 @@
-# @(#)README 8.84 (Berkeley) 8/15/94
-
-This is the README for version 1.32 of nex/nvi, a freely redistributable
-replacement for the Berkeley ex and vi text editors. The compressed or
-gzip'd archive, for this and future versions, can be retrieved by using
-anonymous ftp to ftp.cs.berkeley.edu, from the file ucb/4bsd/nvi.tar.Z,
-or ucb/4bsd/nvi.tar.gz.
-
-If you have any questions about nvi, or problems making it work, please
-contact me by electronic mail at one of the following addresses:
-
- uunet!bostic
- bostic@cs.berkeley.edu
-
-Keith Bostic
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-o Redistribution:
-
-This software is copyrighted by the The Regents of the University of
-California, but may be freely redistributed (or sold, or used to line
-your birdcage) under the following conditions:
-
-/*-
- * Copyright (c) 1991, 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-o Credit where it's due:
-
- This software was originally derived from software contributed
- to the University of California, Berkeley by Steve Kirkendall,
- the author of the vi clone elvis. Without his work, this work
- would have been far more difficult.
-
- POSIX 1003.2 style regular expression support is courtesy of
- Henry Spencer, for which I am *very* grateful.
-
- The curses library was originally done by Ken Arnold. Scrolling
- and general reworking for 4.4BSD was done by Elan Amir.
-
-o From the original vi acknowledgements, by William Joy and Mark Horton:
-
- Bruce Englar encouraged the early development of this display
- editor. Peter Kessler helped bring sanity to version 2's
- command layout. Bill Joy wrote versions 1 and 2.0 through 2.7,
- and created the framework that users see in the present editor.
- Mark Horton added macros and other features and made the editor
- work on a large number of terminals and Unix systems.
-
-o And...
- The financial support of UUNET Communications Services is gratefully
- acknowledged.
-
-=-=-=-=-=-=-=-=-=-=-=
-o Status:
-
-This software is in beta test, and it's pretty stable. Almost all of
-the historic functionality in ex/vi is there, the only major missing
-pieces are open mode and the lisp option. (Also, the options hardtabs,
-optimize, redraw, and slowopen are recognized, but ignored.)
-
-Nvi is mostly 8-bit clean. This isn't difficult to fix, and was left
-in during initial development to keep things simple. Wide character
-support will be integrated at the same time that it is made fully 8-bit
-clean.
-
-There aren't a lot of new features in nex/nvi, but there are a few things
-you might like. The "Additional Features" section of the reference page
-(USD.doc/vi.ref/vi.ref.txt, USD.doc/vi.ref/vi.ref.ps) has more information.
-
-=-=-=-=-=-=-=-=-=-=-=
-o Porting information:
-
-The directory "PORT" has directories for specific OS/machine combinations,
-including V7-style Makefiles, for building nex/nvi on different machines.
-See the file PORT/README for detailed information.
-
-=-=-=-=-=-=-=-=-=-=-=
-o Debugging:
-
-Code fixes are appreciated, of course, but if you can't provide them,
-please email me as much information as you can as to how to reproduce
-the bug, and I'll try to fix it locally. Stack traces of core dumps
-are only rarely helpful -- an example file with a set of keystrokes that
-causes the problem is almost invariably necessary.
-
-Please include the following in the bug report;
-
- o The version of nvi you're running (use :version to get it).
- o The row/column dimensions of the screen (80 x 32).
- o Unless you're confident that they're not part of the problem,
- your startup files (.exrc, .nexrc) and the environment variable
- (EXININT, NEXINIT) values. (Cutting and pasting the output
- of ":set all" is usually sufficient.)
-
-If you're running a memory checker (e.g. Purify) on nvi, you will want
-to recompile everything with "-DPURIFY" in the CFLAGS, first. By
-default, allocated pages are not initialized by the DB code, and they
-will show up as reads of uninitialized memory in the buffer write routines.
-
-=-=-=-=-=-=-=-=-=-=-=
-o Directory layout:
-
-nvi/USD.doc:
- Ex/vi documentation, both historic and current.
-
- edit/ Roff source for "Edit: A tutorial", USD:14 in the
- 4.3BSD manuals.
- ex/ Roff source for "Ex Reference Manual -- Version
- 3.7", USD:16 in the 4.3BSD manuals.
- vi/ Roff source for "An Introduction to Display
- Editing with Vi", USD:15 in the 4.3BSD manuals.
- Includes the "Vi Quick Reference" card.
- vi.man/ Manual page for nex/nvi; an updated version of
- the document distributed with 4.4BSD-Lite.
- vi.ref/ Reference document for nex/nvi; an updated version
- of the document distributed with 4.4BSD-Lite.
-
-nvi/common:
- Source files for pieces of code that are shared by all the editors,
- like searching and logging code or code translating line numbers
- into requests to the dbopen(3) database code. It also has the
- interface code for modifying "records" in the underlying database.
-
-nvi/docs:
- Random nvi documentation:
-
- README -- Nvi main README file.
- bugs.current -- Major known bugs in the current nvi.
- changelog -- Log of changes from version to version.
- features -- Todo list, suggested features list.
- internals/
- autowrite -- Vi autowrite option discussion.
- gdb.script -- GDB debugging scripts.
- input -- Vi maps, executable buffers, and input discussion.
- quoting -- Vi quoting discussion.
- structures -- Out-of-date nvi internal structure description.
- tutorial/ -- Historic vi tutorial(s), of unknown quality.
-
-nvi/ex:
- The ex source code. Because vi has the colon command, lots of
- this code is used by vi. Generally, if functionality is shared
- by both ex and vi, it's in nvi/ex. If it's vi only, it's in
- nvi/vi. Files are generally named by the command(s) they support,
- but occasionally with a name that describes their functionality.
-
-nvi/install:
- Things to install on the local system.
-
- recover.script -- Vi recovery script.
-
-nvi/PORT:
- Porting directories, one per OS/architecture combination. See
- nvi/PORT/README for porting information.
-
- curses/ -- 4.4BSD curses implementation
- db/ -- 4.4BSD DB routines.
- regex/ -- Henry Spencer's POSIX.2 RE support.
-
-nvi/sex:
- The screen support for the ex editor.
-
-nvi/svi:
- The screen support for a curses based vi editor.
-
-nvi/vi:
- The vi source code.
-
-nvi/xaw:
- Place reserved for an X11 (Athena Widget) screen.
diff --git a/usr.bin/vi/docs/bugs.current b/usr.bin/vi/docs/bugs.current
deleted file mode 100644
index 92b2a5c3b43b..000000000000
--- a/usr.bin/vi/docs/bugs.current
+++ /dev/null
@@ -1,47 +0,0 @@
-List of known bugs:
-
-+ The number option doesn't display line numbers in ex append/insert
- mode.
-
-+ The option sidescroll is completely wrong, and setting it does more
- harm than good.
-
-+ We're not blocking signals when manipulating the SCR/EXF chains.
- This is necessary, since we walk them on signal receipt.
-
-+ When nvi edits files that don't have trailing newlines, it appends
- one, regardless.
-
-+ Open mode is not yet implemented.
-
-+ ^C isn't passed to the shell in the script windows as an interrupt
- character.
-
-+ The options:
-
- hardtabs, lisp, optimize, redraw, slowopen
-
- are recognized, but not implemented. These options are unlikely to
- be implemented, so if you want them you might want to say something!
- I will implement lisp if anyone ever documents how it worked.
-
-+ Screen repainting over slow lines, for some screen changes, isn't
- as good as the historic vi's.
-
-+ The line movement commands ('k', 'j' are easy examples) don't find the
- most attractive cursor position correctly when wrapped lines are longer
- than 80 characters, and they're on the second or subsequent lines.
-
-+ Colon commands longer than a single line cause the display to be
- incorrect.
-
-+ The usages of S_{REDRAW,REFORMAT,REFRESH,RENUMBER,RESIZE} are
- inconsistent, and should be reviewed. In particular, S_REFRESH
- in any screen redraws all screens.
-
-+ Historic vi permitted :g/xxx/vi, i.e. you could execute ex/vi as
- global commands. Need to review all of the old commands to verify
- which ones could/could not be used as global commands.
-
-+ If you run out of space in the recovery directory, the recovery
- file is left in place.
diff --git a/usr.bin/vi/docs/changelog b/usr.bin/vi/docs/changelog
deleted file mode 100644
index 335acd863921..000000000000
--- a/usr.bin/vi/docs/changelog
+++ /dev/null
@@ -1,519 +0,0 @@
-1.31 -> 1.32 Mon Aug 15 14:27:49 1994
- + Turn off recno mmap call for Solaris 2.4/SunOS 5.4.
-1.30 -> 1.31 Sun Aug 14 13:13:35 1994
- + Fix bug were cG on the last line of a file wasn't done in line mode,
- and where the cursor wasn't positioned correctly after exiting text
- insert mode.
- + Add termcap workaround to make function keys greater than 9 work
- correctly (or fail if old-style termcap support).
- + Change ex/vi to not flush mapped keys on error -- this is historic
- practice, and people depended on it.
- + Rework vi parser so that no command including a mapped key ever
- becomes the '.' command, matching historic practice.
- + Make <escape> cancellation in the vi parser match POSIX 1003.2.
- + Fix curses bug where standout string was written for each standout
- character, and where standout mode was never exited explicitly.
- Fix bugs in curses SF/sf and SR/sr scrolling, as seen on Sun and
- x86 consoles.
- + The v/global commands execute the print command by default.
- + The number option historically applies to ex as well as vi.
-1.29 -> 1.30 Mon Aug 8 10:30:42 1994
- + Make first read into a temporary set the file's name.
- + Permit any key to continue scrolling or ex commands -- this
- allows stacked colon commands, and matches historic practice.
- + Don't output normal ! command commentary in ex silent mode.
- + Allow +/- flags after substitute commands, make line (flag)
- offsets from vi mode match historic practice.
- + Return <eof> to ex immediately, even if preceded by spaces. Rework
- ex parser to do erase the prompt instead of depending on the print
- routines to do it. Minor fixes to the ex parser for display of
- default and scrolling commands. MORE EX PARSER CHANGES.
-1.28 -> 1.29 Fri Aug 5 10:18:07 1994
- + Make the abbreviated ex delete command work (:dele---###lll for
- example, is historically legal.
- + When autoprint fires, multiple flags may be set, use ex_print
- directly instead of the stub routines.
- + Change v/global commands to turn off autoprint while running.
- + Minor changes to make the ! command display match historic output.
- + Rework the ex parser to permit multiple command separators without
- commands -- MAJOR CHANGE, likely to introduce all sorts of new bugs.
- + Fix cd command to expand argument in the context of each element
- of the cdpath option, make relative paths always relative to the
- current directory.
- + Rework write/quit cases for temporary files, so that user's don't
- discard them accidentally.
- + Check for window size changes when continuing after a suspend.
- + Fix memory problem in svi_screen, used free'd memory.
- + Change the ex change, insert, append commands to match historic
- cursor positions if no data entered by the user.
- + Change ex format flags (#, l, p) to affect future commands, not
- just the current one, to match historic practice.
- + Make the user's EOF character an additional scroll character in ex.
- + Fix ex ^D scrolling to be the value of the scroll option, not half
- the screen.
- + Fix buffer execution to match historic practice -- bugs where the
- '*' command didn't work, and @<carriage-return> didn't work.
- + Fix doubled reporting of deleted lines in filters.
- + Rework the % ` / ? ( ) N n { and ^A commands to always cut into
- numeric buffers regardless of the location or length of the cut.
- This matches historic practice.
- + Fix the { command to check the current line if the cursor doesn't
- start on the first character of the line.
- + Do '!' expansion in the ex read command arguments, it's historic
- practice. In addition, it sets the last '!' command.
-1.27 -> 1.28 Wed Jul 27 21:29:18 1994
- + Add support for scrolling using the CS and SF/sf/SR/sr termcap
- strings to the 4BSD curses.
- + Rework of getkey() introduced a bug where command interrupt put
- nvi into an infinite loop.
- + Piping through a filter historically cut the replaced lines into
- the default buffer, although not the numeric ones.
- + Read of a filter and !! historically moved to the first nonblank
- of the resulting cursor line (most of the time).
- + Rework cursor motion flags, to support '!' as a motion command.
-1.26 -> 1.27 Tue Jul 26 10:27:58 1994
- + Add the meta option, to specify characters the shell will expand.
- + Fix the read command to match historic practice, the white space
- and bang characters weren't getting parsed correctly.
- + Change SIGALRM handler to save and restore errno.
- + Change SunOS include/compat.h to include <vfork.h> so that the
- ex/filter.c code works again.
- + Don't put lines deleted by the ex delete command into the numeric
- buffers, matching historic practice.
- + Fix; if appending to a buffer, default buffer historically only
- references the appended text, not the resulting text.
- + Support multiple, semi-colon separated search strings, and 'z'
- commands after search strings.
- + Make previous context mark setting match historic practice (see
- docs/internals/context).
- + Fix the set command to permit whitespace between the option and
- the question mark, fix question marks in general.
- + Fix bug where ex error messages could be accidentally preceded
- by a single space.
- + Fix bug where curses reorganization could lose screen specific
- mappings as soon as any screen exited.
- + Fix bug in paragraph code where invalid macros could be matched.
- Make paragraph motions stop at formfeed (^L) characters.
- + Change 'c' to match historic practice, it cut text into numeric
- buffers.
-1.25 -> 1.26 Tue Jul 19 17:46:24 1994
- + Ignore SIGWINCH if the screen size is unchanged; SunOS systems
- deliver one when a screen is uncovered.
- + Fix: don't permit a command with a motion component to wrap due
- to wrapscan and return to the original cursor position.
- + Fix: ^E wasn't beeping when reaching the bottom of the file.
- + Fix bg/fg bug where tmp file exiting caused a NULL dereference.
- + Rework file locking code to use fcntl(2) explicitly.
- + Fix bug in section code where invalid macros could be matched.
- + Fix bug where line number reset by vi's Q command.
- + Add explicit character mode designation to character mode buffers.
- + Add <sys/ioctl.h> include to sex/sex_window.c, needed by NET/2
- vintage systems.
- + Change to always flush a character during suspend, 4BSD curses
- has the optimization where it doesn't flush after a standend().
- + Fix bug on OSF1 where <curses.h> changes the values of VERASE,
- VKILL and VWERASE to incorrect ones.
- + Fix bug where optarg used incorrectly in main.c.
- + Block all signals when acting on a signal delivery.
- + Fix recovery bug where RCV_EMAIL could fire even if there wasn't
- a backing file; format recovery message.
-1.24 -> 1.25 Sun Jul 17 14:33:38 1994
- + Stop allowing keyboard suspends (^Z) in insert mode, it's hard
- to get autowrite correct, and it's not historic practice.
- + Fix z^, z+ to match historic practice.
- + Bug in message handling, "vi +35 non-existent_file" lost the
- status message because the "+35" pushed onto the stack erased
- it. For now, change so that messages aren't displayed if there
- are keys waiting -- may need to add a "don't-erase" bit to the
- character in the stack instead.
- + Bug in svi_msgflush(), where error messages could come out in
- normal video.
-1.23 -> 1.24 Sat Jul 16 18:30:18 1994
- + Fix core dump in exf.c, where editing a non-existent file and
- exiting could cause already free'd memory to be free'd.
- + Clean up numerous memory errors, courtesy of Purify.
- + Change process wait code to fail if wait fails, and not attempt
- to interpret the wait return information.
- + Open recovery and DB files for writing as well as reading, System
- V (fcntl) won't let you acquire LOCK_EX locks otherwise.
- + Fix substitute bug where could malloc 0 bytes (AIX breaks).
- + Permit the mapping of <carriage-return>, it's historic practice.
- + Historic vi didn't eat <blank> characters before the force
- flag, match historic practice.
- + Bug in ex argument parsing, corrected for literal characters
- twice.
- + Delete screen specific maps when the screen closes.
- + Move to the first non-<blank> in the line on startup; historic
- practice.
- + Change the ex visual command to move directly to a line if no
- trailing 'z' command.
- + Fix "[[" and "]]" to match historic practice (yet again...).
- + Fix "yb" and "y{" commands to update the cursor correctly.
- + Change "~<motion>" to match the yank cursor movement semantics
- exactly.
- + Move all of the curses related code into sex/svi -- major rework,
- but should help in future ports.
- + Fix bug in split code caused by new file naming code, where would
- drop core when a split screen exited.
- + Change svi_ex_write to do character display translation, so that
- messages with file names in them are displayed correctly.
- + Display the file name on split screens instead of a divider line.
- + Fix move bug, wasn't copying lines before putting them.
- + Fix bug were :n dropped core if no arguments supplied.
- + Don't quote characters in executed buffer: "ifoo<esc>" should leave
- insert mode after the buffer is executed.
- + Tagpop and tagpush should set the absolute mark in case only moving
- within a file.
- + Skip leading whitespace characters before tags and cursor word
- searches.
- + Fix bug in ex_global where re_conv() was allocating the temporary
- buffer and not freeing it.
-1.22 -> 1.23: Wed Jun 29 19:22:33 1994
- + New <sys/cdefs.h> required "inline" to change to "__inline"
- + Fix System V curses code for new ^Z support.
- + Fix off-by-one in the move code, avoid ":1,$mo$" with only one
- line in the buffer.
- + Line orientation of motion commands was remembered too long,
- i.e. '.' command could be incorrectly marked as line oriented.
- + Move file modification time into EXF, so it's shared across
- split screens.
- + Put the prev[ious] command back in, people complained.
- + Random fixes to next/prev semantics changed in 1.22.
- + Historically vi doesn't only move to the last address if there's
- ANYTHING after the addresses, e.g. ":3" moves to line 3, ":3|"
- prints line 3.
-1.21 -> 1.22: Mon Jun 27 11:01:41 1994
- + Make the line between split screens inverse video again.
- + Delete the prev[ious] command, it's not useful enough to keep.
- + Rework :args/file name handling from scratch -- MAJOR CHANGE,
- likely to introduce all sorts of new bugs.
- + Fix RE bug where no subexpressions in the pattern but there were
- subexpressions referenced in the replacement, e.g. "s/XXX/\1/g".
- + Change recovery to not leave unmodified files around after a
- crash, by using the owner 'x' bit on unmodified backup files.
- MAJOR CHANGE, the system recovery script has to change!
- + Change -r option to delete recovery.* files that reference non-
- existent vi.* files.
- + Rework recovery locking so that fcntl(2) locking will work.
- + Fix append (upper-case) buffers, broken by cut fixes.
- + Fix | to not set the absolute motion mark.
- + Read $HOME/.exrc file on startup if the effective user ID is
- root. This makes running vi while su(1)'d work correctly.
- + Use the full pathname of the file as the recovery name, not
- just the last component. Matches historic practice.
- + Keep marks in empty files from being destroyed.
- + Block all caught signals before calling the DB routines.
- + Make the line change report match historic practice (yanked
- lines were different than everything else).
- + Add section on multiple screens to the reference manual.
- + Display all messages at once, combine onto a single line if
- possible. Delete the trailing period from all messages.
-1.20 -> 1.21: Thu May 19 12:21:58 1994
- + Delete the -l flag from the recover mail.
- + Send the user email if ex command :preserve executed, this matches
- historic practice. Lots of changes to the preserve and recovery
- code, change preserve to snapshot files (again, historic practice).
- + Make buffers match historic practice: "add logically stores text
- into buffer a, buffer 1, and the unnamed buffer.
- + Print <tab> characters as ^I on the colon command line if the
- list option set.
- + Adjust ^F and ^B scroll values in the presence of split screens
- and small windows.
- + Break msg* routines out from util.c into msg.c, start thinking
- about message catalogs.
- + Add tildeop set option, based on stevie's option of the same name.
- Changes the ~ command into "[count] ~ motion", i.e. ~ takes a
- trailing motion.
- + Chose NOT to match historic practice on cursor positioning after
- consecutive undo commands on a single line; see vi/v_undo.c for
- the comment.
- + Add a one line cache so that multiple changes to the same line
- are only counted once (e.g. "dl35p" changes one line, not 35).
- + Rework signals some more. Block file sync signals in vi routines
- that interface to DB, so can sync the files at interrupt time.
- Write up all of the signal handling arguments, see signal.c.
-1.19 -> 1.20: Thu May 5 19:24:57 1994
- + Return ^Z to synchronous handling. See the dicussion in signal.c
- and svi_screen.c:svi_curses_init().
- + Fix bug where line change report was wrong in util.c:msg_rpt().
-1.18 -> 1.19: Thu May 5 12:59:51 1994
- + Block DSUSP so that ^Y isn't delivered at SIGTSTP.
- + Fix bug -- put into an empty file leaves the cursor at 1,0,
- not the first nonblank.
- + Fix bug were number of lines reported for the 'P' command was
- off-by-one.
- + Fix bug were 0^D wasn't being handled correctly.
- + Delete remnants of ^Z as a raw character.
- + Fix bug where if a map was an entire colon command, it may never
- have been displayed.
- + Final cursor position fixes for the vi T and t commands.
- + The ex :next command took an optional ex command as it's first
- argument similar to the :edit commands. Match historic practice.
-1.17 -> 1.18: Wed May 4 13:57:10 1994
- + Rework curses information in the PORT/Makefile's.
- + Minor fixes to ^Z asynchronous code.
-1.16 -> 1.17: Wed May 4 11:15:56 1994
- + Make ex comment handling match historic practice.
- + Make ^Z work asynchronously, we can no longer use the SIGTSTP
- handler in the curses library.
-1.15 -> 1.16: Mon May 2 19:42:07 1994
- + Make the 'p' and 'P' commands support counts, i.e. "Y10p" works.
- + Make characters that map to themselves as the first part of the
- mapping work, it's historic practice.
- + Fix bug where "s/./\& /" discarded the space in the replacement
- string.
- + Add support for up/down cursor arrows in text input mode, rework
- left/right support to match industry practice.
- + Fix bug were enough character remapping could corrupt memory.
- + Delete O_REMAPMAX in favor of setting interrupts after N mapped
- characters without a read, delete the map counter per character.
- MAJOR CHANGE. All of the interrupt signal handling has been
- reworked so that interrupts are always turned on instead of
- being turned on periodically, when an interruptible operation is
- pending.
- + Fix bug where vi wait() was interrupted by the recovery alarm.
- + Make +cmd's and initial commands execute with the current line
- set to the last line of the file. This is historic practice.
- + Change "lock failed" error message to a file status message.
- It always fails over NFS, and making all NFS files readonly
- isn't going to fly.
- + Use the historic line number format, but check for overflow.
- + Fix bug where vi command parser ignored buffers specified as
- part of the motion command.
- + Make [@*]buffer commands on character mode buffers match historic
- practice.
- + Fix bug where the cmap/chf entries of the tty structure weren't
- being cleared when new characters were read.
- + Fix bug where the default command motion flags were being set
- when the command was a motion component.
- + Fix wrapmargin bug; if appending characters, and wrapmargin breaks
- the line, an additional space is eaten.
-1.14 -> 1.15: Fri Apr 29 07:44:57 1994
- + Make the ex delete command work in any empty file.
- + Fix bug where 't' command placed the cursor on the character
- instead of to its left.
- + ^D and ^U didn't set the scroll option value historically.
- Note, this change means that any user set value (e.g. 15^D)
- will be lost when splitting the screen, since the split code
- now resets the scroll value regardless.
- + Fix the ( command to set the absolute movement mark.
- + Only use TIOCGWINSZ for window information if SIGWINCH signal
- caught.
- + Delete the -l flag, and make -r work for multiple arguments.
- Add the ex "recover[!] file" command.
- + Switch into ex terminal mode and use the sex routines when
- append/change/insert called from vi mode.
- + Make ^F and ^B match historic practice. This required a fairly
- extensive rework of the svi scrolling code.
- + Cursor positioning in H, M, L, G (first non-blank for 1G) wasn't
- being done correctly. Delete the SETLFNB flag. H, M, and L stay
- logical movements (SETNNB) and G always moves to the first nonblank.
- + System V uses "lines" and "cols", not "li" and "co", change as
- necessary. Check termcap function returns for errors.
- + Fix `<character> command to do start/end of line correction,
- and to set line mode if starting and stopping at column 0.
- + Fix bug in delete code where dropped core if deleted in character
- mode to an empty line. (Rework the delete code for efficiency.)
- + Give up on SunOS 4.1.X, and use "cc" instead of /usr/5bin/cc.
- + Protect ex_getline routine from interrupted system calls (if
- possible, set SA_RESTART on SIGALRM, too).
- + Fix leftright scrolling bug, when moving to a shorter line.
- + Do validity checking on the copy, move, t command target line
- numbers.
- + Change for System V % pattern broke trailing flags for empty
- replacement strings.
- + Fix bug when RCM flags retained in the saved dot structure.
- + Make the ex '=' command work for empty files.
- + Fix bug where special_key array was being free'd (it's no longer
- allocated).
- + Matches cut in line mode only if the starting cursor is at or
- before the first nonblank in its line, and the ending cursor is
- at or after the last nonblank in its line.
- + Add the :wn command, so you can write a file and switch to a new
- file in one command.
- + Allow only a single key as an argument to :viusage.
- + New movement code broke filter/paragraph operations in empty
- files ("!}date" in an empty file was dropping core).
-1.12 -> 1.14: Mon Apr 18 11:05:10 1994 (PUBLICLY AVAILABLE VERSION, 4.4BSD)
- + Fix FILE structure leakage in the ex filter code.
- + Rework suspend code for System V curses. Nvi has to do the
- the work, there's no way to get curses to do it right.
- + Revert SunOS 4.1.X ports to the distributed curses. There's
- a bug in Sun's implementation that we can't live with.
- + Quit immediately if row/column values are unreasonable.
- + Fix the function keys to match vi historic behavior.
- + Replace the echo/awk magic in the Makefile's with awk scripts.
-1.11 -> 1.12: Thu Apr 14 11:10:19 1994
- + Fix bug where only the first vi key was checked for validity.
- + Make 'R' continue to overwrite after a <carriage-return>.
- + Only display the "no recovery" message once.
- + Rework line backup code to restore the line to its previous
- condition.
- + Don't permit :q in a .exrc file or EXINIT variable.
- + Fix wrapscan option bug where forward searches become backward
- searches and do cursor correction accordingly.
- + Change "dd" to move the cursor to the first non-blank on the line.
- + Delete cursor attraction to the first non-blank, change non-blank
- motions to set the most attractive cursor position instead.
- + Fix 'r' substitute option to set the RE to the last RE, not the
- last substitute RE.
- + Fix 'c' and 'g' substitute options to always toggle, and fix
- edcompatible option to not reset them.
- + Display ex error messages in inverse video.
- + Fix errorbells option to match historic practice.
- + Delete fixed character display table in favor of table built based
- on the current locale.
- + Add ":set octal" option, that displays unknown characters as octal
- values instead of the default hexadecimal.
- + Make all command and text input modes interruptible.
- + Fix ex input mode to display error messages immediately, instead
- of waiting for the lines to be resolved.
- + Fix bug where vi calling append could overwrite the command.
- + Fix off-by-one in the ex print routine tab code.
- + Fix incorrect ^D test in vi text input routines.
- + Add autoindent support for ex text insert routines.
- + Add System V substitute command replacement pattern semantics,
- where '%' means the last replacement pattern.
- + Fix bug that \ didn't escape newlines in ex commands.
- + Regularize the names of special characters to CH_*.
- + Change hex insert character from ^Vx<hex_char> to ^X<hex_char>
- + Integrate System V style curses, so SunOS and Solaris ports can
- use the native curses implementation.
-1.10 -> 1.11: Thu Mar 24 16:07:45 EST 1994 (PUBLICLY AVAILABLE VERSION)
- + Change H, M, and L to set the absolute mark, historical practice.
- + Fix bug in stepping through multiple tags files.
- + Add "remapmax" option that turns off map counts so you can remap
- infinitely. If it's off, term_key() can be interrupted from the
- keyboard, which will cause the buffers to flush. I also dropped
- the default max number of remaps to 50. (Only Dave Hitz's TM
- macros and maze appear to go over that limit.)
- + Change :mkexrc to not dump w{300,1200,9600}, lisp options.
- + Fix backward search within a line bug.
- + Change all the includes of "pathnames.h" to use <>'s so that the
- PORT versions can use -I. to replace it with their own versions.
- + Make reads and writes interruptible. Rework code that enters and
- leaves ex for '!' and filter commands, rework all interrupt and
- timer code.
- + Fix core dump when user displayed option in .exrc file.
- + Fix bug where writing empty files didn't update the saved
- modification time.
- + Fix bug where /pattern/ addressing was always a backward search.
- + Fix bug triggered by autoindent of more than 32 characters, where
- nvi wasn't checking the right TEXT length.
- + Fix bug where joining only empty lines caused a core dump.
-1.09 -> 1.10: Sat Mar 19 15:40:29 EST 1994
- + Fix "set all" core dump.
-1.08 -> 1.09: Sat Mar 19 10:11:14 EST 1994
- + If the tag's file path is relative, and it doesn't exist, check
- relative to the tag file location.
- + Fix ~ command to free temporary buffer on error return.
- + Create vi.ref, a first cut at a reference document for vi.
- The manual page and the reference document only document the
- set options, so far.
- + Fix 1G bug not always going to the first non-blank.
- + Upgrade PORT/regex to release alpha3.4, from Henry Spencer.
- + Add MKS vi's "cdpath" option, supporting a cd search path.
- + Handle if search as a motion was discarded, i.e. "d/<erase>".
- + Change nvi to not create multiple recovery files if modifying
- a recovered file.
- + Decide to ignore that the cursor is before the '$' when inserting
- in list mode. It's too hard to fix.
-1.07 -> 1.08: Wed Mar 16 07:37:36 EST 1994
- + Leftright and big line scrolling fixes. This meant more changes
- to the screen display code, so there may be new problems.
- + Don't permit search-style addresses until a file has been read.
- + "c[Ww]" command incorrectly handled the "in whitespace" case.
- + Fix key space allocation bug triggered by cut/paste under SunOS.
- + Ex move command got the final cursor position wrong.
- + Delete "optimize option not implemented" message.
- + Make the literal-next character turn off mapping for the next
- character in text input mode.
-1.06 -> 1.07: Mon Mar 14 11:10:33 EST 1994
- + The "wire down" change in 1.05 broke ex command parsing, there
- wasn't a corresponding change to handle multiple K_VLNEXT chars.
- + Fix final position for vi's 't' command.
-1.05 -> 1.06: Sun Mar 13 16:12:52 EST 1994
- + Wire down ^D, ^H, ^W, and ^V, regardless of the user's termios
- values.
- + Add ^D as the ex scroll command.
- + Support ^Q as a literal-next character.
- + Rework abbreviations to be delimited by any !inword() character.
- + Add options description to the manual page.
- + Minor screen cache fix for svi_get.c.
- + Rework beautify option support to match historical practice.
- + Exit immediately if not reading from a tty and a command fails.
- + Default the SunOS 4.* ports to the distributed curses, not SMI's.
-1.04 -> 1.05: Thu Mar 24 16:07:45 EST 1994
- + Make cursor keys work in input mode.
- + Rework screen column code in vi curses screen. MAJOR CHANGE --
- after this, we'll be debugging curses screen presentation from
- scratch.
- + Explode include files in vi.h into the source files.
-1.03 -> 1.04: Sun Mar 6 14:14:16 EST 1994
- + Make the ex move command keep the marks on the moved lines.
- + Change resize semantics so you can set the screen size to a
- specific value. A couple of screen fixes for the resize code.
- + Fixes for foreground/background due to SIGWINCH.
- + Complete rework of all of vi's cursor movements. The underlying
- assumption in the old code was that the starting cursor position
- was part of the range of lines cut or deleted. The command
- "d[[" is an example where this isn't true. Change it so that all
- motion component commands set the final cursor position separately
- from the range, as it can't be done correctly later. This is a
- MAJOR CHANGE -- after this change, we'll be debugging the cursor
- positioning from scratch.
- + Rewrite the B, b, E, e commands to use vi's getc() interface
- instead of rolling their own.
- + Add a second MARK structure, LMARK, which is the larger mark
- needed by the logging and mark queue code. Everything else uses
- the reworked MARK structure, which is simply a line/column pair.
- + Rework cut/delete to not expect 1-past-the-end in the range, but
- to act on text to the end of the range, inclusive.
- + Sync on write's, to force NFS to flush.
-1.01 -> 1.03: Sun Jan 23 17:50:35 EST 1994 (PUBLICLY AVAILABLE VERSION)
- + Tag stack fixes, was returning to the tag, not the position from
- which the user tagged.
- + Only use from the cursor to the end of the word in cursor word
- searches and tags. (Matches historical vi behavior.)
- + Fix delete-last-line bug when line number option set.
- + Fix usage line for :split command.
- + If O_NUMBER set, long input lines would eventually fail, the column
- count for the second screen of long lines wasn't set correctly.
- + Fix for [[ reaching SOF with a column longer than the first line.
- + Fix for multiple error messages if no screen displayed.
- + Fix :read to set alternate file name as in historical practice.
- + Fix cut to rotate the numeric buffers if line mode flag set.
-1.00 -> 1.01: Wed Jan 12 13:37:18 EST 1994
- + Don't put cut items into numeric buffers if cutting less than
- parts of two lines.
-0.94 -> 1.00: Mon Jan 10 02:27:27 EST 1994
- + Read-ahead not there; BSD tty driver problem, SunOS curses
- problem.
- + Global command could error if it deleted the last line of
- the file.
- + Change '.' to only apply to the 'u' if entered immediately
- after the 'u' command. "1pu.u.u. is still broken, but I
- expect that it's going to be sacrificed for multiple undo.
- + If backward motion on a command, now move to the point; get
- yank cursor positioning correct.
- + Rework cut buffers to match historic practice -- yank/delete
- numeric buffers redone sensibly, ignoring historic practice.
-0.92 -> 0.93: Mon Dec 20 19:52:14 EST 1993
- + Christos Zoulas reimplemented the script windows using pty's,
- which means that they now work reasonably. The down side of
- this is that almost all ports other than 4.4BSD need to include
- two new files, login_tty.c and pty.c from the PORT/clib directory.
- I've added them to the Makefiles.
- + All calloc/malloc/realloc functions now cast their pointers, for
- SunOS -- there should be far fewer warning messages, during the
- build. The remaining messages are where CHAR_T's meet char *'s,
- i.e. where 8-bit clean meets strcmp.
- + The user's argument list handling has been reworked so that there
- is always a single consistent position for use by :next, :prev and
- :rewind.
- + All of the historical options are now at least accepted, although
- not all of them are implemented. (Edcompatible, hardtabs, lisp,
- optimize, redraw, and slowopen aren't implemented.)
- + The RE's have been reworked so that matches of length 0 are handled
- in the same way as vi used to handle them.
- + Several more mapping fixes and ex parser addressing fixes.
diff --git a/usr.bin/vi/docs/internals/quoting b/usr.bin/vi/docs/internals/quoting
deleted file mode 100644
index f20bd3f2b1e9..000000000000
--- a/usr.bin/vi/docs/internals/quoting
+++ /dev/null
@@ -1,219 +0,0 @@
-# @(#)quoting 5.4 (Berkeley) 8/20/93
-
-QUOTING IN EX/VI:
-
-There are two escape characters in historic ex/vi, ^V (or whatever
-character the user specified as their literal next character) and
-backslashes. There are two different areas in ex/vi where escaping
-is interesting: the command and text input modes, and within the ex
-commands themselves. In the examples below, ^V is used as the
-typical literal next character.
-
-1: Escaping characters in ex and vi command and text input modes.
- The set of characters that users might want to escape are as
- follows:
-
- vi text input mode (a, i, o, etc.):
-
- carriage return (^M)
- escape (^[)
- autoindent characters
- (^D, 0, ^, ^T)
- erase, word erase, and line erase
- (^H, ^W, ^U)
- newline (^J) (not historic practice)
- suspend (^Z) (not historic practice)
- repaint (^L) (not historic practice)
-
- vi command line (:colon commands):
-
- carriage return (^M)
- escape (^[)
- erase, word erase, and line erase
- (^H, ^W, ^U)
- newline (^J) (not historic practice)
- suspend (^Z) (not historic practice)
- repaint (^L) (not historic practice)
-
- ex text input mode (a, i, o, etc.):
-
- carriage return (^M)
- erase, word erase, and line erase
- (^H, ^W, ^U)
- newline (^J) (not historic practice)
-
- ex command line:
-
- carriage return (^M)
- erase, word erase, and line erase
- (^H, ^W, ^U)
- newline (^J) (not historic practice)
- suspend (^Z)
-
- I intend to follow historic practice for all of these cases, which
- was that ^V was the only way to escape any of these characters, and
- that whatever character followed the ^V was taken literally, i.e.
- ^V^V is a single ^V.
-
- The historic ex/vi disallowed the insertion of various control
- characters (^D, ^T, whatever) during various different modes, or,
- permitted the insertion of only a single one, or lots of other random
- behaviors (you can use ^D to enter a command in ex). I have
- regularized this behavior in nvi, there are no characters that cannot
- be entered or which have special meaning other than the ones listed
- above.
-
- One comment regarding the autoindent characters. In historic vi,
- if you entered "^V0^D" autoindent erasure was still triggered,
- although it wasn't if you entered "0^V^D". In nvi, if you escape
- either character, autoindent erasure is not triggered.
-
- This doesn't permit whitespace in command names, but that wasn't
- historic practice and doesn't seem worth doing.
-
- Fun facts to know and tell:
- The historic vi implementation for the 'r' command requires
- *three* ^V's to replace a single character with ^V.
-
-2: Ex commands:
-
- Ex commands are delimited by '|' or newline characters. Within
- the commands, whitespace characters delimit the arguments.
-
- I intend to treat ^V, followed by any character, as that literal
- character.
-
- This is historic behavior in vi, although there are special
- cases where it's impossible to escape a character, generally
- a whitespace character.
-
-3: Escaping characters in file names in ex commands:
-
- :cd [directory] (directory)
- :chdir [directory] (directory)
- :edit [+cmd] [file] (file)
- :ex [+cmd] [file] (file)
- :file [file] (file)
- :next [file ...] (file ...)
- :read [!cmd | file] (file)
- :source [file] (file)
- :write [!cmd | file] (file)
- :wq [file] (file)
- :xit [file] (file)
-
- I intend to treat a backslash in a file name, followed by any
- character, as that literal character.
-
- This is historic behavior in vi.
-
- In addition, since file names are also subject to word expansion,
- the rules for escape characters in section 3 of this document also
- apply. This is NOT historic behavior in vi, making it impossible
- to insert a whitespace, newline or carriage return character into
- a file name. This change could cause a problem if there were files
- with ^V's in their names, but I think that's unlikely.
-
-4: Escaping characters in non-file arguments in ex commands:
-
- :abbreviate word string (word, string)
-* :edit [+cmd] [file] (+cmd)
-* :ex [+cmd] [file] (+cmd)
- :k key (key)
- :map word string (word, string)
- :mark key (key)
-* :set [option ...] (option)
-* :tag string (string)
- :unabbreviate word (word)
- :unmap word (word)
-
- These commands use whitespace to delimit their arguments, and use
- ^V to escape those characters. The exceptions are starred in the
- above list, and are discussed below.
-
- In general, I intend to treat a ^V in any argument, followed by
- any character, as that literal character. This will permit
- editing of files name "foo|", for example, by using the string
- "foo\^V|", where the literal next character protects the pipe
- from the ex command parser and the backslash protects it from the
- shell expansion.
-
- This is backward compatible with historical vi, although there
- were a number of special cases where vi wasn't consistent.
-
-4.1: The edit/ex commands:
-
- The edit/ex commands are a special case because | symbols may
- occur in the "+cmd" field, for example:
-
- :edit +10|s/abc/ABC/ file.c
-
- In addition, the edit and ex commands have historically ignored
- literal next characters in the +cmd string, so that the following
- command won't work.
-
- :edit +10|s/X/^V / file.c
-
- I intend to handle the literal next character in edit/ex consistently
- with how it is handled in other commands.
-
- More fun facts to know and tell:
- The acid test for the ex/edit commands:
-
- date > file1; date > file2
- vi
- :edit +1|s/./XXX/|w file1| e file2|1 | s/./XXX/|wq
-
- No version of vi, of which I'm aware, handles it.
-
-4.2: The set command:
-
- The set command treats ^V's as literal characters, so the following
- command won't work. Backslashes do work in this case, though, so
- the second version of the command does work.
-
- set tags=tags_file1^V tags_file2
- set tags=tags_file1\ tags_file2
-
- I intend to continue permitting backslashes in set commands, but
- to also permit literal next characters to work as well. This is
- backward compatible, but will also make set consistent with the
- other commands. I think it's unlikely to break any historic
- .exrc's, given that there are probably very few files with ^V's
- in their name.
-
-4.3: The tag command:
-
- The tag command ignores ^V's and backslashes; there's no way to
- get a space into a tag name.
-
- I think this is a don't care, and I don't intend to fix it.
-
-5: Regular expressions:
-
- :global /pattern/ command
- :substitute /pattern/replace/
- :vglobal /pattern/ command
-
- I intend to treat a backslash in the pattern, followed by the
- delimiter character or a backslash, as that literal character.
-
- This is historic behavior in vi. It would get rid of a fairly
- hard-to-explain special case if we could just use the character
- immediately following the backslash in all cases, or, if we
- changed nvi to permit using the literal next character as a
- pattern escape character, but that would probably break historic
- scripts.
-
- There is an additional escaping issue for regular expressions.
- Within the pattern and replacement, the '|' character did not
- delimit ex commands. For example, the following is legal.
-
- :substitute /|/PIPE/|s/P/XXX/
-
- This is a special case that I will support.
-
-6: Ending anything with an escape character:
-
- In all of the above rules, an escape character (either ^V or a
- backslash) at the end of an argument or file name is not handled
- specially, but used as a literal character.
diff --git a/usr.bin/vi/docs/internals/structures b/usr.bin/vi/docs/internals/structures
deleted file mode 100644
index d49ab65cbeed..000000000000
--- a/usr.bin/vi/docs/internals/structures
+++ /dev/null
@@ -1,61 +0,0 @@
-# @(#)structures 5.2 (Berkeley) 11/1/93
-
-There are three major data structures in this package. The first is a
-single global structure (named GS) which contains information common to
-all files and screens. It's really pretty tiny, and functions more as a
-single place to hang things than anything else.
-
-The second and third structures are the file structures (named EXF) and
-the screen structures (named SCR). They contain information theoretically
-unique to a screen or file, respectively. Each SCR structure has a set
-of functions which update the screen and/or return information about the
-screen from the underlying screen package.
-
-The GS structure contains linked lists SCR structures. The structures
-can also be classed by persistence. The GS structure never goes away
-and the SCR structure persists over instances of files.
-
-File names have different properties than files themselves, so the name
-information for a file is held in an FREF structure which is chained from
-the SCR structure.
-
-In general, functions are always passed an SCR structure and often an EXF
-structure as well. The SCR structure is necessary for any routine that
-wishes to talk to the screen, the EXF structure is necessary for any
-routine that wants to modify the file. The relationship between an SCR
-structure and its underlying EXF structure is not fixed, and although you
-can translate from an SCR to the underlying EXF, it is discouraged. If
-this becomes too onerous, I suspect I'll just stop passing around the EXF
-in the future.
-
-The naming of the structures is consistent across the program. (Macros
-even depend on it, so don't try and change it!) The global structure is
-"gp", the screen structure is "sp", and the file structure is "ep".
-
-A few other data structures:
-
-TEXT In nvi/cut.h. This structure describes a portion of a line,
- and is used by the input routines and as the "line" part of a
- cut buffer.
-
-CB In nvi/cut.h. A cut buffer. A cut buffer is a place to
- hang a list of TEXT structures.
-
-MARK In nvi/mark.h. A cursor position, consisting of a line number
- and a column number.
-
-MSG In nvi/msg.h. A chain of messages for the user.
-
-SEQ In nvi/seq.h. An abbreviation or a map entry.
-
-EXCMDARG
- In nvi/ex/excmd.h.stub. The structure that gets passed around
- to the functions that implement the ex commands. (The main
- ex command loop (see nvi/ex/ex.c) builds this up and then passes
- it to the ex functions.)
-
-VICMDARG
- In nvi/vi/vcmd.h. The structure that gets passed around to the
- functions that implement the vi commands. (The main vi command
- loop (see nvi/vi/vi.c) builds this up and then passes it to the
- vi functions.)
diff --git a/usr.bin/vi/ex/ex.c b/usr.bin/vi/ex/ex.c
deleted file mode 100644
index c0455a1f996a..000000000000
--- a/usr.bin/vi/ex/ex.c
+++ /dev/null
@@ -1,1866 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex.c 8.155 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-static void badlno __P((SCR *, recno_t));
-static __inline EXCMDLIST const *
- ex_comm_search __P((char *, size_t));
-static int ep_line __P((SCR *, EXF *, MARK *, char **, size_t *, int *));
-static int ep_range __P((SCR *, EXF *, EXCMDARG *, char **, size_t *));
-
-/*
- * ex --
- * Read an ex command and execute it.
- */
-int
-ex(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- enum input irval;
- TEXT *tp;
- u_int flags, saved_mode;
- int eval;
-
- if (ex_init(sp, ep))
- return (1);
-
- if (sp->s_refresh(sp, ep))
- return (ex_end(sp));
-
- /* If reading from a file, messages should have line info. */
- if (!F_ISSET(sp->gp, G_STDIN_TTY)) {
- sp->if_lno = 1;
- sp->if_name = strdup("input");
- }
-
- /*
- * !!!
- * Historically, the beautify option applies to ex command input read
- * from a file. In addition, the first time a ^H was discarded from
- * the input, a message "^H discarded" was displayed. We don't bother.
- */
- LF_INIT(TXT_BACKSLASH | TXT_CNTRLD | TXT_CR | TXT_EXSUSPEND);
-
- for (eval = 0;; ++sp->if_lno) {
- /* Set the flags that the user can change. */
- if (O_ISSET(sp, O_BEAUTIFY))
- LF_SET(TXT_BEAUTIFY);
- else
- LF_CLR(TXT_BEAUTIFY);
- if (O_ISSET(sp, O_PROMPT))
- LF_SET(TXT_PROMPT);
- else
- LF_CLR(TXT_PROMPT);
-
- /*
- * Get the next command. Interrupt flag manipulation is
- * safe because ex_icmd clears them all.
- */
- CLR_INTERRUPT(sp);
- F_SET(sp, S_INTERRUPTIBLE);
- irval = sp->s_get(sp, ep, sp->tiqp, ':', flags);
- if (INTERRUPTED(sp)) {
- (void)fputc('\n', stdout);
- (void)fflush(stdout);
- goto refresh;
- }
- switch (irval) {
- case INP_OK:
- break;
- case INP_EOF:
- case INP_ERR:
- F_SET(sp, S_EXIT_FORCE);
- /* FALLTHROUGH */
- case INP_INTR:
- goto ret;
- }
-
- /*
- * If the user entered a carriage return, send ex_cmd()
- * a separator -- it discards single newlines.
- */
- tp = sp->tiqp->cqh_first;
- if (tp->len == 0) {
- tp->len = 1;
- tp->lb[0] = ' ';
- }
-
- saved_mode = F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE);
- if (ex_icmd(sp, ep,
- tp->lb, tp->len, 1) && !F_ISSET(sp->gp, G_STDIN_TTY))
- F_SET(sp, S_EXIT_FORCE);
- (void)msg_rpt(sp, 0);
- if (saved_mode != F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE))
- break;
-
-refresh: if (sp->s_refresh(sp, ep)) {
- eval = 1;
- break;
- }
- }
-ret: if (sp->if_name != NULL) {
- FREE(sp->if_name, strlen(sp->if_name) + 1);
- sp->if_name = NULL;
- }
- return (ex_end(sp) || eval);
-}
-
-/*
- * ex_cfile --
- * Execute ex commands from a file.
- */
-int
-ex_cfile(sp, ep, filename, needsep)
- SCR *sp;
- EXF *ep;
- char *filename;
- int needsep;
-{
- struct stat sb;
- int fd, len, rval;
- char *bp;
-
- bp = NULL;
- if ((fd = open(filename, O_RDONLY, 0)) < 0 || fstat(fd, &sb))
- goto err;
-
- /*
- * XXX
- * We'd like to test if the file is too big to malloc. Since we don't
- * know what size or type off_t's or size_t's are, what the largest
- * unsigned integral type is, or what random insanity the local C
- * compiler will perpetrate, doing the comparison in a portable way
- * is flatly impossible. Hope that malloc fails if the file is too
- * large.
- */
- MALLOC(sp, bp, char *, (size_t)sb.st_size + 1);
- if (bp == NULL)
- goto err;
-
- len = read(fd, bp, (int)sb.st_size);
- if (len == -1 || len != sb.st_size) {
- if (len != sb.st_size)
- errno = EIO;
-err: rval = 1;
- msgq(sp, M_SYSERR, filename);
- } else {
- bp[sb.st_size] = '\0'; /* XXX */
-
- /*
- * Run the command. Messages include file/line information,
- * but we don't care if we can't get space.
- */
- sp->if_lno = 1;
- sp->if_name = strdup(filename);
- F_SET(sp, S_VLITONLY);
- rval = ex_icmd(sp, ep, bp, len, needsep);
- F_CLR(sp, S_VLITONLY);
- free(sp->if_name);
- sp->if_name = NULL;
- }
-
- /*
- * !!!
- * THE UNDERLYING EXF MAY HAVE CHANGED.
- */
- if (bp != NULL)
- FREE(bp, sb.st_size);
- if (fd >= 0)
- (void)close(fd);
- return (rval);
-}
-
-/*
- * ex_icmd --
- * Call ex_cmd() after turning off interruptible bits.
- */
-int
-ex_icmd(sp, ep, cmd, len, needsep)
- SCR *sp;
- EXF *ep;
- char *cmd;
- size_t len;
- int needsep;
-{
- /*
- * Ex goes through here for each vi :colon command and for each ex
- * command, however, globally executed commands don't go through
- * here, instead, they call ex_cmd directly. So, reset all of the
- * interruptible flags now.
- *
- * !!!
- * Previous versions of nvi cleared mapped characters on error. This
- * feature was removed when users complained that it wasn't historic
- * practice.
- */
- CLR_INTERRUPT(sp);
- return (ex_cmd(sp, ep, cmd, len, needsep));
-}
-
-/* Special command structure for :s as a repeat substitution command. */
-static EXCMDLIST const cmd_subagain =
- {"s", ex_subagain, E_ADDR2|E_NORC,
- "s",
- "[line [,line]] s [cgr] [count] [#lp]",
- "repeat the last subsitution"};
-
-/* Special command structure for :d[flags]. */
-static EXCMDLIST const cmd_del2 =
- {"delete", ex_delete, E_ADDR2|E_AUTOPRINT|E_NORC,
- "1bca1",
- "[line [,line]] d[elete][flags] [buffer] [count] [flags]",
- "delete lines from the file"};
-
-/*
- * ex_cmd --
- * Parse and execute a string containing ex commands.
- */
-int
-ex_cmd(sp, ep, cmd, cmdlen, needsep)
- SCR *sp;
- EXF *ep;
- char *cmd;
- size_t cmdlen;
- int needsep;
-{
- enum { NOTSET, NEEDSEP_N, NEEDSEP_NR, NONE } sep;
- EX_PRIVATE *exp;
- EXCMDARG exc;
- EXCMDLIST const *cp;
- MARK cur;
- recno_t lno, num;
- size_t arg1_len, len, save_cmdlen;
- long flagoff;
- u_int saved_mode;
- int blank, ch, cnt, delim, flags, namelen, nl;
- int optnum, uselastcmd, tmp, vi_address;
- char *arg1, *save_cmd, *p, *s, *t;
-
- /* Init. */
- nl = 0;
- sep = needsep ? NOTSET : NONE;
-loop: if (nl) {
- nl = 0;
- ++sp->if_lno;
- }
- arg1 = NULL;
- save_cmdlen = 0;
-
- /* It's possible that we've been interrupted during a command. */
- if (INTERRUPTED(sp))
- return (0);
-
- /* Skip <blank>s, empty lines. */
- for (blank = 0; cmdlen > 0; ++cmd, --cmdlen)
- if ((ch = *cmd) == '\n')
- ++sp->if_lno;
- else if (isblank(ch))
- blank = 1;
- else
- break;
-
- /*
- * !!!
- * Permit extra colons at the start of the line. Historically,
- * ex/vi allowed a single extra one. It's simpler not to count.
- * The stripping is done here because, historically, any command
- * could have preceding colons, e.g. ":g/pattern/:p" worked.
- */
- if (cmdlen != 0 && ch == ':') {
- if (sep == NOTSET)
- sep = NEEDSEP_N;
- while (--cmdlen > 0 && (ch = *++cmd) == ':');
- }
-
- /*
- * Command lines that start with a double-quote are comments.
- *
- * !!!
- * Historically, there was no escape or delimiter for a comment,
- * e.g. :"foo|set was a single comment and nothing was output.
- * Since nvi permits users to escape <newline> characters into
- * command lines, we have to check for that case.
- */
- if (cmdlen != 0 && ch == '"') {
- while (--cmdlen > 0 && *++cmd != '\n');
- if (*cmd == '\n') {
- nl = 1;
- ++cmd;
- --cmdlen;
- }
- goto loop;
- }
-
- /* Skip whitespace. */
- for (; cmdlen > 0; ++cmd, --cmdlen) {
- ch = *cmd;
- if (!isblank(ch))
- break;
- }
-
- /*
- * The last point at which an empty line can mean do nothing.
- *
- * !!!
- * Historically, in ex mode, lines containing only <blank> characters
- * were the same as a single <carriage-return>, i.e. a default command.
- * In vi mode, they were ignored.
- *
- * In .exrc files this was a serious annoyance, as vi kept trying to
- * treat them as print commands. We ignore backward compatibility in
- * this case, and discard lines containing only <blank> characters from
- * .exrc files.
- */
- if (cmdlen == 0 && (!IN_EX_MODE(sp) || ep == NULL || !blank))
- return (0);
-
- /* Initialize the structure passed to underlying functions. */
- memset(&exc, 0, sizeof(EXCMDARG));
- exp = EXP(sp);
- if (argv_init(sp, ep, &exc))
- goto err;
-
- /*
- * Check to see if this is a command for which we may want to output
- * a \r separator instead of a \n. (The command :1<CR> puts out a \n,
- * but the command :<CR> puts out a \r.) If the line is empty except
- * for <blank>s, <carriage-return> or <eof>, we'll probably want to
- * output \r. I don't think there's any way to get <blank> characters
- * *after* the command character, but this is the ex parser, and I've
- * been wrong before.
- */
- if (sep == NOTSET)
- sep = cmdlen == 0 || cmdlen == 1 && cmd[0] == '\004' ?
- NEEDSEP_NR : NEEDSEP_N;
-
- /* Parse command addresses. */
- if (ep_range(sp, ep, &exc, &cmd, &cmdlen))
- goto err;
-
- /* Skip whitespace. */
- for (; cmdlen > 0; ++cmd, --cmdlen) {
- ch = *cmd;
- if (!isblank(ch))
- break;
- }
-
- /*
- * If no command, ex does the last specified of p, l, or #, and vi
- * moves to the line. Otherwise, determine the length of the command
- * name by looking for the first non-alphabetic character. (There
- * are a few non-alphabetic characters in command names, but they're
- * all single character commands.) This isn't a great test, because
- * it means that, for the command ":e +cut.c file", we'll report that
- * the command "cut" wasn't known. However, it makes ":e+35 file" work
- * correctly.
- *
- * !!!
- * Historically, lines with multiple adjacent (or <blank> separated)
- * command separators were very strange. For example, the command
- * |||<carriage-return>, when the cursor was on line 1, displayed
- * lines 2, 3 and 5 of the file. In addition, the command " | "
- * would only display the line after the next line, instead of the
- * next two lines. No ideas why. It worked reasonably when executed
- * from vi mode, and displayed lines 2, 3, and 4, so we do a default
- * command for each separator.
- */
-#define SINGLE_CHAR_COMMANDS "\004!#&*<=>@~"
- if (cmdlen != 0 && cmd[0] != '|' && cmd[0] != '\n') {
- if (strchr(SINGLE_CHAR_COMMANDS, *cmd)) {
- p = cmd;
- ++cmd;
- --cmdlen;
- namelen = 1;
- } else {
- for (p = cmd; cmdlen > 0; --cmdlen, ++cmd)
- if (!isalpha(*cmd))
- break;
- if ((namelen = cmd - p) == 0) {
- msgq(sp, M_ERR, "Unknown command name");
- goto err;
- }
- }
-
- /*
- * !!!
- * Historic vi permitted flags to immediately follow any
- * subset of the 'delete' command, but then did not permit
- * further arguments (flag, buffer, count). Make it work.
- * Permit further arguments for the few shreds of dignity
- * it offers.
- *
- * !!!
- * Note, adding commands that start with 'd', and match
- * "delete" up to a l, p, +, - or # character can break
- * this code.
- */
- if (p[0] == 'd') {
- for (s = p,
- t = cmds[C_DELETE].name; *s == *t; ++s, ++t);
- if (s[0] == 'l' || s[0] == 'p' ||
- s[0] == '+' || s[0] == '-' || s[0] == '#') {
- len = (cmd - p) - (s - p);
- cmd -= len;
- cmdlen += len;
- cp = &cmd_del2;
- goto skip;
- }
- }
-
- /*
- * Search the table for the command.
- *
- * !!!
- * Historic vi permitted the mark to immediately follow the
- * 'k' in the 'k' command. Make it work.
- *
- * !!!
- * Historic vi permitted pretty much anything to follow the
- * substitute command, e.g. "s/e/E/|s|sgc3p" was fine. Make
- * the command "sgc" work.
- */
- if ((cp = ex_comm_search(p, namelen)) == NULL)
- switch (p[0]) {
- case 's':
- cmd -= namelen - 1;
- cmdlen += namelen - 1;
- cp = &cmd_subagain;
- break;
- case 'k':
- if (p[1] && !p[2]) {
- cmd -= namelen - 1;
- cmdlen += namelen - 1;
- cp = &cmds[C_K];
- break;
- }
- /* FALLTHROUGH */
- default:
- msgq(sp, M_ERR,
- "The %.*s command is unknown", namelen, p);
- goto err;
- }
-
- /* Some commands are either not implemented or turned off. */
-skip: if (F_ISSET(cp, E_NOPERM)) {
- msgq(sp, M_ERR,
- "The %s command is not currently supported",
- cp->name);
- goto err;
- }
-
- /* Some commands aren't okay in globals. */
- if (F_ISSET(sp, S_GLOBAL) && F_ISSET(cp, E_NOGLOBAL)) {
- msgq(sp, M_ERR,
- "The %s command can't be used as part of a global command",
- cp->name);
- goto err;
- }
-
- /*
- * Multiple < and > characters; another "feature". Note,
- * The string passed to the underlying function may not be
- * nul terminated in this case.
- */
- if ((cp == &cmds[C_SHIFTL] && *p == '<') ||
- (cp == &cmds[C_SHIFTR] && *p == '>')) {
- for (ch = *p; cmdlen > 0; --cmdlen, ++cmd)
- if (*cmd != ch)
- break;
- if (argv_exp0(sp, ep, &exc, p, cmd - p))
- goto err;
- }
-
- /*
- * The visual command has a different syntax when called
- * from ex than when called from a vi colon command. FMH.
- */
- if (cp == &cmds[C_VISUAL_EX] && IN_VI_MODE(sp))
- cp = &cmds[C_VISUAL_VI];
-
- /* Set the format style flags for the next command. */
- if (cp == &cmds[C_HASH])
- exp->fdef = E_F_HASH;
- else if (cp == &cmds[C_LIST])
- exp->fdef = E_F_LIST;
- else if (cp == &cmds[C_PRINT])
- exp->fdef = E_F_PRINT;
- uselastcmd = 0;
- } else {
- /* Print is the default command. */
- cp = &cmds[C_PRINT];
-
- /* Set the saved format flags. */
- F_SET(&exc, exp->fdef);
-
- /*
- * !!!
- * If no address was specified, and it's not a global command,
- * we up the address by one. (I have not an idea why global
- * commands are exempted, but it's (ahem) historic practice.
- */
- if (exc.addrcnt == 0 && !F_ISSET(sp, S_GLOBAL)) {
- exc.addrcnt = 1;
- exc.addr1.lno = sp->lno + 1;
- exc.addr1.cno = sp->cno;
- }
-
- uselastcmd = 1;
- }
-
- /*
- * !!!
- * Historically, the number option applied to both ex and vi. One
- * strangeness was that ex didn't switch display formats until a
- * command was entered, e.g. <CR>'s after the set didn't change to
- * the new format, but :1p would.
- */
- if (O_ISSET(sp, O_NUMBER)) {
- optnum = 1;
- F_SET(&exc, E_F_HASH);
- } else
- optnum = 0;
-
- /* Initialize local flags to the command flags. */
- LF_INIT(cp->flags);
-
- /*
- * File state must be checked throughout this code, because it is
- * called when reading the .exrc file and similar things. There's
- * this little chicken and egg problem -- if we read the file first,
- * we won't know how to display it. If we read/set the exrc stuff
- * first, we can't allow any command that requires file state. We
- * don't have a "reading an rc" bit, because we want the commands
- * to work when the user source's the rc file later. Historic vi
- * generally took the easy way out and dropped core.
- */
- if (LF_ISSET(E_NORC) && ep == NULL) {
- msgq(sp, M_ERR,
- "The %s command requires that a file have already been read in",
- cp->name);
- goto err;
- }
-
- /*
- * There are three normal termination cases for an ex command. They
- * are the end of the string (cmdlen), or unescaped (by literal next
- * characters) newline or '|' characters. As we're past any addresses,
- * we can now determine how long the command is, so we don't have to
- * look for all the possible terminations. There are three exciting
- * special cases:
- *
- * 1: The bang, global, vglobal and the filter versions of the read and
- * write commands are delimited by newlines (they can contain shell
- * pipes).
- * 2: The ex, edit, next and visual in vi mode commands all take ex
- * commands as their first arguments.
- * 3: The substitute command takes an RE as its first argument, and
- * wants it to be specially delimited.
- *
- * Historically, '|' characters in the first argument of the ex, edit,
- * next, vi visual, and substitute commands didn't delimit the command.
- * And, in the filter cases for read and write, and the bang, global
- * and vglobal commands, they did not delimit the command at all.
- *
- * For example, the following commands were legal:
- *
- * :edit +25|s/abc/ABC/ file.c
- * :substitute s/|/PIPE/
- * :read !spell % | columnate
- * :global/pattern/p|l
- *
- * It's not quite as simple as it sounds, however. The command:
- *
- * :substitute s/a/b/|s/c/d|set
- *
- * was also legal, i.e. the historic ex parser (using the word loosely,
- * since "parser" implies some regularity) delimited the RE's based on
- * its delimiter and not anything so irretrievably vulgar as a command
- * syntax.
- *
- * One thing that makes this easier is that we can ignore most of the
- * command termination conditions for the commands that want to take
- * the command up to the next newline. None of them are legal in .exrc
- * files, so if we're here, we only dealing with a single line, and we
- * can just eat it.
- *
- * Anyhow, the following code makes this all work. First, for the
- * special cases we move past their special argument(s). Then, we
- * do normal command processing on whatever is left. Barf-O-Rama.
- */
- arg1_len = 0;
- save_cmd = cmd;
- if (cp == &cmds[C_EDIT] || cp == &cmds[C_EX] ||
- cp == &cmds[C_NEXT] || cp == &cmds[C_VISUAL_VI]) {
- /*
- * Move to the next non-whitespace character. A '!'
- * immediately following the command is eaten as a
- * force flag.
- */
- if (cmdlen > 0 && *cmd == '!') {
- ++cmd;
- --cmdlen;
- F_SET(&exc, E_FORCE);
-
- /* Reset, don't reparse. */
- save_cmd = cmd;
- }
- for (tmp = 0; cmdlen > 0; --cmdlen, ++cmd)
- if (!isblank(*cmd))
- break;
- /*
- * QUOTING NOTE:
- *
- * The historic implementation ignored all escape characters
- * so there was no way to put a space or newline into the +cmd
- * field. We do a simplistic job of fixing it by moving to the
- * first whitespace character that isn't escaped by a literal
- * next character. The literal next characters are stripped
- * as they're no longer useful.
- */
- if (cmdlen > 0 && *cmd == '+') {
- ++cmd;
- --cmdlen;
- for (arg1 = p = cmd; cmdlen > 0; --cmdlen, ++cmd) {
- ch = *cmd;
- if (IS_ESCAPE(sp, ch) && cmdlen > 1) {
- --cmdlen;
- ch = *++cmd;
- } else if (isblank(ch))
- break;
- *p++ = ch;
- }
- arg1_len = cmd - arg1;
-
- /* Reset, so the first argument isn't reparsed. */
- save_cmd = cmd;
- }
- } else if (cp == &cmds[C_BANG] ||
- cp == &cmds[C_GLOBAL] || cp == &cmds[C_VGLOBAL]) {
- cmd += cmdlen;
- cmdlen = 0;
- } else if (cp == &cmds[C_READ] || cp == &cmds[C_WRITE]) {
- /*
- * Move to the next character. If it's a '!', it's a filter
- * command and we want to eat it all, otherwise, we're done.
- */
- for (; cmdlen > 0; --cmdlen, ++cmd) {
- ch = *cmd;
- if (!isblank(ch))
- break;
- }
- if (cmdlen > 0 && ch == '!') {
- cmd += cmdlen;
- cmdlen = 0;
- }
- } else if (cp == &cmds[C_SUBSTITUTE]) {
- /*
- * Move to the next non-whitespace character, we'll use it as
- * the delimiter. If the character isn't an alphanumeric or
- * a '|', it's the delimiter, so parse it. Otherwise, we're
- * into something like ":s g", so use the special substitute
- * command.
- */
- for (; cmdlen > 0; --cmdlen, ++cmd)
- if (!isblank(cmd[0]))
- break;
-
- if (isalnum(cmd[0]) || cmd[0] == '|')
- cp = &cmd_subagain;
- else if (cmdlen > 0) {
- /*
- * QUOTING NOTE:
- *
- * Backslashes quote delimiter characters for RE's.
- * The backslashes are NOT removed since they'll be
- * used by the RE code. Move to the third delimiter
- * that's not escaped (or the end of the command).
- */
- delim = *cmd;
- ++cmd;
- --cmdlen;
- for (cnt = 2; cmdlen > 0 && cnt; --cmdlen, ++cmd)
- if (cmd[0] == '\\' && cmdlen > 1) {
- ++cmd;
- --cmdlen;
- } else if (cmd[0] == delim)
- --cnt;
- }
- }
- /*
- * Use normal quoting and termination rules to find the end of this
- * command.
- *
- * QUOTING NOTE:
- *
- * Historically, vi permitted ^V's to escape <newline>'s in the .exrc
- * file. It was almost certainly a bug, but that's what bug-for-bug
- * compatibility means, Grasshopper. Also, ^V's escape the command
- * delimiters. Literal next quote characters in front of the newlines,
- * '|' characters or literal next characters are stripped as as they're
- * no longer useful.
- */
- vi_address = cmdlen != 0 && cmd[0] != '\n';
- for (p = cmd, cnt = 0; cmdlen > 0; --cmdlen, ++cmd) {
- ch = cmd[0];
- if (IS_ESCAPE(sp, ch) && cmdlen > 1) {
- tmp = cmd[1];
- if (tmp == '\n' || tmp == '|') {
- if (tmp == '\n')
- ++sp->if_lno;
- --cmdlen;
- ++cmd;
- ++cnt;
- ch = tmp;
- }
- } else if (ch == '\n' || ch == '|') {
- if (ch == '\n')
- nl = 1;
- --cmdlen;
- break;
- }
- *p++ = ch;
- }
-
- /*
- * Save off the next command information, go back to the
- * original start of the command.
- */
- p = cmd + 1;
- cmd = save_cmd;
- save_cmd = p;
- save_cmdlen = cmdlen;
- cmdlen = ((save_cmd - cmd) - 1) - cnt;
-
- /*
- * !!!
- * The "set tags" command historically used a backslash, not the
- * user's literal next character, to escape whitespace. Handle
- * it here instead of complicating the argv_exp3() code. Note,
- * this isn't a particularly complex trap, and if backslashes were
- * legal in set commands, this would have to be much more complicated.
- */
- if (cp == &cmds[C_SET])
- for (p = cmd, len = cmdlen; len > 0; --len, ++p)
- if (*p == '\\')
- *p = CH_LITERAL;
-
- /*
- * Set the default addresses. It's an error to specify an address for
- * a command that doesn't take them. If two addresses are specified
- * for a command that only takes one, lose the first one. Two special
- * cases here, some commands take 0 or 2 addresses. For most of them
- * (the E_ADDR2_ALL flag), 0 defaults to the entire file. For one
- * (the `!' command, the E_ADDR2_NONE flag), 0 defaults to no lines.
- *
- * Also, if the file is empty, some commands want to use an address of
- * 0, i.e. the entire file is 0 to 0, and the default first address is
- * 0. Otherwise, an entire file is 1 to N and the default line is 1.
- * Note, we also add the E_ZERO flag to the command flags, for the case
- * where the 0 address is only valid if it's a default address.
- *
- * Also, set a flag if we set the default addresses. Some commands
- * (ex: z) care if the user specified an address of if we just used
- * the current cursor.
- */
- switch (LF_ISSET(E_ADDR1|E_ADDR2|E_ADDR2_ALL|E_ADDR2_NONE)) {
- case E_ADDR1: /* One address: */
- switch (exc.addrcnt) {
- case 0: /* Default cursor/empty file. */
- exc.addrcnt = 1;
- F_SET(&exc, E_ADDRDEF);
- if (LF_ISSET(E_ZERODEF)) {
- if (file_lline(sp, ep, &lno))
- goto err;
- if (lno == 0) {
- exc.addr1.lno = 0;
- LF_SET(E_ZERO);
- } else
- exc.addr1.lno = sp->lno;
- } else
- exc.addr1.lno = sp->lno;
- exc.addr1.cno = sp->cno;
- break;
- case 1:
- break;
- case 2: /* Lose the first address. */
- exc.addrcnt = 1;
- exc.addr1 = exc.addr2;
- }
- break;
- case E_ADDR2_NONE: /* Zero/two addresses: */
- if (exc.addrcnt == 0) /* Default to nothing. */
- break;
- goto two;
- case E_ADDR2_ALL: /* Zero/two addresses: */
- if (exc.addrcnt == 0) { /* Default entire/empty file. */
- exc.addrcnt = 2;
- F_SET(&exc, E_ADDRDEF);
- if (file_lline(sp, ep, &exc.addr2.lno))
- goto err;
- if (LF_ISSET(E_ZERODEF) && exc.addr2.lno == 0) {
- exc.addr1.lno = 0;
- LF_SET(E_ZERO);
- } else
- exc.addr1.lno = 1;
- exc.addr1.cno = exc.addr2.cno = 0;
- F_SET(&exc, E_ADDR2_ALL);
- break;
- }
- /* FALLTHROUGH */
- case E_ADDR2: /* Two addresses: */
-two: switch (exc.addrcnt) {
- case 0: /* Default cursor/empty file. */
- exc.addrcnt = 2;
- F_SET(&exc, E_ADDRDEF);
- if (LF_ISSET(E_ZERODEF) && sp->lno == 1) {
- if (file_lline(sp, ep, &lno))
- goto err;
- if (lno == 0) {
- exc.addr1.lno = exc.addr2.lno = 0;
- LF_SET(E_ZERO);
- } else
- exc.addr1.lno = exc.addr2.lno = sp->lno;
- } else
- exc.addr1.lno = exc.addr2.lno = sp->lno;
- exc.addr1.cno = exc.addr2.cno = sp->cno;
- break;
- case 1: /* Default to first address. */
- exc.addrcnt = 2;
- exc.addr2 = exc.addr1;
- break;
- case 2:
- break;
- }
- break;
- default:
- if (exc.addrcnt) /* Error. */
- goto usage;
- }
-
- /*
- * !!!
- * The ^D scroll command historically scrolled the value of the scroll
- * option or to EOF. It was an error if the cursor was already at EOF.
- * (Leading addresses were permitted, but were then ignored.)
- */
- if (cp == &cmds[C_SCROLL]) {
- exc.addrcnt = 2;
- exc.addr1.lno = sp->lno + 1;
- exc.addr2.lno = sp->lno + O_VAL(sp, O_SCROLL);
- exc.addr1.cno = exc.addr2.cno = sp->cno;
- if (file_lline(sp, ep, &lno))
- goto err;
- if (lno != 0 && lno > sp->lno && exc.addr2.lno > lno)
- exc.addr2.lno = lno;
- }
-
- flagoff = 0;
- for (p = cp->syntax; *p != '\0'; ++p) {
- /*
- * The force flag is sensitive to leading whitespace, i.e.
- * "next !" is different from "next!". Handle it before
- * skipping leading <blank>s.
- */
- if (*p == '!') {
- if (cmdlen > 0 && *cmd == '!') {
- ++cmd;
- --cmdlen;
- F_SET(&exc, E_FORCE);
- }
- continue;
- }
-
- /* Skip leading <blank>s. */
- for (; cmdlen > 0; --cmdlen, ++cmd)
- if (!isblank(*cmd))
- break;
-
- /*
- * Quit when reach the end of the command, unless it's a
- * command that does its own parsing, in which case we want
- * to build a reasonable argv for it. This code guarantees
- * that there will be an argv when the function gets called,
- * so the correct test is for a length of 0, not for the
- * argc > 0. Since '!' can precede commands that do their
- * own parsing, we have to have already handled it.
- */
- if (cmdlen == 0 && *p != 'S' && *p != 's')
- break;
-
- switch (*p) {
- case '1': /* +, -, #, l, p */
- /*
- * !!!
- * Historically, some flags were ignored depending
- * on where they occurred in the command line. For
- * example, in the command, ":3+++p--#", historic vi
- * acted on the '#' flag, but ignored the '-' flags.
- * It's unambiguous what the flags mean, so we just
- * handle them regardless of the stupidity of their
- * location.
- */
- for (; cmdlen; --cmdlen, ++cmd)
- switch (*cmd) {
- case '+':
- ++flagoff;
- break;
- case '-':
- --flagoff;
- break;
- case '#':
- optnum = 0;
- F_SET(&exc, E_F_HASH);
- exp->fdef |= E_F_HASH;
- break;
- case 'l':
- F_SET(&exc, E_F_LIST);
- exp->fdef |= E_F_LIST;
- break;
- case 'p':
- F_SET(&exc, E_F_PRINT);
- exp->fdef |= E_F_PRINT;
- break;
- default:
- goto end1;
- }
-end1: break;
- case '2': /* -, ., +, ^ */
- case '3': /* -, ., +, ^, = */
- for (; cmdlen; --cmdlen, ++cmd)
- switch (*cmd) {
- case '-':
- F_SET(&exc, E_F_DASH);
- break;
- case '.':
- F_SET(&exc, E_F_DOT);
- break;
- case '+':
- F_SET(&exc, E_F_PLUS);
- break;
- case '^':
- F_SET(&exc, E_F_CARAT);
- break;
- case '=':
- if (*p == '3') {
- F_SET(&exc, E_F_EQUAL);
- break;
- }
- /* FALLTHROUGH */
- default:
- goto end2;
- }
-end2: break;
- case 'b': /* buffer */
- /*
- * !!!
- * Historically, "d #" was a delete with a flag, not a
- * delete into the '#' buffer. If the current command
- * permits a flag, don't use one as a buffer. However,
- * the 'l' and 'p' flags were legal buffer names in the
- * historic ex, and were used as buffers, not flags.
- */
- if ((cmd[0] == '+' || cmd[0] == '-' || cmd[0] == '#') &&
- strchr(p, '1') != NULL)
- break;
- /*
- * !!!
- * Digits can't be buffer names in ex commands, or the
- * command "d2" would be a delete into buffer '2', and
- * not a two-line deletion.
- */
- if (!isdigit(cmd[0])) {
- exc.buffer = *cmd;
- ++cmd;
- --cmdlen;
- F_SET(&exc, E_BUFFER);
- }
- break;
- case 'c': /* count [01+a] */
- ++p;
- /* Validate any signed value. */
- if (!isdigit(*cmd) &&
- (*p != '+' || (*cmd != '+' && *cmd != '-')))
- break;
- /* If a signed value, set appropriate flags. */
- if (*cmd == '-')
- F_SET(&exc, E_COUNT_NEG);
- else if (*cmd == '+')
- F_SET(&exc, E_COUNT_POS);
-/* 8-bit XXX */ if ((lno = strtol(cmd, &t, 10)) == 0 && *p != '0') {
- msgq(sp, M_ERR, "Count may not be zero");
- goto err;
- }
- cmdlen -= (t - cmd);
- cmd = t;
- /*
- * Count as address offsets occur in commands taking
- * two addresses. Historic vi practice was to use
- * the count as an offset from the *second* address.
- *
- * Set a count flag; some underlying commands (see
- * join) do different things with counts than with
- * line addresses.
- */
- if (*p == 'a') {
- exc.addr1 = exc.addr2;
- exc.addr2.lno = exc.addr1.lno + lno - 1;
- } else
- exc.count = lno;
- F_SET(&exc, E_COUNT);
- break;
- case 'f': /* file */
- if (argv_exp2(sp, ep,
- &exc, cmd, cmdlen, cp == &cmds[C_BANG]))
- goto err;
- goto countchk;
- case 'l': /* line */
- if (ep_line(sp, ep, &cur, &cmd, &cmdlen, &tmp))
- goto err;
- /* Line specifications are always required. */
- if (!tmp) {
- msgq(sp, M_ERR,
- "%s: bad line specification", cmd);
- goto err;
- }
- /* The line must exist for these commands. */
- if (file_lline(sp, ep, &lno))
- goto err;
- if (cur.lno > lno) {
- badlno(sp, lno);
- goto err;
- }
- exc.lineno = cur.lno;
- break;
- case 'S': /* string, file exp. */
- if (argv_exp1(sp, ep,
- &exc, cmd, cmdlen, cp == &cmds[C_BANG]))
- goto err;
- goto addr2;
- case 's': /* string */
- if (argv_exp0(sp, ep, &exc, cmd, cmdlen))
- goto err;
- goto addr2;
- case 'W': /* word string */
- /*
- * QUOTING NOTE:
- *
- * Literal next characters escape the following
- * character. Quoting characters are stripped
- * here since they are no longer useful.
- *
- * First there was the word.
- */
- for (p = t = cmd; cmdlen > 0; --cmdlen, ++cmd) {
- ch = *cmd;
- if (IS_ESCAPE(sp, ch) && cmdlen > 1) {
- --cmdlen;
- *p++ = *++cmd;
- } else if (isblank(ch)) {
- ++cmd;
- --cmdlen;
- break;
- } else
- *p++ = ch;
- }
- if (argv_exp0(sp, ep, &exc, t, p - t))
- goto err;
-
- /* Delete intervening whitespace. */
- for (; cmdlen > 0; --cmdlen, ++cmd) {
- ch = *cmd;
- if (!isblank(ch))
- break;
- }
- if (cmdlen == 0)
- goto usage;
-
- /* Followed by the string. */
- for (p = t = cmd; cmdlen > 0; --cmdlen, ++cmd, ++p) {
- ch = *cmd;
- if (IS_ESCAPE(sp, ch) && cmdlen > 1) {
- --cmdlen;
- *p = *++cmd;
- } else
- *p = ch;
- }
- if (argv_exp0(sp, ep, &exc, t, p - t))
- goto err;
- goto addr2;
- case 'w': /* word */
- if (argv_exp3(sp, ep, &exc, cmd, cmdlen))
- goto err;
-countchk: if (*++p != 'N') { /* N */
- /*
- * If a number is specified, must either be
- * 0 or that number, if optional, and that
- * number, if required.
- */
- num = *p - '0';
- if ((*++p != 'o' || exp->argsoff != 0) &&
- exp->argsoff != num)
- goto usage;
- }
- goto addr2;
- default:
- msgq(sp, M_ERR,
- "Internal syntax table error (%s: %c)",
- cp->name, *p);
- }
- }
-
- /* Skip trailing whitespace. */
- for (; cmdlen; --cmdlen) {
- ch = *cmd++;
- if (!isblank(ch))
- break;
- }
-
- /*
- * There shouldn't be anything left, and no more required
- * fields, i.e neither 'l' or 'r' in the syntax string.
- */
- if (cmdlen || strpbrk(p, "lr")) {
-usage: msgq(sp, M_ERR, "Usage: %s", cp->usage);
- goto err;
- }
-
- /* Verify that the addresses are legal. */
-addr2: switch (exc.addrcnt) {
- case 2:
- if (file_lline(sp, ep, &lno))
- goto err;
- /*
- * Historic ex/vi permitted commands with counts to go past
- * EOF. So, for example, if the file only had 5 lines, the
- * ex command "1,6>" would fail, but the command ">300"
- * would succeed. Since we don't want to have to make all
- * of the underlying commands handle random line numbers,
- * fix it here.
- */
- if (exc.addr2.lno > lno)
- if (F_ISSET(&exc, E_COUNT))
- exc.addr2.lno = lno;
- else {
- badlno(sp, lno);
- goto err;
- }
- /* FALLTHROUGH */
- case 1:
- num = exc.addr1.lno;
- /*
- * If it's a "default vi command", zero is okay. Historic
- * vi allowed this, note, it's also the hack that allows
- * "vi +100 nonexistent_file" to work.
- */
- if (num == 0 && (IN_EX_MODE(sp) || uselastcmd != 1) &&
- !LF_ISSET(E_ZERO)) {
- msgq(sp, M_ERR,
- "The %s command doesn't permit an address of 0",
- cp->name);
- goto err;
- }
- if (file_lline(sp, ep, &lno))
- goto err;
- if (num > lno) {
- badlno(sp, lno);
- goto err;
- }
- break;
- }
-
- /*
- * If doing a default command and there's nothing left on the line,
- * vi just moves to the line. For example, ":3" and ":'a,'b" just
- * move to line 3 and line 'b, respectively, but ":3|" prints line 3.
- *
- * !!!
- * This is done before the absolute mark gets set; historically,
- * "/a/,/b/" did NOT set vi's absolute mark, but "/a/,/b/d" did.
- */
- if (IN_VI_MODE(sp) && uselastcmd && vi_address == 0) {
- switch (exc.addrcnt) {
- case 2:
- sp->lno = exc.addr2.lno ? exc.addr2.lno : 1;
- sp->cno = exc.addr2.cno;
- break;
- case 1:
- sp->lno = exc.addr1.lno ? exc.addr1.lno : 1;
- sp->cno = exc.addr1.cno;
- break;
- }
- cmd = save_cmd;
- cmdlen = save_cmdlen;
- goto loop;
- }
-
- /*
- * Set the absolute mark -- we have to set it for vi here, in case
- * it's a compound command, e.g. ":5p|6" should set the absolute
- * mark for vi.
- */
- if (F_ISSET(exp, EX_ABSMARK)) {
- cur.lno = sp->lno;
- cur.cno = sp->cno;
- F_CLR(exp, EX_ABSMARK);
- if (mark_set(sp, ep, ABSMARK1, &cur, 1))
- goto err;
- }
-
- /* Final setup for the command. */
- exc.cmd = cp;
-
-#if defined(DEBUG) && 0
- TRACE(sp, "ex_cmd: %s", exc.cmd->name);
- if (exc.addrcnt > 0) {
- TRACE(sp, "\taddr1 %d", exc.addr1.lno);
- if (exc.addrcnt > 1)
- TRACE(sp, " addr2: %d", exc.addr2.lno);
- TRACE(sp, "\n");
- }
- if (exc.lineno)
- TRACE(sp, "\tlineno %d", exc.lineno);
- if (exc.flags)
- TRACE(sp, "\tflags %0x", exc.flags);
- if (F_ISSET(&exc, E_BUFFER))
- TRACE(sp, "\tbuffer %c", exc.buffer);
- TRACE(sp, "\n");
- if (exc.argc) {
- for (cnt = 0; cnt < exc.argc; ++cnt)
- TRACE(sp, "\targ %d: {%s}", cnt, exc.argv[cnt]);
- TRACE(sp, "\n");
- }
-#endif
- /* Clear autoprint flag. */
- F_CLR(exp, EX_AUTOPRINT);
-
- /* Increment the command count if not called from vi. */
- if (IN_EX_MODE(sp))
- ++sp->ccnt;
-
- /*
- * If file state available, and not doing a global command,
- * log the start of an action.
- */
- if (ep != NULL && !F_ISSET(sp, S_GLOBAL))
- (void)log_cursor(sp, ep);
-
- /*
- * !!!
- * There are two special commands for the purposes of this code: the
- * default command (<carriage-return>) or the scrolling commands (^D
- * and <EOF>) as the first non-<blank> characters in the line.
- *
- * If this is the first command in the command line, we received the
- * command from the ex command loop and we're talking to a tty, and
- * and there's nothing else on the command line, and it's one of the
- * special commands, we erase the prompt character with a '\r'. Else,
- * we put out a newline character to separate the command from the
- * output from the command. It's OK if vi calls us -- we won't be in
- * ex mode so we'll do nothing.
- *
- * !!!
- * Historically, ex only put out a \r, so, if the displayed line was
- * only a single character long, and <eof> was represented as ^D, the
- * output wouldn't overwrite the user's input. Sex currently doesn't
- * display the <eof> character if it's going to be the scroll command,
- * i.e. if it's the first non-<blank> character in the line. If sex
- * is changed to run in cooked mode, i.e. <eof> is displayed, this code
- * will have to overwrite it. We also don't treat lines with extra
- * prompt characters as empty -- it's not worth the effort since we'd
- * have to overwrite some indeterminate number of columns with spaces
- * to clean up. For now, put out enough spaces to overwrite the prompt.
- */
- if (sep != NONE) {
- if (ep != NULL &&
- IN_EX_MODE(sp) && F_ISSET(sp->gp, G_STDIN_TTY))
- if (sep == NEEDSEP_NR &&
- (uselastcmd || cp == &cmds[C_SCROLL])) {
- (void)putchar('\r');
- for (len = KEY_LEN(sp, PROMPTCHAR); len--;)
- (void)putchar(' ');
- (void)putchar('\r');
- } else
- (void)putchar('\n');
- sep = NONE;
- }
-
- /* Save the current mode. */
- saved_mode = F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE);
-
- /* Do the command. */
- if (cp->fn(sp, ep, &exc))
- goto err;
-
-#ifdef DEBUG
- /* Make sure no function left the temporary space locked. */
- if (F_ISSET(sp->gp, G_TMP_INUSE)) {
- F_CLR(sp->gp, G_TMP_INUSE);
- msgq(sp, M_ERR, "Error: ex: temporary buffer not released");
- goto err;
- }
-#endif
- if (saved_mode != F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE)) {
- /*
- * Only here if the mode of the underlying file changed, e.g.
- * the user switched files or is exiting. Two things that we
- * might have to save: first, any "+cmd" field set up for an
- * ex/edit command will have to be saved for later, also, any
- * part of the current ex command that hasn't been executed
- * yet. For example:
- *
- * :edit +25 file.c|s/abc/ABC/|1
- *
- * !!!
- * The historic vi just hung, of course; nvi handles it by
- * pushing the keys onto the tty queue. Since the commands
- * are intended as ex commands, add additional characters
- * to make it all work if we're switching modes to vi. Also,
- * + commands were oriented to the last line in the file,
- * historically, make the cursor start out there.
- *
- * For the fun of it, if you want to see if a vi clone got the
- * ex argument parsing right, try:
- *
- * echo 'foo|bar' > file1; echo 'foo/bar' > file2;
- * vi
- * :edit +1|s/|/PIPE/|w file1| e file2|1 | s/\//SLASH/|wq
- */
- if (arg1_len == 0 && save_cmdlen == 0)
- return (0);
- if (term_push(sp, "\n", 1, 0))
- goto err;
- if (save_cmdlen != 0)
- if (term_push(sp, save_cmd, save_cmdlen, 0))
- goto err;
- if (arg1 != NULL) {
- if (IN_VI_MODE(sp) && save_cmdlen != 0 &&
- term_push(sp, "|", 1, 0))
- goto err;
- if (term_push(sp, arg1, arg1_len, 0))
- goto err;
- if (file_lline(sp, ep, &sp->frp->lno))
- goto err;
- F_SET(sp->frp, FR_CURSORSET);
- }
- if (IN_VI_MODE(sp) && term_push(sp, ":", 1, 0))
- goto err;
- return (0);
- }
-
- /*
- * Integrate any offset parsed by the underlying command, and make
- * sure the referenced line exists.
- *
- * XXX
- * May not match historic practice (I've never been able to completely
- * figure it out.) For example, the '=' command from vi mode often
- * got the offset wrong, and complained it was too large, but didn't
- * seem to have a problem with the cursor. If anyone complains, ask
- * them how it's supposed to work, they probably know.
- */
- if (ep != NULL && (flagoff += exc.flagoff)) {
- if (flagoff < 0) {
- if (sp->lno <= -flagoff) {
- msgq(sp, M_ERR, "Flag offset before line 1");
- goto err;
- }
- } else {
- if (file_lline(sp, ep, &lno))
- goto err;
- if (sp->lno + flagoff > lno) {
- msgq(sp, M_ERR, "Flag offset past end-of-file");
- goto err;
- }
- }
- sp->lno += flagoff;
- }
-
- /*
- * If the command was successful and we're in ex command mode, we
- * may want to display a line. Make sure there's a line to display.
- */
- if (ep != NULL &&
- IN_EX_MODE(sp) && !F_ISSET(sp, S_GLOBAL) && sp->lno != 0) {
- /*
- * The print commands have already handled the `print' flags.
- * If so, clear them.
- */
- if (LF_ISSET(E_F_PRCLEAR))
- F_CLR(&exc, E_F_HASH | E_F_LIST | E_F_PRINT);
-
- /* If hash only set because of the number option, discard it. */
- if (optnum)
- F_CLR(&exc, E_F_HASH);
-
- /*
- * If there was an explicit flag to display the new cursor
- * line, or we're in ex mode, autoprint is set, and a change
- * was made, display the line. If any print flags set use
- * them, otherwise default to print.
- */
- LF_INIT(F_ISSET(&exc, E_F_HASH | E_F_LIST | E_F_PRINT));
- if (!LF_ISSET(E_F_HASH | E_F_LIST | E_F_PRINT) &&
- O_ISSET(sp, O_AUTOPRINT) &&
- (F_ISSET(exp, EX_AUTOPRINT) || F_ISSET(cp, E_AUTOPRINT)))
- LF_INIT(E_F_PRINT);
-
- if (LF_ISSET(E_F_HASH | E_F_LIST | E_F_PRINT)) {
- memset(&exc, 0, sizeof(EXCMDARG));
- exc.addrcnt = 2;
- exc.addr1.lno = exc.addr2.lno = sp->lno;
- exc.addr1.cno = exc.addr2.cno = sp->cno;
- (void)ex_print(sp, ep, &exc.addr1, &exc.addr2, flags);
- }
- }
-
- cmd = save_cmd;
- cmdlen = save_cmdlen;
- goto loop;
- /* NOTREACHED */
-
- /*
- * If we haven't put out a separator line, do it now. For more
- * detailed comments, see above.
- */
-err: if (sep != NONE &&
- ep != NULL && IN_EX_MODE(sp) && F_ISSET(sp->gp, G_STDIN_TTY))
- (void)fputc('\n', stdout);
- /*
- * On error, we discard any keys we have left, as well as any keys
- * that were mapped. The test of save_cmdlen isn't necessarily
- * correct. If we fail early enough we don't know if the entire
- * string was a single command or not. Try and guess, it's useful
- * to know if part of the command was discarded.
- */
- if (save_cmdlen == 0)
- for (; cmdlen; --cmdlen) {
- ch = *cmd++;
- if (IS_ESCAPE(sp, ch) && cmdlen > 1) {
- --cmdlen;
- ++cmd;
- } else if (ch == '\n' || ch == '|') {
- if (cmdlen > 1)
- save_cmdlen = 1;
- break;
- }
- }
- if (save_cmdlen != 0)
- msgq(sp, M_ERR,
- "Ex command failed: remaining command input discarded");
- /*
- * !!!
- * Previous versions of nvi cleared mapped characters on error. This
- * feature was removed when users complained that it wasn't historic
- * practice.
- */
- return (1);
-}
-
-/*
- * ep_range --
- * Get a line range for ex commands.
- */
-static int
-ep_range(sp, ep, excp, cmdp, cmdlenp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *excp;
- char **cmdp;
- size_t *cmdlenp;
-{
- MARK cur, savecursor;
- size_t cmdlen;
- int savecursor_set, tmp;
- char *cmd;
-
- /* Percent character is all lines in the file. */
- cmd = *cmdp;
- cmdlen = *cmdlenp;
- if (*cmd == '%') {
- excp->addr1.lno = 1;
- if (file_lline(sp, ep, &excp->addr2.lno))
- return (1);
-
- /* If an empty file, then the first line is 0, not 1. */
- if (excp->addr2.lno == 0)
- excp->addr1.lno = 0;
- excp->addr1.cno = excp->addr2.cno = 0;
- excp->addrcnt = 2;
-
- ++*cmdp;
- --*cmdlenp;
- return (0);
- }
-
- /* Parse comma or semi-colon delimited line specs. */
- for (savecursor_set = 0, excp->addrcnt = 0; cmdlen > 0;)
- switch (*cmd) {
- case ';': /* Semi-colon delimiter. */
- /*
- * Comma delimiters delimit; semi-colon delimiters
- * change the current address for the 2nd address
- * to be the first address. Trailing or multiple
- * delimiters are discarded.
- */
- if (excp->addrcnt == 0)
- goto done;
- if (!savecursor_set) {
- savecursor.lno = sp->lno;
- savecursor.cno = sp->cno;
- sp->lno = excp->addr1.lno;
- sp->cno = excp->addr1.cno;
- savecursor_set = 1;
- }
- ++cmd;
- --cmdlen;
- break;
- case ',': /* Comma delimiter. */
- /* If no addresses yet, defaults to ".". */
- if (excp->addrcnt == 0) {
- excp->addr1.lno = sp->lno;
- excp->addr1.cno = sp->cno;
- excp->addrcnt = 1;
- }
- /* FALLTHROUGH */
- case ' ': /* Whitespace. */
- case '\t': /* Whitespace. */
- ++cmd;
- --cmdlen;
- break;
- default:
- if (ep_line(sp, ep, &cur, &cmd, &cmdlen, &tmp))
- return (1);
- if (!tmp)
- goto done;
-
- /*
- * Extra addresses are discarded, starting with
- * the first.
- */
- switch (excp->addrcnt) {
- case 0:
- excp->addr1 = cur;
- excp->addrcnt = 1;
- break;
- case 1:
- excp->addr2 = cur;
- excp->addrcnt = 2;
- break;
- case 2:
- excp->addr1 = excp->addr2;
- excp->addr2 = cur;
- break;
- }
- break;
- }
-
- /*
- * XXX
- * This is probably not the right behavior for savecursor --
- * need to figure out what the historical ex did for ";,;,;5p"
- * or similar stupidity.
- */
-done: if (savecursor_set) {
- sp->lno = savecursor.lno;
- sp->cno = savecursor.cno;
- }
- if (excp->addrcnt == 2 && excp->addr2.lno < excp->addr1.lno) {
- msgq(sp, M_ERR,
- "The second address is smaller than the first");
- return (1);
- }
- *cmdp = cmd;
- *cmdlenp = cmdlen;
- return (0);
-}
-
-/*
- * Get a single line address specifier.
- *
- * The way the "previous context" mark worked was that any "non-relative"
- * motion set it. While ex/vi wasn't totally consistent about this, ANY
- * numeric address, search pattern, '$', or mark reference in an address
- * was considered non-relative, and set the value. Which should explain
- * why we're hacking marks down here. The problem was that the mark was
- * only set if the command was called, i.e. we have to set a flag and test
- * it later.
- *
- * XXX
- * This is not exactly historic practice, although it's fairly close.
- */
-static int
-ep_line(sp, ep, cur, cmdp, cmdlenp, addr_found)
- SCR *sp;
- EXF *ep;
- MARK *cur;
- char **cmdp;
- size_t *cmdlenp;
- int *addr_found;
-{
- EX_PRIVATE *exp;
- MARK m;
- long total;
- u_int flags;
- size_t cmdlen;
- int (*sf) __P((SCR *, EXF *, MARK *, MARK *, char *, char **, u_int *));
- char *cmd, *endp;
-
- exp = EXP(sp);
- *addr_found = 0;
-
- cmd = *cmdp;
- cmdlen = *cmdlenp;
- switch (*cmd) {
- case '$': /* Last line in the file. */
- *addr_found = 1;
- F_SET(exp, EX_ABSMARK);
-
- cur->cno = 0;
- if (file_lline(sp, ep, &cur->lno))
- return (1);
- ++cmd;
- --cmdlen;
- break; /* Absolute line number. */
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- *addr_found = 1;
- F_SET(exp, EX_ABSMARK);
-
- cur->cno = 0;
-/* 8-bit XXX */ cur->lno = strtol(cmd, &endp, 10);
- cmdlen -= (endp - cmd);
- cmd = endp;
- break;
- case '\'': /* Use a mark. */
- *addr_found = 1;
- F_SET(exp, EX_ABSMARK);
-
- if (cmdlen == 1) {
- msgq(sp, M_ERR, "No mark name supplied");
- return (1);
- }
- if (mark_get(sp, ep, cmd[1], cur))
- return (1);
- cmd += 2;
- cmdlen -= 2;
- break;
- case '\\': /* Search: forward/backward. */
- /*
- * !!!
- * I can't find any difference between // and \/ or between
- * ?? and \?. Mark Horton doesn't remember there being any
- * difference. C'est la vie.
- */
- if (cmdlen < 2 || cmd[1] != '/' && cmd[1] != '?') {
- msgq(sp, M_ERR, "\\ not followed by / or ?");
- return (1);
- }
- ++cmd;
- --cmdlen;
- sf = cmd[0] == '/' ? f_search : b_search;
- goto search;
- case '/': /* Search forward. */
- sf = f_search;
- goto search;
- case '?': /* Search backward. */
- sf = b_search;
-search: F_SET(exp, EX_ABSMARK);
-
- if (ep == NULL) {
- msgq(sp, M_ERR,
- "A search address requires that a file have already been read in");
- return (1);
- }
- *addr_found = 1;
- m.lno = sp->lno;
- m.cno = sp->cno;
- flags = SEARCH_MSG | SEARCH_PARSE | SEARCH_SET;
- if (sf(sp, ep, &m, &m, cmd, &endp, &flags))
- return (1);
- cur->lno = m.lno;
- cur->cno = m.cno;
- cmdlen -= (endp - cmd);
- cmd = endp;
- break;
- case '.': /* Current position. */
- *addr_found = 1;
- cur->cno = sp->cno;
-
- /* If an empty file, then '.' is 0, not 1. */
- if (sp->lno == 1) {
- if (file_lline(sp, ep, &cur->lno))
- return (1);
- if (cur->lno != 0)
- cur->lno = 1;
- } else
- cur->lno = sp->lno;
- ++cmd;
- --cmdlen;
- break;
- }
-
- /*
- * Evaluate any offset. Offsets are +/- any number, or any number
- * of +/- signs, or any combination thereof. If no address found
- * yet, offset is relative to ".".
- */
- for (total = 0; cmdlen > 0 && (cmd[0] == '-' || cmd[0] == '+');) {
- if (!*addr_found) {
- cur->lno = sp->lno;
- cur->cno = sp->cno;
- *addr_found = 1;
- }
-
- if (cmdlen > 1 && isdigit(cmd[1])) {
-/* 8-bit XXX */ total += strtol(cmd, &endp, 10);
- cmdlen -= (endp - cmd);
- cmd = endp;
- } else {
- total += cmd[0] == '-' ? -1 : 1;
- --cmdlen;
- ++cmd;
- }
- }
-
- if (*addr_found) {
- if (total < 0 && -total > cur->lno) {
- msgq(sp, M_ERR,
- "Reference to a line number less than 0");
- return (1);
- }
- cur->lno += total;
-
- *cmdp = cmd;
- *cmdlenp = cmdlen;
- }
- return (0);
-}
-
-/*
- * ex_is_abbrev -
- * The vi text input routine needs to know if ex thinks this is
- * an [un]abbreviate command, so it can turn off abbreviations.
- * Usual ranting in the vi/v_ntext:txt_abbrev() routine.
- */
-int
-ex_is_abbrev(name, len)
- char *name;
- size_t len;
-{
- EXCMDLIST const *cp;
-
- return ((cp = ex_comm_search(name, len)) != NULL &&
- (cp == &cmds[C_ABBR] || cp == &cmds[C_UNABBREVIATE]));
-}
-
-/*
- * ex_is_unmap -
- * The vi text input routine needs to know if ex thinks this is
- * an unmap command, so it can turn off input mapping. Usual
- * ranting in the vi/v_ntext:txt_unmap() routine.
- */
-int
-ex_is_unmap(name, len)
- char *name;
- size_t len;
-{
- EXCMDLIST const *cp;
-
- /*
- * The command the vi input routines are really interested in
- * is "unmap!", not just unmap.
- */
- if (name[len - 1] != '!')
- return (0);
- --len;
- return ((cp = ex_comm_search(name, len)) != NULL &&
- cp == &cmds[C_UNMAP]);
-}
-
-static __inline EXCMDLIST const *
-ex_comm_search(name, len)
- char *name;
- size_t len;
-{
- EXCMDLIST const *cp;
-
- for (cp = cmds; cp->name != NULL; ++cp) {
- if (cp->name[0] > name[0])
- return (NULL);
- if (cp->name[0] != name[0])
- continue;
- if (!memcmp(name, cp->name, len))
- return (cp);
- }
- return (NULL);
-}
-
-static void
-badlno(sp, lno)
- SCR *sp;
- recno_t lno;
-{
- if (lno == 0)
- msgq(sp, M_ERR, "Illegal address: the file is empty");
- else
- msgq(sp, M_ERR, "Illegal address: only %lu line%s in the file",
- lno, lno > 1 ? "s" : "");
-}
diff --git a/usr.bin/vi/ex/ex_append.c b/usr.bin/vi/ex/ex_append.c
deleted file mode 100644
index 97172dc4ab0d..000000000000
--- a/usr.bin/vi/ex/ex_append.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_append.c 8.22 (Berkeley) 8/7/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-#include "../sex/sex_screen.h"
-
-enum which {APPEND, CHANGE, INSERT};
-
-static int aci __P((SCR *, EXF *, EXCMDARG *, enum which));
-
-/*
- * ex_append -- :[line] a[ppend][!]
- * Append one or more lines of new text after the specified line,
- * or the current line if no address is specified.
- */
-int
-ex_append(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- return (aci(sp, ep, cmdp, APPEND));
-}
-
-/*
- * ex_change -- :[line[,line]] c[hange][!] [count]
- * Change one or more lines to the input text.
- */
-int
-ex_change(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- return (aci(sp, ep, cmdp, CHANGE));
-}
-
-/*
- * ex_insert -- :[line] i[nsert][!]
- * Insert one or more lines of new text before the specified line,
- * or the current line if no address is specified.
- */
-int
-ex_insert(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- return (aci(sp, ep, cmdp, INSERT));
-}
-
-static int
-aci(sp, ep, cmdp, cmd)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
- enum which cmd;
-{
- MARK m;
- TEXTH *sv_tiqp, tiq;
- TEXT *tp;
- struct termios t;
- u_int flags;
- int rval;
-
- rval = 0;
-
- /*
- * Set input flags; the ! flag turns off autoindent for append,
- * change and insert.
- */
- LF_INIT(TXT_DOTTERM | TXT_NLECHO);
- if (!F_ISSET(cmdp, E_FORCE) && O_ISSET(sp, O_AUTOINDENT))
- LF_SET(TXT_AUTOINDENT);
- if (O_ISSET(sp, O_BEAUTIFY))
- LF_SET(TXT_BEAUTIFY);
-
- /* Input is interruptible. */
- F_SET(sp, S_INTERRUPTIBLE);
-
- /*
- * If this code is called by vi, the screen TEXTH structure (sp->tiqp)
- * may already be in use, e.g. ":append|s/abc/ABC/" would fail as we're
- * only halfway through the line when the append code fires. Use the
- * local structure instead.
- *
- * If this code is called by vi, we want to reset the terminal and use
- * ex's s_get() routine. It actually works fine if we use vi's s_get()
- * routine, but it doesn't look as nice. Maybe if we had a separate
- * window or something, but getting a line at a time looks awkward.
- */
- if (IN_VI_MODE(sp)) {
- memset(&tiq, 0, sizeof(TEXTH));
- CIRCLEQ_INIT(&tiq);
- sv_tiqp = sp->tiqp;
- sp->tiqp = &tiq;
-
- if (F_ISSET(sp->gp, G_STDIN_TTY))
- SEX_RAW(t);
- (void)write(STDOUT_FILENO, "\n", 1);
- LF_SET(TXT_NLECHO);
-
- }
-
- /* Set the line number, so that autoindent works correctly. */
- sp->lno = cmdp->addr1.lno;
-
- if (sex_get(sp, ep, sp->tiqp, 0, flags) != INP_OK)
- goto err;
-
- /*
- * If doing a change, replace lines for as long as possible. Then,
- * append more lines or delete remaining lines. Changes to an empty
- * file are just appends, and inserts are the same as appends to the
- * previous line.
- *
- * !!!
- * Adjust the current line number for the commands to match historic
- * practice if the user doesn't enter anything, and set the address
- * to which we'll append. This is safe because an address of 0 is
- * illegal for change and insert.
- */
- m = cmdp->addr1;
- switch (cmd) {
- case INSERT:
- --m.lno;
- /* FALLTHROUGH */
- case APPEND:
- if (sp->lno == 0)
- sp->lno = 1;
- break;
- case CHANGE:
- --m.lno;
- if (sp->lno != 1)
- --sp->lno;
- break;
- }
-
- /*
- * !!!
- * Cut into the unnamed buffer.
- */
- if (cmd == CHANGE &&
- (cut(sp, ep, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE) ||
- delete(sp, ep, &cmdp->addr1, &cmdp->addr2, 1)))
- goto err;
-
- for (tp = sp->tiqp->cqh_first;
- tp != (TEXT *)sp->tiqp; tp = tp->q.cqe_next) {
- if (file_aline(sp, ep, 1, m.lno, tp->lb, tp->len)) {
-err: rval = 1;
- break;
- }
- sp->lno = ++m.lno;
- }
-
- if (IN_VI_MODE(sp)) {
- sp->tiqp = sv_tiqp;
- text_lfree(&tiq);
-
- /* Reset the terminal state. */
- if (F_ISSET(sp->gp, G_STDIN_TTY)) {
- if (SEX_NORAW(t))
- rval = 1;
- F_SET(sp, S_REFRESH);
- }
- }
- return (rval);
-}
diff --git a/usr.bin/vi/ex/ex_args.c b/usr.bin/vi/ex/ex_args.c
deleted file mode 100644
index 9213e84417a3..000000000000
--- a/usr.bin/vi/ex/ex_args.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_args.c 8.27 (Berkeley) 8/4/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_next -- :next [+cmd] [files]
- * Edit the next file, optionally setting the list of files.
- *
- * !!!
- * The :next command behaved differently from the :rewind command in
- * historic vi. See nvi/docs/autowrite for details, but the basic
- * idea was that it ignored the force flag if the autowrite flag was
- * set. This implementation handles them all identically.
- */
-int
-ex_next(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- ARGS **argv, **pc;
- FREF *frp;
- int noargs;
- char **ap;
-
- if (file_m1(sp, ep, F_ISSET(cmdp, E_FORCE), FS_ALL | FS_POSSIBLE))
- return (1);
-
- /*
- * If the first argument is a plus sign, '+', it's an initial
- * ex command.
- */
- argv = cmdp->argv;
- if (cmdp->argc && argv[0]->bp[0] == '+') {
- --cmdp->argc;
- pc = argv++;
- } else
- pc = NULL;
-
- /* Any other arguments are a replacement file list. */
- if (cmdp->argc) {
- /* Free the current list. */
- if (!F_ISSET(sp, S_ARGNOFREE) && sp->argv != NULL) {
- for (ap = sp->argv; *ap != NULL; ++ap)
- free(*ap);
- free(sp->argv);
- }
- F_CLR(sp, S_ARGNOFREE | S_ARGRECOVER);
- sp->cargv = NULL;
-
- /* Create a new list. */
- CALLOC_RET(sp,
- sp->argv, char **, cmdp->argc + 1, sizeof(char *));
- for (ap = sp->argv,
- argv = cmdp->argv; argv[0]->len != 0; ++ap, ++argv)
- if ((*ap =
- v_strdup(sp, argv[0]->bp, argv[0]->len)) == NULL)
- return (1);
- *ap = NULL;
-
- /* Switch to the first one. */
- sp->cargv = sp->argv;
- if ((frp = file_add(sp, *sp->cargv)) == NULL)
- return (1);
- noargs = 0;
- } else {
- if (sp->cargv == NULL || sp->cargv[1] == NULL) {
- msgq(sp, M_ERR, "No more files to edit");
- return (1);
- }
- if ((frp = file_add(sp, sp->cargv[1])) == NULL)
- return (1);
- if (F_ISSET(sp, S_ARGRECOVER))
- F_SET(frp, FR_RECOVER);
- noargs = 1;
- }
-
- if (file_init(sp, frp, NULL, F_ISSET(cmdp, E_FORCE)))
- return (1);
- if (noargs)
- ++sp->cargv;
-
- /* Push the initial command onto the stack. */
- if (pc != NULL)
- if (IN_EX_MODE(sp))
- (void)term_push(sp, pc[0]->bp, pc[0]->len, 0);
- else if (IN_VI_MODE(sp)) {
- (void)term_push(sp, "\n", 1, 0);
- (void)term_push(sp, pc[0]->bp, pc[0]->len, 0);
- (void)term_push(sp, ":", 1, 0);
- (void)file_lline(sp, sp->ep, &sp->frp->lno);
- F_SET(sp->frp, FR_CURSORSET);
- }
-
- F_SET(sp, S_FSWITCH);
- return (0);
-}
-
-/*
- * ex_prev -- :prev
- * Edit the previous file.
- */
-int
-ex_prev(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- FREF *frp;
-
- if (file_m1(sp, ep, F_ISSET(cmdp, E_FORCE), FS_ALL | FS_POSSIBLE))
- return (1);
-
- if (sp->cargv == sp->argv) {
- msgq(sp, M_ERR, "No previous files to edit");
- return (1);
- }
- if ((frp = file_add(sp, sp->cargv[-1])) == NULL)
- return (1);
-
- if (file_init(sp, frp, NULL, F_ISSET(cmdp, E_FORCE)))
- return (1);
-
- --sp->cargv;
- F_SET(sp, S_FSWITCH);
- return (0);
-}
-
-/*
- * ex_rew -- :rew
- * Re-edit the list of files.
- */
-int
-ex_rew(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- FREF *frp;
-
- /*
- * !!!
- * Historic practice -- you can rewind to the current file.
- */
- if (sp->argv == NULL) {
- msgq(sp, M_ERR, "No previous files to rewind");
- return (1);
- }
-
- if (file_m1(sp, ep, F_ISSET(cmdp, E_FORCE), FS_ALL | FS_POSSIBLE))
- return (1);
-
- /*
- * !!!
- * Historic practice, start at the beginning of the file.
- */
- for (frp = sp->frefq.cqh_first;
- frp != (FREF *)&sp->frefq; frp = frp->q.cqe_next)
- F_CLR(frp, FR_CURSORSET | FR_FNONBLANK);
-
- /* Switch to the first one. */
- sp->cargv = sp->argv;
- if ((frp = file_add(sp, *sp->cargv)) == NULL)
- return (1);
- if (file_init(sp, frp, NULL, F_ISSET(cmdp, E_FORCE)))
- return (1);
-
- F_SET(sp, S_FSWITCH);
- return (0);
-}
-
-/*
- * ex_args -- :args
- * Display the list of files.
- */
-int
-ex_args(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- int cnt, col, len, sep;
- char **ap;
-
- if (sp->argv == NULL) {
- (void)ex_printf(EXCOOKIE, "No file list to display.\n");
- return (0);
- }
-
- col = len = sep = 0;
- for (cnt = 1, ap = sp->argv; *ap != NULL; ++ap) {
- col += len = strlen(*ap) + sep + (ap == sp->cargv ? 2 : 0);
- if (col >= sp->cols - 1) {
- col = len;
- sep = 0;
- (void)ex_printf(EXCOOKIE, "\n");
- } else if (cnt != 1) {
- sep = 1;
- (void)ex_printf(EXCOOKIE, " ");
- }
- ++cnt;
-
- if (ap == sp->cargv)
- (void)ex_printf(EXCOOKIE, "[%s]", *ap);
- else
- (void)ex_printf(EXCOOKIE, "%s", *ap);
- }
- (void)ex_printf(EXCOOKIE, "\n");
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_at.c b/usr.bin/vi/ex/ex_at.c
deleted file mode 100644
index fc5922fb61f9..000000000000
--- a/usr.bin/vi/ex/ex_at.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_at.c 8.25 (Berkeley) 8/1/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_at -- :@[@ | buffer]
- * :*[* | buffer]
- *
- * Execute the contents of the buffer.
- */
-int
-ex_at(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- CB *cbp;
- EX_PRIVATE *exp;
- TEXT *tp;
- int name;
-
- exp = EXP(sp);
-
- /*
- * !!!
- * Historically, [@*]<carriage-return> and [@*][@*] executed the most
- * recently executed buffer in ex mode. In vi mode, only @@ repeated
- * the last buffer. We change historic practice and make @* work from
- * vi mode as well, it's simpler and more consistent.
- */
- name = F_ISSET(cmdp, E_BUFFER) ? cmdp->buffer : '@';
- if (name == '@' || name == '*') {
- if (!exp->at_lbuf_set) {
- msgq(sp, M_ERR, "No previous buffer to execute");
- return (1);
- }
- name = exp->at_lbuf;
- }
-
- CBNAME(sp, cbp, name);
- if (cbp == NULL) {
- msgq(sp, M_ERR, "Buffer %s is empty", KEY_NAME(sp, name));
- return (1);
- }
-
- /* Save for reuse. */
- exp->at_lbuf = name;
- exp->at_lbuf_set = 1;
-
- /*
- * !!!
- * Historic practice is that if the buffer was cut in line mode,
- * <newlines> were appended to each line as it was pushed onto
- * the stack. If the buffer was cut in character mode, <newlines>
- * were appended to all lines but the last one.
- */
- for (tp = cbp->textq.cqh_last;
- tp != (void *)&cbp->textq; tp = tp->q.cqe_prev)
- if ((F_ISSET(cbp, CB_LMODE) ||
- tp->q.cqe_next != (void *)&cbp->textq) &&
- term_push(sp, "\n", 1, 0) ||
- term_push(sp, tp->lb, tp->len, 0))
- return (1);
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_bang.c b/usr.bin/vi/ex/ex_bang.c
deleted file mode 100644
index 70bbb57c0522..000000000000
--- a/usr.bin/vi/ex/ex_bang.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_bang.c 8.33 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-#include "../sex/sex_screen.h"
-
-/*
- * ex_bang -- :[line [,line]] ! command
- *
- * Pass the rest of the line after the ! character to the program named by
- * the O_SHELL option.
- *
- * Historical vi did NOT do shell expansion on the arguments before passing
- * them, only file name expansion. This means that the O_SHELL program got
- * "$t" as an argument if that is what the user entered. Also, there's a
- * special expansion done for the bang command. Any exclamation points in
- * the user's argument are replaced by the last, expanded ! command.
- *
- * There's some fairly amazing slop in this routine to make the different
- * ways of getting here display the right things. It took a long time to
- * get it right (wrong?), so be careful.
- */
-int
-ex_bang(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- enum filtertype ftype;
- ARGS *ap;
- EX_PRIVATE *exp;
- MARK rm;
- recno_t lno;
- size_t blen;
- int rval;
- char *bp, *msg;
-
- ap = cmdp->argv[0];
- if (ap->len == 0) {
- msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage);
- return (1);
- }
-
- /* Set the last bang command. */
- exp = EXP(sp);
- if (exp->lastbcomm != NULL)
- free(exp->lastbcomm);
- if ((exp->lastbcomm = strdup(ap->bp)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- return (1);
- }
-
- /*
- * If the command was modified by the expansion, we redisplay it.
- * Redisplaying it in vi mode is tricky, and handled separately
- * in each case below. If we're in ex mode, it's easy, so we just
- * do it here.
- */
- bp = NULL;
- if (F_ISSET(cmdp, E_MODIFY) && !F_ISSET(sp, S_EXSILENT)) {
- if (IN_EX_MODE(sp)) {
- (void)ex_printf(EXCOOKIE, "!%s\n", ap->bp);
- (void)ex_fflush(EXCOOKIE);
- }
- /*
- * Vi: Display the command if modified. Historic vi displayed
- * the command if it was modified due to file name and/or bang
- * expansion. If piping lines, it was immediately overwritten
- * by any error or line change reporting. We don't the user to
- * have to page through the responses, so we only post it until
- * it's erased by something else. Otherwise, pass it on to the
- * ex_exec_proc routine to display after the screen has been
- * cleaned up.
- */
- if (IN_VI_MODE(sp)) {
- GET_SPACE_RET(sp, bp, blen, ap->len + 3);
- bp[0] = '!';
- memmove(bp + 1, ap->bp, ap->len);
- bp[ap->len + 1] = '\n';
- bp[ap->len + 2] = '\0';
- }
- }
-
- /*
- * If addresses were specified, pipe lines from the file through the
- * command.
- *
- * Historically, vi lines were replaced by both the stdout and stderr
- * lines of the command, but ex by only the stdout lines. This makes
- * no sense to me, so nvi makes it consistent for both, and matches
- * vi's historic behavior.
- */
- if (cmdp->addrcnt != 0) {
- /* Autoprint is set historically, even if the command fails. */
- F_SET(exp, EX_AUTOPRINT);
-
- /* Vi gets a busy message. */
- if (bp != NULL)
- (void)sp->s_busy(sp, bp);
-
- /*
- * !!!
- * Historical vi permitted "!!" in an empty file. When it
- * happens, we get called with two addresses of 1,1 and a
- * bad attitude. The simple solution is to turn it into a
- * FILTER_READ operation, but that means that we don't put
- * an empty line into the default cut buffer as did historic
- * vi. Tough.
- */
- ftype = FILTER;
- if (cmdp->addr1.lno == 1 && cmdp->addr2.lno == 1) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno == 0) {
- cmdp->addr1.lno = cmdp->addr2.lno = 0;
- ftype = FILTER_READ;
- }
- }
- rval = filtercmd(sp, ep,
- &cmdp->addr1, &cmdp->addr2, &rm, ap->bp, ftype);
-
- /*
- * If in vi mode, move to the first nonblank.
- *
- * !!!
- * Historic vi wasn't consistent in this area -- if you used
- * a forward motion it moved to the first nonblank, but if you
- * did a backward motion it didn't. And, if you followed a
- * backward motion with a forward motion, it wouldn't move to
- * the nonblank for either. Going to the nonblank generally
- * seems more useful, so we do it.
- */
- if (rval == 0) {
- sp->lno = rm.lno;
- if (IN_VI_MODE(sp)) {
- sp->cno = 0;
- (void)nonblank(sp, ep, sp->lno, &sp->cno);
- }
- }
- goto ret2;
- }
-
- /*
- * If no addresses were specified, run the command. If the file
- * has been modified and autowrite is set, write the file back.
- * If the file has been modified, autowrite is not set and the
- * warn option is set, tell the user about the file.
- */
- msg = NULL;
- if (F_ISSET(ep, F_MODIFIED))
- if (O_ISSET(sp, O_AUTOWRITE)) {
- if (file_write(sp, ep, NULL, NULL, NULL, FS_ALL)) {
- rval = 1;
- goto ret1;
- }
- } else if (O_ISSET(sp, O_WARN) && !F_ISSET(sp, S_EXSILENT))
- msg = "File modified since last write.\n";
-
- /* Run the command. */
- rval = ex_exec_proc(sp, ap->bp, bp, msg);
-
- /* Vi requires user permission to continue. */
- if (IN_VI_MODE(sp))
- F_SET(sp, S_CONTINUE);
-
-ret2: if (IN_EX_MODE(sp)) {
- /*
- * Put ex error messages out so they aren't confused with
- * the autoprint output.
- */
- if (rval)
- (void)sex_refresh(sp, sp->ep);
-
- /* Ex terminates with a bang, even if the command fails. */
- if (!F_ISSET(sp, S_EXSILENT))
- (void)write(STDOUT_FILENO, "!\n", 2);
- }
-
- /* Free the extra space. */
-ret1: if (bp != NULL)
- FREE_SPACE(sp, bp, blen);
-
- /*
- * XXX
- * The ! commands never return an error, so that autoprint always
- * happens in the ex parser.
- */
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_cd.c b/usr.bin/vi/ex/ex_cd.c
deleted file mode 100644
index 3732f7b2465f..000000000000
--- a/usr.bin/vi/ex/ex_cd.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_cd.c 8.16 (Berkeley) 8/8/94";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <pwd.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_cd -- :cd[!] [directory]
- * Change directories.
- */
-int
-ex_cd(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- struct passwd *pw;
- ARGS *ap;
- CDPATH *cdp;
- char *dir; /* XXX END OF THE STACK, DON'T TRUST GETCWD. */
- char buf[MAXPATHLEN * 2];
-
- /*
- * !!!
- * Historic practice is that the cd isn't attempted if the file has
- * been modified, unless its name begins with a leading '/' or the
- * force flag is set.
- */
- if (F_ISSET(ep, F_MODIFIED) &&
- !F_ISSET(cmdp, E_FORCE) && sp->frp->name[0] != '/') {
- msgq(sp, M_ERR,
- "File modified since last complete write; write or use ! to override");
- return (1);
- }
-
- switch (cmdp->argc) {
- case 0:
- /* If no argument, change to the user's home directory. */
- if ((dir = getenv("HOME")) == NULL) {
- if ((pw = getpwuid(getuid())) == NULL ||
- pw->pw_dir == NULL || pw->pw_dir[0] == '\0') {
- msgq(sp, M_ERR,
- "Unable to find home directory location");
- return (1);
- }
- dir = pw->pw_dir;
- }
- break;
- case 1:
- dir = cmdp->argv[0]->bp;
- break;
- default:
- abort();
- }
-
- /* Try the current directory first. */
- if (!chdir(dir))
- goto ret;
-
- /*
- * If moving to the user's home directory, or, the path begins with
- * "/", "./" or "../", it's the only place we try.
- */
- if (cmdp->argc == 0 ||
- (ap = cmdp->argv[0])->bp[0] == '/' ||
- ap->len == 1 && ap->bp[0] == '.' ||
- ap->len >= 2 && ap->bp[0] == '.' && ap->bp[1] == '.' &&
- (ap->bp[2] == '/' || ap->bp[2] == '\0'))
- goto err;
-
- /* If the user has a CDPATH variable, try its elements. */
- for (cdp = EXP(sp)->cdq.tqh_first; cdp != NULL; cdp = cdp->q.tqe_next) {
- (void)snprintf(buf, sizeof(buf), "%s/%s", cdp->path, dir);
- if (!chdir(buf)) {
-ret: if (getcwd(buf, sizeof(buf)) != NULL)
- msgq(sp, M_INFO, "New directory: %s", buf);
- return (0);
- }
- }
-err: msgq(sp, M_SYSERR, "%s", dir);
- return (1);
-}
-
-#define FREE_CDPATH(cdp) { \
- TAILQ_REMOVE(&exp->cdq, (cdp), q); \
- free((cdp)->path); \
- FREE((cdp), sizeof(CDPATH)); \
-}
-/*
- * ex_cdalloc --
- * Create a new list of cd paths.
- */
-int
-ex_cdalloc(sp, str)
- SCR *sp;
- char *str;
-{
- EX_PRIVATE *exp;
- CDPATH *cdp;
- size_t len;
- int founddot;
- char *p, *t;
-
- /* Free current queue. */
- exp = EXP(sp);
- while ((cdp = exp->cdq.tqh_first) != NULL)
- FREE_CDPATH(cdp);
-
- /*
- * Create new queue. The CDPATH environmental variable (and the
- * user's manual entry) are delimited by colon characters.
- */
- for (p = t = str, founddot = 0;; ++p) {
- if (*p == '\0' || *p == ':') {
- /*
- * Empty strings specify ".". The only way to get an
- * empty string is a leading colon, colons in a row,
- * or a trailing colon. Or, to put it the other way,
- * if the the length is zero, then it's either ":XXX",
- * "XXX::XXXX" , "XXX:", or "", and the only failure
- * mode is the last one. Note, the string ":" gives
- * us two entries of '.', so we only include one of
- * them.
- */
- if ((len = p - t) == 0) {
- if (p == str && *p == '\0')
- break;
- if (founddot) {
- if (*p == '\0')
- break;
- continue;
- }
- len = 1;
- t = ".";
- founddot = 1;
- }
- MALLOC_RET(sp, cdp, CDPATH *, sizeof(CDPATH));
- MALLOC(sp, cdp->path, char *, len + 1);
- if (cdp->path == NULL) {
- free(cdp);
- return (1);
- }
- memmove(cdp->path, t, len);
- cdp->path[len] = '\0';
- TAILQ_INSERT_TAIL(&exp->cdq, cdp, q);
- t = p + 1;
- }
- if (*p == '\0')
- break;
- }
- return (0);
-}
- /* Free previous queue. */
-/*
- * ex_cdfree --
- * Free the cd path list.
- */
-int
-ex_cdfree(sp)
- SCR *sp;
-{
- EX_PRIVATE *exp;
- CDPATH *cdp;
-
- /* Free up cd path information. */
- exp = EXP(sp);
- while ((cdp = exp->cdq.tqh_first) != NULL)
- FREE_CDPATH(cdp);
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_delete.c b/usr.bin/vi/ex/ex_delete.c
deleted file mode 100644
index 08c4250e3c12..000000000000
--- a/usr.bin/vi/ex/ex_delete.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_delete.c 8.12 (Berkeley) 8/5/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_delete: [line [,line]] d[elete] [buffer] [count] [flags]
- *
- * Delete lines from the file.
- */
-int
-ex_delete(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- recno_t lno;
-
- /*
- * !!!
- * Historically, lines deleted in ex were not placed in the numeric
- * buffers. We follow historic practice so that we don't overwrite
- * vi buffers accidentally.
- */
- if (cut(sp, ep,
- F_ISSET(cmdp, E_BUFFER) ? &cmdp->buffer : NULL,
- &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE))
- return (1);
-
- /* Delete the lines. */
- if (delete(sp, ep, &cmdp->addr1, &cmdp->addr2, 1))
- return (1);
-
- /* Set the cursor to the line after the last line deleted. */
- sp->lno = cmdp->addr1.lno;
-
- /* Or the last line in the file if deleted to the end of the file. */
- if (file_lline(sp, ep, &lno))
- return (1);
- if (sp->lno > lno)
- sp->lno = lno;
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_digraph.c b/usr.bin/vi/ex/ex_digraph.c
deleted file mode 100644
index 07399234ba9e..000000000000
--- a/usr.bin/vi/ex/ex_digraph.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_digraph.c 8.6 (Berkeley) 3/25/94";
-#endif /* not lint */
-
-#ifndef NO_DIGRAPH
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-static void do_digraph __P((SCR *, EXF *, int, u_char *));
-
-/* This stuff is used to build the default digraphs table. */
-static u_char digtable[][4] = {
-# ifdef CS_IBMPC
- "C,\200", "u\"\1", "e'\2", "a^\3",
- "a\"\4", "a`\5", "a@\6", "c,\7",
- "e^\10", "e\"\211", "e`\12", "i\"\13",
- "i^\14", "i`\15", "A\"\16", "A@\17",
- "E'\20", "ae\21", "AE\22", "o^\23",
- "o\"\24", "o`\25", "u^\26", "u`\27",
- "y\"\30", "O\"\31", "U\"\32", "a'\240",
- "i'!", "o'\"", "u'#", "n~$",
- "N~%", "a-&", "o-'", "~?(",
- "~!-", "\"<.", "\">/",
-# ifdef CS_SPECIAL
- "2/+", "4/,", "^+;", "^q<",
- "^c=", "^r>", "^t?", "pp]",
- "^^^", "oo_", "*a`", "*ba",
- "*pc", "*Sd", "*se", "*uf",
- "*tg", "*Ph", "*Ti", "*Oj",
- "*dk", "*Hl", "*hm", "*En",
- "*No", "eqp", "pmq", "ger",
- "les", "*It", "*iu", "*/v",
- "*=w", "sq{", "^n|", "^2}",
- "^3~", "^_\377",
-# endif /* CS_SPECIAL */
-# endif /* CS_IBMPC */
-# ifdef CS_LATIN1
- "~!!", "a-*", "\">+", "o-:",
- "\"<>", "~??",
-
- "A`@", "A'A", "A^B", "A~C",
- "A\"D", "A@E", "AEF", "C,G",
- "E`H", "E'I", "E^J", "E\"K",
- "I`L", "I'M", "I^N", "I\"O",
- "-DP", "N~Q", "O`R", "O'S",
- "O^T", "O~U", "O\"V", "O/X",
- "U`Y", "U'Z", "U^[", "U\"\\",
- "Y'_",
-
- "a``", "a'a", "a^b", "a~c",
- "a\"d", "a@e", "aef", "c,g",
- "e`h", "e'i", "e^j", "e\"k",
- "i`l", "i'm", "i^n", "i\"o",
- "-dp", "n~q", "o`r", "o's",
- "o^t", "o~u", "o\"v", "o/x",
- "u`y", "u'z", "u^{", "u\"|",
- "y'~",
-# endif /* CS_LATIN1 */
- ""
-};
-
-int
-digraph_init(sp)
- SCR *sp;
-{
- int i;
-
- for (i = 0; *digtable[i]; i++)
- do_digraph(sp, NULL, 0, digtable[i]);
- do_digraph(sp, NULL, 0, NULL);
- return (0);
-}
-
-int
-ex_digraph(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- do_digraph(sp, ep, F_ISSET(cmdp, E_FORCE), cmdp->argv[0]->bp);
- return (0);
-}
-
-static struct _DIG
-{
- struct _DIG *next;
- char key1;
- char key2;
- char dig;
- char save;
-} *digs;
-
-int
-digraph(sp, key1, key2)
- SCR *sp;
- char key1; /* the underlying character */
- char key2; /* the second character */
-{
- int new_key;
- register struct _DIG *dp;
-
- /* if digraphs are disabled, then just return the new char */
- if (O_ISSET(sp, O_DIGRAPH))
- {
- return key2;
- }
-
- /* remember the new key, so we can return it if this isn't a digraph */
- new_key = key2;
-
- /* sort key1 and key2, so that their original order won't matter */
- if (key1 > key2)
- {
- key2 = key1;
- key1 = new_key;
- }
-
- /* scan through the digraph chart */
- for (dp = digs;
- dp && (dp->key1 != key1 || dp->key2 != key2);
- dp = dp->next)
- {
- }
-
- /* if this combination isn't in there, just use the new key */
- if (!dp)
- {
- return new_key;
- }
-
- /* else use the digraph key */
- return dp->dig;
-}
-
-/* this function lists or defines digraphs */
-static void
-do_digraph(sp, ep, bang, extra)
- SCR *sp;
- EXF *ep;
- int bang;
- u_char *extra;
-{
- int dig;
- register struct _DIG *dp;
- struct _DIG *prev;
- static int user_defined = 0; /* boolean: are all later digraphs user-defined? */
- char listbuf[8];
-
- /* if "extra" is NULL, then we've reached the end of the built-ins */
- if (!extra)
- {
- user_defined = 1;
- return;
- }
-
- /* if no args, then display the existing digraphs */
- if (*extra < ' ')
- {
- listbuf[0] = listbuf[1] = listbuf[2] = listbuf[5] = ' ';
- listbuf[7] = '\0';
- for (dig = 0, dp = digs; dp; dp = dp->next)
- {
- if (dp->save || bang)
- {
- dig += 7;
- if (dig >= sp->cno)
- {
- addch('\n');
- refresh();
- dig = 7;
- }
- listbuf[3] = dp->key1;
- listbuf[4] = dp->key2;
- listbuf[6] = dp->dig;
- addstr(listbuf);
- }
- }
- addch('\n');
- refresh();
- return;
- }
-
- /* make sure we have at least two characters */
- if (!extra[1])
- {
- msgq(sp, M_ERR,
- "Digraphs must be composed of two characters");
- return;
- }
-
- /* sort key1 and key2, so that their original order won't matter */
- if (extra[0] > extra[1])
- {
- dig = extra[0];
- extra[0] = extra[1];
- extra[1] = dig;
- }
-
- /* locate the new digraph character */
- for (dig = 2; extra[dig] == ' ' || extra[dig] == '\t'; dig++)
- {
- }
- dig = extra[dig];
- if (!bang && dig)
- {
- dig |= 0x80;
- }
-
- /* search for the digraph */
- for (prev = (struct _DIG *)0, dp = digs;
- dp && (dp->key1 != extra[0] || dp->key2 != extra[1]);
- prev = dp, dp = dp->next)
- {
- }
-
- /* deleting the digraph? */
- if (!dig)
- {
- if (!dp)
- {
-#ifndef CRUNCH
- msgq(sp, M_ERR,
- "%c%c not a digraph", extra[0], extra[1]);
-#endif
- return;
- }
- if (prev)
- prev->next = dp->next;
- else
- digs = dp->next;
- free(dp);
- return;
- }
-
- /* if necessary, create a new digraph struct for the new digraph */
- if (dig && !dp)
- {
- MALLOC(sp, dp, struct _DIG *, sizeof(struct _DIG));
- if (dp == NULL)
- return;
- if (prev)
- prev->next = dp;
- else
- digs = dp;
- dp->next = (struct _DIG *)0;
- }
-
- /* assign it the new digraph value */
- dp->key1 = extra[0];
- dp->key2 = extra[1];
- dp->dig = dig;
- dp->save = user_defined;
-}
-
-void
-digraph_save(sp, fd)
- SCR *sp;
- int fd;
-{
- static char buf[] = "digraph! XX Y\n";
- register struct _DIG *dp;
-
- for (dp = digs; dp; dp = dp->next)
- {
- if (dp->save)
- {
- buf[9] = dp->key1;
- buf[10] = dp->key2;
- buf[12] = dp->dig;
- write(fd, buf, (unsigned)14);
- }
- }
-}
-#endif
diff --git a/usr.bin/vi/ex/ex_display.c b/usr.bin/vi/ex/ex_display.c
deleted file mode 100644
index 139127e602b3..000000000000
--- a/usr.bin/vi/ex/ex_display.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_display.c 8.21 (Berkeley) 8/3/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "tag.h"
-#include "excmd.h"
-
-static int bdisplay __P((SCR *, EXF *));
-static void db __P((SCR *, CB *, CHAR_T *));
-
-/*
- * ex_display -- :display b[uffers] | s[creens] | t[ags]
- *
- * Display buffers, tags or screens.
- */
-int
-ex_display(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- switch (cmdp->argv[0]->bp[0]) {
- case 'b':
-#undef ARG
-#define ARG "buffers"
- if (cmdp->argv[0]->len >= sizeof(ARG) ||
- memcmp(cmdp->argv[0]->bp, ARG, cmdp->argv[0]->len))
- break;
- return (bdisplay(sp, ep));
- case 's':
-#undef ARG
-#define ARG "screens"
- if (cmdp->argv[0]->len >= sizeof(ARG) ||
- memcmp(cmdp->argv[0]->bp, ARG, cmdp->argv[0]->len))
- break;
- return (ex_sdisplay(sp, ep));
- case 't':
-#undef ARG
-#define ARG "tags"
- if (cmdp->argv[0]->len >= sizeof(ARG) ||
- memcmp(cmdp->argv[0]->bp, ARG, cmdp->argv[0]->len))
- break;
- return (ex_tagdisplay(sp, ep));
- }
- msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage);
- return (1);
-}
-
-/*
- * bdisplay --
- *
- * Display buffers.
- */
-static int
-bdisplay(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- CB *cbp;
-
- if (sp->gp->cutq.lh_first == NULL && sp->gp->dcbp == NULL) {
- (void)ex_printf(EXCOOKIE, "No cut buffers to display.\n");
- return (0);
- }
-
- /* Buffers can be infinitely long, make it interruptible. */
- F_SET(sp, S_INTERRUPTIBLE);
-
- /* Display regular cut buffers. */
- for (cbp = sp->gp->cutq.lh_first; cbp != NULL; cbp = cbp->q.le_next) {
- if (isdigit(cbp->name))
- continue;
- if (cbp->textq.cqh_first != (void *)&cbp->textq)
- db(sp, cbp, NULL);
- if (INTERRUPTED(sp))
- return (0);
- }
- /* Display numbered buffers. */
- for (cbp = sp->gp->cutq.lh_first; cbp != NULL; cbp = cbp->q.le_next) {
- if (!isdigit(cbp->name))
- continue;
- if (cbp->textq.cqh_first != (void *)&cbp->textq)
- db(sp, cbp, NULL);
- if (INTERRUPTED(sp))
- return (0);
- }
- /* Display default buffer. */
- if ((cbp = sp->gp->dcbp) != NULL)
- db(sp, cbp, "default buffer");
- return (0);
-}
-
-/*
- * db --
- * Display a buffer.
- */
-static void
-db(sp, cbp, name)
- SCR *sp;
- CB *cbp;
- CHAR_T *name;
-{
- CHAR_T *p;
- TEXT *tp;
- size_t len;
-
- (void)ex_printf(EXCOOKIE, "********** %s%s\n",
- name == NULL ? KEY_NAME(sp, cbp->name) : name,
- F_ISSET(cbp, CB_LMODE) ? " (line mode)" : " (character mode)");
- for (tp = cbp->textq.cqh_first;
- tp != (void *)&cbp->textq; tp = tp->q.cqe_next) {
- for (len = tp->len, p = tp->lb; len--; ++p) {
- (void)ex_printf(EXCOOKIE, "%s", KEY_NAME(sp, *p));
- if (INTERRUPTED(sp))
- return;
- }
- (void)ex_printf(EXCOOKIE, "\n");
- }
-}
diff --git a/usr.bin/vi/ex/ex_edit.c b/usr.bin/vi/ex/ex_edit.c
deleted file mode 100644
index bfe0a2ae24ae..000000000000
--- a/usr.bin/vi/ex/ex_edit.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_edit.c 8.18 (Berkeley) 8/4/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_edit -- :e[dit][!] [+cmd] [file]
- * :vi[sual][!] [+cmd] [file]
- *
- * Edit a file; if none specified, re-edit the current file. The second
- * form of the command can only be executed while in vi mode. See the
- * hack in ex.c:ex_cmd().
- *
- * !!!
- * Historic vi didn't permit the '+' command form without specifying
- * a file name as well.
- */
-int
-ex_edit(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- ARGS *ap;
- FREF *frp;
-
- frp = sp->frp;
- switch (cmdp->argc) {
- case 0:
- /*
- * If the name has been changed, we edit that file, not the
- * original name. If the user was editing a temporary file,
- * create another one. The reason for this is that we do
- * special exit processing of temporary files, and reusing
- * them is tricky.
- */
- if (F_ISSET(frp, FR_TMPFILE)) {
- if ((frp = file_add(sp, NULL)) == NULL)
- return (1);
- } else {
- if ((frp = file_add(sp, frp->name)) == NULL)
- return (1);
- set_alt_name(sp, sp->frp->name);
- }
- break;
- case 1:
- ap = cmdp->argv[0];
- if ((frp = file_add(sp, ap->bp)) == NULL)
- return (1);
- set_alt_name(sp, ap->bp);
- break;
- default:
- abort();
- }
-
- /*
- * Check for modifications.
- *
- * !!!
- * Contrary to POSIX 1003.2-1992, autowrite did not affect :edit.
- */
- if (file_m2(sp, ep, F_ISSET(cmdp, E_FORCE)))
- return (1);
-
- /* Switch files. */
- if (file_init(sp, frp, NULL, F_ISSET(cmdp, E_FORCE)))
- return (1);
- F_SET(sp, S_FSWITCH);
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_equal.c b/usr.bin/vi/ex/ex_equal.c
deleted file mode 100644
index a80d72352db8..000000000000
--- a/usr.bin/vi/ex/ex_equal.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_equal.c 8.6 (Berkeley) 4/26/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_equal -- :address =
- */
-int
-ex_equal(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- recno_t lno;
-
- /*
- * Print out the line number matching the specified address,
- * or the number of the last line in the file if no address
- * specified.
- *
- * !!!
- * Historically, ":0=" displayed 0, and ":=" or ":1=" in an
- * empty file displayed 1. Until somebody complains loudly,
- * we're going to do it right. The tables in excmd.c permit
- * lno to get away with any address from 0 to the end of the
- * file, which, in an empty file, is 0.
- */
- if (F_ISSET(cmdp, E_ADDRDEF)) {
- if (file_lline(sp, ep, &lno))
- return (1);
- } else
- lno = cmdp->addr1.lno;
-
- (void)ex_printf(EXCOOKIE, "%ld\n", lno);
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_exit.c b/usr.bin/vi/ex/ex_exit.c
deleted file mode 100644
index 3f0a3622a2ab..000000000000
--- a/usr.bin/vi/ex/ex_exit.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_exit.c 8.13 (Berkeley) 8/4/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_quit -- :quit[!]
- * Quit.
- */
-int
-ex_quit(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- int force;
-
- force = F_ISSET(cmdp, E_FORCE);
-
- /* Check for modifications. */
- if (file_m2(sp, ep, force))
- return (1);
-
- /* Check for more files to edit. */
- if (ex_ncheck(sp, force))
- return (1);
-
- F_SET(sp, force ? S_EXIT_FORCE : S_EXIT);
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_global.c b/usr.bin/vi/ex/ex_global.c
deleted file mode 100644
index 624bf8e51136..000000000000
--- a/usr.bin/vi/ex/ex_global.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_global.c 8.41 (Berkeley) 8/9/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-enum which {GLOBAL, VGLOBAL};
-
-static int global __P((SCR *, EXF *, EXCMDARG *, enum which));
-
-/*
- * ex_global -- [line [,line]] g[lobal][!] /pattern/ [commands]
- * Exec on lines matching a pattern.
- */
-int
-ex_global(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- return (global(sp, ep,
- cmdp, F_ISSET(cmdp, E_FORCE) ? VGLOBAL : GLOBAL));
-}
-
-/*
- * ex_vglobal -- [line [,line]] v[global] /pattern/ [commands]
- * Exec on lines not matching a pattern.
- */
-int
-ex_vglobal(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- return (global(sp, ep, cmdp, VGLOBAL));
-}
-
-static int
-global(sp, ep, cmdp, cmd)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
- enum which cmd;
-{
- MARK abs;
- RANGE *rp;
- EX_PRIVATE *exp;
- recno_t elno, lno;
- regmatch_t match[1];
- regex_t *re, lre;
- size_t clen, len;
- int delim, eval, reflags, replaced, rval;
- char *cb, *ptrn, *p, *t;
-
- /*
- * Skip leading white space. Historic vi allowed any non-
- * alphanumeric to serve as the global command delimiter.
- */
- for (p = cmdp->argv[0]->bp; isblank(*p); ++p);
- if (*p == '\0' || isalnum(*p)) {
- msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage);
- return (1);
- }
- delim = *p++;
-
- /*
- * Get the pattern string, toss escaped characters.
- *
- * QUOTING NOTE:
- * Only toss an escaped character if it escapes a delimiter.
- */
- for (ptrn = t = p;;) {
- if (p[0] == '\0' || p[0] == delim) {
- if (p[0] == delim)
- ++p;
- /*
- * !!!
- * Nul terminate the pattern string -- it's passed
- * to regcomp which doesn't understand anything else.
- */
- *t = '\0';
- break;
- }
- if (p[0] == '\\' && p[1] == delim)
- ++p;
- *t++ = *p++;
- }
-
- /* If the pattern string is empty, use the last one. */
- if (*ptrn == '\0') {
- if (!F_ISSET(sp, S_SRE_SET)) {
- msgq(sp, M_ERR, "No previous regular expression");
- return (1);
- }
- re = &sp->sre;
- } else {
- /* Set RE flags. */
- reflags = 0;
- if (O_ISSET(sp, O_EXTENDED))
- reflags |= REG_EXTENDED;
- if (O_ISSET(sp, O_IGNORECASE))
- reflags |= REG_ICASE;
-
- /* Convert vi-style RE's to POSIX 1003.2 RE's. */
- if (re_conv(sp, &ptrn, &replaced))
- return (1);
-
- /* Compile the RE. */
- re = &lre;
- eval = regcomp(re, ptrn, reflags);
-
- /* Free up any allocated memory. */
- if (replaced)
- FREE_SPACE(sp, ptrn, 0);
-
- if (eval) {
- re_error(sp, eval, re);
- return (1);
- }
-
- /*
- * Set saved RE. Historic practice is that
- * globals set direction as well as the RE.
- */
- sp->sre = lre;
- sp->searchdir = FORWARD;
- F_SET(sp, S_SRE_SET);
- }
-
- /*
- * Get a copy of the command string; the default command is print.
- * Don't worry about a set of <blank>s with no command, that will
- * default to print in the ex parser.
- */
- if ((clen = strlen(p)) == 0) {
- p = "p";
- clen = 1;
- }
- MALLOC_RET(sp, cb, char *, clen);
- memmove(cb, p, clen);
-
- /*
- * The global commands sets the substitute RE as well as
- * the everything-else RE.
- */
- sp->subre = sp->sre;
- F_SET(sp, S_SUBRE_SET);
-
- /* Set the global flag. */
- F_SET(sp, S_GLOBAL);
-
- /* The global commands always set the previous context mark. */
- abs.lno = sp->lno;
- abs.cno = sp->cno;
- if (mark_set(sp, ep, ABSMARK1, &abs, 1))
- goto err;
-
- /*
- * For each line... The semantics of global matching are that we first
- * have to decide which lines are going to get passed to the command,
- * and then pass them to the command, ignoring other changes. There's
- * really no way to do this in a single pass, since arbitrary line
- * creation, deletion and movement can be done in the ex command. For
- * example, a good vi clone test is ":g/X/mo.-3", or "g/X/.,.+1d".
- * What we do is create linked list of lines that are tracked through
- * each ex command. There's a callback routine which the DB interface
- * routines call when a line is created or deleted. This doesn't help
- * the layering much.
- */
- exp = EXP(sp);
- for (rval = 0, lno = cmdp->addr1.lno,
- elno = cmdp->addr2.lno; lno <= elno; ++lno) {
- /* Someone's unhappy, time to stop. */
- if (INTERRUPTED(sp))
- goto interrupted;
-
- /* Get the line and search for a match. */
- if ((t = file_gline(sp, ep, lno, &len)) == NULL) {
- GETLINE_ERR(sp, lno);
- goto err;
- }
- match[0].rm_so = 0;
- match[0].rm_eo = len;
- switch(eval = regexec(re, t, 1, match, REG_STARTEND)) {
- case 0:
- if (cmd == VGLOBAL)
- continue;
- break;
- case REG_NOMATCH:
- if (cmd == GLOBAL)
- continue;
- break;
- default:
- re_error(sp, eval, re);
- goto err;
- }
-
- /* If follows the last entry, extend the last entry's range. */
- if ((rp = exp->rangeq.cqh_last) != (void *)&exp->rangeq &&
- rp->stop == lno - 1) {
- ++rp->stop;
- continue;
- }
-
- /* Allocate a new range, and append it to the list. */
- CALLOC(sp, rp, RANGE *, 1, sizeof(RANGE));
- if (rp == NULL)
- goto err;
- rp->start = rp->stop = lno;
- CIRCLEQ_INSERT_TAIL(&exp->rangeq, rp, q);
- }
-
- exp = EXP(sp);
- exp->range_lno = OOBLNO;
- for (;;) {
- /*
- * Start at the beginning of the range each time, it may have
- * been changed (or exhausted) if lines were inserted/deleted.
- */
- if ((rp = exp->rangeq.cqh_first) == (void *)&exp->rangeq)
- break;
- if (rp->start > rp->stop) {
- CIRCLEQ_REMOVE(&exp->rangeq, exp->rangeq.cqh_first, q);
- free(rp);
- continue;
- }
-
- /*
- * Execute the command, setting the cursor to the line so that
- * relative addressing works. This means that the cursor moves
- * to the last line sent to the command, by default, even if
- * the command fails.
- */
- exp->range_lno = sp->lno = rp->start++;
- if (ex_cmd(sp, ep, cb, clen, 0))
- goto err;
-
- /* Someone's unhappy, time to stop. */
- if (INTERRUPTED(sp)) {
-interrupted: msgq(sp, M_INFO, "Interrupted");
- break;
- }
- }
-
- /* Set the cursor to the new value, making sure it exists. */
- if (exp->range_lno != OOBLNO) {
- if (file_lline(sp, ep, &lno))
- return (1);
- sp->lno =
- lno < exp->range_lno ? (lno ? lno : 1) : exp->range_lno;
- }
- if (0) {
-err: rval = 1;
- }
-
- /* Command we ran may have set the autoprint flag, clear it. */
- F_CLR(exp, EX_AUTOPRINT);
-
- /* Clear the global flag. */
- F_CLR(sp, S_GLOBAL);
-
- /* Free any remaining ranges and the command buffer. */
- while ((rp = exp->rangeq.cqh_first) != (void *)&exp->rangeq) {
- CIRCLEQ_REMOVE(&exp->rangeq, exp->rangeq.cqh_first, q);
- free(rp);
- }
- free(cb);
- return (rval);
-}
-
-/*
- * global_insdel --
- * Update the ranges based on an insertion or deletion.
- */
-void
-global_insdel(sp, ep, op, lno)
- SCR *sp;
- EXF *ep;
- enum operation op;
- recno_t lno;
-{
- EX_PRIVATE *exp;
- RANGE *nrp, *rp;
-
- exp = EXP(sp);
-
- switch (op) {
- case LINE_APPEND:
- return;
- case LINE_DELETE:
- for (rp = exp->rangeq.cqh_first;
- rp != (void *)&exp->rangeq; rp = nrp) {
- nrp = rp->q.cqe_next;
- /* If range less than the line, ignore it. */
- if (rp->stop < lno)
- continue;
- /* If range greater than the line, decrement range. */
- if (rp->start > lno) {
- --rp->start;
- --rp->stop;
- continue;
- }
- /* Lno is inside the range, decrement the end point. */
- if (rp->start > --rp->stop) {
- CIRCLEQ_REMOVE(&exp->rangeq, rp, q);
- free(rp);
- }
- }
- break;
- case LINE_INSERT:
- for (rp = exp->rangeq.cqh_first;
- rp != (void *)&exp->rangeq; rp = rp->q.cqe_next) {
- /* If range less than the line, ignore it. */
- if (rp->stop < lno)
- continue;
- /* If range greater than the line, increment range. */
- if (rp->start >= lno) {
- ++rp->start;
- ++rp->stop;
- continue;
- }
- /*
- * Lno is inside the range, so the range must be split.
- * Since we're inserting a new element, neither range
- * can be exhausted.
- */
- CALLOC(sp, nrp, RANGE *, 1, sizeof(RANGE));
- if (nrp == NULL) {
- F_SET(sp, S_INTERRUPTED);
- return;
- }
- nrp->start = lno + 1;
- nrp->stop = rp->stop + 1;
- rp->stop = lno - 1;
- CIRCLEQ_INSERT_AFTER(&exp->rangeq, rp, nrp, q);
- rp = nrp;
- }
- break;
- case LINE_RESET:
- return;
- }
- /*
- * If the command deleted/inserted lines, the cursor moves to
- * the line after the deleted/inserted line.
- */
- exp->range_lno = lno;
-}
diff --git a/usr.bin/vi/ex/ex_init.c b/usr.bin/vi/ex/ex_init.c
deleted file mode 100644
index 79b0e4b9a4af..000000000000
--- a/usr.bin/vi/ex/ex_init.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_init.c 8.16 (Berkeley) 8/8/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-#include "tag.h"
-
-/*
- * ex_screen_copy --
- * Copy ex screen.
- */
-int
-ex_screen_copy(orig, sp)
- SCR *orig, *sp;
-{
- EX_PRIVATE *oexp, *nexp;
-
- /* Create the private ex structure. */
- CALLOC_RET(orig, nexp, EX_PRIVATE *, 1, sizeof(EX_PRIVATE));
- sp->ex_private = nexp;
-
- /* Initialize queues. */
- TAILQ_INIT(&nexp->tagq);
- TAILQ_INIT(&nexp->tagfq);
- TAILQ_INIT(&nexp->cdq);
- CIRCLEQ_INIT(&nexp->rangeq);
-
- if (orig == NULL) {
- nexp->at_lbuf_set = 0;
- } else {
- oexp = EXP(orig);
-
- nexp->at_lbuf = oexp->at_lbuf;
- nexp->at_lbuf_set = oexp->at_lbuf_set;
-
- if (oexp->lastbcomm != NULL &&
- (nexp->lastbcomm = strdup(oexp->lastbcomm)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- return(1);
- }
-
- if (ex_tagcopy(orig, sp))
- return (1);
- }
- return (0);
-}
-
-/*
- * ex_screen_end --
- * End a vi screen.
- */
-int
-ex_screen_end(sp)
- SCR *sp;
-{
- EX_PRIVATE *exp;
- int rval;
-
- rval = 0;
- exp = EXP(sp);
-
- if (argv_free(sp))
- rval = 1;
-
- if (exp->ibp != NULL)
- FREE(exp->ibp, exp->ibp_len);
-
- if (exp->lastbcomm != NULL)
- FREE(exp->lastbcomm, strlen(exp->lastbcomm) + 1);
-
- if (ex_tagfree(sp))
- rval = 1;
-
- if (ex_cdfree(sp))
- rval = 1;
-
- /* Free private memory. */
- FREE(exp, sizeof(EX_PRIVATE));
- sp->ex_private = NULL;
-
- return (rval);
-}
-
-/*
- * ex_init --
- * Initialize ex.
- */
-int
-ex_init(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- size_t len;
-
- /*
- * The default address is the last line of the file. If the address
- * set bit is on for this file, load the address, ensuring that it
- * exists.
- */
- if (F_ISSET(sp->frp, FR_CURSORSET)) {
- sp->lno = sp->frp->lno;
- sp->cno = sp->frp->cno;
-
- if (file_gline(sp, ep, sp->lno, &len) == NULL) {
- if (file_lline(sp, ep, &sp->lno))
- return (1);
- if (sp->lno == 0)
- sp->lno = 1;
- sp->cno = 0;
- } else if (sp->cno >= len)
- sp->cno = 0;
- } else {
- if (file_lline(sp, ep, &sp->lno))
- return (1);
- if (sp->lno == 0)
- sp->lno = 1;
- sp->cno = 0;
- }
-
- /* Display the status line. */
- return (msg_status(sp, ep, sp->lno, 0));
-}
-
-/*
- * ex_end --
- * End ex session.
- */
-int
-ex_end(sp)
- SCR *sp;
-{
- return (0);
-}
-
-/*
- * ex_optchange --
- * Handle change of options for vi.
- */
-int
-ex_optchange(sp, opt)
- SCR *sp;
- int opt;
-{
- switch (opt) {
- case O_CDPATH:
- return (ex_cdalloc(sp, O_STR(sp, O_CDPATH)));
- case O_TAGS:
- return (ex_tagalloc(sp, O_STR(sp, O_TAGS)));
- }
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_map.c b/usr.bin/vi/ex/ex_map.c
deleted file mode 100644
index a1f1915bc703..000000000000
--- a/usr.bin/vi/ex/ex_map.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_map.c 8.17 (Berkeley) 7/16/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_map -- :map[!] [input] [replacement]
- * Map a key/string or display mapped keys.
- *
- * Historical note:
- * Historic vi maps were fairly bizarre, and likely to differ in
- * very subtle and strange ways from this implementation. Two
- * things worth noting are that vi would often hang or drop core
- * if the map was strange enough (ex: map X "xy$@x^V), or, simply
- * not work. One trick worth remembering is that if you put a
- * mark at the start of the map, e.g. map X mx"xy ...), or if you
- * put the map in a .exrc file, things would often work much better.
- * No clue why.
- */
-int
-ex_map(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- enum seqtype stype;
- CHAR_T *input, *p;
-
- stype = F_ISSET(cmdp, E_FORCE) ? SEQ_INPUT : SEQ_COMMAND;
-
- switch (cmdp->argc) {
- case 0:
- if (seq_dump(sp, stype, 1) == 0)
- msgq(sp, M_INFO, "No %s map entries",
- stype == SEQ_INPUT ? "input" : "command");
- return (0);
- case 2:
- input = cmdp->argv[0]->bp;
- break;
- default:
- abort();
- }
-
- /*
- * If the mapped string is #[0-9]* (and wasn't quoted) then store
- * the function key mapping, and call the screen specific routine.
- * Note, if the screen specific routine is able to create the
- * mapping, the SEQ_FUNCMAP type stays around, maybe the next screen
- * type can get it right.
- */
- if (input[0] == '#') {
- for (p = input + 1; isdigit(*p); ++p);
- if (p[0] != '\0')
- goto nofunc;
-
- if (seq_set(sp, NULL, 0, input, cmdp->argv[0]->len,
- cmdp->argv[1]->bp, cmdp->argv[1]->len, stype, SEQ_FUNCMAP))
- return (1);
- return (sp->s_fmap(sp, stype, input, cmdp->argv[0]->len,
- cmdp->argv[1]->bp, cmdp->argv[1]->len));
- }
-
- /* Some single keys may not be remapped in command mode. */
-nofunc: if (stype == SEQ_COMMAND && input[1] == '\0')
- switch (KEY_VAL(sp, input[0])) {
- case K_COLON:
- case K_ESCAPE:
- case K_NL:
- msgq(sp, M_ERR, "The %s character may not be remapped",
- KEY_NAME(sp, input[0]));
- return (1);
- }
- return (seq_set(sp, NULL, 0, input, cmdp->argv[0]->len,
- cmdp->argv[1]->bp, cmdp->argv[1]->len, stype, SEQ_USERDEF));
-}
-
-/*
- * ex_unmap -- (:unmap[!] key)
- * Unmap a key.
- */
-int
-ex_unmap(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- if (seq_delete(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len,
- F_ISSET(cmdp, E_FORCE) ? SEQ_INPUT : SEQ_COMMAND)) {
- msgq(sp, M_INFO, "\"%s\" isn't mapped", cmdp->argv[0]->bp);
- return (1);
- }
- return (0);
-}
-
-/*
- * map_save --
- * Save the mapped sequences to a file.
- */
-int
-map_save(sp, fp)
- SCR *sp;
- FILE *fp;
-{
- if (seq_save(sp, fp, "map ", SEQ_COMMAND))
- return (1);
- return (seq_save(sp, fp, "map! ", SEQ_INPUT));
-}
diff --git a/usr.bin/vi/ex/ex_mark.c b/usr.bin/vi/ex/ex_mark.c
deleted file mode 100644
index bd1e0fd5140b..000000000000
--- a/usr.bin/vi/ex/ex_mark.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_mark.c 8.6 (Berkeley) 5/21/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-int
-ex_mark(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- if (cmdp->argv[0]->len != 1) {
- msgq(sp, M_ERR, "Mark names must be a single character");
- return (1);
- }
- return (mark_set(sp, ep, cmdp->argv[0]->bp[0], &cmdp->addr1, 1));
-}
diff --git a/usr.bin/vi/ex/ex_mkexrc.c b/usr.bin/vi/ex/ex_mkexrc.c
deleted file mode 100644
index 095d51e55862..000000000000
--- a/usr.bin/vi/ex/ex_mkexrc.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_mkexrc.c 8.12 (Berkeley) 7/15/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-#include <pathnames.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_mkexrc -- :mkexrc[!] [file]
- *
- * Create (or overwrite) a .exrc file with the current info.
- */
-int
-ex_mkexrc(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- struct stat sb;
- FILE *fp;
- int fd, sverrno;
- char *fname;
-
- switch (cmdp->argc) {
- case 0:
- fname = _PATH_EXRC;
- break;
- case 1:
- fname = cmdp->argv[0]->bp;
- set_alt_name(sp, fname);
- break;
- default:
- abort();
- }
-
- if (!F_ISSET(cmdp, E_FORCE) && !stat(fname, &sb)) {
- msgq(sp, M_ERR,
- "%s exists, not written; use ! to override", fname);
- return (1);
- }
-
- /* Create with max permissions of rw-r--r--. */
- if ((fd = open(fname, O_CREAT | O_TRUNC | O_WRONLY,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
- msgq(sp, M_SYSERR, fname);
- return (1);
- }
-
- if ((fp = fdopen(fd, "w")) == NULL) {
- sverrno = errno;
- (void)close(fd);
- errno = sverrno;
- goto e2;
- }
-
- if (abbr_save(sp, fp) || ferror(fp))
- goto e1;
- if (map_save(sp, fp) || ferror(fp))
- goto e1;
- if (opts_save(sp, fp) || ferror(fp))
- goto e1;
-#ifndef NO_DIGRAPH
- digraph_save(sp, fd);
-#endif
- if (fclose(fp))
- goto e2;
-
- msgq(sp, M_INFO, "New .exrc file: %s. ", fname);
- return (0);
-
-e1: sverrno = errno;
- (void)fclose(fp);
- errno = sverrno;
-e2: msgq(sp, M_ERR, "%s: incomplete: %s", fname, strerror(errno));
- return (1);
-}
diff --git a/usr.bin/vi/ex/ex_open.c b/usr.bin/vi/ex/ex_open.c
deleted file mode 100644
index 385fdd3cd922..000000000000
--- a/usr.bin/vi/ex/ex_open.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_open.c 8.4 (Berkeley) 5/21/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_open -- :[line] o[pen] [/pattern/] [flags]
- *
- * Switch to single line "open" mode.
- */
-int
-ex_open(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- /* If open option off, disallow open command. */
- if (!O_ISSET(sp, O_OPEN)) {
- msgq(sp, M_ERR,
- "The open command requires that the open option be set");
- return (1);
- }
-
- msgq(sp, M_ERR, "The open command is not yet implemented");
- return (1);
-}
diff --git a/usr.bin/vi/ex/ex_print.c b/usr.bin/vi/ex/ex_print.c
deleted file mode 100644
index c3aa22f00c07..000000000000
--- a/usr.bin/vi/ex/ex_print.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_print.c 8.14 (Berkeley) 8/7/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_list -- :[line [,line]] l[ist] [count] [flags]
- *
- * Display the addressed lines such that the output is unambiguous.
- */
-int
-ex_list(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- if (ex_print(sp, ep,
- &cmdp->addr1, &cmdp->addr2, cmdp->flags | E_F_LIST))
- return (1);
- sp->lno = cmdp->addr2.lno;
- sp->cno = cmdp->addr2.cno;
- return (0);
-}
-
-/*
- * ex_number -- :[line [,line]] nu[mber] [count] [flags]
- *
- * Display the addressed lines with a leading line number.
- */
-int
-ex_number(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- if (ex_print(sp, ep,
- &cmdp->addr1, &cmdp->addr2, cmdp->flags | E_F_HASH))
- return (1);
- sp->lno = cmdp->addr2.lno;
- sp->cno = cmdp->addr2.cno;
- return (0);
-}
-
-/*
- * ex_pr -- :[line [,line]] p[rint] [count] [flags]
- *
- * Display the addressed lines.
- */
-int
-ex_pr(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- if (ex_print(sp, ep, &cmdp->addr1, &cmdp->addr2, cmdp->flags))
- return (1);
- sp->lno = cmdp->addr2.lno;
- sp->cno = cmdp->addr2.cno;
- return (0);
-}
-
-/*
- * ex_print --
- * Print the selected lines.
- */
-int
-ex_print(sp, ep, fp, tp, flags)
- SCR *sp;
- EXF *ep;
- MARK *fp, *tp;
- register int flags;
-{
- recno_t from, to;
- size_t col, len;
- char *p;
-
- F_SET(sp, S_INTERRUPTIBLE);
- for (from = fp->lno, to = tp->lno; from <= to; ++from) {
- /*
- * Display the line number. The %6 format is specified
- * by POSIX 1003.2, and is almost certainly large enough.
- * Check, though, just in case.
- */
- if (LF_ISSET(E_F_HASH))
- if (from <= 999999)
- col = ex_printf(EXCOOKIE, "%6ld ", from);
- else
- col = ex_printf(EXCOOKIE, "TOOBIG ");
- else
- col = 0;
-
- /*
- * Display the line. The format for E_F_PRINT isn't very good,
- * especially in handling end-of-line tabs, but they're almost
- * backward compatible.
- */
- if ((p = file_gline(sp, ep, from, &len)) == NULL) {
- GETLINE_ERR(sp, from);
- return (1);
- }
-
- if (len == 0 && !LF_ISSET(E_F_LIST))
- (void)ex_printf(EXCOOKIE, "\n");
- else if (ex_ldisplay(sp, p, len, col, flags))
- return (1);
-
- if (INTERRUPTED(sp))
- break;
- }
-
- return (0);
-}
-
-/*
- * ex_ldisplay --
- * Display a line.
- */
-int
-ex_ldisplay(sp, lp, len, col, flags)
- SCR *sp;
- CHAR_T *lp;
- size_t len, col;
- u_int flags;
-{
- CHAR_T ch, *kp;
- u_long ts;
- size_t tlen;
-
- ts = O_VAL(sp, O_TABSTOP);
- for (;; --len) {
- if (len > 0)
- ch = *lp++;
- else if (LF_ISSET(E_F_LIST))
- ch = '$';
- else
- break;
- if (ch == '\t' && !LF_ISSET(E_F_LIST))
- for (tlen = ts - col % ts;
- col < sp->cols && tlen--; ++col)
- (void)ex_printf(EXCOOKIE, " ");
- else {
- kp = KEY_NAME(sp, ch);
- tlen = KEY_LEN(sp, ch);
- if (col + tlen < sp->cols) {
- (void)ex_printf(EXCOOKIE, "%s", kp);
- col += tlen;
- } else
- for (; tlen--; ++kp, ++col) {
- if (col == sp->cols) {
- col = 0;
- (void)ex_printf(EXCOOKIE, "\n");
- }
- (void)ex_printf(EXCOOKIE, "%c", *kp);
- }
- }
- if (len == 0)
- break;
- }
- (void)ex_printf(EXCOOKIE, "\n");
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_read.c b/usr.bin/vi/ex/ex_read.c
deleted file mode 100644
index dafc4adfba92..000000000000
--- a/usr.bin/vi/ex/ex_read.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_read.c 8.39 (Berkeley) 8/9/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_read -- :read [file]
- * :read [!cmd]
- * Read from a file or utility.
- *
- * !!!
- * Historical vi wouldn't undo a filter read, for no apparent reason.
- */
-int
-ex_read(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- struct stat sb;
- CHAR_T *arg, *name;
- EX_PRIVATE *exp;
- FILE *fp;
- MARK rm;
- recno_t nlines;
- size_t arglen, blen, len;
- int btear, farg, rval;
- char *p;
-
- /*
- * 0 args: we're done.
- * 1 args: check for "read !arg".
- * 2 args: check for "read ! arg".
- * >2 args: object, too many args.
- */
- farg = 0;
- switch (cmdp->argc) {
- case 0:
- break;
- case 1:
- arg = cmdp->argv[0]->bp;
- arglen = cmdp->argv[0]->len;
- if (*arg == '!') {
- ++arg;
- --arglen;
- farg = 1;
- }
- break;
- case 2:
- if (cmdp->argv[0]->len == 1 && cmdp->argv[0]->bp[0] == '!') {
- arg = cmdp->argv[1]->bp;
- arglen = cmdp->argv[1]->len;
- farg = 2;
- break;
- }
- /* FALLTHROUGH */
- default:
- goto badarg;
- }
-
- if (farg != 0) {
- /* File name and bang expand the user's argument. */
- if (argv_exp1(sp, ep, cmdp, arg, arglen, 1))
- return (1);
-
- /* If argc unchanged, there wasn't anything to expand. */
- if (cmdp->argc == farg)
- goto usage;
-
- /* Set the last bang command. */
- exp = EXP(sp);
- if (exp->lastbcomm != NULL)
- free(exp->lastbcomm);
- if ((exp->lastbcomm = strdup(cmdp->argv[farg]->bp)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- return (1);
- }
-
- /* Redisplay the user's argument if it's changed. */
- if (F_ISSET(cmdp, E_MODIFY) && IN_VI_MODE(sp)) {
- len = cmdp->argv[farg]->len;
- GET_SPACE_RET(sp, p, blen, len + 2);
- p[0] = '!';
- memmove(p + 1,
- cmdp->argv[farg]->bp, cmdp->argv[farg]->len + 1);
- (void)sp->s_busy(sp, p);
- FREE_SPACE(sp, p, blen);
- }
-
- if (filtercmd(sp, ep, &cmdp->addr1,
- NULL, &rm, cmdp->argv[farg]->bp, FILTER_READ))
- return (1);
-
- /* The filter version of read set the autoprint flag. */
- F_SET(EXP(sp), EX_AUTOPRINT);
-
- /* If in vi mode, move to the first nonblank. */
- sp->lno = rm.lno;
- if (IN_VI_MODE(sp)) {
- sp->cno = 0;
- (void)nonblank(sp, ep, sp->lno, &sp->cno);
- }
- return (0);
- }
-
- /* Shell and file name expand the user's argument. */
- if (argv_exp2(sp, ep, cmdp, arg, arglen, 0))
- return (1);
-
- /*
- * 0 args: no arguments, read the current file, don't set the
- * alternate file name.
- * 1 args: read it, switching to it or settgin the alternate file
- * name.
- * >1 args: object, too many args.
- */
- switch (cmdp->argc) {
- case 1:
- name = sp->frp->name;
- break;
- case 2:
- name = cmdp->argv[1]->bp;
- /*
- * !!!
- * Historically, if you had an "unnamed" file, the read command
- * renamed the file.
- */
- if (F_ISSET(sp->frp, FR_TMPFILE) &&
- !F_ISSET(sp->frp, FR_READNAMED)) {
- if ((p = v_strdup(sp,
- cmdp->argv[1]->bp, cmdp->argv[1]->len)) != NULL) {
- free(sp->frp->name);
- sp->frp->name = p;
- }
- F_SET(sp->frp, FR_NAMECHANGE | FR_READNAMED);
- } else
- set_alt_name(sp, name);
- break;
- default:
-badarg: msgq(sp, M_ERR,
- "%s expanded into too many file names", cmdp->argv[0]->bp);
-usage: msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage);
- return (1);
- }
-
- /*
- * !!!
- * Historically, vi did not permit reads from non-regular files,
- * nor did it distinguish between "read !" and "read!", so there
- * was no way to "force" it.
- */
- if ((fp = fopen(name, "r")) == NULL || fstat(fileno(fp), &sb)) {
- msgq(sp, M_SYSERR, "%s", name);
- return (1);
- }
- if (!S_ISREG(sb.st_mode)) {
- (void)fclose(fp);
- msgq(sp, M_ERR, "Only regular files may be read");
- return (1);
- }
-
- /* Turn on busy message. */
- btear = F_ISSET(sp, S_EXSILENT) ? 0 : !busy_on(sp, "Reading...");
- rval = ex_readfp(sp, ep, name, fp, &cmdp->addr1, &nlines, 1);
- if (btear)
- busy_off(sp);
-
- /*
- * Set the cursor to the first line read in, if anything read
- * in, otherwise, the address. (Historic vi set it to the
- * line after the address regardless, but since that line may
- * not exist we don't bother.)
- */
- sp->lno = cmdp->addr1.lno;
- if (nlines)
- ++sp->lno;
-
- return (rval);
-}
-
-/*
- * ex_readfp --
- * Read lines into the file.
- */
-int
-ex_readfp(sp, ep, name, fp, fm, nlinesp, success_msg)
- SCR *sp;
- EXF *ep;
- char *name;
- FILE *fp;
- MARK *fm;
- recno_t *nlinesp;
- int success_msg;
-{
- EX_PRIVATE *exp;
- recno_t lcnt, lno;
- size_t len;
- u_long ccnt; /* XXX: can't print off_t portably. */
- int rval;
-
- rval = 0;
- exp = EXP(sp);
-
- /*
- * Add in the lines from the output. Insertion starts at the line
- * following the address.
- */
- ccnt = 0;
- lcnt = 0;
- for (lno = fm->lno; !ex_getline(sp, fp, &len); ++lno, ++lcnt) {
- if (INTERRUPTED(sp)) {
- if (!success_msg)
- msgq(sp, M_INFO, "Interrupted");
- break;
- }
- if (file_aline(sp, ep, 1, lno, exp->ibp, len)) {
- rval = 1;
- break;
- }
- ccnt += len;
- }
-
- if (ferror(fp)) {
- msgq(sp, M_SYSERR, "%s", name);
- rval = 1;
- }
-
- if (fclose(fp)) {
- msgq(sp, M_SYSERR, "%s", name);
- return (1);
- }
-
- if (rval)
- return (1);
-
- /* Return the number of lines read in. */
- if (nlinesp != NULL)
- *nlinesp = lcnt;
-
- if (success_msg)
- msgq(sp, M_INFO, "%s%s: %lu line%s, %lu characters",
- INTERRUPTED(sp) ? "Interrupted read: " : "",
- name, lcnt, lcnt == 1 ? "" : "s", ccnt);
-
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_screen.c b/usr.bin/vi/ex/ex_screen.c
deleted file mode 100644
index 179ed07a0afe..000000000000
--- a/usr.bin/vi/ex/ex_screen.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_screen.c 8.13 (Berkeley) 6/27/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_split -- :s[plit] [file ...]
- * Split the screen, optionally setting the file list.
- */
-int
-ex_split(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- return (sp->s_split(sp, cmdp->argc ? cmdp->argv : NULL, cmdp->argc));
-}
-
-/*
- * ex_bg -- :bg
- * Hide the screen.
- */
-int
-ex_bg(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- return (sp->s_bg(sp));
-}
-
-/*
- * ex_fg -- :fg [file]
- * Show the screen.
- */
-int
-ex_fg(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- return (sp->s_fg(sp, cmdp->argc ? cmdp->argv[0]->bp : NULL));
-}
-
-/*
- * ex_resize -- :resize [+-]rows
- * Change the screen size.
- */
-int
-ex_resize(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- enum adjust adj;
-
- if (!F_ISSET(cmdp, E_COUNT)) {
- msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage);
- return (1);
- }
- if (F_ISSET(cmdp, E_COUNT_NEG))
- adj = A_DECREASE;
- else if (F_ISSET(cmdp, E_COUNT_POS))
- adj = A_INCREASE;
- else
- adj = A_SET;
- return (sp->s_rabs(sp, cmdp->count, adj));
-}
-
-/*
- * ex_sdisplay --
- * Display the list of screens.
- */
-int
-ex_sdisplay(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- SCR *tsp;
- int cnt, col, len, sep;
-
- if ((tsp = sp->gp->hq.cqh_first) == (void *)&sp->gp->hq) {
- (void)ex_printf(EXCOOKIE,
- "No backgrounded screens to display.\n");
- return (0);
- }
-
- col = len = sep = 0;
- for (cnt = 1; tsp != (void *)&sp->gp->hq; tsp = tsp->q.cqe_next) {
- col += len = strlen(tsp->frp->name) + sep;
- if (col >= sp->cols - 1) {
- col = len;
- sep = 0;
- (void)ex_printf(EXCOOKIE, "\n");
- } else if (cnt != 1) {
- sep = 1;
- (void)ex_printf(EXCOOKIE, " ");
- }
- (void)ex_printf(EXCOOKIE, "%s", tsp->frp->name);
- ++cnt;
- }
- (void)ex_printf(EXCOOKIE, "\n");
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_shell.c b/usr.bin/vi/ex/ex_shell.c
deleted file mode 100644
index bcbb97d317fd..000000000000
--- a/usr.bin/vi/ex/ex_shell.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_shell.c 8.24 (Berkeley) 8/5/94";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-#include "../svi/svi_screen.h"
-
-/*
- * ex_shell -- :sh[ell]
- * Invoke the program named in the SHELL environment variable
- * with the argument -i.
- */
-int
-ex_shell(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- char buf[MAXPATHLEN];
-
- (void)snprintf(buf, sizeof(buf), "%s -i", O_STR(sp, O_SHELL));
- return (ex_exec_proc(sp, buf, "\n", NULL));
-}
-
-/*
- * ex_exec_proc --
- * Run a separate process.
- */
-int
-ex_exec_proc(sp, cmd, p1, p2)
- SCR *sp;
- char *cmd, *p1, *p2;
-{
- const char *name;
- pid_t pid;
- int rval, teardown;
-
- /* Clear the rest of the screen. */
- if (sp->s_clear(sp))
- return (1);
-
- /* Save ex/vi terminal settings, and restore the original ones. */
- teardown = !ex_sleave(sp);
-
- /*
- * Flush waiting messages (autowrite, for example) so the output
- * matches historic practice.
- */
- (void)sex_refresh(sp, sp->ep);
-
- /* Put out various messages. */
- if (p1 != NULL)
- (void)write(STDOUT_FILENO, p1, strlen(p1));
- if (p2 != NULL)
- (void)write(STDOUT_FILENO, p2, strlen(p2));
-
- SIGBLOCK(sp->gp);
- switch (pid = vfork()) {
- case -1: /* Error. */
- SIGUNBLOCK(sp->gp);
-
- msgq(sp, M_SYSERR, "vfork");
- rval = 1;
- break;
- case 0: /* Utility. */
- /* The utility has default signal behavior. */
- sig_end();
-
- if ((name = strrchr(O_STR(sp, O_SHELL), '/')) == NULL)
- name = O_STR(sp, O_SHELL);
- else
- ++name;
- execl(O_STR(sp, O_SHELL), name, "-c", cmd, NULL);
- msgq(sp, M_ERR, "Error: execl: %s: %s",
- O_STR(sp, O_SHELL), strerror(errno));
- _exit(127);
- /* NOTREACHED */
- default: /* Parent. */
- SIGUNBLOCK(sp->gp);
-
- rval = proc_wait(sp, (long)pid, cmd, 0);
- break;
- }
-
- /* Restore ex/vi terminal settings. */
- if (teardown)
- ex_rleave(sp);
-
- /*
- * XXX
- * Stat of the tty structures (see ex_sleave, ex_rleave) only give
- * us 1-second resolution on the tty changes. A fast '!' command,
- * e.g. ":!pwd" can beat us to the refresh. When there's better
- * resolution from the stat(2) timers, this can go away.
- */
- F_SET(sp, S_REFRESH);
-
- return (rval);
-}
diff --git a/usr.bin/vi/ex/ex_stop.c b/usr.bin/vi/ex/ex_stop.c
deleted file mode 100644
index 3487bbb6d753..000000000000
--- a/usr.bin/vi/ex/ex_stop.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_stop.c 8.7 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-#include "../sex/sex_screen.h"
-
-/*
- * ex_stop -- :stop[!]
- * :suspend[!]
- * Suspend execution.
- */
-int
-ex_stop(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- /* For some strange reason, the force flag turns off autowrite. */
- if (!F_ISSET(cmdp, E_FORCE) &&
- F_ISSET(ep, F_MODIFIED) && O_ISSET(sp, O_AUTOWRITE) &&
- file_write(sp, ep, NULL, NULL, NULL, FS_ALL))
- return (1);
- return (sp->s_suspend(sp));
-}
diff --git a/usr.bin/vi/ex/ex_tag.c b/usr.bin/vi/ex/ex_tag.c
deleted file mode 100644
index 0bb8c3e6982f..000000000000
--- a/usr.bin/vi/ex/ex_tag.c
+++ /dev/null
@@ -1,905 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * David Hitz of Auspex Systems, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_tag.c 8.43 (Berkeley) 8/4/94";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/mman.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-#include "tag.h"
-
-static char *binary_search __P((char *, char *, char *));
-static int compare __P((char *, char *, char *));
-static char *linear_search __P((char *, char *, char *));
-static int search __P((SCR *, char *, char *, char **));
-static int tag_get __P((SCR *, char *, char **, char **, char **));
-
-/*
- * ex_tagfirst --
- * The tag code can be entered from main, i.e. "vi -t tag".
- */
-int
-ex_tagfirst(sp, tagarg)
- SCR *sp;
- char *tagarg;
-{
- FREF *frp;
- MARK m;
- long tl;
- u_int flags;
- int sval;
- char *p, *tag, *name, *search;
-
- /* Taglength may limit the number of characters. */
- if ((tl = O_VAL(sp, O_TAGLENGTH)) != 0 && strlen(tagarg) > tl)
- tagarg[tl] = '\0';
-
- /* Get the tag information. */
- if (tag_get(sp, tagarg, &tag, &name, &search))
- return (1);
-
- /* Create the file entry. */
- if ((frp = file_add(sp, name)) == NULL)
- return (1);
- if (file_init(sp, frp, NULL, 0))
- return (1);
-
- /*
- * !!!
- * The historic tags file format (from a long, long time ago...)
- * used a line number, not a search string. I got complaints, so
- * people are still using the format.
- */
- if (isdigit(search[0])) {
- m.lno = atoi(search);
- m.cno = 0;
- } else {
- /*
- * Search for the tag; cheap fallback for C functions if
- * the name is the same but the arguments have changed.
- */
- m.lno = 1;
- m.cno = 0;
- flags = SEARCH_FILE | SEARCH_TAG | SEARCH_TERM;
- sval = f_search(sp, sp->ep, &m, &m, search, NULL, &flags);
- if (sval && (p = strrchr(search, '(')) != NULL) {
- p[1] = '\0';
- sval = f_search(sp, sp->ep,
- &m, &m, search, NULL, &flags);
- }
- if (sval)
- msgq(sp, M_ERR, "%s: search pattern not found", tag);
- }
-
- /* Set up the screen. */
- frp->lno = m.lno;
- frp->cno = m.cno;
- F_SET(frp, FR_CURSORSET);
-
- /* Might as well make this the default tag. */
- if ((EXP(sp)->tlast = strdup(tagarg)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- return (1);
- }
- return (0);
-}
-
-/* Free a tag or tagf structure from a queue. */
-#define FREETAG(tp) { \
- TAILQ_REMOVE(&exp->tagq, (tp), q); \
- if ((tp)->search != NULL) \
- free((tp)->search); \
- FREE((tp), sizeof(TAGF)); \
-}
-#define FREETAGF(tfp) { \
- TAILQ_REMOVE(&exp->tagfq, (tfp), q); \
- free((tfp)->name); \
- FREE((tfp), sizeof(TAGF)); \
-}
-
-/*
- * ex_tagpush -- :tag [file]
- * Move to a new tag.
- *
- * The tags stacks in nvi are a bit tricky. Each tag contains a file name,
- * search string, and line/column numbers. The search string is only used
- * for the first access and for user display. The first record on the stack
- * is the place where we first did a tag, so it has no search string. The
- * second record is the first tag, and so on. Note, this means that the
- * "current" tag is always on the stack. Each tag has a line/column which is
- * the location from which the user tagged the following TAG entry, and which
- * is used as the return location.
- */
-int
-ex_tagpush(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- enum {TC_CHANGE, TC_CURRENT} which;
- EX_PRIVATE *exp;
- FREF *frp;
- MARK m;
- TAG *tp;
- u_int flags;
- int sval;
- long tl;
- char *name, *p, *search, *tag;
-
- exp = EXP(sp);
- switch (cmdp->argc) {
- case 1:
- if (exp->tlast != NULL)
- FREE(exp->tlast, strlen(exp->tlast) + 1);
- if ((exp->tlast = strdup(cmdp->argv[0]->bp)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- return (1);
- }
- break;
- case 0:
- if (exp->tlast == NULL) {
- msgq(sp, M_ERR, "No previous tag entered");
- return (1);
- }
- break;
- default:
- abort();
- }
-
- /* Taglength may limit the number of characters. */
- if ((tl = O_VAL(sp, O_TAGLENGTH)) != 0 && strlen(exp->tlast) > tl)
- exp->tlast[tl] = '\0';
-
- /* Get the tag information. */
- if (tag_get(sp, exp->tlast, &tag, &name, &search))
- return (1);
-
- /* Get the (possibly new) FREF structure. */
- if ((frp = file_add(sp, name)) == NULL)
- goto err;
-
- if (sp->frp == frp)
- which = TC_CURRENT;
- else {
- if (file_m1(sp, sp->ep,
- F_ISSET(cmdp, E_FORCE), FS_ALL | FS_POSSIBLE))
- goto err;
- which = TC_CHANGE;
- }
-
- /*
- * Get a tag structure -- if this is the first tag, push it on the
- * stack as a placeholder and get another tag structure. Set the
- * line/column of the most recent element on the stack to be the
- * current values, including the file pointer. Then push the new
- * TAG onto the stack with the new file and search string for user
- * display.
- */
- CALLOC(sp, tp, TAG *, 1, sizeof(TAG));
- if (tp != NULL && exp->tagq.tqh_first == NULL) {
- TAILQ_INSERT_HEAD(&exp->tagq, tp, q);
- CALLOC(sp, tp, TAG *, 1, sizeof(TAG));
- }
- if (exp->tagq.tqh_first != NULL) {
- exp->tagq.tqh_first->frp = sp->frp;
- exp->tagq.tqh_first->lno = sp->lno;
- exp->tagq.tqh_first->cno = sp->cno;
- }
- if (tp != NULL) {
- if ((tp->search = strdup(search)) == NULL)
- msgq(sp, M_SYSERR, NULL);
- else
- tp->slen = strlen(search);
- tp->frp = frp;
- TAILQ_INSERT_HEAD(&exp->tagq, tp, q);
- }
-
- /* Switch files. */
- if (which == TC_CHANGE && file_init(sp, frp, NULL, 0)) {
- if (tp != NULL)
- FREETAG(tp);
- /* Handle special, first-tag case. */
- if (exp->tagq.tqh_first->q.tqe_next == NULL)
- TAILQ_REMOVE(&exp->tagq, exp->tagq.tqh_first, q);
-err: free(tag);
- return (1);
- }
-
- /*
- * !!!
- * Historic vi accepted a line number as well as a search
- * string, and people are apparently still using the format.
- */
- if (isdigit(search[0])) {
- m.lno = atoi(search);
- m.cno = 0;
- sval = 0;
- } else {
- /*
- * Search for the tag; cheap fallback for C functions
- * if the name is the same but the arguments have changed.
- */
- m.lno = 1;
- m.cno = 0;
- flags = SEARCH_FILE | SEARCH_TAG | SEARCH_TERM;
- sval = f_search(sp, sp->ep, &m, &m, search, NULL, &flags);
- if (sval && (p = strrchr(search, '(')) != NULL) {
- p[1] = '\0';
- sval = f_search(sp, sp->ep,
- &m, &m, search, NULL, &flags);
- p[1] = '(';
- }
- if (sval)
- msgq(sp, M_ERR, "%s: search pattern not found", tag);
- }
- free(tag);
-
- switch (which) {
- case TC_CHANGE:
- frp->lno = m.lno;
- frp->cno = m.cno;
- F_SET(frp, FR_CURSORSET);
- F_SET(sp, S_FSWITCH);
- break;
- case TC_CURRENT:
- if (sval)
- return (1);
- sp->lno = m.lno;
- sp->cno = m.cno;
- break;
- }
- return (0);
-}
-
-/*
- * ex_tagpop -- :tagp[op][!] [number | file]
- * Pop the tag stack.
- */
-int
-ex_tagpop(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- EX_PRIVATE *exp;
- TAG *ntp, *tp;
- long off;
- size_t arglen;
- char *arg, *p, *t;
-
- /* Check for an empty stack. */
- exp = EXP(sp);
- if (exp->tagq.tqh_first == NULL) {
- msgq(sp, M_INFO, "The tags stack is empty");
- return (1);
- }
-
- switch (cmdp->argc) {
- case 0: /* Pop one tag. */
- ntp = exp->tagq.tqh_first;
- break;
- case 1: /* Name or number. */
- arg = cmdp->argv[0]->bp;
- off = strtol(arg, &p, 10);
- if (*p == '\0') {
- if (off < 1)
- return (0);
- for (tp = exp->tagq.tqh_first;
- tp != NULL && --off > 1; tp = tp->q.tqe_next);
- if (tp == NULL) {
- msgq(sp, M_ERR,
-"Less than %s entries on the tags stack; use :display to see the tags stack",
- arg);
- return (1);
- }
- ntp = tp;
- } else {
- arglen = strlen(arg);
- for (tp = exp->tagq.tqh_first;
- tp != NULL; ntp = tp, tp = tp->q.tqe_next) {
- /* Use the user's original file name. */
- p = tp->frp->name;
- if ((t = strrchr(p, '/')) == NULL)
- t = p;
- else
- ++t;
- if (!strncmp(arg, t, arglen))
- break;
- }
- if (tp == NULL) {
- msgq(sp, M_ERR,
-"No file named %s on the tags stack; use :display to see the tags stack",
- arg);
- return (1);
- }
- }
- break;
- default:
- abort();
- }
-
- /* Update the cursor from the saved TAG information. */
- tp = ntp->q.tqe_next;
- if (tp->frp == sp->frp) {
- sp->lno = tp->lno;
- sp->cno = tp->cno;
- } else {
- if (file_m1(sp, ep,
- F_ISSET(cmdp, E_FORCE), FS_ALL | FS_POSSIBLE))
- return (1);
- if (file_init(sp, tp->frp, NULL, 0))
- return (1);
-
- tp->frp->lno = tp->lno;
- tp->frp->cno = tp->cno;
- F_SET(sp->frp, FR_CURSORSET);
-
- F_SET(sp, S_FSWITCH);
- }
-
- /* Pop entries off the queue up to ntp. */
- for (;;) {
- tp = exp->tagq.tqh_first;
- FREETAG(tp);
- if (tp == ntp)
- break;
- }
-
- /* If returning to the first tag, the stack is now empty. */
- if (exp->tagq.tqh_first->q.tqe_next == NULL)
- TAILQ_REMOVE(&exp->tagq, exp->tagq.tqh_first, q);
- return (0);
-}
-
-/*
- * ex_tagtop -- :tagt[op][!]
- * Clear the tag stack.
- */
-int
-ex_tagtop(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- EX_PRIVATE *exp;
- TAG *tp;
-
- /* Find oldest saved information. */
- exp = EXP(sp);
- for (tp = exp->tagq.tqh_first;
- tp != NULL && tp->q.tqe_next != NULL; tp = tp->q.tqe_next);
- if (tp == NULL) {
- msgq(sp, M_INFO, "The tags stack is empty");
- return (1);
- }
-
- /* If not switching files, it's easy; else do the work. */
- if (tp->frp == sp->frp) {
- sp->lno = tp->lno;
- sp->cno = tp->cno;
- } else {
- if (file_m1(sp, sp->ep,
- F_ISSET(cmdp, E_FORCE), FS_ALL | FS_POSSIBLE))
- return (1);
- if (file_init(sp, tp->frp, NULL, 0))
- return (1);
-
- tp->frp->lno = tp->lno;
- tp->frp->cno = tp->cno;
-
- F_SET(sp->frp, FR_CURSORSET);
- F_SET(sp, S_FSWITCH);
- }
-
- /* Empty out the queue. */
- while ((tp = exp->tagq.tqh_first) != NULL)
- FREETAG(tp);
- return (0);
-}
-
-/*
- * ex_tagdisplay --
- * Display the list of tags.
- */
-int
-ex_tagdisplay(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- EX_PRIVATE *exp;
- TAG *tp;
- size_t len, maxlen;
- int cnt;
- char *name;
-
- exp = EXP(sp);
- if ((tp = exp->tagq.tqh_first) == NULL) {
- (void)ex_printf(EXCOOKIE, "No tags to display.\n");
- return (0);
- }
-
- /*
- * Figure out the formatting. MNOC is the maximum
- * number of file name columns before we split the line.
- */
-#define MNOC 15
- for (maxlen = 0,
- tp = exp->tagq.tqh_first; tp != NULL; tp = tp->q.tqe_next) {
- len = strlen(name = tp->frp->name); /* The original name. */
- if (maxlen < len && len < MNOC)
- maxlen = len;
- }
-
- for (cnt = 1, tp = exp->tagq.tqh_first; tp != NULL;
- ++cnt, tp = tp->q.tqe_next) {
- len = strlen(name = tp->frp->name); /* The original name. */
- if (len > maxlen || len + tp->slen > sp->cols)
- if (tp == NULL || tp->search == NULL)
- (void)ex_printf(EXCOOKIE,
- "%2d %s\n", cnt, name);
- else
- (void)ex_printf(EXCOOKIE,
- "%2d %s\n** %*.*s %s\n", cnt, name,
- (int)maxlen, (int)maxlen, "", tp->search);
- else
- if (tp == NULL || tp->search == NULL)
- (void)ex_printf(EXCOOKIE, "%2d %*.*s\n",
- cnt, (int)maxlen, (int)len, name);
- else
- (void)ex_printf(EXCOOKIE, "%2d %*.*s %s\n",
- cnt, (int)maxlen, (int)len, name,
- tp->search);
- }
- return (0);
-}
-
-/*
- * ex_tagalloc --
- * Create a new list of tag files.
- */
-int
-ex_tagalloc(sp, str)
- SCR *sp;
- char *str;
-{
- EX_PRIVATE *exp;
- TAGF *tp;
- size_t len;
- char *p, *t;
-
- /* Free current queue. */
- exp = EXP(sp);
- while ((tp = exp->tagfq.tqh_first) != NULL)
- FREETAGF(tp);
-
- /* Create new queue. */
- for (p = t = str;; ++p) {
- if (*p == '\0' || isblank(*p)) {
- if ((len = p - t) > 1) {
- MALLOC_RET(sp, tp, TAGF *, sizeof(TAGF));
- MALLOC(sp, tp->name, char *, len + 1);
- if (tp->name == NULL) {
- FREE(tp, sizeof(TAGF));
- return (1);
- }
- memmove(tp->name, t, len);
- tp->name[len] = '\0';
- tp->flags = 0;
- TAILQ_INSERT_TAIL(&exp->tagfq, tp, q);
- }
- t = p + 1;
- }
- if (*p == '\0')
- break;
- }
- return (0);
-}
- /* Free previous queue. */
-/*
- * ex_tagfree --
- * Free the tags file list.
- */
-int
-ex_tagfree(sp)
- SCR *sp;
-{
- EX_PRIVATE *exp;
- TAG *tp;
- TAGF *tfp;
-
- /* Free up tag information. */
- exp = EXP(sp);
- while ((tp = exp->tagq.tqh_first) != NULL)
- FREETAG(tp);
- while ((tfp = exp->tagfq.tqh_first) != NULL)
- FREETAGF(tfp);
- if (exp->tlast != NULL)
- free(exp->tlast);
- return (0);
-}
-
-/*
- * ex_tagcopy --
- * Copy a screen's tag structures.
- */
-int
-ex_tagcopy(orig, sp)
- SCR *orig, *sp;
-{
- EX_PRIVATE *oexp, *nexp;
- TAG *ap, *tp;
- TAGF *atfp, *tfp;
-
- /* Copy tag stack. */
- oexp = EXP(orig);
- nexp = EXP(sp);
- for (ap = oexp->tagq.tqh_first; ap != NULL; ap = ap->q.tqe_next) {
- MALLOC(sp, tp, TAG *, sizeof(TAG));
- if (tp == NULL)
- goto nomem;
- *tp = *ap;
- if (ap->search != NULL &&
- (tp->search = strdup(ap->search)) == NULL)
- goto nomem;
- TAILQ_INSERT_TAIL(&nexp->tagq, tp, q);
- }
-
- /* Copy list of tag files. */
- for (atfp = oexp->tagfq.tqh_first;
- atfp != NULL; atfp = atfp->q.tqe_next) {
- MALLOC(sp, tfp, TAGF *, sizeof(TAGF));
- if (tfp == NULL)
- goto nomem;
- *tfp = *atfp;
- if ((tfp->name = strdup(atfp->name)) == NULL)
- goto nomem;
- TAILQ_INSERT_TAIL(&nexp->tagfq, tfp, q);
- }
-
- /* Copy the last tag. */
- if (oexp->tlast != NULL &&
- (nexp->tlast = strdup(oexp->tlast)) == NULL) {
-nomem: msgq(sp, M_SYSERR, NULL);
- return (1);
- }
- return (0);
-}
-
-/*
- * tag_get --
- * Get a tag from the tags files.
- */
-static int
-tag_get(sp, tag, tagp, filep, searchp)
- SCR *sp;
- char *tag, **tagp, **filep, **searchp;
-{
- struct stat sb;
- EX_PRIVATE *exp;
- TAGF *tfp;
- size_t plen, slen, tlen;
- int dne;
- char *p, pbuf[MAXPATHLEN];
-
- /*
- * Find the tag, only display missing file messages once, and
- * then only if we didn't find the tag.
- */
- dne = 0;
- exp = EXP(sp);
- for (p = NULL, tfp = exp->tagfq.tqh_first;
- tfp != NULL && p == NULL; tfp = tfp->q.tqe_next) {
- errno = 0;
- F_CLR(tfp, TAGF_DNE);
- if (search(sp, tfp->name, tag, &p))
- if (errno == ENOENT) {
- if (!F_ISSET(tfp, TAGF_DNE_WARN)) {
- dne = 1;
- F_SET(tfp, TAGF_DNE);
- }
- } else
- msgq(sp, M_SYSERR, tfp->name);
- else
- if (p != NULL)
- break;
- }
-
- if (p == NULL) {
- msgq(sp, M_ERR, "%s: tag not found", tag);
- if (dne)
- for (tfp = exp->tagfq.tqh_first;
- tfp != NULL; tfp = tfp->q.tqe_next)
- if (F_ISSET(tfp, TAGF_DNE)) {
- errno = ENOENT;
- msgq(sp, M_SYSERR, tfp->name);
- F_SET(tfp, TAGF_DNE_WARN);
- }
- return (1);
- }
-
- /*
- * Set the return pointers; tagp points to the tag, and, incidentally
- * the allocated string, filep points to the file name, and searchp
- * points to the search string. All three are nul-terminated.
- */
- for (*tagp = p; *p && !isblank(*p); ++p);
- if (*p == '\0')
- goto malformed;
- for (*p++ = '\0'; isblank(*p); ++p);
- for (*filep = p; *p && !isblank(*p); ++p);
- if (*p == '\0')
- goto malformed;
- for (*p++ = '\0'; isblank(*p); ++p);
- *searchp = p;
- if (*p == '\0') {
-malformed: free(*tagp);
- msgq(sp, M_ERR, "%s: corrupted tag in %s", tag, tfp->name);
- return (1);
- }
-
- /*
- * !!!
- * If the tag file path is a relative path, see if it exists. If it
- * doesn't, look relative to the tags file path. It's okay for a tag
- * file to not exist, and, historically, vi simply displayed a "new"
- * file. However, if the path exists relative to the tag file, it's
- * pretty clear what's happening, so we may as well do it right.
- */
- if ((*filep)[0] != '/'
- && stat(*filep, &sb) && (p = strrchr(tfp->name, '/')) != NULL) {
- *p = '\0';
- plen = snprintf(pbuf, sizeof(pbuf), "%s/%s", tfp->name, *filep);
- *p = '/';
- if (stat(pbuf, &sb) == 0) {
- slen = strlen(*searchp);
- tlen = strlen(*tagp);
- MALLOC(sp, p, char *, plen + slen + tlen + 5);
- if (p != NULL) {
- memmove(p, *tagp, tlen);
- free(*tagp);
- *tagp = p;
- *(p += tlen) = '\0';
- memmove(++p, pbuf, plen);
- *filep = p;
- *(p += plen) = '\0';
- memmove(++p, *searchp, slen);
- *searchp = p;
- *(p += slen) = '\0';
- }
- }
- }
- return (0);
-}
-
-#define EQUAL 0
-#define GREATER 1
-#define LESS (-1)
-
-/*
- * search --
- * Search a file for a tag.
- */
-static int
-search(sp, name, tname, tag)
- SCR *sp;
- char *name, *tname, **tag;
-{
- struct stat sb;
- int fd, len;
- char *endp, *back, *front, *map, *p;
-
- if ((fd = open(name, O_RDONLY, 0)) < 0)
- return (1);
-
- /*
- * XXX
- * We'd like to test if the file is too big to mmap. Since we don't
- * know what size or type off_t's or size_t's are, what the largest
- * unsigned integral type is, or what random insanity the local C
- * compiler will perpetrate, doing the comparison in a portable way
- * is flatly impossible. Hope that malloc fails if the file is too
- * large.
- */
- if (fstat(fd, &sb) || (map = mmap(NULL, (size_t)sb.st_size,
- PROT_READ, MAP_PRIVATE, fd, (off_t)0)) == (caddr_t)-1) {
- (void)close(fd);
- return (1);
- }
- front = map;
- back = front + sb.st_size;
-
- front = binary_search(tname, front, back);
- front = linear_search(tname, front, back);
-
- if (front == NULL || (endp = strchr(front, '\n')) == NULL) {
- *tag = NULL;
- goto done;
- }
-
- len = endp - front;
- MALLOC(sp, p, char *, len + 1);
- if (p == NULL) {
- *tag = NULL;
- goto done;
- }
- memmove(p, front, len);
- p[len] = '\0';
- *tag = p;
-
-done: if (munmap(map, (size_t)sb.st_size))
- msgq(sp, M_SYSERR, "munmap");
- if (close(fd))
- msgq(sp, M_SYSERR, "close");
- return (0);
-}
-
-/*
- * Binary search for "string" in memory between "front" and "back".
- *
- * This routine is expected to return a pointer to the start of a line at
- * *or before* the first word matching "string". Relaxing the constraint
- * this way simplifies the algorithm.
- *
- * Invariants:
- * front points to the beginning of a line at or before the first
- * matching string.
- *
- * back points to the beginning of a line at or after the first
- * matching line.
- *
- * Base of the Invariants.
- * front = NULL;
- * back = EOF;
- *
- * Advancing the Invariants:
- *
- * p = first newline after halfway point from front to back.
- *
- * If the string at "p" is not greater than the string to match,
- * p is the new front. Otherwise it is the new back.
- *
- * Termination:
- *
- * The definition of the routine allows it return at any point,
- * since front is always at or before the line to print.
- *
- * In fact, it returns when the chosen "p" equals "back". This
- * implies that there exists a string is least half as long as
- * (back - front), which in turn implies that a linear search will
- * be no more expensive than the cost of simply printing a string or two.
- *
- * Trying to continue with binary search at this point would be
- * more trouble than it's worth.
- */
-#define SKIP_PAST_NEWLINE(p, back) while (p < back && *p++ != '\n');
-
-static char *
-binary_search(string, front, back)
- register char *string, *front, *back;
-{
- register char *p;
-
- p = front + (back - front) / 2;
- SKIP_PAST_NEWLINE(p, back);
-
- while (p != back) {
- if (compare(string, p, back) == GREATER)
- front = p;
- else
- back = p;
- p = front + (back - front) / 2;
- SKIP_PAST_NEWLINE(p, back);
- }
- return (front);
-}
-
-/*
- * Find the first line that starts with string, linearly searching from front
- * to back.
- *
- * Return NULL for no such line.
- *
- * This routine assumes:
- *
- * o front points at the first character in a line.
- * o front is before or at the first line to be printed.
- */
-static char *
-linear_search(string, front, back)
- char *string, *front, *back;
-{
- while (front < back) {
- switch (compare(string, front, back)) {
- case EQUAL: /* Found it. */
- return (front);
- case LESS: /* No such string. */
- return (NULL);
- case GREATER: /* Keep going. */
- break;
- }
- SKIP_PAST_NEWLINE(front, back);
- }
- return (NULL);
-}
-
-/*
- * Return LESS, GREATER, or EQUAL depending on how the string1 compares
- * with string2 (s1 ??? s2).
- *
- * o Matches up to len(s1) are EQUAL.
- * o Matches up to len(s2) are GREATER.
- *
- * The string "s1" is null terminated. The string s2 is '\t', space, (or
- * "back") terminated.
- *
- * !!!
- * Reasonably modern ctags programs use tabs as separators, not spaces.
- * However, historic programs did use spaces, and, I got complaints.
- */
-static int
-compare(s1, s2, back)
- register char *s1, *s2, *back;
-{
- for (; *s1 && s2 < back && (*s2 != '\t' && *s2 != ' '); ++s1, ++s2)
- if (*s1 != *s2)
- return (*s1 < *s2 ? LESS : GREATER);
- return (*s1 ? GREATER : s2 < back &&
- (*s2 != '\t' && *s2 != ' ') ? LESS : EQUAL);
-}
diff --git a/usr.bin/vi/ex/ex_usage.c b/usr.bin/vi/ex/ex_usage.c
deleted file mode 100644
index b6031b5caa1a..000000000000
--- a/usr.bin/vi/ex/ex_usage.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_usage.c 8.19 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-#include "../vi/vcmd.h"
-
-/*
- * ex_help -- :help
- * Display help message.
- */
-int
-ex_help(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- (void)ex_printf(EXCOOKIE,
- "To see the list of vi commands, enter \":viusage<CR>\"\n");
- (void)ex_printf(EXCOOKIE,
- "To see the list of ex commands, enter \":exusage<CR>\"\n");
- (void)ex_printf(EXCOOKIE,
- "For an ex command usage statement enter \":exusage [cmd]<CR>\"\n");
- (void)ex_printf(EXCOOKIE,
- "For a vi key usage statement enter \":viusage [key]<CR>\"\n");
- (void)ex_printf(EXCOOKIE, "To exit, enter \":q!\"\n");
- return (0);
-}
-
-/*
- * ex_usage -- :exusage [cmd]
- * Display ex usage strings.
- */
-int
-ex_usage(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- ARGS *ap;
- EXCMDLIST const *cp;
- char *name;
-
- switch (cmdp->argc) {
- case 1:
- ap = cmdp->argv[0];
- for (cp = cmds; cp->name != NULL &&
- memcmp(ap->bp, cp->name, ap->len); ++cp);
- if (cp->name == NULL)
- (void)ex_printf(EXCOOKIE,
- "The %.*s command is unknown",
- (int)ap->len, ap->bp);
- else {
- (void)ex_printf(EXCOOKIE,
- "Command: %s\n Usage: %s\n", cp->help, cp->usage);
- /*
- * !!!
- * The "visual" command has two modes, one from ex,
- * one from the vi colon line. Don't ask.
- */
- if (cp != &cmds[C_VISUAL_EX] &&
- cp != &cmds[C_VISUAL_VI])
- break;
- if (cp == &cmds[C_VISUAL_EX])
- cp = &cmds[C_VISUAL_VI];
- else
- cp = &cmds[C_VISUAL_EX];
- (void)ex_printf(EXCOOKIE,
- "Command: %s\n Usage: %s\n", cp->help, cp->usage);
- }
- break;
- case 0:
- F_SET(sp, S_INTERRUPTIBLE);
- for (cp = cmds; cp->name != NULL; ++cp) {
- /* The ^D command has an unprintable name. */
- if (cp == &cmds[C_SCROLL])
- name = "^D";
- else
- name = cp->name;
- (void)ex_printf(EXCOOKIE,
- "%*s: %s\n", MAXCMDNAMELEN, name, cp->help);
- }
- break;
- default:
- abort();
- }
- return (0);
-}
-
-/*
- * ex_viusage -- :viusage [key]
- * Display vi usage strings.
- */
-int
-ex_viusage(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- VIKEYS const *kp;
- int key;
-
- switch (cmdp->argc) {
- case 1:
- if (cmdp->argv[0]->len != 1) {
- msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage);
- return (1);
- }
- key = cmdp->argv[0]->bp[0];
- if (key > MAXVIKEY)
- goto nokey;
-
- /* Special case: '[' and ']' commands. */
- if ((key == '[' || key == ']') && cmdp->argv[0]->bp[1] != key)
- goto nokey;
-
- /* Special case: ~ command. */
- if (key == '~' && O_ISSET(sp, O_TILDEOP))
- kp = &tmotion;
- else
- kp = &vikeys[key];
-
- if (kp->func == NULL)
-nokey: (void)ex_printf(EXCOOKIE,
- "The %s key has no current meaning",
- KEY_NAME(sp, key));
- else
- (void)ex_printf(EXCOOKIE,
- " Key:%s%s\nUsage: %s\n",
- isblank(*kp->help) ? "" : " ", kp->help, kp->usage);
- break;
- case 0:
- F_SET(sp, S_INTERRUPTIBLE);
- for (key = 0; key <= MAXVIKEY; ++key) {
- /* Special case: ~ command. */
- if (key == '~' && O_ISSET(sp, O_TILDEOP))
- kp = &tmotion;
- else
- kp = &vikeys[key];
- if (kp->help != NULL)
- (void)ex_printf(EXCOOKIE, "%s\n", kp->help);
- }
- break;
- default:
- abort();
- }
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_util.c b/usr.bin/vi/ex/ex_util.c
deleted file mode 100644
index e88c28f0e806..000000000000
--- a/usr.bin/vi/ex/ex_util.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_util.c 8.12 (Berkeley) 8/4/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_getline --
- * Return a line from the terminal.
- */
-int
-ex_getline(sp, fp, lenp)
- SCR *sp;
- FILE *fp;
- size_t *lenp;
-{
- EX_PRIVATE *exp;
- size_t off;
- int ch;
- char *p;
-
- exp = EXP(sp);
- for (errno = 0, off = 0, p = exp->ibp;;) {
- if (off >= exp->ibp_len) {
- BINC_RET(sp, exp->ibp, exp->ibp_len, off + 1);
- p = exp->ibp + off;
- }
- if ((ch = getc(fp)) == EOF && !feof(fp)) {
- if (errno == EINTR) {
- errno = 0;
- clearerr(fp);
- continue;
- }
- return (1);
- }
- if (ch == EOF || ch == '\n') {
- if (ch == EOF && !off)
- return (1);
- *lenp = off;
- return (0);
- }
- *p++ = ch;
- ++off;
- }
- /* NOTREACHED */
-}
-
-/*
- * ex_sleave --
- * Save the terminal/signal state, screen modification time.
- * Specific to ex/filter.c and ex/ex_shell.c.
- */
-int
-ex_sleave(sp)
- SCR *sp;
-{
- struct stat sb;
- EX_PRIVATE *exp;
-
- /* Ignore sessions not using tty's. */
- if (!F_ISSET(sp->gp, G_STDIN_TTY))
- return (1);
-
- exp = EXP(sp);
- if (tcgetattr(STDIN_FILENO, &exp->leave_term)) {
- msgq(sp, M_SYSERR, "tcgetattr");
- return (1);
- }
- if (tcsetattr(STDIN_FILENO,
- TCSANOW | TCSASOFT, &sp->gp->original_termios)) {
- msgq(sp, M_SYSERR, "tcsetattr");
- return (1);
- }
- /*
- * The process may write to the terminal. Save the access time
- * (read) and modification time (write) of the tty; if they have
- * changed when we restore the modes, will have to refresh the
- * screen.
- */
- if (fstat(STDIN_FILENO, &sb)) {
- msgq(sp, M_SYSERR, "stat: stdin");
- exp->leave_atime = exp->leave_mtime = 0;
- } else {
- exp->leave_atime = sb.st_atime;
- exp->leave_mtime = sb.st_mtime;
- }
- return (0);
-}
-
-/*
- * ex_rleave --
- * Return the terminal/signal state, not screen modification time.
- * Specific to ex/filter.c and ex/ex_shell.c.
- */
-void
-ex_rleave(sp)
- SCR *sp;
-{
- EX_PRIVATE *exp;
- struct stat sb;
-
- exp = EXP(sp);
-
- /* Restore the terminal modes. */
- if (tcsetattr(STDIN_FILENO, TCSANOW | TCSASOFT, &exp->leave_term))
- msgq(sp, M_SYSERR, "tcsetattr");
-
- /* If the terminal was used, refresh the screen. */
- if (fstat(STDIN_FILENO, &sb) || exp->leave_atime == 0 ||
- exp->leave_atime != sb.st_atime || exp->leave_mtime != sb.st_mtime)
- F_SET(sp, S_REFRESH);
-}
-
-/*
- * ex_ncheck --
- * Check for more files to edit.
- */
-int
-ex_ncheck(sp, force)
- SCR *sp;
- int force;
-{
- /*
- * !!!
- * Historic practice: quit! or two quit's done in succession
- * (where ZZ counts as a quit) didn't check for other files.
- */
- if (!force && sp->ccnt != sp->q_ccnt + 1 &&
- sp->cargv != NULL && sp->cargv[1] != NULL) {
- sp->q_ccnt = sp->ccnt;
- msgq(sp, M_ERR,
- "More files to edit; use n[ext] to go to the next file, q[uit]! to quit");
- return (1);
- }
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_version.c b/usr.bin/vi/ex/ex_version.c
deleted file mode 100644
index 31c2cb711ca5..000000000000
--- a/usr.bin/vi/ex/ex_version.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_version.c 8.62 (Berkeley) 8/15/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_version -- :version
- * Display the program version.
- */
-int
-ex_version(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- static time_t then = 776975285;
-
- (void)ex_printf(EXCOOKIE,
-"Version 1.32, %sThe CSRG, University of California, Berkeley.\n",
- ctime(&then));
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_visual.c b/usr.bin/vi/ex/ex_visual.c
deleted file mode 100644
index cfb0c139f77f..000000000000
--- a/usr.bin/vi/ex/ex_visual.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_visual.c 8.13 (Berkeley) 7/18/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_visual -- :[line] vi[sual] [^-.+] [window_size] [flags]
- *
- * Switch to visual mode.
- */
-int
-ex_visual(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- size_t len;
- int pos;
- char buf[256];
-
- /* If open option off, disallow visual command. */
- if (!O_ISSET(sp, O_OPEN)) {
- msgq(sp, M_ERR,
- "The visual command requires that the open option be set");
- return (1);
- }
-
- /* If a line specified, move to that line. */
- if (cmdp->addrcnt)
- sp->lno = cmdp->addr1.lno;
-
- /*
- * Push a command based on the line position flags. If no
- * flag specified, the line goes at the top of the screen.
- */
- switch (F_ISSET(cmdp, E_F_CARAT | E_F_DASH | E_F_DOT | E_F_PLUS)) {
- case E_F_CARAT:
- pos = '^';
- break;
- case E_F_DASH:
- pos = '-';
- break;
- case E_F_DOT:
- pos = '.';
- break;
- case E_F_PLUS:
- pos = '+';
- break;
- default:
- sp->frp->lno = sp->lno;
- sp->frp->cno = 0;
- F_SET(sp->frp, FR_CURSORSET | FR_FNONBLANK);
- goto nopush;
- }
-
- if (F_ISSET(cmdp, E_COUNT))
- len = snprintf(buf, sizeof(buf),
- "%luz%c%lu", sp->lno, pos, cmdp->count);
- else
- len = snprintf(buf, sizeof(buf), "%luz%c", sp->lno, pos);
- (void)term_push(sp, buf, len, CH_NOMAP | CH_QUOTED);
-
- /*
- * !!!
- * Historically, if no line address was specified, the [p#l] flags
- * caused the cursor to be moved to the last line of the file, which
- * was then positioned as described above. This seems useless, so
- * I haven't implemented it.
- */
- switch (F_ISSET(cmdp, E_F_HASH | E_F_LIST | E_F_PRINT)) {
- case E_F_HASH:
- O_SET(sp, O_NUMBER);
- break;
- case E_F_LIST:
- O_SET(sp, O_LIST);
- break;
- case E_F_PRINT:
- break;
- }
-
- /* Switch modes. */
-nopush: F_CLR(sp, S_SCREENS);
- F_SET(sp, sp->saved_vi_mode);
-
- return (0);
-}
diff --git a/usr.bin/vi/ex/ex_write.c b/usr.bin/vi/ex/ex_write.c
deleted file mode 100644
index 3dbb6e84a08f..000000000000
--- a/usr.bin/vi/ex/ex_write.c
+++ /dev/null
@@ -1,327 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_write.c 8.36 (Berkeley) 8/4/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-enum which {WN, WQ, WRITE, XIT};
-
-static int exwr __P((SCR *, EXF *, EXCMDARG *, enum which));
-
-/*
- * ex_wn -- :wn[!] [>>] [file]
- * Write to a file and switch to the next one.
- */
-int
-ex_wn(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- if (exwr(sp, ep, cmdp, WN))
- return (1);
- if (file_m3(sp, ep, 0))
- return (1);
-
- /* The file name isn't a new file to edit. */
- cmdp->argc = 0;
-
- return (ex_next(sp, ep, cmdp));
-}
-
-/*
- * ex_wq -- :wq[!] [>>] [file]
- * Write to a file and quit.
- */
-int
-ex_wq(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- int force;
-
- if (exwr(sp, ep, cmdp, WQ))
- return (1);
- if (file_m3(sp, ep, 0))
- return (1);
-
- force = F_ISSET(cmdp, E_FORCE);
-
- if (ex_ncheck(sp, force))
- return (1);
-
- F_SET(sp, force ? S_EXIT_FORCE : S_EXIT);
- return (0);
-}
-
-/*
- * ex_write -- :write[!] [>>] [file]
- * :write [!] [cmd]
- * Write to a file.
- */
-int
-ex_write(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- return (exwr(sp, ep, cmdp, WRITE));
-}
-
-
-/*
- * ex_xit -- :x[it]! [file]
- *
- * Write out any modifications and quit.
- */
-int
-ex_xit(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- int force;
-
- if (F_ISSET((ep), F_MODIFIED) && exwr(sp, ep, cmdp, XIT))
- return (1);
- if (file_m3(sp, ep, 0))
- return (1);
-
- force = F_ISSET(cmdp, E_FORCE);
-
- if (ex_ncheck(sp, force))
- return (1);
-
- F_SET(sp, force ? S_EXIT_FORCE : S_EXIT);
- return (0);
-}
-
-/*
- * exwr --
- * The guts of the ex write commands.
- */
-static int
-exwr(sp, ep, cmdp, cmd)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
- enum which cmd;
-{
- EX_PRIVATE *exp;
- MARK rm;
- int flags;
- char *name, *p;
-
- /* All write commands can have an associated '!'. */
- LF_INIT(FS_POSSIBLE);
- if (F_ISSET(cmdp, E_FORCE))
- LF_SET(FS_FORCE);
-
- /* Skip any leading whitespace. */
- if (cmdp->argc != 0)
- for (p = cmdp->argv[0]->bp; *p && isblank(*p); ++p);
-
- /* If no arguments, just write the file back. */
- if (cmdp->argc == 0 || *p == '\0') {
- if (F_ISSET(cmdp, E_ADDR2_ALL))
- LF_SET(FS_ALL);
- return (file_write(sp, ep,
- &cmdp->addr1, &cmdp->addr2, NULL, flags));
- }
-
- /* If "write !" it's a pipe to a utility. */
- exp = EXP(sp);
- if (cmd == WRITE && *p == '!') {
- for (++p; *p && isblank(*p); ++p);
- if (*p == '\0') {
- msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage);
- return (1);
- }
- /* Expand the argument. */
- if (argv_exp1(sp, ep, cmdp, p, strlen(p), 0))
- return (1);
- if (filtercmd(sp, ep, &cmdp->addr1, &cmdp->addr2,
- &rm, cmdp->argv[1]->bp, FILTER_WRITE))
- return (1);
- sp->lno = rm.lno;
- return (0);
- }
-
- /* If "write >>" it's an append to a file. */
- if (cmd != XIT && p[0] == '>' && p[1] == '>') {
- LF_SET(FS_APPEND);
-
- /* Skip ">>" and whitespace. */
- for (p += 2; *p && isblank(*p); ++p);
- }
-
- /* Build an argv so we get an argument count and file expansion. */
- if (argv_exp2(sp, ep, cmdp, p, strlen(p), 0))
- return (1);
-
- switch (cmdp->argc) {
- case 1:
- /*
- * Nothing to expand, write the current file.
- * XXX
- * Should never happen, already checked this case.
- */
- name = NULL;
- break;
- case 2:
- /* One new argument, write it. */
- name = cmdp->argv[exp->argsoff - 1]->bp;
- set_alt_name(sp, name);
- break;
- default:
- /* If expanded to more than one argument, object. */
- msgq(sp, M_ERR, "%s expanded into too many file names",
- cmdp->argv[0]->bp);
- msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage);
- return (1);
- }
-
- if (F_ISSET(cmdp, E_ADDR2_ALL))
- LF_SET(FS_ALL);
- return (file_write(sp, ep, &cmdp->addr1, &cmdp->addr2, name, flags));
-}
-
-/*
- * ex_writefp --
- * Write a range of lines to a FILE *.
- */
-int
-ex_writefp(sp, ep, name, fp, fm, tm, nlno, nch)
- SCR *sp;
- EXF *ep;
- char *name;
- FILE *fp;
- MARK *fm, *tm;
- u_long *nlno, *nch;
-{
- struct stat sb;
- u_long ccnt; /* XXX: can't print off_t portably. */
- recno_t fline, tline, lcnt;
- size_t len;
- int sv_errno;
- char *p;
-
- fline = fm->lno;
- tline = tm->lno;
-
- if (nlno != NULL) {
- *nch = 0;
- *nlno = 0;
- }
-
- /*
- * The vi filter code has multiple processes running simultaneously,
- * and one of them calls ex_writefp(). The "unsafe" function calls
- * in this code are to file_gline() and msgq(). File_gline() is safe,
- * see the comment in filter.c:filtercmd() for details. We don't call
- * msgq if the multiple process bit in the EXF is set.
- *
- * !!!
- * Historic vi permitted files of 0 length to be written. However,
- * since the way vi got around dealing with "empty" files was to
- * always have a line in the file no matter what, it wrote them as
- * files of a single, empty line. We write empty files.
- *
- * "Alex, I'll take vi trivia for $1000."
- */
- ccnt = 0;
- lcnt = 0;
- if (tline != 0) {
- for (; fline <= tline; ++fline, ++lcnt) {
- /* Caller has to provide any interrupt message. */
- if (INTERRUPTED(sp))
- break;
- if ((p = file_gline(sp, ep, fline, &len)) == NULL)
- break;
- if (fwrite(p, 1, len, fp) != len) {
- msgq(sp, M_SYSERR, name);
- (void)fclose(fp);
- return (1);
- }
- ccnt += len;
- if (putc('\n', fp) != '\n')
- break;
- ++ccnt;
- }
- }
-
- /* If it's a regular file, sync it so that NFS is forced to flush. */
- if (!fstat(fileno(fp), &sb) &&
- S_ISREG(sb.st_mode) && fsync(fileno(fp))) {
- sv_errno = errno;
- (void)fclose(fp);
- errno = sv_errno;
- goto err;
- }
- if (fclose(fp))
- goto err;
- if (nlno != NULL) {
- *nch = ccnt;
- *nlno = lcnt;
- }
- return (0);
-
-err: if (!F_ISSET(ep, F_MULTILOCK))
- msgq(sp, M_SYSERR, name);
- return (1);
-}
diff --git a/usr.bin/vi/ex/ex_yank.c b/usr.bin/vi/ex/ex_yank.c
deleted file mode 100644
index 7f5d28002945..000000000000
--- a/usr.bin/vi/ex/ex_yank.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ex_yank.c 8.5 (Berkeley) 5/17/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-/*
- * ex_yank -- :[line [,line]] ya[nk] [buffer] [count]
- *
- * Yank the lines into a buffer.
- */
-int
-ex_yank(sp, ep, cmdp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *cmdp;
-{
- return (cut(sp, ep,
- F_ISSET(cmdp, E_BUFFER) ? &cmdp->buffer : NULL,
- &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE));
-}
diff --git a/usr.bin/vi/ex/excmd.h.stub b/usr.bin/vi/ex/excmd.h.stub
deleted file mode 100644
index 3b4051b0f960..000000000000
--- a/usr.bin/vi/ex/excmd.h.stub
+++ /dev/null
@@ -1,285 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)excmd.h.stub 8.73 (Berkeley) 8/9/94
- */
-
-#define PROMPTCHAR ':' /* Prompt character. */
-
-/* Ex command structure. */
-typedef struct _excmdlist {
- char *name; /* Command name. */
- /* Underlying function. */
- int (*fn) __P((SCR *, EXF *, EXCMDARG *));
-
-#define E_ADDR1 0x0000001 /* One address. */
-#define E_ADDR2 0x0000002 /* Two address. */
-#define E_ADDR2_ALL 0x0000004 /* Zero/two addresses; zero == all. */
-#define E_ADDR2_NONE 0x0000008 /* Zero/two addresses; zero == none. */
-#define E_ADDRDEF 0x0000010 /* Default addresses used. */
-#define E_AUTOPRINT 0x0000020 /* Command always sets autoprint. */
-#define E_BUFFER 0x0000040 /* Buffer name supplied. */
-#define E_COUNT 0x0000080 /* Count supplied. */
-#define E_COUNT_NEG 0x0000100 /* Count was signed negative. */
-#define E_COUNT_POS 0x0000200 /* Count was signed positive. */
-#define E_FORCE 0x0000400 /* ! */
-
-#define E_F_CARAT 0x0000800 /* ^ flag. */
-#define E_F_DASH 0x0001000 /* - flag. */
-#define E_F_DOT 0x0002000 /* . flag. */
-#define E_F_EQUAL 0x0004000 /* = flag. */
-#define E_F_HASH 0x0008000 /* # flag. */
-#define E_F_LIST 0x0010000 /* l flag. */
-#define E_F_PLUS 0x0020000 /* + flag. */
-#define E_F_PRINT 0x0040000 /* p flag. */
-
-#define E_F_PRCLEAR 0x0080000 /* Clear the print (#, l, p) flags. */
-#define E_MODIFY 0x0100000 /* File name expansion modified arg. */
-#define E_NOGLOBAL 0x0200000 /* Not in a global. */
-#define E_NOPERM 0x0400000 /* Permission denied for now. */
-#define E_NORC 0x0800000 /* Not from a .exrc or EXINIT. */
-#define E_ZERO 0x1000000 /* 0 is a legal addr1. */
-#define E_ZERODEF 0x2000000 /* 0 is default addr1 of empty files. */
- u_int32_t flags;
- char *syntax; /* Syntax script. */
- char *usage; /* Usage line. */
- char *help; /* Help line. */
-} EXCMDLIST;
-#define MAXCMDNAMELEN 12 /* Longest command name. */
-extern EXCMDLIST const cmds[]; /* List of ex commands. */
-
-/*
- * Structure passed around to functions implementing ex commands.
- * There are several commands in vi that build one of these and
- * call ex directly. See vi/v_ex.c for details.
- */
-struct _excmdarg {
- EXCMDLIST const *cmd; /* Command entry in command table. */
- CHAR_T buffer; /* Named buffer. */
- recno_t lineno; /* Line number. */
- long count; /* Signed, specified count. */
- long flagoff; /* Signed, flag offset parsed by command. */
- int addrcnt; /* Number of addresses (0, 1 or 2). */
- MARK addr1; /* 1st address. */
- MARK addr2; /* 2nd address. */
- ARGS **argv; /* Array of arguments. */
- int argc; /* Count of arguments. */
- u_int32_t flags; /* Selected flags from EXCMDLIST. */
-};
-
-/* Global ranges. */
-typedef struct _range RANGE;
-struct _range {
- CIRCLEQ_ENTRY(_range) q; /* Linked list of ranges. */
- recno_t start, stop; /* Start/stop of the range. */
-};
-
-/* Cd paths. */
-typedef struct _cdpath CDPATH;
-struct _cdpath {
- TAILQ_ENTRY(_cdpath) q; /* Linked list of cd paths. */
- char *path; /* Path. */
-};
-
-/* Ex private, per-screen memory. */
-typedef struct _ex_private {
- ARGS **args; /* Arguments. */
- int argscnt; /* Argument count. */
- int argsoff; /* Offset into arguments. */
-
- CHAR_T at_lbuf; /* Last executed at buffer's name. */
- int at_lbuf_set; /* If at_lbuf is set. */
-
- char *ibp; /* Line input buffer. */
- size_t ibp_len; /* Line input buffer length. */
-
- u_int32_t fdef; /* Default command flags. */
-
- CHAR_T *lastbcomm; /* Last bang command. */
-
- struct termios leave_term; /* ex_[sr]leave tty state. */
- /* XXX: Should be struct timespec's, but time_t is more portable. */
- time_t leave_atime; /* ex_[sr]leave old access time. */
- time_t leave_mtime; /* ex_[sr]leave old mod time. */
-
- TAILQ_HEAD(_tagh, _tag) tagq; /* Tag list (stack). */
- TAILQ_HEAD(_tagfh, _tagf) tagfq;/* Tag file list. */
- char *tlast; /* Saved last tag. */
-
- TAILQ_HEAD(_cdh, _cdpath) cdq; /* Cd path list. */
-
- /* Linked list of ranges. */
- CIRCLEQ_HEAD(_rangeh, _range) rangeq;
- recno_t range_lno; /* Range set line number. */
-
-#define EX_ABSMARK 0x01 /* Set the absolute mark. */
-#define EX_AUTOPRINT 0x02 /* Autoprint flag. */
- u_int8_t flags;
-} EX_PRIVATE;
-#define EXP(sp) ((EX_PRIVATE *)((sp)->ex_private))
-
-/*
- * !!!
- * Historically, .exrc files and EXINIT variables could only use ^V
- * as an escape character, neither ^Q or a user specified character
- * worked. We enforce that here, just in case someone depends on it.
- */
-#define IS_ESCAPE(sp, ch) \
- (F_ISSET(sp, S_VLITONLY) ? \
- (ch) == CH_LITERAL : KEY_VAL(sp, ch) == K_VLNEXT)
-
-/*
- * Filter actions:
- *
- * FILTER Filter text through the utility.
- * FILTER_READ Read from the utility into the file.
- * FILTER_WRITE Write to the utility, display its output.
- */
-enum filtertype { FILTER, FILTER_READ, FILTER_WRITE };
-int filtercmd __P((SCR *, EXF *,
- MARK *, MARK *, MARK *, char *, enum filtertype));
-
-/* Argument expansion routines. */
-int argv_init __P((SCR *, EXF *, EXCMDARG *));
-int argv_exp0 __P((SCR *, EXF *, EXCMDARG *, char *, size_t));
-int argv_exp1 __P((SCR *, EXF *, EXCMDARG *, char *, size_t, int));
-int argv_exp2 __P((SCR *, EXF *, EXCMDARG *, char *, size_t, int));
-int argv_exp3 __P((SCR *, EXF *, EXCMDARG *, char *, size_t));
-int argv_free __P((SCR *));
-
-/* Ex function prototypes. */
-int ex __P((SCR *, EXF *));
-int ex_cfile __P((SCR *, EXF *, char *, int));
-int ex_cmd __P((SCR *, EXF *, char *, size_t, int));
-int ex_cdalloc __P((SCR *, char *));
-int ex_cdfree __P((SCR *));
-int ex_end __P((SCR *));
-int ex_exec_proc __P((SCR *, char *, char *, char *));
-int ex_gb __P((SCR *, EXF *, TEXTH *, int, u_int));
-int ex_getline __P((SCR *, FILE *, size_t *));
-int ex_icmd __P((SCR *, EXF *, char *, size_t, int));
-int ex_init __P((SCR *, EXF *));
-int ex_is_abbrev __P((char *, size_t));
-int ex_is_unmap __P((char *, size_t));
-int ex_ldisplay __P((SCR *, CHAR_T *, size_t, size_t, u_int));
-int ex_ncheck __P((SCR *, int));
-int ex_optchange __P((SCR *, int));
-int ex_print __P((SCR *, EXF *, MARK *, MARK *, int));
-int ex_readfp __P((SCR *, EXF *, char *, FILE *, MARK *, recno_t *, int));
-void ex_refresh __P((SCR *, EXF *));
-void ex_rleave __P((SCR *));
-int ex_screen_copy __P((SCR *, SCR *));
-int ex_screen_end __P((SCR *));
-int ex_sdisplay __P((SCR *, EXF *));
-int ex_sleave __P((SCR *));
-int ex_suspend __P((SCR *));
-int ex_tdisplay __P((SCR *, EXF *));
-int ex_writefp __P((SCR *, EXF *,
- char *, FILE *, MARK *, MARK *, u_long *, u_long *));
-void global_insdel __P((SCR *, EXF *, enum operation, recno_t));
-int proc_wait __P((SCR *, long, const char *, int));
-int sscr_end __P((SCR *));
-int sscr_exec __P((SCR *, EXF *, recno_t));
-int sscr_input __P((SCR *));
-
-int abbr_save __P((SCR *, FILE *));
-int map_save __P((SCR *, FILE *));
-
-#define EXPROTO(name) int name __P((SCR *, EXF *, EXCMDARG *))
-EXPROTO(ex_abbr);
-EXPROTO(ex_append);
-EXPROTO(ex_args);
-EXPROTO(ex_at);
-EXPROTO(ex_bang);
-EXPROTO(ex_bg);
-EXPROTO(ex_cd);
-EXPROTO(ex_change);
-EXPROTO(ex_color);
-EXPROTO(ex_copy);
-EXPROTO(ex_debug);
-EXPROTO(ex_delete);
-EXPROTO(ex_digraph);
-EXPROTO(ex_display);
-EXPROTO(ex_edit);
-EXPROTO(ex_equal);
-EXPROTO(ex_fg);
-EXPROTO(ex_file);
-EXPROTO(ex_global);
-EXPROTO(ex_help);
-EXPROTO(ex_insert);
-EXPROTO(ex_join);
-EXPROTO(ex_list);
-EXPROTO(ex_map);
-EXPROTO(ex_mark);
-EXPROTO(ex_mkexrc);
-EXPROTO(ex_move);
-EXPROTO(ex_next);
-EXPROTO(ex_number);
-EXPROTO(ex_open);
-EXPROTO(ex_pr);
-EXPROTO(ex_preserve);
-EXPROTO(ex_prev);
-EXPROTO(ex_put);
-EXPROTO(ex_quit);
-EXPROTO(ex_read);
-EXPROTO(ex_recover);
-EXPROTO(ex_resize);
-EXPROTO(ex_rew);
-EXPROTO(ex_script);
-EXPROTO(ex_set);
-EXPROTO(ex_shell);
-EXPROTO(ex_shiftl);
-EXPROTO(ex_shiftr);
-EXPROTO(ex_source);
-EXPROTO(ex_split);
-EXPROTO(ex_stop);
-EXPROTO(ex_subagain);
-EXPROTO(ex_substitute);
-EXPROTO(ex_subtilde);
-EXPROTO(ex_tagpop);
-EXPROTO(ex_tagpush);
-EXPROTO(ex_tagtop);
-EXPROTO(ex_unabbr);
-EXPROTO(ex_undo);
-EXPROTO(ex_unmap);
-EXPROTO(ex_usage);
-EXPROTO(ex_validate);
-EXPROTO(ex_version);
-EXPROTO(ex_vglobal);
-EXPROTO(ex_visual);
-EXPROTO(ex_viusage);
-EXPROTO(ex_wn);
-EXPROTO(ex_wq);
-EXPROTO(ex_write);
-EXPROTO(ex_xit);
-EXPROTO(ex_yank);
-EXPROTO(ex_z);
diff --git a/usr.bin/vi/ex/filter.c b/usr.bin/vi/ex/filter.c
deleted file mode 100644
index 59a221c01cbb..000000000000
--- a/usr.bin/vi/ex/filter.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)filter.c 8.43 (Berkeley) 8/7/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-#include <pathnames.h>
-
-#include "vi.h"
-#include "excmd.h"
-
-static int filter_ldisplay __P((SCR *, FILE *));
-
-/*
- * filtercmd --
- * Run a range of lines through a filter utility and optionally
- * replace the original text with the stdout/stderr output of
- * the utility.
- */
-int
-filtercmd(sp, ep, fm, tm, rp, cmd, ftype)
- SCR *sp;
- EXF *ep;
- MARK *fm, *tm, *rp;
- char *cmd;
- enum filtertype ftype;
-{
- FILE *ifp, *ofp;
- pid_t parent_writer_pid, utility_pid;
- recno_t nread;
- int input[2], output[2], rval, teardown;
- char *name;
-
- /* Set return cursor position; guard against a line number of zero. */
- *rp = *fm;
- if (fm->lno == 0)
- rp->lno = 1;
-
- /*
- * There are three different processes running through this code.
- * They are the utility, the parent-writer and the parent-reader.
- * The parent-writer is the process that writes from the file to
- * the utility, the parent reader is the process that reads from
- * the utility.
- *
- * Input and output are named from the utility's point of view.
- * The utility reads from input[0] and the parent(s) write to
- * input[1]. The parent(s) read from output[0] and the utility
- * writes to output[1].
- *
- * In the FILTER_READ case, the utility isn't expected to want
- * input. Redirect its input from /dev/null. Otherwise open
- * up utility input pipe.
- */
- teardown = 0;
- ofp = NULL;
- input[0] = input[1] = output[0] = output[1] = -1;
- if (ftype == FILTER_READ) {
- if ((input[0] = open(_PATH_DEVNULL, O_RDONLY, 0)) < 0) {
- msgq(sp, M_ERR,
- "filter: %s: %s", _PATH_DEVNULL, strerror(errno));
- return (1);
- }
- } else
- if (pipe(input) < 0) {
- msgq(sp, M_SYSERR, "pipe");
- goto err;
- }
-
- /* Open up utility output pipe. */
- if (pipe(output) < 0) {
- msgq(sp, M_SYSERR, "pipe");
- goto err;
- }
- if ((ofp = fdopen(output[0], "r")) == NULL) {
- msgq(sp, M_SYSERR, "fdopen");
- goto err;
- }
-
- /*
- * Save ex/vi terminal settings, and restore the original ones.
- * Restoration so that users can do things like ":r! cat /dev/tty".
- */
- teardown = ftype != FILTER_WRITE && !ex_sleave(sp);
-
- /* Fork off the utility process. */
- SIGBLOCK(sp->gp);
- switch (utility_pid = vfork()) {
- case -1: /* Error. */
- SIGUNBLOCK(sp->gp);
-
- msgq(sp, M_SYSERR, "vfork");
-err: if (input[0] != -1)
- (void)close(input[0]);
- if (input[1] != -1)
- (void)close(input[1]);
- if (ofp != NULL)
- (void)fclose(ofp);
- else if (output[0] != -1)
- (void)close(output[0]);
- if (output[1] != -1)
- (void)close(output[1]);
- rval = 1;
- goto ret;
- case 0: /* Utility. */
- /* The utility has default signal behavior. */
- sig_end();
-
- /*
- * Redirect stdin from the read end of the input pipe, and
- * redirect stdout/stderr to the write end of the output pipe.
- *
- * !!!
- * Historically, ex only directed stdout into the input pipe,
- * letting stderr come out on the terminal as usual. Vi did
- * not, directing both stdout and stderr into the input pipe.
- * We match that practice for both ex and vi for consistency.
- */
- (void)dup2(input[0], STDIN_FILENO);
- (void)dup2(output[1], STDOUT_FILENO);
- (void)dup2(output[1], STDERR_FILENO);
-
- /* Close the utility's file descriptors. */
- (void)close(input[0]);
- (void)close(input[1]);
- (void)close(output[0]);
- (void)close(output[1]);
-
- if ((name = strrchr(O_STR(sp, O_SHELL), '/')) == NULL)
- name = O_STR(sp, O_SHELL);
- else
- ++name;
-
- execl(O_STR(sp, O_SHELL), name, "-c", cmd, NULL);
- msgq(sp, M_ERR, "Error: execl: %s: %s",
- O_STR(sp, O_SHELL), strerror(errno));
- _exit (127);
- /* NOTREACHED */
- default: /* Parent-reader, parent-writer. */
- SIGUNBLOCK(sp->gp);
-
- /* Close the pipe ends neither parent will use. */
- (void)close(input[0]);
- (void)close(output[1]);
- break;
- }
-
- /*
- * FILTER_READ:
- *
- * Reading is the simple case -- we don't need a parent writer,
- * so the parent reads the output from the read end of the output
- * pipe until it finishes, then waits for the child. Ex_readfp
- * appends to the MARK, and closes ofp.
- *
- * !!!
- * Set the return cursor to the last line read in. Historically,
- * this behaves differently from ":r file" command, which leaves
- * the cursor at the first line read in. Check to make sure that
- * it's not past EOF because we were reading into an empty file.
- */
- if (ftype == FILTER_READ) {
- rval = ex_readfp(sp, ep, "filter", ofp, fm, &nread, 0);
- sp->rptlines[L_ADDED] += nread;
- if (fm->lno == 0)
- rp->lno = nread;
- else
- rp->lno += nread;
- goto uwait;
- }
-
- /*
- * FILTER, FILTER_WRITE
- *
- * Here we need both a reader and a writer. Temporary files are
- * expensive and we'd like to avoid disk I/O. Using pipes has the
- * obvious starvation conditions. It's done as follows:
- *
- * fork
- * child
- * write lines out
- * exit
- * parent
- * FILTER:
- * read lines into the file
- * delete old lines
- * FILTER_WRITE
- * read and display lines
- * wait for child
- *
- * XXX
- * We get away without locking the underlying database because we know
- * that none of the records that we're reading will be modified until
- * after we've read them. This depends on the fact that the current
- * B+tree implementation doesn't balance pages or similar things when
- * it inserts new records. When the DB code has locking, we should
- * treat vi as if it were multiple applications sharing a database, and
- * do the required locking. If necessary a work-around would be to do
- * explicit locking in the line.c:file_gline() code, based on the flag
- * set here.
- */
- rval = 0;
- F_SET(ep, F_MULTILOCK);
-
- SIGBLOCK(sp->gp);
- switch (parent_writer_pid = fork()) {
- case -1: /* Error. */
- SIGUNBLOCK(sp->gp);
-
- msgq(sp, M_SYSERR, "fork");
- (void)close(input[1]);
- (void)close(output[0]);
- rval = 1;
- break;
- case 0: /* Parent-writer. */
- /*
- * Write the selected lines to the write end of the input
- * pipe. This instance of ifp is closed by ex_writefp.
- */
- (void)close(output[0]);
- if ((ifp = fdopen(input[1], "w")) == NULL)
- _exit (1);
- _exit(ex_writefp(sp, ep, "filter", ifp, fm, tm, NULL, NULL));
-
- /* NOTREACHED */
- default: /* Parent-reader. */
- SIGUNBLOCK(sp->gp);
-
- (void)close(input[1]);
- if (ftype == FILTER_WRITE)
- /*
- * Read the output from the read end of the output
- * pipe and display it. Filter_ldisplay closes ofp.
- */
- rval = filter_ldisplay(sp, ofp);
- else {
- /*
- * Read the output from the read end of the output
- * pipe. Ex_readfp appends to the MARK and closes
- * ofp.
- */
- rval = ex_readfp(sp, ep, "filter", ofp, tm, &nread, 0);
- sp->rptlines[L_ADDED] += nread;
- }
-
- /* Wait for the parent-writer. */
- rval |= proc_wait(sp,
- (long)parent_writer_pid, "parent-writer", 1);
-
- /* Delete any lines written to the utility. */
- if (rval == 0 && ftype == FILTER &&
- (cut(sp, ep, NULL, fm, tm, CUT_LINEMODE) ||
- delete(sp, ep, fm, tm, 1))) {
- rval = 1;
- break;
- }
-
- /*
- * If the filter had no output, we may have just deleted
- * the cursor. Don't do any real error correction, we'll
- * try and recover later.
- */
- if (rp->lno > 1 && file_gline(sp, ep, rp->lno, NULL) == NULL)
- --rp->lno;
- break;
- }
- F_CLR(ep, F_MULTILOCK);
-
-uwait: rval |= proc_wait(sp, (long)utility_pid, cmd, 0);
-
- /* Restore ex/vi terminal settings. */
-ret: if (teardown)
- ex_rleave(sp);
- return (rval);
-}
-
-/*
- * proc_wait --
- * Wait for one of the processes.
- *
- * !!!
- * The pid_t type varies in size from a short to a long depending on the
- * system. It has to be cast into something or the standard promotion
- * rules get you. I'm using a long based on the belief that nobody is
- * going to make it unsigned and it's unlikely to be a quad.
- */
-int
-proc_wait(sp, pid, cmd, okpipe)
- SCR *sp;
- long pid;
- const char *cmd;
- int okpipe;
-{
- extern const char *const sys_siglist[];
- size_t len;
- int pstat;
-
- /*
- * Wait for the utility to finish. We can get interrupted
- * by SIGALRM, just ignore it.
- */
- for (;;) {
- errno = 0;
- if (waitpid((pid_t)pid, &pstat, 0) != -1)
- break;
- if (errno != EINTR) {
- msgq(sp, M_SYSERR, "wait error");
- return (1);
- }
- }
-
- /*
- * Display the utility's exit status. Ignore SIGPIPE from the
- * parent-writer, as that only means that the utility chose to
- * exit before reading all of its input.
- */
- if (WIFSIGNALED(pstat) && (!okpipe || WTERMSIG(pstat) != SIGPIPE)) {
- for (; isblank(*cmd); ++cmd);
- len = strlen(cmd);
- msgq(sp, M_ERR, "%.*s%s: received signal: %s%s",
- MIN(len, 20), cmd, len > 20 ? "..." : "",
- sys_siglist[WTERMSIG(pstat)],
- WCOREDUMP(pstat) ? "; core dumped" : "");
- return (1);
- }
- if (WIFEXITED(pstat) && WEXITSTATUS(pstat)) {
- for (; isblank(*cmd); ++cmd);
- len = strlen(cmd);
- msgq(sp, M_ERR, "%.*s%s: exited with status %d",
- MIN(len, 20), cmd, len > 20 ? "..." : "",
- WEXITSTATUS(pstat));
- return (1);
- }
- return (0);
-}
-
-/*
- * filter_ldisplay --
- * Display output from a utility.
- *
- * !!!
- * Historically, the characters were passed unmodified to the terminal.
- * We use the ex print routines to make sure they're printable.
- */
-static int
-filter_ldisplay(sp, fp)
- SCR *sp;
- FILE *fp;
-{
- size_t len;
-
- EX_PRIVATE *exp;
-
- F_SET(sp, S_INTERRUPTIBLE);
- for (exp = EXP(sp); !ex_getline(sp, fp, &len);) {
- if (ex_ldisplay(sp, exp->ibp, len, 0, 0))
- break;
- if (INTERRUPTED(sp))
- break;
- }
- if (ferror(fp))
- msgq(sp, M_SYSERR, "filter input");
- (void)fclose(fp);
- return (0);
-}
diff --git a/usr.bin/vi/ex/tag.h b/usr.bin/vi/ex/tag.h
deleted file mode 100644
index a9fd59d0730b..000000000000
--- a/usr.bin/vi/ex/tag.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)tag.h 8.13 (Berkeley) 7/17/94
- */
-
-struct _tagf { /* Tag file. */
- TAILQ_ENTRY(_tagf) q; /* Linked list of tag files. */
- char *name; /* Tag file name. */
-
-#define TAGF_DNE 0x01 /* Didn't exist. */
-#define TAGF_DNE_WARN 0x02 /* DNE error reported. */
- u_int8_t flags;
-};
-
-struct _tag { /* Tag stack. */
- TAILQ_ENTRY(_tag) q; /* Linked list of tags. */
- FREF *frp; /* Saved file name. */
- recno_t lno; /* Saved line number. */
- size_t cno; /* Saved column number. */
- char *search; /* Search string. */
- size_t slen; /* Search string length. */
-};
-
-int ex_tagalloc __P((SCR *, char *));
-int ex_tagcopy __P((SCR *, SCR *));
-int ex_tagdisplay __P((SCR *, EXF *));
-int ex_tagfirst __P((SCR *, char *));
-int ex_tagfree __P((SCR *));
diff --git a/usr.bin/vi/install/recover.script b/usr.bin/vi/install/recover.script
deleted file mode 100644
index 9f91e4e2bcc1..000000000000
--- a/usr.bin/vi/install/recover.script
+++ /dev/null
@@ -1,32 +0,0 @@
-# @(#)recover.script 8.4 (Berkeley) 8/13/94
-#
-# Recover nvi editor files:
-RECDIR=/var/tmp/vi.recover
-SENDMAIL=/usr/lib/sendmail
-echo 'Recovering nvi editor sessions.'
-
-# Unmodified nvi editor backup files are either zero length or
-# have the execute bit set. Delete both cases.
-vibackup=`echo $RECDIR/vi.*`
-if [ "$vibackup" != "$RECDIR/vi.*" ]; then
- for i in $vibackup; do
- if test -x $i -o ! -s $i; then
- rm $i
- fi
- done
-fi
-
-# It is possible to get incomplete recovery files, if the editor
-# crashes at the right time. Delete any recovery files without
-# corresponding backup files, otherwise send mail to the user.
-virecovery=`echo $RECDIR/recover.*`
-if [ "$virecovery" != "$RECDIR/recover.*" ]; then
- for i in $virecovery; do
- recfile=`awk '/^X-vi-recover-path:/{print $2}' < $i`
- if test ! -n $recfile -a -s $recfile; then
- $SENDMAIL -t < $i
- else
- rm $i
- fi
- done
-fi
diff --git a/usr.bin/vi/sex/sex_confirm.c b/usr.bin/vi/sex/sex_confirm.c
deleted file mode 100644
index 2900928963d5..000000000000
--- a/usr.bin/vi/sex/sex_confirm.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)sex_confirm.c 8.7 (Berkeley) 4/13/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-#include "sex_screen.h"
-
-enum confirm
-sex_confirm(sp, ep, fp, tp)
- SCR *sp;
- EXF *ep;
- MARK *fp, *tp;
-{
- CH ikey;
- recno_t cnt;
-
- if (ex_print(sp, ep, fp, tp, 0))
- return (CONF_QUIT);
-
- for (cnt = fp->cno; cnt; --cnt)
- (void)putc(' ', stdout);
- for (cnt = tp->cno; cnt; --cnt)
- (void)putc('^', stdout);
- (void)fprintf(stdout, "[ynq]");
-
- if (term_key(sp, &ikey, 0) != INP_OK)
- return (CONF_QUIT);
- switch (ikey.ch) {
- case CH_YES:
- return (CONF_YES);
- case CH_QUIT:
- return (CONF_QUIT);
- default:
- case CH_NO:
- return (CONF_NO);
- }
- /* NOTREACHED */
-}
diff --git a/usr.bin/vi/sex/sex_get.c b/usr.bin/vi/sex/sex_get.c
deleted file mode 100644
index a29be5ce0821..000000000000
--- a/usr.bin/vi/sex/sex_get.c
+++ /dev/null
@@ -1,514 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)sex_get.c 8.37 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-#include "../vi/vcmd.h"
-#include "sex_screen.h"
-
-/*
- * !!!
- * The ex input didn't have escape characters like ^V. The only special
- * character was the backslash character, and that only when it preceded
- * a newline as part of a substitution replacement pattern. For example,
- * the command input ":a\<cr>" failed immediately with an error, as the
- * <cr> wasn't part of a substitution replacement pattern. This implies
- * a frightening integration of the editor and the RE engine. There's no
- * way we're going to reproduce those semantics. So, if backslashes are
- * special, this code inserts the backslash and the next character into the
- * string, without regard for the character or the command being entered.
- * Since "\<cr>" was illegal historically (except for the one special case),
- * and the command will fail eventually, historical scripts shouldn't break
- * (presuming they didn't depend on the failure mode itself or the characters
- * remaining when failure occurred.
- */
-static void txt_display __P((SCR *, TEXT *, size_t, size_t *));
-static int txt_outdent __P((SCR *, TEXT *));
-
-#define ERASECH { \
- for (cnt = tp->wd[tp->len]; cnt-- > 0; --col) \
- (void)printf("\b \b"); \
-}
-
-/*
- * sex_get --
- * Get lines from the terminal for ex.
- */
-enum input
-sex_get(sp, ep, tiqh, prompt, flags)
- SCR *sp;
- EXF *ep;
- TEXTH *tiqh;
- ARG_CHAR_T prompt;
- u_int flags;
-{
- /* State of the "[^0]^D" sequences. */
- enum { C_NOTSET, C_CARATSET, C_NOCHANGE, C_ZEROSET } carat_st;
- TEXT *ntp, *tp, ait; /* Input and autoindent text structures. */
- CH ikey; /* Input character. */
- size_t col; /* 0-N: screen column. */
- size_t cnt;
- int rval, istty;
-
- /*
- * !!!
- * Most of the special capabilities (like autoindent, erase,
- * etc.) are turned off if ex isn't talking to a terminal.
- */
- istty = F_ISSET(sp->gp, G_STDIN_TTY);
-
- /*
- * Get a TEXT structure with some initial buffer space, reusing
- * the last one if it's big enough. (All TEXT bookkeeping fields
- * default to 0 -- text_init() handles this.)
- */
- if (tiqh->cqh_first != (void *)tiqh) {
- tp = tiqh->cqh_first;
- if (tp->q.cqe_next != (void *)tiqh || tp->lb_len < 32) {
- text_lfree(tiqh);
- goto newtp;
- }
- tp->len = 0;
- } else {
-newtp: if ((tp = text_init(sp, NULL, 0, 32)) == NULL)
- return (INP_ERR);
- CIRCLEQ_INSERT_HEAD(tiqh, tp, q);
- }
-
- if (istty) {
- /* Display the prompt. */
- if (LF_ISSET(TXT_PROMPT)) {
- col = KEY_LEN(sp, prompt);
- (void)printf("%s", KEY_NAME(sp, prompt));
- }
-
- /* Initialize autoindent value and print it out. */
- if (LF_ISSET(TXT_AUTOINDENT)) {
- if (txt_auto(sp, ep, sp->lno, NULL, 0, tp))
- return (INP_ERR);
- BINC_GOTO(sp, tp->wd, tp->wd_len, tp->len + 1);
- for (cnt = 0; cnt < tp->ai; ++cnt)
- txt_display(sp, tp, cnt, &col);
- }
- } else {
- col = 0;
-
- /* Turn off autoindent here, less special casing below. */
- LF_CLR(TXT_AUTOINDENT);
- }
-
- for (carat_st = C_NOTSET;;) {
- if (istty)
- (void)fflush(stdout);
- /*
- * !!!
- * Historically, ex never mapped commands or keys.
- */
- if (rval = term_key(sp, &ikey, 0))
- return (rval);
-
- if (INTERRUPTED(sp))
- return (INP_INTR);
-
- BINC_GOTO(sp, tp->lb, tp->lb_len, tp->len + 1);
- BINC_GOTO(sp, tp->wd, tp->wd_len, tp->len + 1);
-
- switch (ikey.value) {
- case K_CR:
- case K_NL:
- /* '\' can escape <carriage-return>/<newline>. */
- if (LF_ISSET(TXT_BACKSLASH) &&
- tp->len != 0 && tp->lb[tp->len - 1] == '\\')
- goto ins_ch;
-
- /* Echo the newline if requested. */
- if (istty && LF_ISSET(TXT_NLECHO)) {
- (void)putc('\r', stdout);
- (void)putc('\n', stdout);
- (void)fflush(stdout);
- }
-
- /*
- * CR returns from the ex command line, interrupt
- * always returns.
- */
- if (LF_ISSET(TXT_CR)) {
- /* Terminate with a nul, needed by filter. */
- tp->lb[tp->len] = '\0';
- return (INP_OK);
- }
-
- /* '.' terminates ex input modes. */
- if (LF_ISSET(TXT_DOTTERM) &&
- tp->len == tp->ai + 1 &&
- tp->lb[tp->len - 1] == '.') {
- /* Release the current TEXT. */
- ntp = tp->q.cqe_prev;
- CIRCLEQ_REMOVE(tiqh, tp, q);
- text_free(tp);
- tp = ntp;
- return (INP_OK);
- }
-
- /*
- * If we echoed the newline, display any accumulated
- * error messages.
- */
- if (LF_ISSET(TXT_NLECHO) && sex_refresh(sp, ep))
- return (INP_ERR);
-
- /* Set up bookkeeping for the new line. */
- if ((ntp = text_init(sp, NULL, 0, 32)) == NULL)
- return (INP_ERR);
- ntp->lno = tp->lno + 1;
-
- /*
- * Reset the autoindent line value. 0^D keeps the ai
- * line from changing, ^D changes the level, even if
- * there are no characters in the old line. Note,
- * if using the current tp structure, use the cursor
- * as the length, the user may have erased autoindent
- * characters.
- */
- col = 0;
- if (LF_ISSET(TXT_AUTOINDENT)) {
- if (carat_st == C_NOCHANGE) {
- if (txt_auto(sp, ep,
- OOBLNO, &ait, ait.ai, ntp))
- return (INP_ERR);
- FREE_SPACE(sp, ait.lb, ait.lb_len);
- } else
- if (txt_auto(sp, ep,
- OOBLNO, tp, tp->len, ntp))
- return (INP_ERR);
- carat_st = C_NOTSET;
-
- if (ntp->ai) {
- BINC_GOTO(sp,
- ntp->wd, ntp->wd_len, ntp->len + 1);
- for (cnt = 0; cnt < ntp->ai; ++cnt)
- txt_display(sp, ntp, cnt, &col);
- }
- }
- /*
- * Swap old and new TEXT's, and insert the new TEXT
- * into the queue.
- */
- tp = ntp;
- CIRCLEQ_INSERT_TAIL(tiqh, tp, q);
- break;
- case K_CARAT: /* Delete autoindent chars. */
- if (LF_ISSET(TXT_AUTOINDENT) && tp->len <= tp->ai)
- carat_st = C_CARATSET;
- goto ins_ch;
- case K_ZERO: /* Delete autoindent chars. */
- if (LF_ISSET(TXT_AUTOINDENT) && tp->len <= tp->ai)
- carat_st = C_ZEROSET;
- goto ins_ch;
- case K_CNTRLD: /* Delete autoindent char. */
- /*
- * !!!
- * Historically, the ^D command took (but then ignored)
- * a count. For simplicity, we don't return it unless
- * it's the first character entered. The check for len
- * equal to 0 is okay, TXT_AUTOINDENT won't be set.
- */
- if (LF_ISSET(TXT_CNTRLD)) {
- for (cnt = 0; cnt < tp->len; ++cnt)
- if (!isblank(tp->lb[cnt]))
- break;
- if (cnt == tp->len) {
- tp->len = 1;
- tp->lb[0] = '\004';
- tp->lb[1] = '\0';
- return (INP_OK);
- }
- }
-
- /*
- * If in the first column or no characters to erase,
- * ignore the ^D (this matches historic practice). If
- * not doing autoindent or already inserted non-ai
- * characters, it's a literal. The latter test is done
- * in the switch, as the CARAT forms are N + 1, not N.
- */
- if (!LF_ISSET(TXT_AUTOINDENT))
- goto ins_ch;
- if (tp->len == 0)
- break;
- switch (carat_st) {
- case C_CARATSET: /* ^^D */
- if (tp->len > tp->ai + 1)
- goto ins_ch;
- /* Save the ai string for later. */
- ait.lb = NULL;
- ait.lb_len = 0;
- BINC_GOTO(sp, ait.lb, ait.lb_len, tp->ai);
- memmove(ait.lb, tp->lb, tp->ai);
- ait.ai = ait.len = tp->ai;
-
- carat_st = C_NOCHANGE;
- goto leftmargin;
- case C_ZEROSET: /* 0^D */
- if (tp->len > tp->ai + 1)
- goto ins_ch;
- carat_st = C_NOTSET;
-leftmargin: (void)printf("\b \r");
- tp->ai = tp->len = 0;
- break;
- case C_NOTSET: /* ^D */
- if (tp->len > tp->ai)
- goto ins_ch;
- if (txt_outdent(sp, tp))
- return (INP_ERR);
- break;
- default:
- abort();
- }
- break;
- case K_VERASE:
- if (!istty)
- goto ins_ch;
- if (tp->len) {
- --tp->len;
- if (tp->lb[tp->len] == '\n' ||
- tp->lb[tp->len] == '\r')
- goto repaint;
- ERASECH;
- }
- break;
- case K_VWERASE:
- if (!istty)
- goto ins_ch;
-
- /* Move to the last non-space character. */
- while (tp->len) {
- --tp->len;
- if (tp->lb[tp->len] == '\n' ||
- tp->lb[tp->len] == '\r')
- goto repaint;
- if (!isblank(tp->lb[tp->len])) {
- ++tp->len;
- break;
- } else
- ERASECH;
- }
-
- /* Move to the last space character. */
- while (tp->len) {
- --tp->len;
- if (tp->lb[tp->len] == '\n' ||
- tp->lb[tp->len] == '\r')
- goto repaint;
- if (isblank(tp->lb[tp->len])) {
- ++tp->len;
- break;
- } else
- ERASECH;
- }
- break;
- case K_VKILL:
- if (!istty)
- goto ins_ch;
- while (tp->len) {
- --tp->len;
- if (tp->lb[tp->len] == '\n' ||
- tp->lb[tp->len] == '\r') {
- tp->len = 0;
- goto repaint;
- }
- ERASECH;
- }
- break;
- /*
- * XXX
- * Historic practice is that ^Z suspended command mode, and
- * that it was unaffected by the autowrite option. ^Z ended
- * insert mode, retaining all but the current line of input,
- * which was discarded. When ex was foregrounded, it was in
- * command mode. I don't want to discard input because a user
- * tried to enter a ^Z, and I'd like to be consistent with vi.
- * So, nex matches vi's historic practice, and doesn't permit
- * ^Z in input mode.
- */
- case K_CNTRLZ:
- if (!istty || !LF_ISSET(TXT_EXSUSPEND))
- goto ins_ch;
- sex_suspend(sp);
- goto repaint;
- case K_CNTRLR:
- if (!istty)
- goto ins_ch;
-repaint: if (LF_ISSET(TXT_PROMPT)) {
- col = KEY_LEN(sp, prompt);
- (void)printf("\r%s", KEY_NAME(sp, prompt));
- } else {
- col = 0;
- (void)putc('\r', stdout);
- }
- for (cnt = 0; cnt < tp->len; ++cnt)
- txt_display(sp, tp, cnt, &col);
- break;
- default:
- /*
- * See the TXT_BEAUTIFY comment in vi/v_ntext.c.
- *
- * Silently eliminate any iscntrl() character that
- * wasn't already handled specially, except for <tab>
- * and <ff>.
- */
-ins_ch: if (LF_ISSET(TXT_BEAUTIFY) && iscntrl(ikey.ch) &&
- ikey.value != K_FORMFEED && ikey.value != K_TAB)
- break;
- tp->lb[tp->len] = ikey.ch;
- if (istty)
- txt_display(sp, tp, tp->len, &col);
- ++tp->len;
- break;
- }
- }
- /* NOTREACHED */
-
-binc_err:
- return (INP_ERR);
-}
-
-/*
- * txt_display --
- * Display the character.
- */
-static void
-txt_display(sp, tp, off, colp)
- SCR *sp;
- TEXT *tp;
- size_t off, *colp;
-{
- CHAR_T ch;
- size_t width;
-
- switch (ch = tp->lb[off]) {
- case '\t':
- *colp += tp->wd[off] = width =
- O_VAL(sp, O_TABSTOP) - *colp % O_VAL(sp, O_TABSTOP);
- while (width--)
- putc(' ', stdout);
- break;
- case '\n':
- case '\r':
- (void)putc('\r', stdout);
- (void)putc('\n', stdout);
- break;
- default:
- *colp += tp->wd[off] = KEY_LEN(sp, ch);
- (void)printf("%s", KEY_NAME(sp, ch));
- }
-}
-
-/*
- * txt_outdent --
- * Handle ^D outdents.
- *
- * Ex version of vi/v_ntext.c:txt_outdent(). See that code for the
- * usual ranting and raving.
- */
-static int
-txt_outdent(sp, tp)
- SCR *sp;
- TEXT *tp;
-{
- u_long sw, ts;
- size_t cno, cnt, off, scno, spaces;
-
- ts = O_VAL(sp, O_TABSTOP);
- sw = O_VAL(sp, O_SHIFTWIDTH);
-
- /* Get the current screen column. */
- for (off = scno = 0; off < tp->len; ++off)
- if (tp->lb[off] == '\t')
- scno += STOP_OFF(scno, ts);
- else
- ++scno;
-
- /* Get the previous shiftwidth column. */
- for (cno = scno; --scno % sw != 0;);
-
- /* Decrement characters until less than or equal to that slot. */
- for (; cno > scno; --tp->ai) {
- for (cnt = tp->wd[--tp->len]; cnt-- > 0;)
- (void)printf("\b \b");
- if (tp->lb[--off] == '\t')
- cno -= STOP_OFF(cno, ts);
- else
- --cno;
- }
-
- /* Spaces needed to get to the target. */
- spaces = scno - cno;
-
- /* Maybe just a delete. */
- if (spaces == 0)
- return (0);
-
- /* Make sure there's enough room. */
- BINC_RET(sp, tp->lb, tp->lb_len, tp->len + spaces);
-
- /* Maybe that was enough. */
- if (spaces == 0)
- return (0);
-
- /* Add new space characters. */
- for (; spaces--; ++tp->ai)
- tp->lb[tp->len++] = ' ';
- return (0);
-}
diff --git a/usr.bin/vi/sex/sex_refresh.c b/usr.bin/vi/sex/sex_refresh.c
deleted file mode 100644
index c1be816b4e4c..000000000000
--- a/usr.bin/vi/sex/sex_refresh.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)sex_refresh.c 8.14 (Berkeley) 7/15/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "sex_screen.h"
-
-#ifndef SYSV_CURSES
-#define A_NORMAL 1
-#define A_STANDOUT 2
-#define vidattr(attr) Xvidattr(sp, attr)
-
-static int Xvidattr __P((SCR *, int));
-#endif
-
-/*
- * sex_refresh --
- * In ex, just display any messages.
- */
-int
-sex_refresh(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- MSG *mp;
-
- /* Check for screen resize. */
- if (F_ISSET(sp, S_RESIZE)) {
- sp->rows = O_VAL(sp, O_LINES);
- sp->cols = O_VAL(sp, O_COLUMNS);
- F_CLR(sp, S_RESIZE);
- }
-
- /* Ring the bell. */
- if (F_ISSET(sp, S_BELLSCHED)) {
- sex_bell(sp);
- F_CLR(sp, S_BELLSCHED);
- }
-
- /* Display messages. */
- for (mp = sp->msgq.lh_first;
- mp != NULL && !(F_ISSET(mp, M_EMPTY)); mp = mp->q.le_next) {
- if (F_ISSET(mp, M_INV_VIDEO) &&
- vidattr(A_STANDOUT) == ERR && O_ISSET(sp, O_ERRORBELLS))
- (void)printf("\07");
- (void)printf("%.*s.\n", (int)mp->len, mp->mbuf);
- F_SET(mp, M_EMPTY);
-
- if (F_ISSET(mp, M_INV_VIDEO))
- vidattr(A_NORMAL);
- (void)fflush(stdout);
- }
- return (0);
-}
-
-#ifndef SYSV_CURSES
-/*
- * Xvidattr --
- * Set the video attributes to a value.
- *
- * XXX
- * Just enough to make the above code work when using non-System V
- * curses.
- */
-static int
-Xvidattr(sp, attr)
- SCR *sp;
- int attr;
-{
- SEX_PRIVATE *sxp;
-
- sxp = SXP(sp);
-
- /* Check to see if standout isn't available. */
- if (sxp->SO == NULL)
- return (ERR);
-
- switch (attr) {
- case A_NORMAL:
- (void)tputs(SXP(sp)->SE, 1, vi_putchar);
- break;
- case A_STANDOUT:
- (void)tputs(SXP(sp)->SO, 1, vi_putchar);
- break;
- default:
- abort();
- }
- return (0);
-}
-#endif
diff --git a/usr.bin/vi/sex/sex_screen.c b/usr.bin/vi/sex/sex_screen.c
deleted file mode 100644
index 433899819adf..000000000000
--- a/usr.bin/vi/sex/sex_screen.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)sex_screen.c 8.47 (Berkeley) 7/21/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-#include "sex_screen.h"
-#include "../svi/svi_screen.h"
-
-static void sex_abort __P((void));
-static int sex_noop __P((void));
-static int sex_nope __P((SCR *));
-static int sex_term_init __P((SCR *));
-static void so_se_init __P((SCR *));
-
-/*
- * sex_screen_init --
- * Initialize the ex screen.
- */
-int
-sex_screen_init(sp)
- SCR *sp;
-{
- /* Initialize support routines. */
- sp->s_bell = sex_bell;
- sp->s_bg = (int (*)())sex_nope;
- sp->s_busy = (int (*)())sex_busy;
- sp->s_change = (int (*)())sex_noop;
- sp->s_clear = (int (*)())sex_noop;
- sp->s_colpos = (size_t (*)())sex_abort;
- sp->s_column = (int (*)())sex_abort;
- sp->s_confirm = sex_confirm;
- sp->s_crel = (int (*)())sex_nope;
- sp->s_edit = sex_screen_edit;
- sp->s_end = (int (*)())sex_noop;
- sp->s_ex_cmd = (int (*)())sex_abort;
- sp->s_ex_run = (int (*)())sex_abort;
- sp->s_ex_write = (int (*)())sex_abort;
- sp->s_fg = (int (*)())sex_nope;
- sp->s_fill = (int (*)())sex_abort;
- sp->s_get = sex_get;
- sp->s_key_read = sex_key_read;
- sp->s_optchange = sex_optchange;
- sp->s_fmap = (int (*)())sex_noop;
- sp->s_position = (int (*)())sex_abort;
- sp->s_rabs = (int (*)())sex_nope;
- sp->s_rcm = (size_t (*)())sex_abort;
- sp->s_refresh = sex_refresh;
- sp->s_scroll = (int (*)())sex_abort;
- sp->s_split = (int (*)())sex_nope;
- sp->s_suspend = sex_suspend;
- sp->s_window = sex_window;
-
- return (0);
-}
-
-/*
- * sex_screen_copy --
- * Copy to a new screen.
- */
-int
-sex_screen_copy(orig, sp)
- SCR *orig, *sp;
-{
- SEX_PRIVATE *osex, *nsex;
-
- /* Create the private screen structure. */
- CALLOC_RET(orig, nsex, SEX_PRIVATE *, 1, sizeof(SEX_PRIVATE));
- sp->sex_private = nsex;
-
-/* INITIALIZED AT SCREEN CREATE. */
-
-/* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */
- if (orig == NULL) {
- } else {
- osex = SXP(orig);
-#ifndef SYSV_CURSES
- if (osex->SE != NULL && (nsex->SE = strdup(osex->SE)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- return (1);
- }
- if (osex->SO != NULL && (nsex->SO = strdup(osex->SO)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- free(osex->SE);
- return (1);
- }
-#endif
- }
-
- return (0);
-}
-
-/*
- * sex_screen_end --
- * End a screen.
- */
-int
-sex_screen_end(sp)
- SCR *sp;
-{
-#ifndef SYSV_CURSES
- /* Free inverse video strings. */
- if (SXP(sp)->SE != NULL)
- free(SXP(sp)->SE);
- if (SXP(sp)->SO != NULL)
- free(SXP(sp)->SO);
-#endif
-
- /* Free private memory. */
- FREE(SXP(sp), sizeof(SEX_PRIVATE));
- sp->sex_private = NULL;
-
- return (0);
-}
-
-/*
- * sex_screen_edit --
- * Main ex screen loop. The ex screen is relatively uncomplicated.
- * As long as it has a stdio FILE pointer for output, it's happy.
- */
-int
-sex_screen_edit(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- struct termios t;
- GS *gp;
- int force, rval;
-
- /* Initialize the terminal state. */
- gp = sp->gp;
- if (F_ISSET(gp, G_STDIN_TTY))
- SEX_RAW(t);
-
- /* Write to the terminal. */
- sp->stdfp = stdout;
-
- /*
- * The resize bit is probably set, but clear it, we're
- * going to initialize the screen right now.
- */
- F_CLR(sp, S_RESIZE);
-
- /* Initialize the termcap buffer. */
- if (sex_term_init(sp))
- return (1);
-
- for (;;) {
- /*
- * Run ex. If ex fails, sex data structures
- * may be corrupted, be careful what you do.
- */
- if (rval = ex(sp, sp->ep)) {
- (void)rcv_sync(sp, sp->ep,
- RCV_EMAIL | RCV_ENDSESSION | RCV_PRESERVE);
- (void)screen_end(sp); /* General SCR info. */
- break;
- }
-
- force = 0;
- switch (F_ISSET(sp, S_MAJOR_CHANGE)) {
- case S_EXIT_FORCE:
- force = 1;
- /* FALLTHROUGH */
- case S_EXIT:
- F_CLR(sp, S_EXIT_FORCE | S_EXIT);
- if (file_end(sp, sp->ep, force))
- break;
- (void)screen_end(sp); /* General SCR info. */
- goto ret;
- case 0: /* Changing from ex mode. */
- goto ret;
- case S_FSWITCH:
- F_CLR(sp, S_FSWITCH);
- break;
- case S_SSWITCH:
- default:
- abort();
- }
- }
-
- /* Reset the terminal state. */
-ret: if (F_ISSET(gp, G_STDIN_TTY) && SEX_NORAW(t))
- rval = 1;
- return (rval);
-}
-
-/*
- * sex_term_init --
- * Initialize ex's relationship with the termcap/terminfo entry.
- */
-static int
-sex_term_init(sp)
- SCR *sp;
-{
-
-#ifndef SYSV_CURSES
- /* Initialize standout information. */
- so_se_init(sp);
-#endif
-
- sp->rows = O_VAL(sp, O_LINES);
- sp->cols = O_VAL(sp, O_COLUMNS);
- return (0);
-}
-
-#ifndef SYSV_CURSES
-/*
- * so_se_init --
- * Initialize the inverse video strings.
- */
-static void
-so_se_init(sp)
- SCR *sp;
-{
- SEX_PRIVATE *sxp;
- size_t len;
- char *s, *t, buf[128], tbuf[2048];
-
- if (tgetent(tbuf, O_STR(sp, O_TERM)) != 1)
- return;
-
- sxp = SXP(sp);
-
- /* Get SE. */
- t = buf;
- if ((t = tgetstr("se", &t)) == NULL)
- return;
- if ((len = strlen(t)) == 0)
- return;
- MALLOC_NOMSG(sp, s, char *, len + 1);
- if (s == NULL)
- return;
- memmove(s, buf, len);
- s[len] = '\0';
- sxp->SE = s;
-
- /* Get SO. */
- t = buf;
- if ((t = tgetstr("so", &t)) == NULL)
- goto err;
- if ((len = strlen(t)) == 0)
- goto err;
- MALLOC_NOMSG(sp, s, char *, len + 1);
- if (s == NULL)
- goto err;
- memmove(s, buf, len);
- s[len] = '\0';
- sxp->SO = s;
-
- return;
-
-err: free(sxp->SE);
- sxp->SE = NULL;
- return;
-}
-#endif
-
-/*
- * sex_abort --
- * Fake function. Die.
- */
-static void
-sex_abort()
-{
- abort();
-}
-
-/*
- * sex_noop --
- * Fake function. Do nothing.
- */
-static int
-sex_noop()
-{
- return (0);
-}
-
-/*
- * sex_nope --
- * Fake function. Not in ex, you don't.
- */
-static int
-sex_nope(sp)
- SCR *sp;
-{
- msgq(sp, M_ERR, "Command not applicable to ex mode");
- return (1);
-}
diff --git a/usr.bin/vi/sex/sex_screen.h b/usr.bin/vi/sex/sex_screen.h
deleted file mode 100644
index a2dfeb823ffa..000000000000
--- a/usr.bin/vi/sex/sex_screen.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)sex_screen.h 8.20 (Berkeley) 8/8/94
- */
-
-#define SEX_NORAW(t) \
- tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &(t))
-
-#define SEX_RAW(t) { \
- struct termios __rawt; \
- if (tcgetattr(STDIN_FILENO, &(t))) \
- return (1); \
- __rawt = (t); \
- __rawt.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|INLCR|IGNCR|ICRNL); \
- __rawt.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); \
- __rawt.c_oflag |= OPOST | ONLCR; \
- __rawt.c_cc[VMIN] = 1; \
- __rawt.c_cc[VTIME] = 0; \
- if (tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &__rawt)) \
- return (1); \
-}
-
-typedef struct _sex_private {
-/* INITIALIZED AT SCREEN CREATE. */
- int __sex_unused; /* Make sure it's not empty. */
-
-/* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */
-#ifndef SYSV_CURSES
- char *SE, *SO; /* Inverse video termcap strings. */
-#endif
-} SEX_PRIVATE;
-
-#define SXP(sp) ((SEX_PRIVATE *)((sp)->sex_private))
-
-void sex_bell __P((SCR *));
-void sex_busy __P((SCR *, char const *));
-enum confirm
- sex_confirm __P((SCR *, EXF *, MARK *, MARK *));
-enum input
- sex_get __P((SCR *, EXF *, TEXTH *, ARG_CHAR_T, u_int));
-enum input
- sex_key_read __P((SCR *, int *, struct timeval *));
-int sex_optchange __P((SCR *, int));
-int sex_refresh __P((SCR *, EXF *));
-int sex_screen_copy __P((SCR *, SCR *));
-int sex_screen_edit __P((SCR *, EXF *));
-int sex_screen_end __P((SCR *));
-int sex_suspend __P((SCR *));
-int sex_window __P((SCR *, int));
diff --git a/usr.bin/vi/sex/sex_term.c b/usr.bin/vi/sex/sex_term.c
deleted file mode 100644
index 93ca048928c3..000000000000
--- a/usr.bin/vi/sex/sex_term.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)sex_term.c 8.38 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-#include "../ex/script.h"
-
-/*
- * sex_key_read --
- * Read characters from the input.
- */
-enum input
-sex_key_read(sp, nrp, timeout)
- SCR *sp;
- int *nrp;
- struct timeval *timeout;
-{
- struct timeval t, *tp;
- GS *gp;
- IBUF *tty;
- int maxfd, nr;
-
- *nrp = 0;
- gp = sp->gp;
- tty = gp->tty;
-
- /*
- * We're about to block; check for signals. If a signal received,
- * clear it immediately, so that if it's reset while being serviced
- * we won't miss it.
- *
- * These signal recipients set global flags. None of this has
- * anything to do with input keys, but it's something that can't
- * be done asynchronously without adding locking to handle race
- * conditions, and which needs to be done periodically.
- */
-sigchk: while (F_ISSET(gp, G_SIGINT | G_SIGWINCH)) {
- if (F_ISSET(gp, G_SIGINT))
- return (INP_INTR);
- if (F_ISSET(gp, G_SIGWINCH)) {
- F_CLR(gp, G_SIGWINCH);
- if (!sp->s_window(sp, 1))
- (void)sp->s_refresh(sp, sp->ep);
- }
- }
-
- /*
- * There are three cases here:
- *
- * 1: A read from a file or a pipe. In this case, the reads
- * never timeout regardless. This means that we can hang
- * when trying to complete a map, but we're going to hang
- * on the next read anyway.
- */
- if (!F_ISSET(gp, G_STDIN_TTY)) {
- if ((nr = read(STDIN_FILENO,
- tty->ch + tty->next + tty->cnt,
- tty->nelem - (tty->next + tty->cnt))) > 0)
- goto success;
- return (INP_EOF);
- }
-
- /*
- * 2: A read with an associated timeout. In this case, we are trying
- * to complete a map sequence. Ignore script windows and timeout
- * as specified. If input arrives, we fall into #3, but because
- * timeout isn't NULL, don't read anything but command input.
- *
- * If interrupted, go back and check to see what it was.
- */
- if (timeout != NULL) {
- if (F_ISSET(sp, S_SCRIPT))
- FD_CLR(sp->script->sh_master, &sp->rdfd);
- FD_SET(STDIN_FILENO, &sp->rdfd);
- for (;;) {
- switch (select(STDIN_FILENO + 1,
- &sp->rdfd, NULL, NULL, timeout)) {
- case -1: /* Error or interrupt. */
- if (errno == EINTR)
- goto sigchk;
- goto err;
- case 1: /* Characters ready. */
- break;
- case 0: /* Timeout. */
- return (INP_OK);
- }
- break;
- }
- }
-
- /*
- * 3: At this point, we'll take anything that comes. Select on the
- * command file descriptor and the file descriptor for the script
- * window if there is one. Poll the fd's, increasing the timeout
- * each time each time we don't get anything until we're blocked
- * on I/O.
- *
- * If interrupted, go back and check to see what it was.
- */
- for (t.tv_sec = t.tv_usec = 0;;) {
- /*
- * Reset each time -- sscr_input() may call other
- * routines which could reset bits.
- */
- if (timeout == NULL && F_ISSET(sp, S_SCRIPT)) {
- tp = &t;
-
- FD_SET(STDIN_FILENO, &sp->rdfd);
- if (F_ISSET(sp, S_SCRIPT)) {
- FD_SET(sp->script->sh_master, &sp->rdfd);
- maxfd =
- MAX(STDIN_FILENO, sp->script->sh_master);
- } else
- maxfd = STDIN_FILENO;
- } else {
- tp = NULL;
-
- FD_SET(STDIN_FILENO, &sp->rdfd);
- if (F_ISSET(sp, S_SCRIPT))
- FD_CLR(sp->script->sh_master, &sp->rdfd);
- maxfd = STDIN_FILENO;
- }
-
- switch (select(maxfd + 1, &sp->rdfd, NULL, NULL, tp)) {
- case -1: /* Error or interrupt. */
- if (errno == EINTR)
- goto sigchk;
-err: msgq(sp, M_SYSERR, "select");
- return (INP_ERR);
- case 0: /* Timeout. */
- if (t.tv_usec) {
- ++t.tv_sec;
- t.tv_usec = 0;
- } else
- t.tv_usec += 500000;
- continue;
- }
-
- if (timeout == NULL && F_ISSET(sp, S_SCRIPT) &&
- FD_ISSET(sp->script->sh_master, &sp->rdfd)) {
- sscr_input(sp);
- continue;
- }
-
- switch (nr = read(STDIN_FILENO,
- tty->ch + tty->next + tty->cnt,
- tty->nelem - (tty->next + tty->cnt))) {
- case 0: /* EOF. */
- return (INP_EOF);
- case -1: /* Error or interrupt. */
- if (errno == EINTR)
- goto sigchk;
- msgq(sp, M_SYSERR, "read");
- return (INP_ERR);
- default:
- goto success;
- }
- /* NOTREACHED */
- }
-
-success:
- MEMSET(tty->chf + tty->next + tty->cnt, 0, nr);
- tty->cnt += *nrp = nr;
- return (INP_OK);
-}
diff --git a/usr.bin/vi/sex/sex_util.c b/usr.bin/vi/sex/sex_util.c
deleted file mode 100644
index 5acd788f617a..000000000000
--- a/usr.bin/vi/sex/sex_util.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)sex_util.c 8.15 (Berkeley) 7/16/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-#include "sex_screen.h"
-
-/*
- * sex_bell --
- * Ring the bell.
- */
-void
-sex_bell(sp)
- SCR *sp;
-{
- (void)write(STDOUT_FILENO, "\07", 1); /* \a */
-}
-
-void
-sex_busy(sp, msg)
- SCR *sp;
- char const *msg;
-{
- (void)fprintf(stdout, "%s\n", msg);
- (void)fflush(stdout);
-}
-
-/*
- * sex_optchange --
- * Screen specific "option changed" routine.
- */
-int
-sex_optchange(sp, opt)
- SCR *sp;
- int opt;
-{
- switch (opt) {
- case O_TERM:
- /* Reset the screen size. */
- if (sp->s_window(sp, 0))
- return (1);
- F_SET(sp, S_RESIZE);
- break;
- }
-
- (void)ex_optchange(sp, opt);
-
- return (0);
-}
-
-/*
- * sex_suspend --
- * Suspend an ex screen.
- */
-int
-sex_suspend(sp)
- SCR *sp;
-{
- struct termios t;
- GS *gp;
- int rval;
-
- rval = 0;
-
- /* Save current terminal settings, and restore the original ones. */
- gp = sp->gp;
- if (F_ISSET(gp, G_STDIN_TTY)) {
- if (tcgetattr(STDIN_FILENO, &t)) {
- msgq(sp, M_SYSERR, "suspend: tcgetattr");
- return (1);
- }
- if (F_ISSET(gp, G_TERMIOS_SET) && tcsetattr(STDIN_FILENO,
- TCSASOFT | TCSADRAIN, &gp->original_termios)) {
- msgq(sp, M_SYSERR, "suspend: tcsetattr original");
- return (1);
- }
- }
-
- /* Push out any waiting messages. */
- (void)sex_refresh(sp, sp->ep);
-
- /* Stop the process group. */
- if (kill(0, SIGTSTP)) {
- msgq(sp, M_SYSERR, "suspend: kill");
- rval = 1;
- }
-
- /* Time passes ... */
-
- /* Restore current terminal settings. */
- if (F_ISSET(gp, G_STDIN_TTY) &&
- tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t)) {
- msgq(sp, M_SYSERR, "suspend: tcsetattr current");
- rval = 1;
- }
- return (rval);
-}
diff --git a/usr.bin/vi/sex/sex_window.c b/usr.bin/vi/sex/sex_window.c
deleted file mode 100644
index 61000fba53d6..000000000000
--- a/usr.bin/vi/sex/sex_window.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)sex_window.c 8.8 (Berkeley) 8/17/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-
-/*
- * sex_window --
- * Set the window size.
- */
-int
-sex_window(sp, sigwinch)
- SCR *sp;
- int sigwinch;
-{
- struct winsize win;
- size_t col, row;
- int rval, user_set;
- ARGS *argv[2], a, b;
- char *s, buf[2048];
-
- /*
- * Get the screen rows and columns. If the values are wrong, it's
- * not a big deal -- as soon as the user sets them explicitly the
- * environment will be set and the screen package will use the new
- * values.
- *
- * Try TIOCGWINSZ.
- */
- errno = row = col = 0;
-#ifdef TIOCGWINSZ
- if (ioctl(STDERR_FILENO, TIOCGWINSZ, &win) != -1) {
- row = win.ws_row;
- col = win.ws_col;
- }
-#endif
- /* If here because of a signal, TIOCGWINSZ is all we trust. */
- if (sigwinch) {
- if (row == 0 || col == 0) {
- if (errno > 0)
- msgq(sp, M_SYSERR, "TIOCGWINSZ");
- return (1);
- }
-
- /*
- * !!!
- * SunOS systems deliver SIGWINCH when windows are uncovered
- * as well as when they change size. In addition, we call
- * here when continuing after being suspended since the window
- * may have changed size. Since we don't want to background
- * all of the screens just because the window was uncovered,
- * ignore the signal if there's no change.
- */
- if (row == O_VAL(sp, O_LINES) && col == O_VAL(sp, O_COLUMNS))
- return (1);
-
- goto sigw;
- }
-
- /*
- * !!!
- * If TIOCGWINSZ failed, or had entries of 0, try termcap. This
- * routine is called before any termcap or terminal information
- * has been set up. If there's no TERM environmental variable set,
- * let it go, at least ex can run.
- */
- if (row == 0 || col == 0) {
- if ((s = getenv("TERM")) == NULL)
- goto noterm;
-#ifdef SYSV_CURSES
- if (row == 0)
- if ((rval = tigetnum("lines")) < 0)
- msgq(sp, M_SYSERR, "tigetnum: lines");
- else
- row = rval;
- if (col == 0)
- if ((rval = tigetnum("cols")) < 0)
- msgq(sp, M_SYSERR, "tigetnum: cols");
- else
- col = rval;
-#else
- switch (tgetent(buf, s)) {
- case -1:
- msgq(sp, M_SYSERR, "tgetent: %s", s);
- return (1);
- case 0:
- msgq(sp, M_ERR, "%s: unknown terminal type", s);
- return (1);
- }
- if (row == 0)
- if ((rval = tgetnum("li")) < 0)
- msgq(sp, M_ERR,
- "no \"li\" capability for %s", s);
- else
- row = rval;
- if (col == 0)
- if ((rval = tgetnum("co")) < 0)
- msgq(sp, M_ERR,
- "no \"co\" capability for %s", s);
- else
- col = rval;
-#endif
- }
-
- /* If nothing else, well, it's probably a VT100. */
-noterm: if (row == 0)
- row = 24;
- if (col == 0)
- col = 80;
-
- /* POSIX 1003.2 requires the environment to override. */
- if ((s = getenv("LINES")) != NULL)
- row = strtol(s, NULL, 10);
- if ((s = getenv("COLUMNS")) != NULL)
- col = strtol(s, NULL, 10);
-
-sigw: a.bp = buf;
- b.bp = NULL;
- b.len = 0;
- argv[0] = &a;
- argv[1] = &b;;
-
- /*
- * Tell the options code that the screen size has changed.
- * Since the user didn't do the set, clear the set bits.
- */
- user_set = F_ISSET(&sp->opts[O_LINES], OPT_SET);
- a.len = snprintf(buf, sizeof(buf), "lines=%u", row);
- if (opts_set(sp, NULL, argv))
- return (1);
- if (user_set)
- F_CLR(&sp->opts[O_LINES], OPT_SET);
-
- user_set = F_ISSET(&sp->opts[O_COLUMNS], OPT_SET);
- a.len = snprintf(buf, sizeof(buf), "columns=%u", col);
- if (opts_set(sp, NULL, argv))
- return (1);
- if (user_set)
- F_CLR(&sp->opts[O_COLUMNS], OPT_SET);
-
- F_SET(sp, S_RESIZE);
- return (0);
-}
diff --git a/usr.bin/vi/svi/svi_confirm.c b/usr.bin/vi/svi/svi_confirm.c
deleted file mode 100644
index 06ef25c1bb8d..000000000000
--- a/usr.bin/vi/svi/svi_confirm.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)svi_confirm.c 8.8 (Berkeley) 4/13/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "svi_screen.h"
-
-enum confirm
-svi_confirm(sp, ep, fp, tp)
- SCR *sp;
- EXF *ep;
- MARK *fp, *tp;
-{
- CH ikey;
- size_t oldy, oldx;
-
- /*
- * Refresh the cursor first -- this means that we won't have to
- * set S_UPDATE_MODE to keep refresh from erasing the mode line
- * or SVI_CUR_INVALID because we sneaked the cursor off somewhere
- * else.
- */
- sp->lno = fp->lno;
- sp->cno = fp->cno;
- if (svi_paint(sp, ep))
- return (CONF_QUIT);
-
- getyx(stdscr, oldy, oldx);
- MOVE(sp, INFOLINE(sp), 0);
- clrtoeol();
- ADDNSTR(STR_CONFIRM, sizeof(STR_CONFIRM) - 1);
- MOVEA(sp, oldy, oldx);
- refresh();
-
- if (term_key(sp, &ikey, 0) != INP_OK)
- return (CONF_QUIT);
- switch (ikey.ch) {
- case CH_YES:
- return (CONF_YES);
- case CH_QUIT:
- return (CONF_QUIT);
- default:
- case CH_NO:
- return (CONF_NO);
- }
- /* NOTREACHED */
-}
diff --git a/usr.bin/vi/svi/svi_curses.c b/usr.bin/vi/svi/svi_curses.c
deleted file mode 100644
index 523fff99856a..000000000000
--- a/usr.bin/vi/svi/svi_curses.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)svi_curses.c 8.3 (Berkeley) 8/7/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "svi_screen.h"
-
-/*
- * svi_curses_init --
- * Initialize curses.
- */
-int
-svi_curses_init(sp)
- SCR *sp;
-{
- struct termios t;
- char *p;
-
-#ifdef SYSV_CURSES
- /*
- * The SunOS/System V initscr() isn't reentrant. Don't even think
- * about trying to use it. It fails in subtle ways (e.g. select(2)
- * on fileno(stdin) stops working). We don't care about the SCREEN
- * reference returned by newterm, we never have more than one SCREEN
- * at a time.
- */
- errno = 0;
- if (newterm(O_STR(sp, O_TERM), stdout, stdin) == NULL) {
- msgq(sp, errno ? M_SYSERR : M_ERR, "newterm failed");
- return (1);
- }
-#else
- /*
- * Initscr() doesn't provide useful error values or messages. The
- * reasonable guess is that either malloc failed or the terminal was
- * unknown or lacking some essential feature. Try and guess so the
- * user isn't even more pissed off because of the error message.
- */
- errno = 0;
- if (initscr() == NULL) {
- char kbuf[2048];
- msgq(sp, errno ? M_SYSERR : M_ERR, "initscr failed");
- if ((p = getenv("TERM")) == NULL || !strcmp(p, "unknown"))
- msgq(sp, M_ERR,
- "No TERM environment variable set, or TERM set to \"unknown\"");
- else if (tgetent(kbuf, p) != 1)
- msgq(sp, M_ERR,
-"%s: unknown terminal type, or terminal lacks necessary features", p);
- else
- msgq(sp, M_ERR,
- "%s: terminal type lacks necessary features", p);
- return (1);
- }
-#endif
- /*
- * We use raw mode. What we want is 8-bit clean, however, signals
- * and flow control should continue to work. Admittedly, it sounds
- * like cbreak, but it isn't. Using cbreak() can get you additional
- * things like IEXTEN, which turns on things like DISCARD and LNEXT.
- *
- * !!!
- * If raw isn't turning off echo and newlines, something's wrong.
- * However, it doesn't hurt.
- */
- noecho(); /* No character echo. */
- nonl(); /* No CR/NL translation. */
- raw(); /* 8-bit clean. */
- idlok(stdscr, 1); /* Use hardware insert/delete line. */
-
- /*
- * XXX
- * Historic implementations of curses handled SIGTSTP signals
- * in one of three ways. They either:
- *
- * 1: Set their own handler, regardless.
- * 2: Did not set a handler if a handler was already installed.
- * 3: Set their own handler, but then called any previously set
- * handler after completing their own cleanup.
- *
- * We don't try and figure out which behavior is in place, we
- * just set it to SIG_DFL after initializing the curses interface.
- */
- (void)signal(SIGTSTP, SIG_DFL);
-
- /*
- * If flow control was on, turn it back on. Turn signals on. ISIG
- * turns on VINTR, VQUIT, VDSUSP and VSUSP. See signal.c:sig_init()
- * for a discussion of what's going on here. To sum up, sig_init()
- * already installed a handler for VINTR. We're going to disable the
- * other three.
- *
- * XXX
- * We want to use ^Y as a vi scrolling command. If the user has the
- * DSUSP character set to ^Y (common practice) clean it up. As it's
- * equally possible that the user has VDSUSP set to 'a', we disable
- * it regardless. It doesn't make much sense to suspend vi at read,
- * so I don't think anyone will care. Alternatively, we could look
- * it up in the table of legal command characters and turn it off if
- * it matches one. VDSUSP wasn't in POSIX 1003.1-1990, so we test for
- * it.
- *
- * XXX
- * We don't check to see if the user had signals enabled to start with.
- * If they didn't, it's unclear what we're supposed to do here, but it
- * is also pretty unlikely.
- */
- if (!tcgetattr(STDIN_FILENO, &t)) {
- if (sp->gp->original_termios.c_iflag & IXON)
- t.c_iflag |= IXON;
- if (sp->gp->original_termios.c_iflag & IXOFF)
- t.c_iflag |= IXOFF;
-
- t.c_lflag |= ISIG;
-#ifdef VDSUSP
- t.c_cc[VDSUSP] = _POSIX_VDISABLE;
-#endif
- t.c_cc[VQUIT] = _POSIX_VDISABLE;
- t.c_cc[VSUSP] = _POSIX_VDISABLE;
-
- (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t);
- }
-
- /* Put the cursor keys into application mode. */
- svi_keypad(sp, 1);
-
- /*
- * The first screen in the list gets it all. All other screens
- * are hidden and lose their maps.
- */
- svi_dtoh(sp, "Window resize");
-
- /* Initialize terminal values. */
- SVP(sp)->srows = O_VAL(sp, O_LINES);
-
- /*
- * Initialize screen values.
- *
- * Small windows: see svi/svi_refresh.c:svi_refresh, section 3b.
- *
- * Setup:
- * t_minrows is the minimum rows to display
- * t_maxrows is the maximum rows to display (rows - 1)
- * t_rows is the rows currently being displayed
- */
- sp->rows = SVP(sp)->srows;
- sp->cols = O_VAL(sp, O_COLUMNS);
- sp->woff = 0;
- sp->t_rows = sp->t_minrows = O_VAL(sp, O_WINDOW);
- if (sp->t_rows > sp->rows - 1) {
- sp->t_minrows = sp->t_rows = sp->rows - 1;
- msgq(sp, M_INFO,
- "Windows option value is too large, max is %u", sp->t_rows);
- }
- sp->t_maxrows = sp->rows - 1;
-
- /* Create the screen map. */
- CALLOC(sp, HMAP, SMAP *, SIZE_HMAP(sp), sizeof(SMAP));
- if (HMAP == NULL) {
- if (endwin() == ERR)
- msgq(sp, M_SYSERR, "endwin");
- return (1);
- }
- TMAP = HMAP + (sp->t_rows - 1);
-
- F_SET(SVP(sp), SVI_CUR_INVALID); /* Cursor is invalid. */
- F_SET(SVP(sp), SVI_CURSES_INIT); /* It's initialized. */
-
- return (0);
-}
-
-/*
- * svi_curses_end --
- * Move to the bottom of the screen, end curses.
- */
-int
-svi_curses_end(sp)
- SCR *sp;
-{
- /*
- * XXX
- * By the time we get here, the screen private area (SVI_PRIVATE)
- * is probably gone. Don't use it, and don't call any routines
- * that do.
- *
- * Restore the cursor keys to normal mode.
- */
- svi_keypad(sp, 0);
-
- /* Move to the bottom of the screen. */
- if (move(INFOLINE(sp), 0) == OK) {
- clrtoeol();
- refresh();
- }
-
- /* End curses window. */
- if (endwin() == ERR)
- msgq(sp, M_SYSERR, "endwin");
-
- return (0);
-}
diff --git a/usr.bin/vi/svi/svi_ex.c b/usr.bin/vi/svi/svi_ex.c
deleted file mode 100644
index 9b81080bcb0e..000000000000
--- a/usr.bin/vi/svi/svi_ex.c
+++ /dev/null
@@ -1,650 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)svi_ex.c 8.54 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "../vi/vcmd.h"
-#include "excmd.h"
-#include "svi_screen.h"
-#include "../sex/sex_screen.h"
-
-static int svi_ex_divider __P((SCR *));
-static int svi_ex_done __P((SCR *, EXF *, MARK *));
-static int svi_ex_inv __P((SCR *));
-static int svi_ex_scroll __P((SCR *, int, CH *));
-
-#define MSGS_WAITING(sp) \
- ((sp)->msgq.lh_first != NULL && \
- !F_ISSET((sp)->msgq.lh_first, M_EMPTY))
-
-/*
- * svi_ex_cmd --
- * Execute an ex command.
- */
-int
-svi_ex_cmd(sp, ep, exp, rp)
- SCR *sp;
- EXF *ep;
- EXCMDARG *exp;
- MARK *rp;
-{
- SVI_PRIVATE *svp;
- int rval;
-
- svp = SVP(sp);
- svp->exlcontinue = svp->exlinecount = svp->extotalcount = 0;
-
- (void)svi_busy(sp, NULL);
- rval = exp->cmd->fn(sp, ep, exp);
-
- (void)msg_rpt(sp, 0);
- (void)ex_fflush(EXCOOKIE);
-
- /*
- * If displayed anything, figure out if we have to wait. If the
- * screen wasn't trashed, only one line output and there are no
- * waiting messages, don't wait, but don't overwrite it with mode
- * information either.
- */
- if (svp->extotalcount > 0)
- if (!F_ISSET(sp, S_REFRESH) &&
- svp->extotalcount == 1 && !MSGS_WAITING(sp)) {
- F_SET(sp, S_UPDATE_MODE);
- if (sp->q.cqe_next != (void *)&sp->gp->dq)
- (void)svi_ex_inv(sp);
- } else {
- /* This message isn't interruptible. */
- F_CLR(sp, S_INTERRUPTIBLE);
- (void)svi_ex_scroll(sp, 1, NULL);
- }
- return (svi_ex_done(sp, ep, rp) || rval);
-}
-
-/*
- * svi_ex_run --
- * Execute strings of ex commands.
- */
-int
-svi_ex_run(sp, ep, rp)
- SCR *sp;
- EXF *ep;
- MARK *rp;
-{
- enum input (*get) __P((SCR *, EXF *, TEXTH *, ARG_CHAR_T, u_int));
- struct termios t;
- CH ikey;
- SVI_PRIVATE *svp;
- TEXT *tp;
- int flags, in_exmode, rval;
-
- svp = SVP(sp);
- svp->exlcontinue = svp->exlinecount = svp->extotalcount = 0;
-
- /*
- * There's some tricky stuff going on here to handle when a user has
- * mapped a key to multiple ex commands. Historic practice was that
- * vi ran without any special actions, as if the user were entering
- * the characters, until ex trashed the screen, e.g. something like a
- * '!' command. At that point, we no longer know what the screen
- * looks like, so we can't afford to overwrite anything. The solution
- * is to go into real ex mode until we get to the end of the command
- * strings.
- */
- get = svi_get;
- flags = TXT_BS | TXT_PROMPT;
- for (in_exmode = rval = 0;;) {
- /*
- * Get the next command. Interrupt flag manipulation is safe
- * because ex_icmd clears them all.
- */
- F_SET(sp, S_INTERRUPTIBLE);
- if (get(sp, ep, sp->tiqp, ':', flags) != INP_OK) {
- rval = 1;
- break;
- }
- if (INTERRUPTED(sp))
- break;
-
- /*
- * Len is 0 if the user backspaced over the prompt,
- * 1 if only a CR was entered.
- */
- tp = sp->tiqp->cqh_first;
- if (tp->len == 0)
- break;
-
- if (!in_exmode)
- (void)svi_busy(sp, NULL);
-
- /* Ignore return, presumably an error message was displayed. */
- (void)ex_icmd(sp, ep, tp->lb, tp->len, 0);
- (void)ex_fflush(EXCOOKIE);
-
- /*
- * The file or screen may have changed, in which case, the
- * main editor loop takes care of it.
- */
- if (F_ISSET(sp, S_MAJOR_CHANGE))
- break;
-
- /*
- * If continue not required, and one or no lines, and there
- * are no waiting messages, don't wait, but don't overwrite
- * it with mode information either.
- */
- if (!F_ISSET(sp, S_CONTINUE) && (svp->extotalcount == 0 ||
- svp->extotalcount == 1 && !MSGS_WAITING(sp))) {
- if (svp->extotalcount == 1) {
- F_SET(sp, S_UPDATE_MODE);
- if (sp->q.cqe_next != (void *)&sp->gp->dq)
- svi_ex_inv(sp);
- }
- break;
- }
-
- if (INTERRUPTED(sp))
- break;
-
- /*
- * If the screen is trashed, or there are messages waiting,
- * go into ex mode.
- */
- if (!in_exmode &&
- (F_ISSET(sp, S_REFRESH) || MSGS_WAITING(sp))) {
- /* Initialize the terminal state. */
- if (F_ISSET(sp->gp, G_STDIN_TTY))
- SEX_RAW(t);
- get = sex_get;
- flags = TXT_CR | TXT_NLECHO | TXT_PROMPT;
- in_exmode = 1;
- }
-
- /* Display any waiting messages. */
- if (MSGS_WAITING(sp))
- (void)sex_refresh(sp, ep);
-
- /*
- * Get a continue character; users may continue in ex mode by
- * entering a ':'.
- *
- * !!!
- * Historic practice is that any key can be used to continue.
- * Nvi used to require that the user enter a <carriage-return>
- * or <newline>, but this broke historic users.
- */
- if (in_exmode) {
- (void)write(STDOUT_FILENO,
- STR_CMSG, sizeof(STR_CMSG) - 1);
- if (term_key(sp, &ikey, 0) != INP_OK) {
- rval = 1;
- goto ret;
- }
- } else {
- /* This message isn't interruptible. */
- F_CLR(sp, S_INTERRUPTIBLE);
- (void)svi_ex_scroll(sp, 1, &ikey);
- }
- if (ikey.ch != ':')
- break;
-
- if (in_exmode)
- (void)write(STDOUT_FILENO, "\n", 1);
- else {
- ++svp->extotalcount;
- ++svp->exlinecount;
- }
- }
-
-ret: if (in_exmode) {
- /* Reset the terminal state. */
- if (F_ISSET(sp->gp, G_STDIN_TTY) && SEX_NORAW(t))
- rval = 1;
- F_SET(sp, S_REFRESH);
- } else
- if (svi_ex_done(sp, ep, rp))
- rval = 1;
-
- F_CLR(sp, S_CONTINUE);
- return (rval);
-}
-
-/*
- * svi_msgflush --
- * Flush any accumulated messages.
- */
-int
-svi_msgflush(sp)
- SCR *sp;
-{
- enum {INVERSE, NORMAL} inverse;
- SVI_PRIVATE *svp;
- MSG *mp;
- int rval;
-
- svp = SVP(sp);
- svp->exlcontinue = svp->exlinecount = svp->extotalcount = 0;
-
- /*
- * XXX
- * S_IVIDEO is a bit of a kluge. We can only pass a single magic
- * cookie into the svi_ex_write routine, and it has to be the SCR
- * structure. So, the inverse video bit has to be there.
- */
- inverse = NORMAL;
- for (mp = sp->msgq.lh_first;
- mp != NULL && !F_ISSET(mp, M_EMPTY); mp = mp->q.le_next) {
- /*
- * If the second and subsequent messages fit on the current
- * line, write a separator. Otherwise, put out a newline
- * and break the line.
- */
- if (mp != sp->msgq.lh_first)
- if (mp->len + svp->exlcontinue + 3 >= sp->cols) {
- if (inverse == INVERSE)
- F_SET(sp, S_IVIDEO);
- (void)svi_ex_write(sp, ".\n", 2);
- F_CLR(sp, S_IVIDEO);
- } else {
- if (inverse == INVERSE)
- F_SET(sp, S_IVIDEO);
- (void)svi_ex_write(sp, ";", 1);
- F_CLR(sp, S_IVIDEO);
- (void)svi_ex_write(sp, " ", 2);
- }
-
- inverse = F_ISSET(mp, M_INV_VIDEO) ? INVERSE : NORMAL;
- if (inverse == INVERSE)
- F_SET(sp, S_IVIDEO);
- (void)svi_ex_write(sp, mp->mbuf, mp->len);
- F_CLR(sp, S_IVIDEO);
-
- F_SET(mp, M_EMPTY);
- }
-
- /*
- * None of the messages end with periods, we do it in the message
- * flush routine, which makes it possible to join messages.
- */
- if (inverse == INVERSE)
- F_SET(sp, S_IVIDEO);
- (void)svi_ex_write(sp, ".", 1);
- F_CLR(sp, S_IVIDEO);
-
- /*
- * Figure out if we have to wait. Don't wait for only one line,
- * but don't overwrite it with mode information either.
- */
- if (svp->extotalcount == 1) {
- F_SET(sp, S_UPDATE_MODE);
- if (sp->q.cqe_next != (void *)&sp->gp->dq)
- svi_ex_inv(sp);
- return (0);
- }
-
- rval = svi_ex_scroll(sp, 1, NULL);
- if (svi_ex_done(sp, sp->ep, NULL))
- rval = 1;
- MOVE(sp, INFOLINE(sp), 0);
- clrtoeol();
- return (rval);
-}
-
-/*
- * svi_ex_done --
- * Cleanup from dipping into ex.
- */
-static int
-svi_ex_done(sp, ep, rp)
- SCR *sp;
- EXF *ep;
- MARK *rp;
-{
- SMAP *smp;
- SVI_PRIVATE *svp;
- recno_t lno;
- size_t cnt, len;
-
- /*
- * The file or screen may have changed, in which case,
- * the main editor loop takes care of it.
- */
- if (F_ISSET(sp, S_MAJOR_CHANGE))
- return (0);
-
- /*
- * Otherwise, the only cursor modifications will be real, however, the
- * underlying line may have changed; don't trust anything. This code
- * has been a remarkably fertile place for bugs.
- *
- * Repaint the entire screen if at least half the screen is trashed.
- * Else, repaint only over the overwritten lines. The "-2" comes
- * from one for the mode line and one for the fact that it's an offset.
- * Note the check for small screens.
- *
- * Don't trust ANYTHING.
- */
- svp = SVP(sp);
- if (svp->extotalcount >= HALFTEXT(sp))
- F_SET(sp, S_REDRAW);
- else
- for (cnt = sp->rows - 2; svp->extotalcount--; --cnt)
- if (cnt > sp->t_rows) {
- MOVE(sp, cnt, 0);
- clrtoeol();
- } else {
- smp = HMAP + cnt;
- SMAP_FLUSH(smp);
- if (svi_line(sp, ep, smp, NULL, NULL))
- return (1);
- }
-
- /* Ignore the cursor if the caller doesn't care. */
- if (rp == NULL)
- return (0);
-
- /*
- * Do a reality check on a cursor value, and make sure it's okay.
- * If necessary, change it. Ex keeps track of the line number,
- * but it doesn't care about the column and it may have disappeared.
- */
- if (file_gline(sp, ep, sp->lno, &len) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno != 0)
- GETLINE_ERR(sp, sp->lno);
- sp->lno = 1;
- sp->cno = 0;
- } else if (sp->cno >= len)
- sp->cno = len ? len - 1 : 0;
-
- rp->lno = sp->lno;
- rp->cno = sp->cno;
- return (0);
-}
-
-/*
- * svi_ex_write --
- * Write out the ex messages.
- */
-int
-svi_ex_write(cookie, line, llen)
- void *cookie;
- const char *line;
- int llen;
-{
- SCR *sp;
- SVI_PRIVATE *svp;
- size_t oldy, oldx;
- int len, rlen, tlen;
- const char *p, *t;
-
- /*
- * XXX
- * If it's a 4.4BSD system, we could just use fpurge(3).
- * This shouldn't be too expensive, though.
- */
- sp = cookie;
- svp = SVP(sp);
- if (INTERRUPTED(sp))
- return (llen);
-
- p = line; /* In case of a write of 0. */
- for (rlen = llen; llen;) {
- /* Get the next line. */
- if ((p = memchr(line, '\n', llen)) == NULL)
- len = llen;
- else
- len = p - line;
-
- /*
- * The max is sp->cols characters, and we may
- * have already written part of the line.
- */
- if (len + svp->exlcontinue > sp->cols)
- len = sp->cols - svp->exlcontinue;
-
- /*
- * If the first line output, do nothing.
- * If the second line output, draw the divider line.
- * If drew a full screen, remove the divider line.
- * If it's a continuation line, move to the continuation
- * point, else, move the screen up.
- */
- if (svp->exlcontinue == 0) {
- if (svp->extotalcount == 1) {
- MOVE(sp, INFOLINE(sp) - 1, 0);
- clrtoeol();
- if (svi_ex_divider(sp))
- return (-1);
- F_SET(svp, SVI_DIVIDER);
- ++svp->extotalcount;
- ++svp->exlinecount;
- }
- if (svp->extotalcount == sp->t_maxrows &&
- F_ISSET(svp, SVI_DIVIDER)) {
- --svp->extotalcount;
- --svp->exlinecount;
- F_CLR(svp, SVI_DIVIDER);
- }
- if (svp->extotalcount != 0 &&
- svi_ex_scroll(sp, 0, NULL))
- return (-1);
- MOVE(sp, INFOLINE(sp), 0);
- ++svp->extotalcount;
- ++svp->exlinecount;
- if (F_ISSET(sp, S_INTERRUPTIBLE) && INTERRUPTED(sp))
- break;
- } else
- MOVE(sp, INFOLINE(sp), svp->exlcontinue);
-
- /* Display the line, doing character translation. */
- if (F_ISSET(sp, S_IVIDEO))
- standout();
- for (t = line, tlen = len; tlen--; ++t)
- ADDCH(*t);
- if (F_ISSET(sp, S_IVIDEO))
- standend();
-
- /* Clear to EOL. */
- getyx(stdscr, oldy, oldx);
- if (oldx < sp->cols)
- clrtoeol();
-
- /* If we loop, it's a new line. */
- svp->exlcontinue = 0;
-
- /* Reset for the next line. */
- line += len;
- llen -= len;
- if (p != NULL) {
- ++line;
- --llen;
- }
- }
- /* Refresh the screen, even if it's a partial. */
- refresh();
-
- /* Set up next continuation line. */
- if (p == NULL)
- getyx(stdscr, oldy, svp->exlcontinue);
- return (rlen);
-}
-
-/*
- * svi_ex_scroll --
- * Scroll the screen for ex output.
- */
-static int
-svi_ex_scroll(sp, mustwait, chp)
- SCR *sp;
- int mustwait;
- CH *chp;
-{
- CH ikey;
- SVI_PRIVATE *svp;
-
- /*
- * Scroll the screen. Instead of scrolling the entire screen, delete
- * the line above the first line output so preserve the maximum amount
- * of the screen.
- */
- svp = SVP(sp);
- if (svp->extotalcount >= sp->rows) {
- MOVE(sp, 0, 0);
- } else
- MOVE(sp, INFOLINE(sp) - svp->extotalcount, 0);
-
- deleteln();
-
- /* If there are screens below us, push them back into place. */
- if (sp->q.cqe_next != (void *)&sp->gp->dq) {
- MOVE(sp, INFOLINE(sp), 0);
- insertln();
- }
-
- /* If just displayed a full screen, wait. */
- if (mustwait || svp->exlinecount == sp->t_maxrows) {
- MOVE(sp, INFOLINE(sp), 0);
- if (F_ISSET(sp, S_INTERRUPTIBLE)) {
- ADDNSTR(STR_QMSG, (int)sizeof(STR_QMSG) - 1);
- } else {
- ADDNSTR(STR_CMSG, (int)sizeof(STR_CMSG) - 1);
- }
- clrtoeol();
- refresh();
- /*
- * !!!
- * Historic practice is that any key can be used to continue.
- * Nvi used to require that the user enter a <carriage-return>
- * or <newline>, but this broke historic users.
- */
- if (term_key(sp, &ikey, 0) != INP_OK)
- return (-1);
- if (ikey.ch == CH_QUIT && F_ISSET(sp, S_INTERRUPTIBLE))
- F_SET(sp, S_INTERRUPTED);
- if (chp != NULL)
- *chp = ikey;
- svp->exlinecount = 0;
- }
- return (0);
-}
-
-/*
- * svi_ex_inv --
- * Change whatever is on the info line to inverse video so we have
- * a divider line between split screens.
- */
-static int
-svi_ex_inv(sp)
- SCR *sp;
-{
- CHAR_T ch;
- size_t spcnt, col, row;
-
- row = INFOLINE(sp);
-
- /*
- * Walk through the line, retrieving each character and writing
- * it back out in inverse video. Since curses doesn't have an
- * EOL marker, only put out trailing spaces if we find another
- * character.
- *
- * XXX
- * This is a major kluge -- curses should have an interface
- * that allows us to change attributes on a per line basis.
- */
- MOVE(sp, row, 0);
- standout();
- for (spcnt = col = 0;;) {
- ch = winch(stdscr);
- if (isspace(ch)) {
- ++spcnt;
- if (++col >= sp->cols)
- break;
- MOVE(sp, row, col);
- } else {
- if (spcnt) {
- MOVE(sp, row, col - spcnt);
- for (; spcnt > 0; --spcnt)
- ADDCH(' ');
- }
- ADDCH(ch);
- if (++col >= sp->cols)
- break;
- }
- }
- standend();
- return (0);
-}
-
-/*
- * svi_ex_divider --
- * Draw a dividing line between the screens.
- */
-static int
-svi_ex_divider(sp)
- SCR *sp;
-{
- size_t len;
-
-#define DIVIDESTR "+=+=+=+=+=+=+=+"
- len = sizeof(DIVIDESTR) - 1 > sp->cols ?
- sp->cols : sizeof(DIVIDESTR) - 1;
- standout();
- ADDNSTR(DIVIDESTR, len);
- standend();
- return (0);
-}
diff --git a/usr.bin/vi/svi/svi_get.c b/usr.bin/vi/svi/svi_get.c
deleted file mode 100644
index db790a954eee..000000000000
--- a/usr.bin/vi/svi/svi_get.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)svi_get.c 8.25 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "../vi/vcmd.h"
-#include "svi_screen.h"
-
-/*
- * svi_get --
- * Fill a buffer from the terminal for vi.
- */
-enum input
-svi_get(sp, ep, tiqh, prompt, flags)
- SCR *sp;
- EXF *ep;
- TEXTH *tiqh;
- ARG_CHAR_T prompt;
- u_int flags;
-{
- MARK save;
- SMAP *esmp;
- recno_t bot_lno;
- size_t bot_off, cnt;
- int eval;
-
- /*
- * The approach used is to fake like the user is doing input on
- * the last line of the screen. This makes all of the scrolling
- * work correctly, and allows us the use of the vi text editing
- * routines, not to mention practically infinite length ex commands.
- *
- * Save the current location.
- */
- bot_lno = TMAP->lno;
- bot_off = TMAP->off;
- save.lno = sp->lno;
- save.cno = sp->cno;
-
- /*
- * If it's a small screen, TMAP may be small for the screen.
- * Fix it, filling in fake lines as we go.
- */
- if (ISSMALLSCREEN(sp))
- for (esmp = HMAP + (sp->t_maxrows - 1); TMAP < esmp; ++TMAP) {
- TMAP[1].lno = TMAP[0].lno + 1;
- TMAP[1].off = 1;
- }
-
- /* Build the fake entry. */
- TMAP[1].lno = TMAP[0].lno + 1;
- TMAP[1].off = 1;
- SMAP_FLUSH(&TMAP[1]);
- ++TMAP;
-
- /* Move to it. */
- sp->lno = TMAP[0].lno;
- sp->cno = 0;
-
- if (O_ISSET(sp, O_ALTWERASE))
- LF_SET(TXT_ALTWERASE);
- if (O_ISSET(sp, O_TTYWERASE))
- LF_SET(TXT_TTYWERASE);
- LF_SET(TXT_APPENDEOL |
- TXT_CR | TXT_ESCAPE | TXT_INFOLINE | TXT_MAPINPUT);
-
- /* Don't update the modeline for now. */
- F_SET(SVP(sp), SVI_INFOLINE);
-
- eval = v_ntext(sp, ep, tiqh, NULL, NULL, 0, NULL, prompt, 0, flags);
-
- F_CLR(SVP(sp), SVI_INFOLINE);
-
- /* Put it all back. */
- --TMAP;
- sp->lno = save.lno;
- sp->cno = save.cno;
-
- /*
- * If it's a small screen, TMAP may be wrong. Clear any
- * lines that might have been overwritten.
- */
- if (ISSMALLSCREEN(sp)) {
- for (cnt = sp->t_rows; cnt <= sp->t_maxrows; ++cnt) {
- MOVE(sp, cnt, 0);
- clrtoeol();
- }
- TMAP = HMAP + (sp->t_rows - 1);
- }
-
- /*
- * The map may be wrong if the user entered more than one
- * (logical) line. Fix it. If the user entered a whole
- * screen, this will be slow, but it's not worth caring.
- */
- while (bot_lno != TMAP->lno || bot_off != TMAP->off)
- if (svi_sm_1down(sp, ep))
- return (INP_ERR);
-
- /*
- * Invalidate the cursor and the line size cache, the line never
- * really existed. This fixes bugs where the user searches for
- * the last line on the screen + 1 and the refresh routine thinks
- * that's where we just were.
- */
- F_SET(SVP(sp), SVI_CUR_INVALID);
- SVI_SCR_CFLUSH(SVP(sp));
-
- return (eval ? INP_ERR : INP_OK);
-}
diff --git a/usr.bin/vi/svi/svi_line.c b/usr.bin/vi/svi/svi_line.c
deleted file mode 100644
index 8b437e5690de..000000000000
--- a/usr.bin/vi/svi/svi_line.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)svi_line.c 8.25 (Berkeley) 5/16/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "svi_screen.h"
-
-#if defined(DEBUG) && 0
-#define TABCH '-'
-#define TABSTR "--------------------"
-#else
-#define TABSTR " "
-#define TABCH ' '
-#endif
-
-/*
- * svi_line --
- * Update one line on the screen.
- */
-int
-svi_line(sp, ep, smp, yp, xp)
- SCR *sp;
- EXF *ep;
- SMAP *smp;
- size_t *xp, *yp;
-{
- SMAP *tsmp;
- size_t chlen, cols_per_screen, cno_cnt, len, scno, skip_screens;
- size_t offset_in_char, offset_in_line;
- size_t oldy, oldx;
- int ch, is_cached, is_infoline, is_partial, is_tab;
- int list_tab, list_dollar;
- char *p, nbuf[10];
-
-#if defined(DEBUG) && 0
- TRACE(sp, "svi_line: row %u: line: %u off: %u\n",
- smp - HMAP, smp->lno, smp->off);
-#endif
-
- /*
- * Assume that, if the cache entry for the line is filled in, the
- * line is already on the screen, and all we need to do is return
- * the cursor position. If the calling routine doesn't need the
- * cursor position, we can just return.
- */
- is_cached = SMAP_CACHE(smp);
- if (yp == NULL && is_cached)
- return (0);
-
- /*
- * A nasty side effect of this routine is that it returns the screen
- * position for the "current" character. Not pretty, but this is the
- * only routine that really knows what's out there.
- *
- * Move to the line. This routine can be called by svi_sm_position(),
- * which uses it to fill in the cache entry so it can figure out what
- * the real contents of the screen are. Because of this, we have to
- * return to whereever we started from.
- */
- getyx(stdscr, oldy, oldx);
- MOVE(sp, smp - HMAP, 0);
-
- /* Get a copy of the line. */
- p = file_gline(sp, ep, smp->lno, &len);
-
- /*
- * Special case if we're printing the info/mode line. Skip printing
- * the leading number, as well as other minor setup. If painting the
- * line between two screens, it's always in reverse video. The only
- * time this code paints the mode line is when the user is entering
- * text for a ":" command, so we can put the code here instead of
- * dealing with the empty line logic below. This is a kludge, but it's
- * pretty much confined to this module.
- *
- * Set the number of screens to skip until a character is displayed.
- * Left-right screens are special, because we don't bother building
- * a buffer to be skipped over.
- *
- * Set the number of columns for this screen.
- */
- cols_per_screen = sp->cols;
- list_tab = O_ISSET(sp, O_LIST);
- if (is_infoline = ISINFOLINE(sp, smp)) {
- list_dollar = 0;
- if (O_ISSET(sp, O_LEFTRIGHT))
- skip_screens = 0;
- else
- skip_screens = smp->off - 1;
- } else {
- list_dollar = list_tab;
- skip_screens = smp->off - 1;
-
- /*
- * If O_NUMBER is set and it's line number 1 or the line exists
- * and this is the first screen of a folding line or any left-
- * right line, display the line number.
- */
- if (O_ISSET(sp, O_NUMBER)) {
- cols_per_screen -= O_NUMBER_LENGTH;
- if ((smp->lno == 1 || p != NULL) && skip_screens == 0) {
- (void)snprintf(nbuf,
- sizeof(nbuf), O_NUMBER_FMT, smp->lno);
- ADDSTR(nbuf);
- }
- }
- }
-
- /*
- * Special case non-existent lines and the first line of an empty
- * file. In both cases, the cursor position is 0, but corrected
- * for the O_NUMBER field if it was displayed.
- */
- if (p == NULL || len == 0) {
- /* Fill in the cursor. */
- if (yp != NULL && smp->lno == sp->lno) {
- *yp = smp - HMAP;
- *xp = sp->cols - cols_per_screen;
- }
-
- /* If the line is on the screen, quit. */
- if (is_cached)
- goto ret;
-
- /* Set line cacheing information. */
- smp->c_sboff = smp->c_eboff = 0;
- smp->c_scoff = smp->c_eclen = 0;
-
- /* Lots of special cases for empty lines. */
- if (skip_screens == 0)
- if (p == NULL) {
- if (smp->lno == 1) {
- if (list_dollar) {
- ch = '$';
- goto empty;
- }
- } else {
- ch = '~';
- goto empty;
- }
- } else
- if (list_dollar) {
- ch = '$';
-empty: ADDCH(ch);
- }
-
- clrtoeol();
- MOVEA(sp, oldy, oldx);
- return (0);
- }
-
- /*
- * If we wrote a line that's this or a previous one, we can do this
- * much more quickly -- we cached the starting and ending positions
- * of that line. The way it works is we keep information about the
- * lines displayed in the SMAP. If we're painting the screen in
- * the forward, this saves us from reformatting the physical line for
- * every line on the screen. This wins big on binary files with 10K
- * lines.
- *
- * Test for the first screen of the line, then the current screen line,
- * then the line behind us, then do the hard work. Note, it doesn't
- * do us any good to have a line in front of us -- it would be really
- * hard to try and figure out tabs in the reverse direction, i.e. how
- * many spaces a tab takes up in the reverse direction depends on
- * what characters preceded it.
- */
- if (smp->off == 1) {
- smp->c_sboff = offset_in_line = 0;
- smp->c_scoff = offset_in_char = 0;
- p = &p[offset_in_line];
- } else if (is_cached) {
- offset_in_line = smp->c_sboff;
- offset_in_char = smp->c_scoff;
- p = &p[offset_in_line];
- if (skip_screens != 0)
- cols_per_screen = sp->cols;
- } else if (smp != HMAP &&
- SMAP_CACHE(tsmp = smp - 1) && tsmp->lno == smp->lno) {
- if (tsmp->c_eclen != tsmp->c_ecsize) {
- offset_in_line = tsmp->c_eboff;
- offset_in_char = tsmp->c_eclen;
- } else {
- offset_in_line = tsmp->c_eboff + 1;
- offset_in_char = 0;
- }
-
- /* Put starting info for this line in the cache. */
- smp->c_sboff = offset_in_line;
- smp->c_scoff = offset_in_char;
- p = &p[offset_in_line];
- if (skip_screens != 0)
- cols_per_screen = sp->cols;
- } else {
- offset_in_line = 0;
- offset_in_char = 0;
-
- /* This is the loop that skips through screens. */
- if (skip_screens == 0) {
- smp->c_sboff = offset_in_line;
- smp->c_scoff = offset_in_char;
- } else for (scno = 0; offset_in_line < len; ++offset_in_line) {
- scno += chlen =
- (ch = *(u_char *)p++) == '\t' && !list_tab ?
- TAB_OFF(sp, scno) : KEY_LEN(sp, ch);
- if (scno < cols_per_screen)
- continue;
- /*
- * Reset cols_per_screen to second and subsequent line
- * length.
- */
- scno -= cols_per_screen;
- cols_per_screen = sp->cols;
-
- /*
- * If crossed the last skipped screen boundary, start
- * displaying the characters.
- */
- if (--skip_screens)
- continue;
-
- /* Put starting info for this line in the cache. */
- if (scno) {
- smp->c_sboff = offset_in_line;
- smp->c_scoff = offset_in_char = chlen - scno;
- --p;
- } else {
- smp->c_sboff = ++offset_in_line;
- smp->c_scoff = 0;
- }
- break;
- }
- }
-
- /*
- * Set the number of characters to skip before reaching the cursor
- * character. Offset by 1 and use 0 as a flag value. Svi_line is
- * called repeatedly with a valid pointer to a cursor position.
- * Don't fill anything in unless it's the right line and the right
- * character, and the right part of the character...
- */
- if (yp == NULL ||
- smp->lno != sp->lno || sp->cno < offset_in_line ||
- offset_in_line + cols_per_screen < sp->cno) {
- cno_cnt = 0;
- /* If the line is on the screen, quit. */
- if (is_cached)
- goto ret;
- } else
- cno_cnt = (sp->cno - offset_in_line) + 1;
-
- /* This is the loop that actually displays characters. */
- for (is_partial = 0, scno = 0;
- offset_in_line < len; ++offset_in_line, offset_in_char = 0) {
- if ((ch = *(u_char *)p++) == '\t' && !list_tab) {
- scno += chlen = TAB_OFF(sp, scno) - offset_in_char;
- is_tab = 1;
- } else {
- scno += chlen = KEY_LEN(sp, ch) - offset_in_char;
- is_tab = 0;
- }
-
- /*
- * Only display up to the right-hand column. Set a flag if
- * the entire character wasn't displayed for use in setting
- * the cursor. If reached the end of the line, set the cache
- * info for the screen. Don't worry about there not being
- * characters to display on the next screen, its lno/off won't
- * match up in that case.
- */
- if (scno >= cols_per_screen) {
- smp->c_ecsize = chlen;
- chlen -= scno - cols_per_screen;
- smp->c_eclen = chlen;
- smp->c_eboff = offset_in_line;
- if (scno > cols_per_screen)
- is_partial = 1;
-
- /* Terminate the loop. */
- offset_in_line = len;
- }
-
- /*
- * If the caller wants the cursor value, and this was the
- * cursor character, set the value. There are two ways to
- * put the cursor on a character -- if it's normal display
- * mode, it goes on the last column of the character. If
- * it's input mode, it goes on the first. In normal mode,
- * set the cursor only if the entire character was displayed.
- */
- if (cno_cnt &&
- --cno_cnt == 0 && (F_ISSET(sp, S_INPUT) || !is_partial)) {
- *yp = smp - HMAP;
- if (F_ISSET(sp, S_INPUT))
- *xp = scno - chlen;
- else
- *xp = scno - 1;
- if (O_ISSET(sp, O_NUMBER) &&
- !is_infoline && smp->off == 1)
- *xp += O_NUMBER_LENGTH;
-
- /* If the line is on the screen, quit. */
- if (is_cached)
- goto ret;
- }
-
- /* If the line is on the screen, don't display anything. */
- if (is_cached)
- continue;
-
- /*
- * Display the character. If it's a tab and tabs aren't some
- * ridiculous length, do it fast. (We do tab expansion here
- * because curses doesn't have a way to set the tab length.)
- */
- if (is_tab) {
- if (chlen <= sizeof(TABSTR) - 1) {
- ADDNSTR(TABSTR, chlen);
- } else
- while (chlen--)
- ADDCH(TABCH);
- } else
- ADDNSTR(KEY_NAME(sp, ch) + offset_in_char, chlen);
- }
-
- if (scno < cols_per_screen) {
- /* If didn't paint the whole line, update the cache. */
- smp->c_ecsize = smp->c_eclen = KEY_LEN(sp, ch);
- smp->c_eboff = len - 1;
-
- /*
- * If not the info/mode line, and O_LIST set, and at the
- * end of the line, and the line ended on this screen,
- * add a trailing $.
- */
- if (list_dollar) {
- ++scno;
- ADDCH('$');
- }
-
- /* If still didn't paint the whole line, clear the rest. */
- if (scno < cols_per_screen)
- clrtoeol();
- }
-
-ret: MOVEA(sp, oldy, oldx);
- return (0);
-}
-
-/*
- * svi_number --
- * Repaint the numbers on all the lines.
- */
-int
-svi_number(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- SMAP *smp;
- size_t oldy, oldx;
- char *lp, nbuf[10];
-
- /*
- * Try and avoid getting the last line in the file, by getting the
- * line after the last line in the screen -- if it exists, we know
- * we have to to number all the lines in the screen. Get the one
- * after the last instead of the last, so that the info line doesn't
- * fool us.
- *
- * If that test fails, we have to check each line for existence.
- *
- * XXX
- * The problem is that file_lline will lie, and tell us that the
- * info line is the last line in the file.
- */
- lp = file_gline(sp, ep, TMAP->lno + 1, NULL);
-
- getyx(stdscr, oldy, oldx);
- for (smp = HMAP; smp <= TMAP; ++smp) {
- if (smp->off != 1)
- continue;
- if (ISINFOLINE(sp, smp))
- break;
- if (smp->lno != 1 && lp == NULL &&
- file_gline(sp, ep, smp->lno, NULL) == NULL)
- break;
- MOVE(sp, smp - HMAP, 0);
- (void)snprintf(nbuf, sizeof(nbuf), O_NUMBER_FMT, smp->lno);
- ADDSTR(nbuf);
- }
- MOVEA(sp, oldy, oldx);
- return (0);
-}
diff --git a/usr.bin/vi/svi/svi_refresh.c b/usr.bin/vi/svi/svi_refresh.c
deleted file mode 100644
index bc8bd92c1acd..000000000000
--- a/usr.bin/vi/svi/svi_refresh.c
+++ /dev/null
@@ -1,818 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)svi_refresh.c 8.60 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "svi_screen.h"
-#include "../sex/sex_screen.h"
-
-static int svi_modeline __P((SCR *, EXF *));
-
-int
-svi_refresh(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- SCR *tsp;
- u_int paintbits;
-
- /*
- * 1: Resize the screen.
- *
- * Notice that a resize is requested, and set up everything so that
- * the file gets reinitialized. Done here, instead of in the vi loop
- * because there may be other initialization that other screens need
- * to do. The actual changing of the row/column values was done by
- * calling the ex options code which put them into the environment,
- * which is used by curses. Stupid, but ugly.
- */
- if (F_ISSET(sp, S_RESIZE)) {
- /* Reinitialize curses. */
- if (svi_curses_end(sp) || svi_curses_init(sp))
- return (1);
-
- /* Invalidate the line size cache. */
- SVI_SCR_CFLUSH(SVP(sp));
-
- /*
- * Fill the map, incidentally losing any svi_line()
- * cached information.
- */
- if (svi_sm_fill(sp, ep, sp->lno, P_FILL))
- return (1);
- F_CLR(sp, S_RESIZE | S_REFORMAT);
- F_SET(sp, S_REDRAW);
- }
-
- /*
- * 2: S_REFRESH
- *
- * If S_REFRESH is set in the current screen, repaint everything
- * that we can find.
- */
- if (F_ISSET(sp, S_REFRESH))
- for (tsp = sp->gp->dq.cqh_first;
- tsp != (void *)&sp->gp->dq; tsp = tsp->q.cqe_next)
- if (tsp != sp)
- F_SET(tsp, S_REDRAW);
- /*
- * 3: Related or dirtied screens, or screens with messages.
- *
- * If related screens share a view into a file, they may have been
- * modified as well. Refresh any screens with paint or dirty bits
- * set, or where messages are waiting. Finally, if we refresh any
- * screens other than the current one, the cursor will be trashed.
- */
- paintbits = S_REDRAW | S_REFORMAT | S_REFRESH;
- if (O_ISSET(sp, O_NUMBER))
- paintbits |= S_RENUMBER;
- for (tsp = sp->gp->dq.cqh_first;
- tsp != (void *)&sp->gp->dq; tsp = tsp->q.cqe_next)
- if (tsp != sp &&
- (F_ISSET(tsp, paintbits) ||
- F_ISSET(SVP(tsp), SVI_SCREENDIRTY) ||
- tsp->msgq.lh_first != NULL &&
- !F_ISSET(tsp->msgq.lh_first, M_EMPTY))) {
- (void)svi_paint(tsp, tsp->ep);
- F_CLR(SVP(tsp), SVI_SCREENDIRTY);
- F_SET(SVP(sp), SVI_CUR_INVALID);
- }
-
- /*
- * 4: Refresh the current screen.
- *
- * Always refresh the current screen, it may be a cursor movement.
- * Also, always do it last -- that way, S_REFRESH can be set in
- * the current screen only, and the screen won't flash.
- */
- F_CLR(sp, SVI_SCREENDIRTY);
- return (svi_paint(sp, ep));
-}
-
-/*
- * svi_paint --
- * This is the guts of the vi curses screen code. The idea is that
- * the SCR structure passed in contains the new coordinates of the
- * screen. What makes this hard is that we don't know how big
- * characters are, doing input can put the cursor in illegal places,
- * and we're frantically trying to avoid repainting unless it's
- * absolutely necessary. If you change this code, you'd better know
- * what you're doing. It's subtle and quick to anger.
- */
-int
-svi_paint(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- SMAP *smp, tmp;
- SVI_PRIVATE *svp;
- recno_t lastline, lcnt;
- size_t cwtotal, cnt, len, x, y;
- int ch, didpaint, leftright_warp;
- char *p;
-
-#define LNO sp->lno
-#define OLNO svp->olno
-#define CNO sp->cno
-#define OCNO svp->ocno
-#define SCNO svp->sc_col
-
- didpaint = leftright_warp = 0;
- svp = SVP(sp);
-
- /*
- * 1: Reformat the lines.
- *
- * If the lines themselves have changed (:set list, for example),
- * fill in the map from scratch. Adjust the screen that's being
- * displayed if the leftright flag is set.
- */
- if (F_ISSET(sp, S_REFORMAT)) {
- /* Invalidate the line size cache. */
- SVI_SCR_CFLUSH(SVP(sp));
-
- /* Toss svi_line() cached information. */
- if (svi_sm_fill(sp, ep, HMAP->lno, P_TOP))
- return (1);
- if (O_ISSET(sp, O_LEFTRIGHT) &&
- (cnt = svi_opt_screens(sp, ep, LNO, &CNO)) != 1)
- for (smp = HMAP; smp <= TMAP; ++smp)
- smp->off = cnt;
- F_CLR(sp, S_REFORMAT);
- F_SET(sp, S_REDRAW);
- }
-
- /*
- * 2: Line movement.
- *
- * Line changes can cause the top line to change as well. As
- * before, if the movement is large, the screen is repainted.
- *
- * 2a: Tiny screens.
- *
- * Tiny screens cannot be permitted into the "scrolling" parts of
- * the smap code for two reasons. If the screen size is 1 line,
- * HMAP == TMAP and the code will quickly drop core. If the screen
- * size is 2, none of the divisions by 2 will work, and scrolling
- * won't work. In fact, because no line change will be less than
- * HALFTEXT(sp), we always ending up "filling" the map, with a
- * P_MIDDLE flag, which isn't what the user wanted. Tiny screens
- * can go into the "fill" portions of the smap code, however.
- */
- if (sp->t_rows <= 2) {
- if (LNO < HMAP->lno) {
- if (svi_sm_fill(sp, ep, LNO, P_TOP))
- return (1);
- } else if (LNO > TMAP->lno)
- if (svi_sm_fill(sp, ep, LNO, P_BOTTOM))
- return (1);
- if (sp->t_rows == 1) {
- HMAP->off = svi_opt_screens(sp, ep, LNO, &CNO);
- goto paint;
- }
- F_SET(sp, S_REDRAW);
- goto adjust;
- }
-
- /*
- * 2b: Small screens.
- *
- * Users can use the window, w300, w1200 and w9600 options to make
- * the screen artificially small. The behavior of these options
- * in the historic vi wasn't all that consistent, and, in fact, it
- * was never documented how various screen movements affected the
- * screen size. Generally, one of three things would happen:
- * 1: The screen would expand in size, showing the line
- * 2: The screen would scroll, showing the line
- * 3: The screen would compress to its smallest size and
- * repaint.
- * In general, scrolling didn't cause compression (200^D was handled
- * the same as ^D), movement to a specific line would (:N where N
- * was 1 line below the screen caused a screen compress), and cursor
- * movement would scroll if it was 11 lines or less, and compress if
- * it was more than 11 lines. (And, no, I have no idea where the 11
- * comes from.)
- *
- * What we do is try and figure out if the line is less than half of
- * a full screen away. If it is, we expand the screen if there's
- * room, and then scroll as necessary. The alternative is to compress
- * and repaint.
- *
- * !!!
- * This code is a special case from beginning to end. Unfortunately,
- * home modems are still slow enough that it's worth having.
- *
- * XXX
- * If the line a really long one, i.e. part of the line is on the
- * screen but the column offset is not, we'll end up in the adjust
- * code, when we should probably have compressed the screen.
- */
- if (ISSMALLSCREEN(sp))
- if (LNO < HMAP->lno) {
- lcnt = svi_sm_nlines(sp, ep, HMAP, LNO, sp->t_maxrows);
- if (lcnt <= HALFSCREEN(sp))
- for (; lcnt && sp->t_rows != sp->t_maxrows;
- --lcnt, ++sp->t_rows) {
- ++TMAP;
- if (svi_sm_1down(sp, ep))
- return (1);
- }
- else
- goto small_fill;
- } else if (LNO > TMAP->lno) {
- lcnt = svi_sm_nlines(sp, ep, TMAP, LNO, sp->t_maxrows);
- if (lcnt <= HALFSCREEN(sp))
- for (; lcnt && sp->t_rows != sp->t_maxrows;
- --lcnt, ++sp->t_rows) {
- if (svi_sm_next(sp, ep, TMAP, TMAP + 1))
- return (1);
- ++TMAP;
- if (svi_line(sp, ep, TMAP, NULL, NULL))
- return (1);
- }
- else {
-small_fill: MOVE(sp, INFOLINE(sp), 0);
- clrtoeol();
- for (; sp->t_rows > sp->t_minrows;
- --sp->t_rows, --TMAP) {
- MOVE(sp, TMAP - HMAP, 0);
- clrtoeol();
- }
- if (svi_sm_fill(sp, ep, LNO, P_FILL))
- return (1);
- F_SET(sp, S_REDRAW);
- goto adjust;
- }
- }
-
- /*
- * 3a: Line down, or current screen.
- */
- if (LNO >= HMAP->lno) {
- /* Current screen. */
- if (LNO <= TMAP->lno)
- goto adjust;
-
- /*
- * If less than half a screen above the line, scroll down
- * until the line is on the screen.
- */
- lcnt = svi_sm_nlines(sp, ep, TMAP, LNO, HALFTEXT(sp));
- if (lcnt < HALFTEXT(sp)) {
- while (lcnt--)
- if (svi_sm_1up(sp, ep))
- return (1);
- goto adjust;
- }
- goto bottom;
- }
-
- /*
- * 3b: Line up.
- */
- lcnt = svi_sm_nlines(sp, ep, HMAP, LNO, HALFTEXT(sp));
- if (lcnt < HALFTEXT(sp)) {
- /*
- * If less than half a screen below the line, scroll up until
- * the line is the first line on the screen. Special check so
- * that if the screen has been emptied, we refill it.
- */
- if (file_gline(sp, ep, HMAP->lno, &len) != NULL) {
- while (lcnt--)
- if (svi_sm_1down(sp, ep))
- return (1);
- goto adjust;
- }
-
- /*
- * If less than a full screen from the bottom of the file,
- * put the last line of the file on the bottom of the screen.
- */
-bottom: if (file_lline(sp, ep, &lastline))
- return (1);
- tmp.lno = LNO;
- tmp.off = 1;
- lcnt = svi_sm_nlines(sp, ep, &tmp, lastline, sp->t_rows);
- if (lcnt < sp->t_rows) {
- if (svi_sm_fill(sp, ep, lastline, P_BOTTOM))
- return (1);
- F_SET(sp, S_REDRAW);
- goto adjust;
- }
- /* It's not close, just put the line in the middle. */
- goto middle;
- }
-
- /*
- * If less than half a screen from the top of the file, put the first
- * line of the file at the top of the screen. Otherwise, put the line
- * in the middle of the screen.
- */
- tmp.lno = 1;
- tmp.off = 1;
- lcnt = svi_sm_nlines(sp, ep, &tmp, LNO, HALFTEXT(sp));
- if (lcnt < HALFTEXT(sp)) {
- if (svi_sm_fill(sp, ep, 1, P_TOP))
- return (1);
- } else
-middle: if (svi_sm_fill(sp, ep, LNO, P_MIDDLE))
- return (1);
- F_SET(sp, S_REDRAW);
-
- /*
- * At this point we know part of the line is on the screen. Since
- * scrolling is done using logical lines, not physical, all of the
- * line may not be on the screen. While that's not necessarily bad,
- * if the part the cursor is on isn't there, we're going to lose.
- * This can be tricky; if the line covers the entire screen, lno
- * may be the same as both ends of the map, that's why we test BOTH
- * the top and the bottom of the map. This isn't a problem for
- * left-right scrolling, the cursor movement code handles the problem.
- *
- * There's a performance issue here if editing *really* long lines.
- * This gets to the right spot by scrolling, and, in a binary, by
- * scrolling hundreds of lines. If the adjustment looks like it's
- * going to be a serious problem, refill the screen and repaint.
- */
-adjust: if (!O_ISSET(sp, O_LEFTRIGHT) &&
- (LNO == HMAP->lno || LNO == TMAP->lno)) {
- cnt = svi_opt_screens(sp, ep, LNO, &CNO);
- if (LNO == HMAP->lno && cnt < HMAP->off)
- if ((HMAP->off - cnt) > HALFTEXT(sp)) {
- HMAP->off = cnt;
- svi_sm_fill(sp, ep, OOBLNO, P_TOP);
- F_SET(sp, S_REDRAW);
- } else
- while (cnt < HMAP->off)
- if (svi_sm_1down(sp, ep))
- return (1);
- if (LNO == TMAP->lno && cnt > TMAP->off)
- if ((cnt - TMAP->off) > HALFTEXT(sp)) {
- TMAP->off = cnt;
- svi_sm_fill(sp, ep, OOBLNO, P_BOTTOM);
- F_SET(sp, S_REDRAW);
- } else
- while (cnt > TMAP->off)
- if (svi_sm_1up(sp, ep))
- return (1);
- }
-
- /*
- * If the screen needs to be repainted, skip cursor optimization.
- * However, in the code above we skipped leftright scrolling on
- * the grounds that the cursor code would handle it. Make sure
- * the right screen is up.
- */
- if (F_ISSET(sp, S_REDRAW)) {
- if (O_ISSET(sp, O_LEFTRIGHT)) {
- cnt = svi_opt_screens(sp, ep, LNO, &CNO);
- if (HMAP->off != cnt)
- for (smp = HMAP; smp <= TMAP; ++smp)
- smp->off = cnt;
- }
- goto paint;
- }
-
- /*
- * 4: Cursor movements.
- *
- * Decide cursor position. If the line has changed, the cursor has
- * moved over a tab, or don't know where the cursor was, reparse the
- * line. Otherwise, we've just moved over fixed-width characters,
- * and can calculate the left/right scrolling and cursor movement
- * without reparsing the line. Note that we don't know which (if any)
- * of the characters between the old and new cursor positions changed.
- *
- * XXX
- * With some work, it should be possible to handle tabs quickly, at
- * least in obvious situations, like moving right and encountering
- * a tab, without reparsing the whole line.
- */
-
- /* If the line we're working with has changed, reparse. */
- if (F_ISSET(SVP(sp), SVI_CUR_INVALID) || LNO != OLNO) {
- F_CLR(SVP(sp), SVI_CUR_INVALID);
- goto slow;
- }
-
- /* Otherwise, if nothing's changed, go fast. */
- if (CNO == OCNO)
- goto fast;
-
- /*
- * Get the current line. If this fails, we either have an empty
- * file and can just repaint, or there's a real problem. This
- * isn't a performance issue because there aren't any ways to get
- * here repeatedly.
- */
- if ((p = file_gline(sp, ep, LNO, &len)) == NULL) {
- if (file_lline(sp, ep, &lastline))
- return (1);
- if (lastline == 0)
- goto slow;
- GETLINE_ERR(sp, LNO);
- return (1);
- }
-
-#ifdef DEBUG
- /* This is just a test. */
- if (CNO >= len && len != 0) {
- msgq(sp, M_ERR, "Error: %s/%d: cno (%u) >= len (%u)",
- tail(__FILE__), __LINE__, CNO, len);
- return (1);
- }
-#endif
- /*
- * The basic scheme here is to look at the characters in between
- * the old and new positions and decide how big they are on the
- * screen, and therefore, how many screen positions to move.
- */
- if (CNO < OCNO) {
- /*
- * 4a: Cursor moved left.
- *
- * Point to the old character. The old cursor position can
- * be past EOL if, for example, we just deleted the rest of
- * the line. In this case, since we don't know the width of
- * the characters we traversed, we have to do it slowly.
- */
- p += OCNO;
- cnt = (OCNO - CNO) + 1;
- if (OCNO >= len)
- goto slow;
-
- /*
- * Quick sanity check -- it's hard to figure out exactly when
- * we cross a screen boundary as we do in the cursor right
- * movement. If cnt is so large that we're going to cross the
- * boundary no matter what, stop now.
- */
- if (SCNO + 1 + MAX_CHARACTER_COLUMNS < cnt)
- goto lscreen;
-
- /*
- * Count up the widths of the characters. If it's a tab
- * character, go do it the the slow way.
- */
- for (cwtotal = 0; cnt--; cwtotal += KEY_LEN(sp, ch))
- if ((ch = *(u_char *)p--) == '\t')
- goto slow;
-
- /*
- * Decrement the screen cursor by the total width of the
- * characters minus 1.
- */
- cwtotal -= 1;
-
- /*
- * If we're moving left, and there's a wide character in the
- * current position, go to the end of the character.
- */
- if (KEY_LEN(sp, ch) > 1)
- cwtotal -= KEY_LEN(sp, ch) - 1;
-
- /*
- * If the new column moved us off of the current logical line,
- * calculate a new one. If doing leftright scrolling, we've
- * moved off of the current screen, as well. Since most files
- * don't have more than two screens, we optimize moving from
- * screen 2 to screen 1.
- */
- if (SCNO < cwtotal) {
-lscreen: if (O_ISSET(sp, O_LEFTRIGHT)) {
- cnt = HMAP->off == 2 ? 1 :
- svi_opt_screens(sp, ep, LNO, &CNO);
- for (smp = HMAP; smp <= TMAP; ++smp)
- smp->off = cnt;
- leftright_warp = 1;
- goto paint;
- }
- goto slow;
- }
- SCNO -= cwtotal;
- } else {
- /*
- * 4b: Cursor moved right.
- *
- * Point to the first character to the right.
- */
- p += OCNO + 1;
- cnt = CNO - OCNO;
-
- /*
- * Count up the widths of the characters. If it's a tab
- * character, go do it the the slow way. If we cross a
- * screen boundary, we can quit.
- */
- for (cwtotal = SCNO; cnt--;) {
- if ((ch = *(u_char *)p++) == '\t')
- goto slow;
- if ((cwtotal += KEY_LEN(sp, ch)) >= SCREEN_COLS(sp))
- break;
- }
-
- /*
- * Increment the screen cursor by the total width of the
- * characters.
- */
- SCNO = cwtotal;
-
- /* See screen change comment in section 4a. */
- if (SCNO >= SCREEN_COLS(sp)) {
- if (O_ISSET(sp, O_LEFTRIGHT)) {
- cnt = svi_opt_screens(sp, ep, LNO, &CNO);
- for (smp = HMAP; smp <= TMAP; ++smp)
- smp->off = cnt;
- leftright_warp = 1;
- goto paint;
- }
- goto slow;
- }
- }
-
- /*
- * 4c: Fast cursor update.
- *
- * Retrieve the current cursor position, and correct it
- * for split screens.
- */
-fast: getyx(stdscr, y, x);
- y -= sp->woff;
- goto number;
-
- /*
- * 4d: Slow cursor update.
- *
- * Walk through the map and find the current line. If doing left-right
- * scrolling and the cursor movement has changed the screen displayed,
- * scroll the screen left or right, unless we're updating the info line
- * in which case we just scroll that one line. Then update the screen
- * lines for this file line until we have a new screen cursor position.
- */
-slow: for (smp = HMAP; smp->lno != LNO; ++smp);
- if (O_ISSET(sp, O_LEFTRIGHT)) {
- cnt = svi_opt_screens(sp, ep, LNO, &CNO) % SCREEN_COLS(sp);
- if (cnt != HMAP->off) {
- if (ISINFOLINE(sp, smp))
- smp->off = cnt;
- else {
- for (smp = HMAP; smp <= TMAP; ++smp)
- smp->off = cnt;
- leftright_warp = 1;
- }
- goto paint;
- }
- }
- for (y = -1; smp <= TMAP && smp->lno == LNO; ++smp) {
- if (svi_line(sp, ep, smp, &y, &SCNO))
- return (1);
- if (y != -1)
- break;
- }
- goto number;
-
- /*
- * 5: Repaint the entire screen.
- *
- * Lost big, do what you have to do. We flush the cache as S_REDRAW
- * gets set when the screen isn't worth fixing, and it's simpler to
- * repaint. So, don't trust anything that we think we know about it.
- */
-paint: for (smp = HMAP; smp <= TMAP; ++smp)
- SMAP_FLUSH(smp);
- for (smp = HMAP; smp <= TMAP; ++smp)
- if (svi_line(sp, ep, smp, &y, &SCNO))
- return (1);
- /*
- * If it's a small screen and we're redrawing, clear the unused lines,
- * ex may have overwritten them.
- */
- if (F_ISSET(sp, S_REDRAW)) {
- if (ISSMALLSCREEN(sp))
- for (cnt = sp->t_rows; cnt <= sp->t_maxrows; ++cnt) {
- MOVE(sp, cnt, 0);
- clrtoeol();
- }
- F_CLR(sp, S_REDRAW);
- }
-
- didpaint = 1;
-
- /*
- * 6: Repaint the line numbers.
- *
- * If O_NUMBER is set and the S_RENUMBER bit is set, and we didn't
- * repaint the screen, repaint all of the line numbers, they've
- * changed.
- */
-number: if (O_ISSET(sp, O_NUMBER) && F_ISSET(sp, S_RENUMBER) && !didpaint) {
- if (svi_number(sp, ep))
- return (1);
- F_CLR(sp, S_RENUMBER);
- }
-
- /*
- * 7: Refresh the screen.
- *
- * If the screen was corrupted, refresh it.
- */
- if (F_ISSET(sp, S_REFRESH)) {
- wrefresh(curscr);
- F_CLR(sp, S_REFRESH);
- }
-
- if (F_ISSET(sp, S_BELLSCHED))
- svi_bell(sp);
- /*
- * If the bottom line isn't in use by the colon command, and
- * we're not in the middle of a map:
- *
- * Display any messages. Don't test S_UPDATE_MODE. The
- * message printing routine set it to avoid anyone else
- * destroying the message we're about to display.
- *
- * If the bottom line isn't in use by anyone, put out the
- * standard status line.
- */
- if (!F_ISSET(SVP(sp), SVI_INFOLINE) && !KEYS_WAITING(sp))
- if (sp->msgq.lh_first != NULL &&
- !F_ISSET(sp->msgq.lh_first, M_EMPTY))
- svi_msgflush(sp);
- else if (!F_ISSET(sp, S_UPDATE_MODE))
- svi_modeline(sp, ep);
-
- /* Update saved information. */
- OCNO = CNO;
- OLNO = LNO;
-
- /* Place the cursor. */
- MOVE(sp, y, SCNO);
-
- /* Flush it all out. */
- refresh();
-
- /*
- * XXX
- * Recalculate the "most favorite" cursor position. Vi doesn't know
- * that we've warped the screen and it's going to have a completely
- * wrong idea about where the cursor should be. This is vi's problem,
- * and fixing it here is a gross violation of layering.
- */
- if (leftright_warp)
- (void)svi_column(sp, ep, &sp->rcm);
-
- return (0);
-}
-
-/*
- * svi_modeline --
- * Update the mode line.
- */
-static int
-svi_modeline(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- size_t cols, curlen, endpoint, len, midpoint;
- char *p, buf[20];
-
- /* Clear the mode line. */
- MOVE(sp, INFOLINE(sp), 0);
- clrtoeol();
-
- /*
- * We put down the file name, the ruler, the mode and the dirty flag.
- * If there's not enough room, there's not enough room, we don't play
- * any special games. We try to put the ruler in the middle and the
- * mode and dirty flag at the end.
- *
- * !!!
- * Leave the last character blank, in case it's a really dumb terminal
- * with hardware scroll. Second, don't paint the last character in the
- * screen, SunOS 4.1.1 and Ultrix 4.2 curses won't let you.
- */
- cols = sp->cols - 1;
-
- curlen = 0;
- if (sp->q.cqe_next != (void *)&sp->gp->dq) {
- for (p = sp->frp->name; *p != '\0'; ++p);
- while (--p > sp->frp->name) {
- if (*p == '/') {
- ++p;
- break;
- }
- if ((curlen += KEY_LEN(sp, *p)) > cols) {
- curlen -= KEY_LEN(sp, *p);
- ++p;
- break;
- }
- }
-
- MOVE(sp, INFOLINE(sp), 0);
- standout();
- for (; *p != '\0'; ++p)
- ADDCH(*p);
- standend();
- }
-
- /*
- * Display the ruler. If we're not at the midpoint yet, move there.
- * Otherwise, just add in two extra spaces.
- *
- * XXX
- * Assume that numbers, commas, and spaces only take up a single
- * column on the screen.
- */
- if (O_ISSET(sp, O_RULER)) {
- len = snprintf(buf,
- sizeof(buf), "%lu,%lu", sp->lno, sp->cno + 1);
- midpoint = (cols - ((len + 1) / 2)) / 2;
- if (curlen < midpoint) {
- MOVE(sp, INFOLINE(sp), midpoint);
- ADDSTR(buf);
- curlen += len;
- } else if (curlen + 2 + len < cols) {
- ADDSTR(" ");
- ADDSTR(buf);
- curlen += 2 + len;
- }
- }
-
- /*
- * Display the mode and the modified flag, as close to the end of the
- * line as possible, but guaranteeing at least two spaces between the
- * ruler and the modified flag.
- *
- * XXX
- * Assume that mode name characters, asterisks, and spaces only take
- * up a single column on the screen.
- */
- endpoint = cols;
- if (O_ISSET(sp, O_SHOWDIRTY) && F_ISSET(ep, F_MODIFIED))
- --endpoint;
-
-#define MODESIZE 9
- if (O_ISSET(sp, O_SHOWMODE))
- endpoint -= MAX_MODE_NAME;
-
- if (endpoint < curlen + 2)
- return (0);
-
- MOVE(sp, INFOLINE(sp), endpoint);
- if (O_ISSET(sp, O_SHOWDIRTY) && F_ISSET(ep, F_MODIFIED))
- ADDSTR("*");
- if (O_ISSET(sp, O_SHOWMODE))
- ADDSTR(sp->showmode);
- return (0);
-}
diff --git a/usr.bin/vi/svi/svi_relative.c b/usr.bin/vi/svi/svi_relative.c
deleted file mode 100644
index a1af33fe9c91..000000000000
--- a/usr.bin/vi/svi/svi_relative.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)svi_relative.c 8.16 (Berkeley) 5/21/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "svi_screen.h"
-
-static size_t svi_screens
- __P((SCR *, EXF *, char *, size_t, recno_t, size_t *));
-
-/*
- * svi_column --
- * Return the logical column of the cursor.
- */
-int
-svi_column(sp, ep, cp)
- SCR *sp;
- EXF *ep;
- size_t *cp;
-{
- size_t col;
-
- col = SVP(sp)->sc_col;
- if (O_ISSET(sp, O_NUMBER))
- col -= O_NUMBER_LENGTH;
- *cp = col;
- return (0);
-}
-
-/*
- * svi_opt_screens --
- * Return the screen columns necessary to display the line, or
- * if specified, the physical character column within the line,
- * including space required for the O_NUMBER and O_LIST options.
- */
-size_t
-svi_opt_screens(sp, ep, lno, cnop)
- SCR *sp;
- EXF *ep;
- recno_t lno;
- size_t *cnop;
-{
- size_t cols, screens;
-
- /*
- * Check for a cached value. We maintain a cache because, if the
- * line is large, this routine gets called repeatedly. One other
- * hack, lots of time the cursor is on column one, which is an easy
- * one.
- */
- if (cnop == NULL) {
- if (SVP(sp)->ss_lno == lno)
- return (SVP(sp)->ss_screens);
- } else if (*cnop == 0)
- return (1);
-
- /* Figure out how many columns the line/column needs. */
- cols = svi_screens(sp, ep, NULL, 0, lno, cnop);
-
- /* Leading number if O_NUMBER option set. */
- if (O_ISSET(sp, O_NUMBER))
- cols += O_NUMBER_LENGTH;
-
- /* Trailing '$' if O_LIST option set. */
- if (O_ISSET(sp, O_LIST) && cnop == NULL)
- cols += KEY_LEN(sp, '$');
-
- screens = (cols / sp->cols + (cols % sp->cols ? 1 : 0));
- if (screens == 0)
- screens = 1;
-
- /* Cache the value. */
- if (cnop == NULL) {
- SVP(sp)->ss_lno = lno;
- SVP(sp)->ss_screens = screens;
- }
- return (screens);
-}
-
-/*
- * svi_screens --
- * Return the screen columns necessary to display the line, or,
- * if specified, the physical character column within the line.
- */
-static size_t
-svi_screens(sp, ep, lp, llen, lno, cnop)
- SCR *sp;
- EXF *ep;
- char *lp;
- size_t llen;
- recno_t lno;
- size_t *cnop;
-{
- size_t chlen, cno, len, scno, tab_off;
- int ch, listset;
- char *p;
-
- /* Need the line to go any further. */
- if (lp == NULL)
- lp = file_gline(sp, ep, lno, &llen);
-
- /* Missing or empty lines are easy. */
- if (lp == NULL || llen == 0)
- return (0);
-
- listset = O_ISSET(sp, O_LIST);
-
-#define SET_CHLEN { \
- chlen = (ch = *(u_char *)p++) == '\t' && \
- !listset ? TAB_OFF(sp, tab_off) : KEY_LEN(sp, ch); \
-}
-#define TAB_RESET { \
- /* \
- * If past the end of the screen, and the character was a tab, \
- * reset the screen column to 0. Otherwise, display the rest \
- * of the character on the next line. \
- */ \
- if ((tab_off += chlen) >= sp->cols) \
- if (ch == '\t') { \
- tab_off = 0; \
- scno -= scno % sp->cols; \
- } else \
- tab_off -= sp->cols; \
-}
- p = lp;
- len = llen;
- scno = tab_off = 0;
- if (cnop == NULL)
- while (len--) {
- SET_CHLEN;
- scno += chlen;
- TAB_RESET;
- }
- else
- for (cno = *cnop; len--; --cno) {
- SET_CHLEN;
- scno += chlen;
- TAB_RESET;
- if (cno == 0)
- break;
- }
- return (scno);
-}
-
-/*
- * svi_rcm --
- * Return the physical column from the line that will display a
- * character closest to the currently most attractive character
- * position (which is stored as a screen column).
- */
-size_t
-svi_rcm(sp, ep, lno)
- SCR *sp;
- EXF *ep;
- recno_t lno;
-{
- size_t len;
-
- /* Last character is easy, and common. */
- if (sp->rcm_last)
- return (file_gline(sp,
- ep, lno, &len) == NULL || len == 0 ? 0 : len - 1);
-
- /* First character is easy, and common. */
- if (HMAP->off == 1 && sp->rcm == 0)
- return (0);
-
- /*
- * Get svi_cm_private() to do the hard work. If doing leftright
- * scrolling, we use the current screen offset, otherwise, use
- * the first screen, i.e. an offset of 1.
- *
- * XXX
- * I'm not sure that an offset of 1 is right. What happens is that
- * the vi main loop calls us for the VM_RCM case. By using an offset
- * of 1, we're assuming that every VM_RCM command changes lines, and
- * that we want to position on the first screen for that line. This
- * is currently the way it works, but it's not clean. I'd prefer it if
- * we could find the SMAP entry the cursor references, and use that
- * screen offset. Unfortunately, that's not going to be easy, as we
- * don't keep that information around and it may be expensive to get.
- */
- return (svi_cm_private(sp, ep, lno,
- O_ISSET(sp, O_LEFTRIGHT) ? HMAP->off : 1, sp->rcm));
-}
-
-/*
- * svi_cm_public --
- * Return the physical column from the line that will display a
- * character closest to the specified screen column.
- *
- * The extra interface is because it's called by vi, which doesn't
- * have a handle on the SMAP structure.
- */
-size_t
-svi_cm_public(sp, ep, lno, cno)
- SCR *sp;
- EXF *ep;
- recno_t lno;
- size_t cno;
-{
- return (svi_cm_private(sp, ep, lno, HMAP->off, cno));
-}
-
-/*
- * svi_cm_private --
- * Return the physical column from the line that will display a
- * character closest to the specified screen column, taking into
- * account the screen offset.
- *
- * The offset is for the commands that move logical distances, i.e.
- * if it's a logical scroll the closest physical distance is based
- * on the logical line, not the physical line.
- */
-size_t
-svi_cm_private(sp, ep, lno, off, cno)
- SCR *sp;
- EXF *ep;
- recno_t lno;
- size_t off, cno;
-{
- size_t chlen, len, llen, scno, tab_off;
- int ch, listset;
- char *lp, *p;
-
- /* Need the line to go any further. */
- lp = file_gline(sp, ep, lno, &llen);
-
- /* Missing or empty lines are easy. */
- if (lp == NULL || llen == 0)
- return (0);
-
- listset = O_ISSET(sp, O_LIST);
-
- /* Discard screen (logical) lines. */
- for (scno = 0, p = lp, len = llen; --off;) {
- for (; len && scno < sp->cols; --len)
- scno += (ch = *(u_char *)p++) == '\t' &&
- !listset ? TAB_OFF(sp, scno) : KEY_LEN(sp, ch);
-
- /*
- * If reached the end of the physical line, return
- * the last physical character in the line.
- */
- if (len == 0)
- return (llen - 1);
-
- /*
- * If the character was a tab, reset the screen column to 0.
- * Otherwise, the rest of the character is displayed on the
- * next line.
- */
- if (ch == '\t')
- scno = 0;
- else
- scno -= sp->cols;
- }
-
- /* Step through the line until reach the right character or EOL. */
- for (tab_off = scno; len--;) {
- SET_CHLEN;
-
- /*
- * If we've reached the specific character, there are three
- * cases.
- *
- * 1: scno == cno, i.e. the current character ends at the
- * screen character we care about.
- * a: off < llen - 1, i.e. not the last character in
- * the line, return the offset of the next character.
- * b: else return the offset of the last character.
- * 2: scno != cno, i.e. this character overruns the character
- * we care about, return the offset of this character.
- */
- if ((scno += chlen) >= cno) {
- off = p - lp;
- return (scno == cno ?
- (off < llen - 1 ? off : llen - 1) : off - 1);
- }
-
- TAB_RESET;
- }
-
- /* No such character; return the start of the last character. */
- return (llen - 1);
-}
diff --git a/usr.bin/vi/svi/svi_screen.c b/usr.bin/vi/svi/svi_screen.c
deleted file mode 100644
index 05e07eaeb6f1..000000000000
--- a/usr.bin/vi/svi/svi_screen.c
+++ /dev/null
@@ -1,332 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)svi_screen.c 8.91 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "../vi/vcmd.h"
-#include "svi_screen.h"
-#include "../sex/sex_screen.h"
-
-/*
- * svi_screen_init --
- * Initialize a screen.
- */
-int
-svi_screen_init(sp)
- SCR *sp;
-{
- /* Initialize support routines. */
- sp->s_bell = svi_bell;
- sp->s_bg = svi_bg;
- sp->s_busy = svi_busy;
- sp->s_change = svi_change;
- sp->s_clear = svi_clear;
- sp->s_colpos = svi_cm_public;
- sp->s_column = svi_column;
- sp->s_confirm = svi_confirm;
- sp->s_crel = svi_crel;
- sp->s_edit = svi_screen_edit;
- sp->s_end = svi_screen_end;
- sp->s_ex_cmd = svi_ex_cmd;
- sp->s_ex_run = svi_ex_run;
- sp->s_ex_write = svi_ex_write;
- sp->s_fg = svi_fg;
- sp->s_fill = svi_sm_fill;
- sp->s_get = svi_get;
- sp->s_key_read = sex_key_read;
- sp->s_optchange = svi_optchange;
- sp->s_fmap = svi_fmap;
- sp->s_position = svi_sm_position;
- sp->s_rabs = svi_rabs;
- sp->s_rcm = svi_rcm;
- sp->s_refresh = svi_refresh;
- sp->s_scroll = svi_sm_scroll;
- sp->s_split = svi_split;
- sp->s_suspend = svi_suspend;
- sp->s_window = sex_window;
-
- return (0);
-}
-
-/*
- * svi_screen_copy --
- * Copy to a new screen.
- */
-int
-svi_screen_copy(orig, sp)
- SCR *orig, *sp;
-{
- SVI_PRIVATE *osvi, *nsvi;
-
- /* Create the private screen structure. */
- CALLOC_RET(orig, nsvi, SVI_PRIVATE *, 1, sizeof(SVI_PRIVATE));
- sp->svi_private = nsvi;
-
-/* INITIALIZED AT SCREEN CREATE. */
- /* Invalidate the line size cache. */
- SVI_SCR_CFLUSH(nsvi);
-
-/* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */
- if (orig == NULL) {
- } else {
- osvi = SVP(orig);
- nsvi->srows = osvi->srows;
- if (osvi->VB != NULL && (nsvi->VB = strdup(osvi->VB)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- return (1);
- }
-
- F_SET(nsvi, F_ISSET(osvi, SVI_CURSES_INIT));
- }
- return (0);
-}
-
-/*
- * svi_screen_end --
- * End a screen.
- */
-int
-svi_screen_end(sp)
- SCR *sp;
-{
- SVI_PRIVATE *svp;
-
- svp = SVP(sp);
-
- /* Free the screen map. */
- if (HMAP != NULL)
- FREE(HMAP, SIZE_HMAP(sp) * sizeof(SMAP));
-
- /* Free the visual bell string. */
- if (svp->VB != NULL)
- free(svp->VB);
-
- /* Free private memory. */
- FREE(svp, sizeof(SVI_PRIVATE));
- sp->svi_private = NULL;
-
- return (0);
-}
-
-/*
- * We use a single curses "window" for each vi screen. The model would be
- * simpler with two windows (one for the text, and one for the modeline)
- * because scrolling the text window down would work correctly then, not
- * affecting the mode line. As it is we have to play games to make it look
- * right. The reason for this choice is that it would be difficult for
- * curses to optimize the movement, i.e. detect that the downward scroll
- * isn't going to change the modeline, set the scrolling region on the
- * terminal and only scroll the first part of the text window. (Even if
- * curses did detect it, the set-scrolling-region terminal commands can't
- * be used by curses because it's indeterminate where the cursor ends up
- * after they are sent.)
- */
-/*
- * svi_screen_edit --
- * Main vi curses screen loop.
- */
-int
-svi_screen_edit(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- SCR *tsp;
- int ecurses, escreen, force, rval;
-
- escreen = ecurses = rval = 0;
-
- /* Initialize curses. */
- if (svi_curses_init(sp)) {
- escreen = 1;
- goto err;
- }
- ecurses = 1;
-
- /*
- * The resize bit is probably set, as a result of the terminal being
- * set. We clear it as we just finished initializing the screen.
- * However, we will want to fill in the map from scratch, so provide
- * a line number just in case, and set the reformat flag.
- */
- HMAP->lno = 1;
- F_CLR(sp, S_RESIZE);
- F_SET(sp, S_REFORMAT);
-
- /*
- * The historic 4BSD curses had an uneasy relationship with termcap.
- * Termcap used a static buffer to hold the terminal information,
- * which was was then used by the curses functions. We want to use
- * it too, for lots of random things, but we've put it off until after
- * svi_curses_init:initscr() was called. Do it now.
- */
- if (svi_term_init(sp))
- goto err;
-
- for (;;) {
- /* Reset the cursor. */
- F_SET(SVP(sp), SVI_CUR_INVALID);
-
- /*
- * Run vi. If vi fails, svi data structures may be
- * corrupted, be extremely careful what you free up.
- */
- if (vi(sp, sp->ep)) {
- (void)rcv_sync(sp, sp->ep,
- RCV_EMAIL | RCV_ENDSESSION | RCV_PRESERVE);
- escreen = 1;
- goto err;
- }
-
- force = 0;
- switch (F_ISSET(sp, S_MAJOR_CHANGE)) {
- case S_EXIT_FORCE:
- force = 1;
- /* FALLTHROUGH */
- case S_EXIT:
- F_CLR(sp, S_EXIT_FORCE | S_EXIT);
- if (file_end(sp, sp->ep, force))/* File end. */
- break;
- /*
- * !!!
- * NB: sp->frp may now be NULL, if it was a tmp file.
- */
- (void)svi_join(sp, &tsp); /* Find a new screen. */
- if (tsp == NULL)
- (void)svi_swap(sp, &tsp, NULL);
- if (tsp == NULL) {
- escreen = 1;
- goto ret;
- }
- (void)screen_end(sp); /* Screen end. */
- sp = tsp;
- break;
- case 0: /* Exit vi mode. */
- svi_dtoh(sp, "Exit from vi");
- goto ret;
- case S_FSWITCH: /* File switch. */
- F_CLR(sp, S_FSWITCH);
- F_SET(sp, S_REFORMAT);
- break;
- case S_SSWITCH: /* Screen switch. */
- F_CLR(sp, S_SSWITCH);
- sp = sp->nextdisp;
- break;
- default:
- abort();
- }
- }
-
- if (0) {
-err: rval = 1;
- }
-
-ret: if (svi_term_end(sp)) /* Terminal end (uses sp). */
- rval = 1;
- if (ecurses && svi_curses_end(sp)) /* Curses end (uses sp). */
- rval = 1;
- if (escreen && screen_end(sp)) /* Screen end. */
- rval = 1;
- return (rval);
-}
-
-/*
- * svi_crel --
- * Change the relative size of the current screen.
- */
-int
-svi_crel(sp, count)
- SCR *sp;
- long count;
-{
- /* Can't grow beyond the size of the window. */
- if (count > O_VAL(sp, O_WINDOW))
- count = O_VAL(sp, O_WINDOW);
-
- sp->t_minrows = sp->t_rows = count;
- if (sp->t_rows > sp->rows - 1)
- sp->t_minrows = sp->t_rows = sp->rows - 1;
- TMAP = HMAP + (sp->t_rows - 1);
- F_SET(sp, S_REDRAW);
- return (0);
-}
-
-/*
- * svi_dtoh --
- * Move all but the current screen to the hidden queue.
- */
-void
-svi_dtoh(sp, emsg)
- SCR *sp;
- char *emsg;
-{
- SCR *tsp;
- int hidden;
-
- for (hidden = 0;
- (tsp = sp->gp->dq.cqh_first) != (void *)&sp->gp->dq; ++hidden) {
- if (_HMAP(tsp) != NULL) {
- FREE(_HMAP(tsp), SIZE_HMAP(tsp) * sizeof(SMAP));
- _HMAP(tsp) = NULL;
- }
- CIRCLEQ_REMOVE(&sp->gp->dq, tsp, q);
- CIRCLEQ_INSERT_TAIL(&sp->gp->hq, tsp, q);
- }
- CIRCLEQ_REMOVE(&sp->gp->hq, sp, q);
- CIRCLEQ_INSERT_TAIL(&sp->gp->dq, sp, q);
- if (hidden > 1)
- msgq(sp, M_INFO,
- "%s backgrounded %d screens; use :display to list the screens",
- emsg, hidden - 1);
-}
diff --git a/usr.bin/vi/svi/svi_screen.h b/usr.bin/vi/svi/svi_screen.h
deleted file mode 100644
index 3b4643dc10d1..000000000000
--- a/usr.bin/vi/svi/svi_screen.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)svi_screen.h 8.52 (Berkeley) 7/20/94
- */
-
-/*
- * Structure for mapping lines to the screen. An SMAP is an array, with one
- * structure element per screen line, which holds information describing the
- * physical line which is displayed in the screen line. The first two fields
- * (lno and off) are all that are necessary to describe a line. The rest of
- * the information is useful to keep information from being re-calculated.
- *
- * Lno is the line number. Off is the screen offset into the line. For
- * example, the pair 2:1 would be the first screen of line 2, and 2:2 would
- * be the second. If doing left-right scrolling, all of the offsets will be
- * the same, i.e. for the second screen, 1:2, 2:2, 3:2, etc. If doing the
- * standard vi scrolling, it will be staggered, i.e. 1:1, 1:2, 1:3, 2:1, 3:1,
- * etc.
- *
- * The SMAP is always as large as the physical screen, plus a slot for the
- * info line, so that there is room to add any screen into another one at
- * screen exit.
- */
-typedef struct _smap {
- recno_t lno; /* 1-N: Physical file line number. */
- size_t off; /* 1-N: Screen offset in the line. */
-
- /* svi_line() cache information. */
- size_t c_sboff; /* 0-N: offset of first character byte. */
- size_t c_eboff; /* 0-N: offset of last character byte. */
- u_char c_scoff; /* 0-N: offset into the first character. */
- u_char c_eclen; /* 1-N: columns from the last character. */
- u_char c_ecsize; /* 1-N: size of the last character. */
-} SMAP;
-
- /* Macros to flush/test cached information. */
-#define SMAP_CACHE(smp) ((smp)->c_ecsize != 0)
-#define SMAP_FLUSH(smp) ((smp)->c_ecsize = 0)
-
-typedef struct _svi_private {
-/* INITIALIZED AT SCREEN CREATE. */
- SMAP *h_smap; /* First slot of the line map. */
- SMAP *t_smap; /* Last slot of the line map. */
-
- size_t exlinecount; /* Ex overwrite count. */
- size_t extotalcount; /* Ex overwrite count. */
- size_t exlcontinue; /* Ex line continue value. */
-
- /* svi_opt_screens() cache information. */
-#define SVI_SCR_CFLUSH(svp) svp->ss_lno = OOBLNO
- recno_t ss_lno; /* 1-N: Line number. */
- size_t ss_screens; /* Return value. */
-
- recno_t olno; /* 1-N: old cursor file line. */
- size_t ocno; /* 0-N: old file cursor column. */
- size_t sc_col; /* 0-N: LOGICAL screen column. */
-
-/* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */
- size_t srows; /* 1-N: Rows in the terminal/window. */
-
- char *VB; /* Visual bell termcap string. */
-
-#define SVI_CURSES_INIT 0x001 /* Curses/termcap initialized. */
-#define SVI_CUR_INVALID 0x002 /* Cursor position is unknown. */
-#define SVI_DIVIDER 0x004 /* Screen divider is displayed. */
-#define SVI_INFOLINE 0x008 /* The infoline is being used by v_ntext(). */
-#define SVI_SCREENDIRTY 0x010 /* Screen needs refreshing. */
- u_int8_t flags;
-} SVI_PRIVATE;
-
-#define SVP(sp) ((SVI_PRIVATE *)((sp)->svi_private))
-#define HMAP (SVP(sp)->h_smap)
-#define TMAP (SVP(sp)->t_smap)
-#define _HMAP(sp) (SVP(sp)->h_smap)
-#define _TMAP(sp) (SVP(sp)->t_smap)
-
-/*
- * One extra slot is always allocated for the map so that we can use
- * it to do vi :colon command input; see svi_get().
- */
-#define SIZE_HMAP(sp) (SVP(sp)->srows + 1)
-
-#define O_NUMBER_FMT "%7lu " /* O_NUMBER format, length. */
-#define O_NUMBER_LENGTH 8
- /* Columns on a screen. */
-#define SCREEN_COLS(sp) \
- ((O_ISSET(sp, O_NUMBER) ? (sp)->cols - O_NUMBER_LENGTH : (sp)->cols))
-
-#define HALFSCREEN(sp) ((sp)->t_maxrows / 2) /* Half the screen. */
-#define HALFTEXT(sp) ((sp)->t_rows / 2) /* Half the text. */
-
-#define INFOLINE(sp) ((sp)->t_maxrows) /* Info line test, offset. */
-#define ISINFOLINE(sp, smp) (((smp) - HMAP) == INFOLINE(sp))
-
- /* Small screen test. */
-#define ISSMALLSCREEN(sp) ((sp)->t_minrows != (sp)->t_maxrows)
-
-/*
- * Next tab offset.
- *
- * !!!
- * There are problems with how the historical vi handled tabs. For example,
- * by doing "set ts=3" and building lines that fold, you can get it to step
- * through tabs as if they were spaces and move inserted characters to new
- * positions when <esc> is entered. I think that nvi does tabs correctly,
- * but there may be some historical incompatibilities.
- */
-#define TAB_OFF(sp, c) (O_VAL(sp, O_TABSTOP) - (c) % O_VAL(sp, O_TABSTOP))
-
-/* Move in a screen (absolute), and fail if it doesn't work. */
-#ifdef DEBUG
-#define MOVEA(sp, lno, cno) { \
- if (move(lno, cno) == ERR) { \
- msgq(sp, M_ERR, \
- "Error: %s/%d: move:l(%u), c(%u), abs", \
- tail(__FILE__), __LINE__, lno, cno); \
- return (1); \
- } \
-}
-#else
-#define MOVEA(sp, lno, cno) (void)move(lno, cno)
-#endif
-
-/* Move in a window, and fail if it doesn't work. */
-#ifdef DEBUG
-#define MOVE(sp, lno, cno) { \
- size_t __lno = (sp)->woff + (lno); \
- if (move(__lno, cno) == ERR) { \
- msgq(sp, M_ERR, \
- "Error: %s/%d: move:l(%u), c(%u), o(%u)", \
- tail(__FILE__), __LINE__, lno, cno, sp->woff); \
- return (1); \
- } \
-}
-#else
-#define MOVE(sp, lno, cno) (void)move((sp)->woff + (lno), cno)
-#endif
-
-/* Add a character. */
-#define ADDCH(ch) { \
- CHAR_T __ch = ch; \
- ADDNSTR(KEY_NAME(sp, __ch), KEY_LEN(sp, __ch)); \
-}
-
-/* Add a string len bytes long. */
-#ifdef DEBUG
-#define ADDNSTR(str, len) { \
- if (addnstr(str, len) == ERR) { \
- int __x, __y; \
- getyx(stdscr, __y, __x); \
- msgq(sp, M_ERR, "Error: %s/%d: addnstr: (%d/%u)", \
- tail(__FILE__), __LINE__, __y, __x); \
- return (1); \
- } \
-}
-#else
-#define ADDNSTR(str, len) (void)addnstr(str, len)
-#endif
-
-/* Add a string. */
-#ifdef DEBUG
-#define ADDSTR(str) { \
- if (addstr(str) == ERR) { \
- int __x, __y; \
- getyx(stdscr, __y, __x); \
- msgq(sp, M_ERR, "Error: %s/%d: addstr: (%d/%u)", \
- tail(__FILE__), __LINE__, __y, __x); \
- return (1); \
- } \
-}
-#else
-#define ADDSTR(str) (void)addstr(str);
-#endif
-
-/* Public routines. */
-void svi_bell __P((SCR *));
-int svi_bg __P((SCR *));
-int svi_busy __P((SCR *, char const *));
-int svi_change __P((SCR *, EXF *, recno_t, enum operation));
-size_t svi_cm_public __P((SCR *, EXF *, recno_t, size_t));
-int svi_column __P((SCR *, EXF *, size_t *));
-enum confirm
- svi_confirm __P((SCR *, EXF *, MARK *, MARK *));
-int svi_clear __P((SCR *));
-int svi_crel __P((SCR *, long));
-int svi_ex_cmd __P((SCR *, EXF *, struct _excmdarg *, MARK *));
-int svi_ex_run __P((SCR *, EXF *, MARK *));
-int svi_ex_write __P((void *, const char *, int));
-int svi_fg __P((SCR *, CHAR_T *));
-int svi_fmap __P((SCR *, enum seqtype, CHAR_T *, size_t, CHAR_T *, size_t));
-enum input
- svi_get __P((SCR *, EXF *, TEXTH *, ARG_CHAR_T, u_int));
-int svi_optchange __P((SCR *, int));
-int svi_rabs __P((SCR *, long, enum adjust));
-size_t svi_rcm __P((SCR *, EXF *, recno_t));
-int svi_refresh __P((SCR *, EXF *));
-int svi_screen_copy __P((SCR *, SCR *));
-int svi_screen_edit __P((SCR *, EXF *));
-int svi_screen_end __P((SCR *));
-int svi_sm_fill __P((SCR *, EXF *, recno_t, enum position));
-int svi_sm_position __P((SCR *, EXF *, MARK *, u_long, enum position));
-int svi_sm_scroll __P((SCR *, EXF *, MARK *, recno_t, enum sctype));
-int svi_split __P((SCR *, ARGS *[], int));
-int svi_suspend __P((SCR *));
-int svi_swap __P((SCR *, SCR **, char *));
-
-/* Private routines. */
-size_t svi_cm_private __P((SCR *, EXF *, recno_t, size_t, size_t));
-int svi_curses_end __P((SCR *));
-int svi_curses_init __P((SCR *));
-void svi_dtoh __P((SCR *, char *));
-int svi_init __P((SCR *));
-int svi_join __P((SCR *, SCR **));
-void svi_keypad __P((SCR *, int));
-int svi_line __P((SCR *, EXF *, SMAP *, size_t *, size_t *));
-int svi_msgflush __P((SCR *));
-int svi_number __P((SCR *, EXF *));
-size_t svi_opt_screens __P((SCR *, EXF *, recno_t, size_t *));
-int svi_paint __P((SCR *, EXF *));
-int svi_sm_1down __P((SCR *, EXF *));
-int svi_sm_1up __P((SCR *, EXF *));
-int svi_sm_cursor __P((SCR *, EXF *, SMAP **));
-int svi_sm_next __P((SCR *, EXF *, SMAP *, SMAP *));
-recno_t svi_sm_nlines __P((SCR *, EXF *, SMAP *, recno_t, size_t));
-int svi_sm_prev __P((SCR *, EXF *, SMAP *, SMAP *));
-int svi_term_end __P((SCR *sp));
-int svi_term_init __P((SCR *sp));
-
-/* Private debugging routines. */
-#ifdef DEBUG
-int svi_gdbrefresh __P((void));
-#endif
diff --git a/usr.bin/vi/svi/svi_split.c b/usr.bin/vi/svi/svi_split.c
deleted file mode 100644
index 160f49556c42..000000000000
--- a/usr.bin/vi/svi/svi_split.c
+++ /dev/null
@@ -1,627 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)svi_split.c 8.46 (Berkeley) 8/9/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "svi_screen.h"
-
-/*
- * svi_split --
- * Split the screen.
- */
-int
-svi_split(sp, argv, argc)
- SCR *sp;
- ARGS *argv[];
- int argc;
-{
- MSG *mp, *next;
- SCR *tsp, saved_sp;
- SVI_PRIVATE saved_svp;
- SMAP *smp;
- size_t cnt, half;
- int issmallscreen, splitup;
- char **ap;
-
- /* Check to see if it's possible. */
- half = sp->rows / 2;
- if (half < MINIMUM_SCREEN_ROWS) {
- msgq(sp, M_ERR, "Screen must be larger than %d to split",
- MINIMUM_SCREEN_ROWS);
- return (1);
- }
-
- /* Get a new screen. */
- if (screen_init(sp, &tsp, 0))
- return (1);
- CALLOC(sp, _HMAP(tsp), SMAP *, SIZE_HMAP(sp), sizeof(SMAP));
- if (_HMAP(tsp) == NULL)
- return (1);
-
- /*
- * We're about to modify the current screen. Save the contents
- * in case something goes horribly, senselessly wrong.
- */
- saved_sp = *sp;
- saved_svp = *SVP(sp);
-
-/* INITIALIZED AT SCREEN CREATE. */
-
-/* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */
- /*
- * Small screens: see svi/svi_refresh.c:svi_refresh, section 3b.
- * Set a flag so we know to fix the screen up later.
- */
- issmallscreen = ISSMALLSCREEN(sp);
-
- /*
- * Split the screen, and link the screens together. If the cursor
- * is in the top half of the current screen, the new screen goes
- * under the current screen. Else, it goes above the current screen.
- *
- * The columns in the screen don't change.
- */
- tsp->cols = sp->cols;
-
- cnt = svi_sm_cursor(sp, sp->ep, &smp) ? 0 : smp - HMAP;
- if (cnt <= half) { /* Parent is top half. */
- /* Child. */
- tsp->rows = sp->rows - half;
- tsp->woff = sp->woff + half;
- tsp->t_maxrows = tsp->rows - 1;
-
- /* Parent. */
- sp->rows = half;
- sp->t_maxrows = sp->rows - 1;
-
- splitup = 0;
- } else { /* Parent is bottom half. */
- /* Child. */
- tsp->rows = sp->rows - half;
- tsp->woff = sp->woff;
- tsp->t_maxrows = tsp->rows - 1;
-
- /* Parent. */
- sp->rows = half;
- sp->woff += tsp->rows;
- sp->t_maxrows = sp->rows - 1;
-
- /* Shift the parent's map down. */
- memmove(_HMAP(sp),
- _HMAP(sp) + tsp->rows, sp->t_maxrows * sizeof(SMAP));
-
- splitup = 1;
- }
-
- /*
- * Small screens: see svi/svi_refresh.c:svi_refresh, section 3b.
- *
- * The child may have different screen options sizes than the
- * parent, so use them. Make sure that the text counts aren't
- * larger than the new screen sizes.
- */
- if (issmallscreen) {
- /* Fix the text line count for the parent. */
- if (splitup)
- sp->t_rows -= tsp->rows;
-
- /* Fix the parent screen. */
- if (sp->t_rows > sp->t_maxrows)
- sp->t_rows = sp->t_maxrows;
- if (sp->t_minrows > sp->t_maxrows)
- sp->t_minrows = sp->t_maxrows;
-
- /* Fix the child screen. */
- tsp->t_minrows = tsp->t_rows = O_VAL(sp, O_WINDOW);
- if (tsp->t_rows > tsp->t_maxrows)
- tsp->t_rows = tsp->t_maxrows;
- if (tsp->t_minrows > tsp->t_maxrows)
- tsp->t_minrows = tsp->t_maxrows;
-
- /*
- * If we split up, i.e. the child is on top, lines that
- * were painted in the parent may not be painted in the
- * child. Clear any lines not being used in the child
- * screen.
- *
- */
- if (splitup)
- for (cnt = tsp->t_rows; ++cnt <= tsp->t_maxrows;) {
- MOVE(tsp, cnt, 0);
- clrtoeol();
- }
- } else {
- sp->t_minrows = sp->t_rows = sp->rows - 1;
-
- /*
- * The new screen may be a small screen, even though the
- * parent was not. Don't complain if O_WINDOW is too large,
- * we're splitting the screen so the screen is much smaller
- * than normal. Clear any lines not being used in the child
- * screen.
- */
- tsp->t_minrows = tsp->t_rows = O_VAL(sp, O_WINDOW);
- if (tsp->t_rows > tsp->rows - 1)
- tsp->t_minrows = tsp->t_rows = tsp->rows - 1;
- else
- for (cnt = tsp->t_rows; ++cnt <= tsp->t_maxrows;) {
- MOVE(tsp, cnt, 0);
- clrtoeol();
- }
- }
-
- /* Adjust the ends of both maps. */
- _TMAP(sp) = _HMAP(sp) + (sp->t_rows - 1);
- _TMAP(tsp) = _HMAP(tsp) + (tsp->t_rows - 1);
-
- /* Reset the length of the default scroll. */
- sp->defscroll = sp->t_maxrows / 2;
- tsp->defscroll = tsp->t_maxrows / 2;
-
- /*
- * If files specified, build the file list, else, link to the
- * current file.
- */
- if (argv == NULL) {
- if ((tsp->frp = file_add(tsp, sp->frp->name)) == NULL)
- goto err;
- } else {
- /* Create a new argument list. */
- CALLOC(sp, tsp->argv, char **, argc + 1, sizeof(char *));
- if (tsp->argv == NULL)
- goto err;
- for (ap = tsp->argv, argv; argv[0]->len != 0; ++ap, ++argv)
- if ((*ap =
- v_strdup(sp, argv[0]->bp, argv[0]->len)) == NULL)
- goto err;
- *ap = NULL;
-
- /* Switch to the first one. */
- tsp->cargv = tsp->argv;
- if ((tsp->frp = file_add(tsp, *tsp->cargv)) == NULL)
- goto err;
- }
-
- /*
- * Copy the file state flags, start the file. Fill the child's
- * screen map. If the file is unchanged, keep the screen and
- * cursor the same.
- */
- if (argv == NULL) {
- tsp->ep = sp->ep;
- ++sp->ep->refcnt;
-
- tsp->frp->flags = sp->frp->flags;
- tsp->frp->lno = sp->lno;
- tsp->frp->cno = sp->cno;
- F_SET(tsp->frp, FR_CURSORSET);
-
- /* Copy the parent's map into the child's map. */
- memmove(_HMAP(tsp), _HMAP(sp), tsp->t_rows * sizeof(SMAP));
- } else {
- if (file_init(tsp, tsp->frp, NULL, 0))
- goto err;
- (void)svi_sm_fill(tsp, tsp->ep, 1, P_TOP);
- }
-
- /* Everything's initialized, put the screen on the displayed queue.*/
- if (splitup) {
- /* Link in before the parent. */
- CIRCLEQ_INSERT_BEFORE(&sp->gp->dq, sp, tsp, q);
- } else {
- /* Link in after the parent. */
- CIRCLEQ_INSERT_AFTER(&sp->gp->dq, sp, tsp, q);
- }
-
- /* Clear the current information lines in both screens. */
- MOVE(sp, INFOLINE(sp), 0);
- clrtoeol();
- MOVE(tsp, INFOLINE(tsp), 0);
- clrtoeol();
-
- /* Redraw the status line for the parent screen. */
- (void)msg_status(sp, sp->ep, sp->lno, 0);
-
- /* Save the parent screen's cursor information. */
- sp->frp->lno = sp->lno;
- sp->frp->cno = sp->cno;
- F_SET(sp->frp, FR_CURSORSET);
-
- /* Completely redraw the child screen. */
- F_SET(tsp, S_REDRAW);
-
- /* Switch screens. */
- sp->nextdisp = tsp;
- F_SET(sp, S_SSWITCH);
- return (0);
-
- /* Recover the original screen. */
-err: *sp = saved_sp;
- *SVP(sp) = saved_svp;
-
- /* Copy any (probably error) messages in the new screen. */
- for (mp = tsp->msgq.lh_first; mp != NULL; mp = next) {
- if (!F_ISSET(mp, M_EMPTY))
- msg_app(sp->gp, sp,
- mp->flags & M_INV_VIDEO, mp->mbuf, mp->len);
- next = mp->q.le_next;
- if (mp->mbuf != NULL)
- free(mp->mbuf);
- free(mp);
- }
-
- /* Free the new screen. */
- if (tsp->argv != NULL) {
- for (ap = tsp->argv; *ap != NULL; ++ap)
- free(*ap);
- free(tsp->argv);
- }
- free(_HMAP(tsp));
- free(SVP(tsp));
- FREE(tsp, sizeof(SCR));
- return (1);
-}
-
-/*
- * svi_bg --
- * Background the screen, and switch to the next one.
- */
-int
-svi_bg(csp)
- SCR *csp;
-{
- SCR *sp;
-
- /* Try and join with another screen. */
- if ((svi_join(csp, &sp)))
- return (1);
- if (sp == NULL) {
- msgq(csp, M_ERR,
- "You may not background your only displayed screen");
- return (1);
- }
-
- /* Move the old screen to the hidden queue. */
- CIRCLEQ_REMOVE(&csp->gp->dq, csp, q);
- CIRCLEQ_INSERT_TAIL(&csp->gp->hq, csp, q);
-
- /* Switch screens. */
- csp->nextdisp = sp;
- F_SET(csp, S_SSWITCH);
-
- return (0);
-}
-
-/*
- * svi_join --
- * Join the screen into a related screen, if one exists,
- * and return that screen.
- */
-int
-svi_join(csp, nsp)
- SCR *csp, **nsp;
-{
- SCR *sp;
- size_t cnt;
-
- /*
- * If a split screen, add space to parent/child. Make no effort
- * to clean up the screen's values. If it's not exiting, we'll
- * get it when the user asks to show it again.
- */
- if ((sp = csp->q.cqe_prev) == (void *)&csp->gp->dq) {
- if ((sp = csp->q.cqe_next) == (void *)&csp->gp->dq) {
- *nsp = NULL;
- return (0);
- }
- sp->woff = csp->woff;
- }
- sp->rows += csp->rows;
- if (ISSMALLSCREEN(sp)) {
- sp->t_maxrows += csp->rows;
- for (cnt = sp->t_rows; ++cnt <= sp->t_maxrows;) {
- MOVE(sp, cnt, 0);
- clrtoeol();
- }
- TMAP = HMAP + (sp->t_rows - 1);
- } else {
- sp->t_maxrows += csp->rows;
- sp->t_rows = sp->t_minrows = sp->t_maxrows;
- TMAP = HMAP + (sp->t_rows - 1);
- if (svi_sm_fill(sp, sp->ep, sp->lno, P_FILL))
- return (1);
- F_SET(sp, S_REDRAW);
- }
-
- /* Reset the length of the default scroll. */
- sp->defscroll = sp->t_maxrows / 2;
-
- /*
- * Save the old screen's cursor information.
- *
- * XXX
- * If called after file_end(), if the underlying file was a tmp
- * file it may have gone away.
- */
- if (csp->frp != NULL) {
- csp->frp->lno = csp->lno;
- csp->frp->cno = csp->cno;
- F_SET(csp->frp, FR_CURSORSET);
- }
-
- *nsp = sp;
- return (0);
-}
-
-/*
- * svi_fg --
- * Background the current screen, and foreground a new one.
- */
-int
-svi_fg(csp, name)
- SCR *csp;
- CHAR_T *name;
-{
- SCR *sp;
-
- if (svi_swap(csp, &sp, name))
- return (1);
- if (sp == NULL) {
- if (name == NULL)
- msgq(csp, M_ERR, "There are no background screens");
- else
- msgq(csp, M_ERR,
- "There's no background screen editing a file named %s",
- name);
- return (1);
- }
-
- /* Move the old screen to the hidden queue. */
- CIRCLEQ_REMOVE(&csp->gp->dq, csp, q);
- CIRCLEQ_INSERT_TAIL(&csp->gp->hq, csp, q);
-
- return (0);
-}
-
-/*
- * svi_swap --
- * Swap the current screen with a hidden one.
- */
-int
-svi_swap(csp, nsp, name)
- SCR *csp, **nsp;
- char *name;
-{
- SCR *sp;
- int issmallscreen;
-
- /* Find the screen, or, if name is NULL, the first screen. */
- for (sp = csp->gp->hq.cqh_first;
- sp != (void *)&csp->gp->hq; sp = sp->q.cqe_next)
- if (name == NULL || !strcmp(sp->frp->name, name))
- break;
- if (sp == (void *)&csp->gp->hq) {
- *nsp = NULL;
- return (0);
- }
- *nsp = sp;
-
- /*
- * Save the old screen's cursor information.
- *
- * XXX
- * If called after file_end(), if the underlying file was a tmp
- * file it may have gone away.
- */
- if (csp->frp != NULL) {
- csp->frp->lno = csp->lno;
- csp->frp->cno = csp->cno;
- F_SET(csp->frp, FR_CURSORSET);
- }
-
- /* Switch screens. */
- csp->nextdisp = sp;
- F_SET(csp, S_SSWITCH);
-
- /* Initialize terminal information. */
- SVP(sp)->srows = SVP(csp)->srows;
-
- issmallscreen = ISSMALLSCREEN(sp);
-
- /* Initialize screen information. */
- sp->rows = csp->rows;
- sp->cols = csp->cols;
- sp->woff = csp->woff;
-
- /*
- * Small screens: see svi/svi_refresh.c:svi_refresh, section 3b.
- *
- * The new screens may have different screen options sizes than the
- * old one, so use them. Make sure that text counts aren't larger
- * than the new screen sizes.
- */
- if (issmallscreen) {
- sp->t_minrows = sp->t_rows = O_VAL(sp, O_WINDOW);
- if (sp->t_rows > csp->t_maxrows)
- sp->t_rows = sp->t_maxrows;
- if (sp->t_minrows > csp->t_maxrows)
- sp->t_minrows = sp->t_maxrows;
- } else
- sp->t_rows = sp->t_maxrows = sp->t_minrows = sp->rows - 1;
-
- /* Reset the length of the default scroll. */
- sp->defscroll = sp->t_maxrows / 2;
-
- /*
- * Don't change the screen's cursor information other than to
- * note that the cursor is wrong.
- */
- F_SET(SVP(sp), SVI_CUR_INVALID);
-
- /*
- * The HMAP may be NULL, if the screen got resized and
- * a bunch of screens had to be hidden.
- */
- if (HMAP == NULL)
- CALLOC_RET(sp, HMAP, SMAP *, SIZE_HMAP(sp), sizeof(SMAP));
- TMAP = HMAP + (sp->t_rows - 1);
-
- /* Fill the map. */
- if (svi_sm_fill(sp, sp->ep, sp->lno, P_FILL))
- return (1);
-
- /*
- * The new screen replaces the old screen in the parent/child list.
- * We insert the new screen after the old one. If we're exiting,
- * the exit will delete the old one, if we're foregrounding, the fg
- * code will move the old one to the hidden queue.
- */
- CIRCLEQ_REMOVE(&sp->gp->hq, sp, q);
- CIRCLEQ_INSERT_AFTER(&csp->gp->dq, csp, sp, q);
-
- F_SET(sp, S_REDRAW);
- return (0);
-}
-
-/*
- * svi_rabs --
- * Change the absolute size of the current screen.
- */
-int
-svi_rabs(sp, count, adj)
- SCR *sp;
- long count;
- enum adjust adj;
-{
- SCR *g, *s;
-
- /*
- * Figure out which screens will grow, which will shrink, and
- * make sure it's possible.
- */
- if (count == 0)
- return (0);
- if (adj == A_SET) {
- if (sp->t_maxrows == count)
- return (0);
- if (sp->t_maxrows > count) {
- adj = A_DECREASE;
- count = sp->t_maxrows - count;
- } else {
- adj = A_INCREASE;
- count = count - sp->t_maxrows;
- }
- }
- if (adj == A_DECREASE) {
- if (count < 0)
- count = -count;
- s = sp;
- if (s->t_maxrows < MINIMUM_SCREEN_ROWS + count)
- goto toosmall;
- if ((g = sp->q.cqe_prev) == (void *)&sp->gp->dq) {
- if ((g = sp->q.cqe_next) == (void *)&sp->gp->dq)
- goto toobig;
- g->woff -= count;
- } else
- s->woff += count;
- } else {
- g = sp;
- if ((s = sp->q.cqe_next) != (void *)&sp->gp->dq)
- if (s->t_maxrows < MINIMUM_SCREEN_ROWS + count)
- s = NULL;
- else
- s->woff += count;
- else
- s = NULL;
- if (s == NULL) {
- if ((s = sp->q.cqe_prev) == (void *)&sp->gp->dq) {
-toobig: msgq(sp, M_BERR, "The screen cannot %s",
- adj == A_DECREASE ? "shrink" : "grow");
- return (1);
- }
- if (s->t_maxrows < MINIMUM_SCREEN_ROWS + count) {
-toosmall: msgq(sp, M_BERR,
- "The screen can only shrink to %d rows",
- MINIMUM_SCREEN_ROWS);
- return (1);
- }
- g->woff -= count;
- }
- }
-
- /*
- * Update the screens; we could optimize the reformatting of the
- * screen, but this isn't likely to be a common enough operation
- * to make it worthwhile.
- */
- g->rows += count;
- g->t_rows += count;
- if (g->t_minrows == g->t_maxrows)
- g->t_minrows += count;
- g->t_maxrows += count;
- _TMAP(g) += count;
- (void)msg_status(g, g->ep, g->lno, 0);
- F_SET(g, S_REFORMAT);
-
- s->rows -= count;
- s->t_rows -= count;
- s->t_maxrows -= count;
- if (s->t_minrows > s->t_maxrows)
- s->t_minrows = s->t_maxrows;
- _TMAP(s) -= count;
- (void)msg_status(s, s->ep, s->lno, 0);
- F_SET(s, S_REFORMAT);
-
- return (0);
-}
diff --git a/usr.bin/vi/svi/svi_term.c b/usr.bin/vi/svi/svi_term.c
deleted file mode 100644
index baedfa7f931f..000000000000
--- a/usr.bin/vi/svi/svi_term.c
+++ /dev/null
@@ -1,310 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)svi_term.c 8.5 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "../vi/vcmd.h"
-#include "excmd.h"
-#include "svi_screen.h"
-
-/*
- * XXX
- * THIS REQUIRES THAT ALL SCREENS SHARE A TERMINAL TYPE.
- */
-typedef struct _tklist {
- char *ts; /* Key's termcap string. */
- char *output; /* Corresponding vi command. */
- char *name; /* Name. */
- u_char value; /* Special value (for lookup). */
-} TKLIST;
-static TKLIST const c_tklist[] = { /* Command mappings. */
-#ifdef SYSV_CURSES
- {"kil1", "O", "insert line"},
- {"kdch1", "x", "delete character"},
- {"kcud1", "j", "cursor down"},
- {"kel", "D", "delete to eol"},
- {"kind", "\004", "scroll down"},
- {"kll", "$", "go to eol"},
- {"khome", "^", "go to sol"},
- {"kich1", "i", "insert at cursor"},
- {"kdl1", "dd", "delete line"},
- {"kcub1", "h", "cursor left"},
- {"knp", "\006", "page down"},
- {"kpp", "\002", "page up"},
- {"kri", "\025", "scroll up"},
- {"ked", "dG", "delete to end of screen"},
- {"kcuf1", "l", "cursor right"},
- {"kcuu1", "k", "cursor up"},
-#else
- {"kA", "O", "insert line"},
- {"kD", "x", "delete character"},
- {"kd", "j", "cursor down"},
- {"kE", "D", "delete to eol"},
- {"kF", "\004", "scroll down"},
- {"kH", "$", "go to eol"},
- {"kh", "^", "go to sol"},
- {"kI", "i", "insert at cursor"},
- {"kL", "dd", "delete line"},
- {"kl", "h", "cursor left"},
- {"kN", "\006", "page down"},
- {"kP", "\002", "page up"},
- {"kR", "\025", "scroll up"},
- {"kS", "dG", "delete to end of screen"},
- {"kr", "l", "cursor right"},
- {"ku", "k", "cursor up"},
-#endif
- {NULL},
-};
-static TKLIST const m1_tklist[] = { /* Input mappings (lookup). */
- {NULL},
-};
-static TKLIST const m2_tklist[] = { /* Input mappings (set or delete). */
-#ifdef SYSV_CURSES
- {"kcud1", "\033ja", "cursor down"},
- {"kcub1", "\033ha", "cursor left"},
- {"kcuu1", "\033ka", "cursor up"},
- {"kcuf1", "\033la", "cursor right"},
-#else
- {"kd", "\033ja", "cursor down"},
- {"kl", "\033ha", "cursor left"},
- {"ku", "\033ka", "cursor up"},
- {"kr", "\033la", "cursor right"},
-#endif
- {NULL},
-};
-
-/*
- * svi_term_init --
- * Initialize the special keys defined by the termcap/terminfo entry.
- */
-int
-svi_term_init(sp)
- SCR *sp;
-{
- KEYLIST *kp;
- SEQ *qp;
- TKLIST const *tkp;
- size_t len;
- char *sbp, *s, *t, sbuf[1024];
-
- /* Command mappings. */
- for (tkp = c_tklist; tkp->name != NULL; ++tkp) {
-#ifdef SYSV_CURSES
- if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
- continue;
-#else
- sbp = sbuf;
- if ((t = tgetstr(tkp->ts, &sbp)) == NULL)
- continue;
-#endif
- if (seq_set(sp, tkp->name, strlen(tkp->name), t, strlen(t),
- tkp->output, strlen(tkp->output), SEQ_COMMAND, SEQ_SCREEN))
- return (1);
- }
-
- /* Input mappings needing to be looked up. */
- for (tkp = m1_tklist; tkp->name != NULL; ++tkp) {
-#ifdef SYSV_CURSES
- if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
- continue;
-#else
- sbp = sbuf;
- if ((t = tgetstr(tkp->ts, &sbp)) == NULL)
- continue;
-#endif
- for (kp = keylist;; ++kp)
- if (kp->value == tkp->value)
- break;
- if (kp == NULL)
- continue;
- if (seq_set(sp, tkp->name, strlen(tkp->name),
- t, strlen(t), &kp->ch, 1, SEQ_INPUT, SEQ_SCREEN))
- return (1);
- }
-
- /* Input mappings that are already set or are text deletions. */
- for (tkp = m2_tklist; tkp->name != NULL; ++tkp) {
-#ifdef SYSV_CURSES
- if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
- continue;
-#else
- sbp = sbuf;
- if ((t = tgetstr(tkp->ts, &sbp)) == NULL)
- continue;
-#endif
- /*
- * !!!
- * Some terminals' <cursor_left> keys send single <backspace>
- * characters. This is okay in command mapping, but not okay
- * in input mapping. That combination is the only one we'll
- * ever see, hopefully, so kluge it here for now.
- */
- if (!strcmp(t, "\b"))
- continue;
- if (tkp->output == NULL) {
- if (seq_set(sp, tkp->name, strlen(tkp->name),
- t, strlen(t), NULL, 0, SEQ_INPUT, SEQ_SCREEN))
- return (1);
- } else
- if (seq_set(sp, tkp->name, strlen(tkp->name),
- t, strlen(t), tkp->output, strlen(tkp->output),
- SEQ_INPUT, SEQ_SCREEN))
- return (1);
- }
-
- /* Rework any function key mappings. */
- for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) {
- if (!F_ISSET(qp, SEQ_FUNCMAP))
- continue;
- (void)svi_fmap(sp, qp->stype,
- qp->input, qp->ilen, qp->output, qp->olen);
- }
-
- /* Set up the visual bell information. */
- t = sbuf;
- if (tgetstr("vb", &t) != NULL && (len = t - sbuf) != 0) {
- MALLOC_RET(sp, s, char *, len);
- memmove(s, sbuf, len);
- if (SVP(sp)->VB != NULL)
- free(SVP(sp)->VB);
- SVP(sp)->VB = s;
- return (0);
- }
-
- return (0);
-}
-
-/*
- * svi_term_end --
- * End the special keys defined by the termcap/terminfo entry.
- */
-int
-svi_term_end(sp)
- SCR *sp;
-{
- SEQ *qp, *nqp;
-
- /* Delete screen specific mappings. */
- for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = nqp) {
- nqp = qp->q.le_next;
- if (!F_ISSET(qp, SEQ_SCREEN))
- continue;
- (void)seq_mdel(qp);
- }
- return (0);
-}
-
-/*
- * svi_fmap --
- * Map a function key.
- */
-int
-svi_fmap(sp, stype, from, flen, to, tlen)
- SCR *sp;
- enum seqtype stype;
- CHAR_T *from, *to;
- size_t flen, tlen;
-{
- char *t, keyname[64];
- size_t nlen;
-
- /* If the terminal isn't initialized, there's nothing to do. */
- if (!F_ISSET(SVP(sp), SVI_CURSES_INIT))
- return (0);
-
-#ifdef SYSV_CURSES
- (void)snprintf(keyname, sizeof(keyname), "kf%d", atoi(from + 1));
- if ((t = tigetstr(keyname)) == NULL || t == (char *)-1)
- t = NULL;
-#else
- /*
- * !!!
- * Historically, the 4BSD termcap code didn't support functions keys
- * greater than 9. This was silently enforced -- asking for key k12
- * returned the value for k1. We try and get around this by using
- * the tables specified in the terminfo(TI_ENV) man page from the 3rd
- * Edition SVID. This assumes that the implementors of any System V
- * compatibility code or an extended termcap used those codes.
- */
- { int n; char *sbp, sbuf[1024];
- static const char codes[] = {
-/* 0-10 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';',
-/* 11-19 */ '1', '2', '3', '4', '5', '6', '7', '8', '9',
-/* 20-63 */ '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',
- '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',
- };
- if ((n = atoi(from + 1)) > 63) {
- msgq(sp, M_ERR,
- "Termcap has no code for the %s function key",
- from);
- return (1);
- }
- (void)snprintf(keyname, sizeof(keyname),
- "%c%c", n <= 10 ? 'k' : 'F', codes[n]);
- sbp = sbuf;
- t = tgetstr(keyname, &sbp);
- }
-#endif
- if (t == NULL) {
- msgq(sp, M_ERR, "This terminal has no %s key", from);
- return (1);
- }
- nlen = snprintf(keyname,
- sizeof(keyname), "function key %d", atoi(from + 1));
- return (seq_set(sp, keyname, nlen, t, strlen(t),
- to, tlen, stype, SEQ_SCREEN | SEQ_USERDEF));
-}
diff --git a/usr.bin/vi/svi/svi_util.c b/usr.bin/vi/svi/svi_util.c
deleted file mode 100644
index 5ba8b1e6e6a0..000000000000
--- a/usr.bin/vi/svi/svi_util.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)svi_util.c 8.53 (Berkeley) 8/12/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <curses.h>
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "../vi/vcmd.h"
-#include "excmd.h"
-#include "svi_screen.h"
-#include "../sex/sex_screen.h"
-
-/*
- * svi_bell --
- * Ring the bell.
- */
-void
-svi_bell(sp)
- SCR *sp;
-{
-#ifdef SYSV_CURSES
- if (O_ISSET(sp, O_FLASH))
- flash();
- else
- beep();
-#else
- if (O_ISSET(sp, O_FLASH) && SVP(sp)->VB != NULL) {
- (void)tputs(SVP(sp)->VB, 1, vi_putchar);
- (void)fflush(stdout);
- } else
- (void)write(STDOUT_FILENO, "\007", 1); /* '\a' */
-#endif
- F_CLR(sp, S_BELLSCHED);
-}
-
-/*
- * svi_optchange --
- * Screen specific "option changed" routine.
- */
-int
-svi_optchange(sp, opt)
- SCR *sp;
- int opt;
-{
- switch (opt) {
- case O_TERM:
- /* Toss any saved visual bell information. */
- if (SVP(sp)->VB != NULL) {
- FREE(SVP(sp)->VB, strlen(SVP(sp)->VB) + 1);
- SVP(sp)->VB = NULL;
- }
-
- /* Reset the screen size. */
- if (sp->s_window(sp, 0))
- return (1);
- F_SET(sp, S_RESIZE);
- break;
- case O_WINDOW:
- if (svi_crel(sp, O_VAL(sp, O_WINDOW)))
- return (1);
- break;
- }
-
- (void)v_optchange(sp, opt);
- (void)ex_optchange(sp, opt);
-
- return (0);
-}
-
-/*
- * svi_busy --
- * Put the cursor somewhere so the user will think we're busy.
- */
-int
-svi_busy(sp, msg)
- SCR *sp;
- char const *msg;
-{
- /*
- * search.c:f_search() is called from ex/ex_tag.c:ex_tagfirst(),
- * which runs before the screen really exists. Make sure we don't
- * step on anything.
- *
- * If the terminal isn't initialized, there's nothing to do.
- */
- if (!F_ISSET(SVP(sp), SVI_CURSES_INIT))
- return (0);
-
- MOVE(sp, INFOLINE(sp), 0);
- if (msg) {
- ADDSTR(msg);
- clrtoeol();
- }
- refresh();
- F_SET(SVP(sp), SVI_CUR_INVALID);
- return (0);
-}
-
-/*
- * svi_keypad --
- * Put the keypad/cursor arrows into or out of application mode.
- */
-void
-svi_keypad(sp, on)
- SCR *sp;
- int on;
-{
-#ifdef SYSV_CURSES
- keypad(stdscr, on ? TRUE : FALSE);
-#else
- char *sbp, *t, sbuf[128];
-
- sbp = sbuf;
- if ((t = tgetstr(on ? "ks" : "ke", &sbp)) == NULL)
- return;
- (void)tputs(t, 0, vi_putchar);
- (void)fflush(stdout);
-#endif
-}
-
-/*
- * svi_clear --
- * Clear from the row down to the end of the screen.
- */
-int
-svi_clear(sp)
- SCR *sp;
-{
- size_t oldy, oldx, row;
-
- getyx(stdscr, oldy, oldx);
- for (row = SVP(sp)->srows - 1; row >= oldy; --row) {
- MOVEA(sp, row, 0);
- clrtoeol();
- }
- MOVEA(sp, oldy, oldx);
- refresh();
- return (0);
-}
-
-/*
- * svi_suspend --
- * Suspend an svi screen.
- *
- * See signal.c for a long discussion of what's going on here. Let
- * me put it this way, it's NOT my fault.
- */
-int
-svi_suspend(sp)
- SCR *sp;
-{
- struct termios sv_term;
- sigset_t set;
- int oldx, oldy, rval;
- char *sbp, *t, sbuf[128];
-
- rval = 0;
-
- /*
- * Block SIGALRM, because vi uses timers to decide when to paint
- * busy messages on the screen.
- */
- (void)sigemptyset(&set);
- (void)sigaddset(&set, SIGALRM);
- if (sigprocmask(SIG_BLOCK, &set, NULL)) {
- msgq(sp, M_SYSERR, "suspend: sigblock");
- return (1);
- }
-
- /* Save the current cursor position. */
- getyx(stdscr, oldy, oldx);
-
- /*
- * Move the cursor to the bottom of the screen.
- *
- * XXX
- * Some curses implementations don't turn off inverse video when
- * standend() is called, waiting to see what the next character is
- * going to be, instead. Write a character to force inverse video
- * off, and then clear the line.
- */
- MOVE(sp, INFOLINE(sp), 0);
- ADDCH('.');
- refresh();
- MOVE(sp, INFOLINE(sp), 0);
- clrtoeol();
- refresh();
-
- /* Restore the cursor keys to normal mode. */
- svi_keypad(sp, 0);
-
- /* Send VE/TE. */
-#ifdef SYSV_CURSES
- if ((t = tigetstr("cnorm")) != NULL && t != (char *)-1)
- (void)tputs(t, 0, vi_putchar);
- if ((t = tigetstr("rmcup")) != NULL && t != (char *)-1)
- (void)tputs(t, 0, vi_putchar);
-#else
- sbp = sbuf;
- if ((t = tgetstr("ve", &sbp)) != NULL)
- (void)tputs(t, 0, vi_putchar);
- sbp = sbuf;
- if ((t = tgetstr("te", &sbp)) != NULL)
- (void)tputs(t, 0, vi_putchar);
-#endif
- (void)fflush(stdout);
-
- /* Save current terminal settings, and restore the original ones. */
- if (tcgetattr(STDIN_FILENO, &sv_term)) {
- msgq(sp, M_SYSERR, "suspend: tcgetattr");
- return (1);
- }
- if (tcsetattr(STDIN_FILENO,
- TCSASOFT | TCSADRAIN, &sp->gp->original_termios)) {
- msgq(sp, M_SYSERR, "suspend: tcsetattr original");
- return (1);
- }
-
- /* Push out any waiting messages. */
- (void)write(STDOUT_FILENO, "\n", 1);
- (void)sex_refresh(sp, sp->ep);
-
- /* Stop the process group. */
- if (kill(0, SIGTSTP)) {
- msgq(sp, M_SYSERR, "suspend: kill");
- rval = 1;
- }
-
- /* Time passes ... */
-
- /* Restore current terminal settings. */
- if (tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &sv_term)) {
- msgq(sp, M_SYSERR, "suspend: tcsetattr current");
- rval = 1;
- }
-
- /* Send TI/VS. */
-#ifdef SYSV_CURSES
- if ((t = tigetstr("smcup")) != NULL && t != (char *)-1)
- (void)tputs(t, 0, vi_putchar);
- if ((t = tigetstr("cvvis")) != NULL && t != (char *)-1)
- (void)tputs(t, 0, vi_putchar);
-#else
- sbp = sbuf;
- if ((t = tgetstr("ti", &sbp)) != NULL)
- (void)tputs(t, 0, vi_putchar);
- sbp = sbuf;
- if ((t = tgetstr("vs", &sbp)) != NULL)
- (void)tputs(t, 0, vi_putchar);
-#endif
- (void)fflush(stdout);
-
- /* Put the cursor keys into application mode. */
- svi_keypad(sp, 1);
-
- /*
- * If the screen changed size, do a full refresh. Otherwise,
- * System V has curses repaint it. 4BSD curses will repaint
- * it in the wrefresh() call below.
- */
- if (!sp->s_window(sp, 1))
- (void)sp->s_refresh(sp, sp->ep);
-#ifdef SYSV_CURSES
- else
- redrawwin(stdscr);
-#endif
-
- /*
- * Restore the cursor.
- *
- * !!!
- * Don't use MOVE/MOVEA, we don't want to return without resetting
- * the signals, regardless.
- */
- (void)move(oldy, oldx);
- (void)wrefresh(curscr);
-
- /* Reset the signals. */
- if (sigprocmask(SIG_UNBLOCK, &set, NULL)) {
- msgq(sp, M_SYSERR, "suspend: sigblock");
- rval = 1;
- }
- return (rval);
-}
-
-/*
- * svi_gdbrefresh --
- * Stub routine so can flush out screen changes using gdb.
- */
-#ifdef DEBUG
-int
-svi_gdbrefresh()
-{
- refresh();
- return (0);
-}
-#endif
diff --git a/usr.bin/vi/vi/v_delete.c b/usr.bin/vi/vi/v_delete.c
deleted file mode 100644
index aa2af9814e95..000000000000
--- a/usr.bin/vi/vi/v_delete.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_delete.c 8.14 (Berkeley) 7/28/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-/*
- * v_Delete -- [buffer][count]D
- * Delete line command.
- */
-int
-v_Delete(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t lno;
- size_t len;
-
- if (file_gline(sp, ep, vp->m_start.lno, &len) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno == 0)
- return (0);
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
-
- if (len == 0)
- return (0);
-
- vp->m_stop.lno = vp->m_start.lno;
- vp->m_stop.cno = len - 1;
-
- /* Yank the lines. */
- if (cut(sp, ep,
- F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
- &vp->m_start, &vp->m_stop, CUT_NUMOPT))
- return (1);
- if (delete(sp, ep, &vp->m_start, &vp->m_stop, 0))
- return (1);
-
- vp->m_final.lno = vp->m_start.lno;
- vp->m_final.cno = vp->m_start.cno ? vp->m_start.cno - 1 : 0;
- return (0);
-}
-
-/*
- * v_delete -- [buffer][count]d[count]motion
- * Delete a range of text.
- */
-int
-v_delete(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t nlines;
- size_t len;
- int lmode;
-
- lmode = F_ISSET(vp, VM_LMODE) ? CUT_LINEMODE : 0;
-
- /* Yank the lines. */
- if (cut(sp, ep, F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
- &vp->m_start, &vp->m_stop,
- lmode | (F_ISSET(vp, VM_CUTREQ) ? CUT_NUMREQ : CUT_NUMOPT)))
- return (1);
-
- /* Delete the lines. */
- if (delete(sp, ep, &vp->m_start, &vp->m_stop, lmode))
- return (1);
-
- /*
- * Check for deletion of the entire file. Try to check a close
- * by line so we don't go to the end of the file unnecessarily.
- */
- if (file_gline(sp, ep, vp->m_final.lno + 1, &len) == NULL) {
- if (file_lline(sp, ep, &nlines))
- return (1);
- if (nlines == 0) {
- vp->m_final.lno = 1;
- vp->m_final.cno = 0;
- return (0);
- }
- }
-
- /*
- * One special correction, in case we've deleted the current line or
- * character. We check it here instead of checking in every command
- * that can be a motion component.
- */
- if (file_gline(sp, ep, vp->m_final.lno, &len) == NULL) {
- if (file_gline(sp, ep, nlines, &len) == NULL) {
- GETLINE_ERR(sp, nlines);
- return (1);
- }
- vp->m_final.lno = nlines;
- }
- if (vp->m_final.cno >= len)
- vp->m_final.cno = len ? len - 1 : 0;
-
- /*
- * !!!
- * The "dd" command moved to the first non-blank; "d<motion>" didn't.
- */
- if (F_ISSET(vp, VM_LDOUBLE)) {
- F_CLR(vp, VM_RCM_MASK);
- F_SET(vp, VM_RCM_SETFNB);
- }
- return (0);
-}
diff --git a/usr.bin/vi/vi/v_ex.c b/usr.bin/vi/vi/v_ex.c
deleted file mode 100644
index 6481b407d002..000000000000
--- a/usr.bin/vi/vi/v_ex.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_ex.c 8.10 (Berkeley) 8/4/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-#include "vcmd.h"
-
-static void excmd __P((EXCMDARG *,
- int, int, recno_t, recno_t, int, ARGS *[], ARGS *, char *));
-
-/*
- * v_again -- &
- * Repeat the previous substitution.
- */
-int
-v_again(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- ARGS *ap[2], a;
- EXCMDARG cmd;
-
- excmd(&cmd, C_SUBAGAIN,
- 2, vp->m_start.lno, vp->m_start.lno, 1, ap, &a, "");
- return (sp->s_ex_cmd(sp, ep, &cmd, &vp->m_final));
-}
-
-/*
- * v_at -- @
- * Execute a buffer.
- */
-int
-v_at(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- ARGS *ap[2], a;
- EXCMDARG cmd;
-
- excmd(&cmd, C_AT, 0, OOBLNO, OOBLNO, 0, ap, &a, NULL);
- if (F_ISSET(vp, VC_BUFFER)) {
- F_SET(&cmd, E_BUFFER);
- cmd.buffer = vp->buffer;
- }
- return (sp->s_ex_cmd(sp, ep, &cmd, &vp->m_final));
-}
-
-/*
- * v_ex -- :
- * Execute a colon command line.
- */
-int
-v_ex(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- return (sp->s_ex_run(sp, ep, &vp->m_final));
-}
-
-/*
- * v_exmode -- Q
- * Switch the editor into EX mode.
- */
-int
-v_exmode(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- /* Save the current line/column number. */
- sp->frp->lno = sp->lno;
- sp->frp->cno = sp->cno;
- F_SET(sp->frp, FR_CURSORSET);
-
- /* Switch to ex mode. */
- sp->saved_vi_mode = F_ISSET(sp, S_VI_CURSES | S_VI_XAW);
- F_CLR(sp, S_SCREENS);
- F_SET(sp, S_EX);
- return (0);
-}
-
-/*
- * v_filter -- [count]!motion command(s)
- * Run range through shell commands, replacing text.
- */
-int
-v_filter(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- ARGS *ap[2], a;
- EXCMDARG cmd;
- TEXT *tp;
-
- /*
- * !!!
- * Historical vi permitted "!!" in an empty file, and it's handled
- * as a special case in the ex_bang routine. Don't modify this setup
- * without understanding that one. In particular, note that we're
- * manipulating the ex argument structures behind ex's back.
- *
- * !!!
- * Historical vi did not permit the '!' command to be associated with
- * a non-line oriented motion command, in general, although it did
- * with search commands. So, !f; and !w would fail, but !/;<CR>
- * would succeed, even if they all moved to the same location in the
- * current line. I don't see any reason to disallow '!' using any of
- * the possible motion commands.
- */
- excmd(&cmd, C_BANG,
- 2, vp->m_start.lno, vp->m_stop.lno, 0, ap, &a, NULL);
- EXP(sp)->argsoff = 0; /* XXX */
- if (F_ISSET(vp, VC_ISDOT)) {
- if (argv_exp1(sp, ep, &cmd, "!", 1, 1))
- return (1);
- } else {
- /* Get the command from the user. */
- if (sp->s_get(sp, ep, sp->tiqp,
- '!', TXT_BS | TXT_CR | TXT_ESCAPE | TXT_PROMPT) != INP_OK)
- return (1);
- /*
- * Len is 0 if backspaced over the prompt,
- * 1 if only CR entered.
- */
- tp = sp->tiqp->cqh_first;
- if (tp->len <= 1)
- return (0);
-
- if (argv_exp1(sp, ep, &cmd, tp->lb + 1, tp->len - 1, 1))
- return (1);
- }
- cmd.argc = EXP(sp)->argsoff; /* XXX */
- cmd.argv = EXP(sp)->args; /* XXX */
- return (sp->s_ex_cmd(sp, ep, &cmd, &vp->m_final));
-}
-
-/*
- * v_join -- [count]J
- * Join lines together.
- */
-int
-v_join(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- ARGS *ap[2], a;
- EXCMDARG cmd;
- int lno;
-
- /*
- * YASC.
- * The general rule is that '#J' joins # lines, counting the current
- * line. However, 'J' and '1J' are the same as '2J', i.e. join the
- * current and next lines. This doesn't map well into the ex command
- * (which takes two line numbers), so we handle it here. Note that
- * we never test for EOF -- historically going past the end of file
- * worked just fine.
- */
- lno = vp->m_start.lno + 1;
- if (F_ISSET(vp, VC_C1SET) && vp->count > 2)
- lno = vp->m_start.lno + (vp->count - 1);
-
- excmd(&cmd, C_JOIN, 2, vp->m_start.lno, lno, 0, ap, &a, NULL);
- return (sp->s_ex_cmd(sp, ep, &cmd, &vp->m_final));
-}
-
-/*
- * v_shiftl -- [count]<motion
- * Shift lines left.
- */
-int
-v_shiftl(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- ARGS *ap[2], a;
- EXCMDARG cmd;
-
- excmd(&cmd, C_SHIFTL,
- 2, vp->m_start.lno, vp->m_stop.lno, 0, ap, &a, "<");
- return (sp->s_ex_cmd(sp, ep, &cmd, &vp->m_final));
-}
-
-/*
- * v_shiftr -- [count]>motion
- * Shift lines right.
- */
-int
-v_shiftr(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- ARGS *ap[2], a;
- EXCMDARG cmd;
-
- excmd(&cmd, C_SHIFTR,
- 2, vp->m_start.lno, vp->m_stop.lno, 0, ap, &a, ">");
- return (sp->s_ex_cmd(sp, ep, &cmd, &vp->m_final));
-}
-
-/*
- * v_switch -- ^^
- * Switch to the previous file.
- */
-int
-v_switch(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- ARGS *ap[2], a;
- EXCMDARG cmd;
- char *name;
-
- /*
- * Try the alternate file name, then the previous file
- * name. Use the real name, not the user's current name.
- */
- if ((name = sp->alt_name) == NULL) {
- msgq(sp, M_ERR, "No previous file to edit");
- return (1);
- }
-
- /* If autowrite is set, write out the file. */
- if (file_m1(sp, ep, 0, FS_ALL))
- return (1);
-
- excmd(&cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0, ap, &a, name);
- return (sp->s_ex_cmd(sp, ep, &cmd, &vp->m_final));
-}
-
-/*
- * v_tagpush -- ^[
- * Do a tag search on a the cursor keyword.
- */
-int
-v_tagpush(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- ARGS *ap[2], a;
- EXCMDARG cmd;
-
- excmd(&cmd, C_TAG, 0, OOBLNO, 0, 0, ap, &a, vp->keyword);
- return (sp->s_ex_cmd(sp, ep, &cmd, &vp->m_final));
-}
-
-/*
- * v_tagpop -- ^T
- * Pop the tags stack.
- */
-int
-v_tagpop(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- ARGS *ap[2], a;
- EXCMDARG cmd;
-
- excmd(&cmd, C_TAGPOP, 0, OOBLNO, 0, 0, ap, &a, NULL);
- return (sp->s_ex_cmd(sp, ep, &cmd, &vp->m_final));
-}
-
-/*
- * excmd --
- * Build an EX command structure.
- */
-static void
-excmd(cmdp, cmd_id, naddr, lno1, lno2, force, ap, a, arg)
- EXCMDARG *cmdp;
- int cmd_id, force, naddr;
- recno_t lno1, lno2;
- ARGS *ap[2], *a;
- char *arg;
-{
- memset(cmdp, 0, sizeof(EXCMDARG));
- cmdp->cmd = &cmds[cmd_id];
- cmdp->addrcnt = naddr;
- cmdp->addr1.lno = lno1;
- cmdp->addr2.lno = lno2;
- cmdp->addr1.cno = cmdp->addr2.cno = 1;
- if (force)
- cmdp->flags |= E_FORCE;
- if ((a->bp = arg) == NULL) {
- cmdp->argc = 0;
- a->len = 0;
- } else {
- cmdp->argc = 1;
- a->len = strlen(arg);
- }
- ap[0] = a;
- ap[1] = NULL;
- cmdp->argv = ap;
-}
diff --git a/usr.bin/vi/vi/v_increment.c b/usr.bin/vi/vi/v_increment.c
deleted file mode 100644
index 6961953276dc..000000000000
--- a/usr.bin/vi/vi/v_increment.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_increment.c 8.9 (Berkeley) 5/21/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-static char * const fmt[] = {
-#define DEC 0
- "%ld",
-#define SDEC 1
- "%+ld",
-#define HEXC 2
- "%#0.*lX",
-#define HEXL 3
- "%#0.*lx",
-#define OCTAL 4
- "%#0.*lo",
-};
-
-/*
- * v_increment -- [count]#[#+-]
- * Increment/decrement a keyword number.
- */
-int
-v_increment(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- VI_PRIVATE *vip;
- u_long ulval;
- long lval;
- size_t blen, len, nlen;
- int rval;
- char *bp, *ntype, *p, nbuf[100];
-
- vip = VIP(sp);
-
- /* Do repeat operations. */
- if (vp->character == '#')
- vp->character = vip->inc_lastch;
-
- /* Get new value. */
- if (F_ISSET(vp, VC_C1SET))
- vip->inc_lastval = vp->count;
-
- if (vp->character != '+' && vp->character != '-') {
- msgq(sp, M_ERR, "usage: %s", vp->kp->usage);
- return (1);
- }
- vip->inc_lastch = vp->character;
-
- /* Figure out the resulting type and number. */
- p = vp->keyword;
- len = vp->klen;
- if (len > 1 && p[0] == '0') {
- if (vp->character == '+') {
- ulval = strtoul(vp->keyword, NULL, 0);
- if (ULONG_MAX - ulval < vip->inc_lastval)
- goto overflow;
- ulval += vip->inc_lastval;
- } else {
- ulval = strtoul(vp->keyword, NULL, 0);
- if (ulval < vip->inc_lastval)
- goto underflow;
- ulval -= vip->inc_lastval;
- }
- ntype = fmt[OCTAL];
- if (len > 2)
- if (p[1] == 'X')
- ntype = fmt[HEXC];
- else if (p[1] == 'x')
- ntype = fmt[HEXL];
- nlen = snprintf(nbuf, sizeof(nbuf), ntype, len, ulval);
- } else {
- if (vp->character == '+') {
- lval = strtol(vp->keyword, NULL, 0);
- if (lval > 0 && LONG_MAX - lval < vip->inc_lastval) {
-overflow: msgq(sp, M_ERR, "Resulting number too large");
- return (1);
- }
- lval += vip->inc_lastval;
- } else {
- lval = strtol(vp->keyword, NULL, 0);
- if (lval < 0 && -(LONG_MIN - lval) < vip->inc_lastval) {
-underflow: msgq(sp, M_ERR, "Resulting number too small");
- return (1);
- }
- lval -= vip->inc_lastval;
- }
- ntype = lval != 0 &&
- (*vp->keyword == '+' || *vp->keyword == '-') ?
- fmt[SDEC] : fmt[DEC];
- nlen = snprintf(nbuf, sizeof(nbuf), ntype, lval);
- }
-
- if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) {
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
-
- GET_SPACE_RET(sp, bp, blen, len + nlen);
- memmove(bp, p, vp->m_start.cno);
- memmove(bp + vp->m_start.cno, nbuf, nlen);
- memmove(bp + vp->m_start.cno + nlen,
- p + vp->m_start.cno + vp->klen, len - vp->m_start.cno - vp->klen);
- len = len - vp->klen + nlen;
-
- rval = file_sline(sp, ep, vp->m_start.lno, bp, len);
- FREE_SPACE(sp, bp, blen);
- return (rval);
-}
diff --git a/usr.bin/vi/vi/v_init.c b/usr.bin/vi/vi/v_init.c
deleted file mode 100644
index 069733ce1b23..000000000000
--- a/usr.bin/vi/vi/v_init.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_init.c 8.26 (Berkeley) 8/8/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-#include "excmd.h"
-
-static int v_comment __P((SCR *, EXF *));
-
-/*
- * v_screen_copy --
- * Copy vi screen.
- */
-int
-v_screen_copy(orig, sp)
- SCR *orig, *sp;
-{
- VI_PRIVATE *ovip, *nvip;
-
- /* Create the private vi structure. */
- CALLOC_RET(orig, nvip, VI_PRIVATE *, 1, sizeof(VI_PRIVATE));
- sp->vi_private = nvip;
-
- if (orig == NULL) {
- nvip->inc_lastch = '+';
- nvip->inc_lastval = 1;
- nvip->csearchdir = CNOTSET;
- } else {
- ovip = VIP(orig);
-
- /* User can replay the last input, but nothing else. */
- if (ovip->rep_len != 0) {
- MALLOC(orig, nvip->rep, char *, ovip->rep_len);
- if (nvip->rep != NULL) {
- memmove(nvip->rep, ovip->rep, ovip->rep_len);
- nvip->rep_len = ovip->rep_len;
- }
- }
-
- nvip->inc_lastch = ovip->inc_lastch;
- nvip->inc_lastval = ovip->inc_lastval;
-
- if (ovip->ps != NULL &&
- (nvip->ps = strdup(ovip->ps)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- return (1);
- }
-
- nvip->lastckey = ovip->lastckey;
- nvip->csearchdir = ovip->csearchdir;
- }
- return (0);
-}
-
-/*
- * v_screen_end --
- * End a vi screen.
- */
-int
-v_screen_end(sp)
- SCR *sp;
-{
- VI_PRIVATE *vip;
-
- vip = VIP(sp);
-
- if (vip->rep != NULL)
- free(vip->rep);
-
- if (vip->ps != NULL)
- free(vip->ps);
-
- /* Free private memory. */
- FREE(vip, sizeof(VI_PRIVATE));
- sp->vi_private = NULL;
-
- return (0);
-}
-
-/*
- * v_init --
- * Initialize vi.
- */
-int
-v_init(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- size_t len;
-
- /*
- * The default address is line 1, column 0. If the address set
- * bit is on for this file, load the address, ensuring that it
- * exists.
- */
- if (F_ISSET(sp->frp, FR_CURSORSET)) {
- sp->lno = sp->frp->lno;
- sp->cno = sp->frp->cno;
-
- if (file_gline(sp, ep, sp->lno, &len) == NULL) {
- if (sp->lno != 1 || sp->cno != 0) {
- if (file_lline(sp, ep, &sp->lno))
- return (1);
- if (sp->lno == 0)
- sp->lno = 1;
- sp->cno = 0;
- }
- } else if (sp->cno >= len)
- sp->cno = 0;
-
- if (F_ISSET(sp->frp, FR_FNONBLANK)) {
- sp->cno = 0;
- if (nonblank(sp, ep, sp->lno, &sp->cno))
- return (1);
-
- /* Reset strange attraction. */
- sp->rcm = 0;
- sp->rcm_last = 0;
- }
- } else {
- sp->lno = 1;
- sp->cno = 0;
-
- if (O_ISSET(sp, O_COMMENT) && v_comment(sp, ep))
- return (1);
-
- /* Vi always starts up on the first non-<blank>. */
- if (nonblank(sp, ep, sp->lno, &sp->cno))
- return (1);
-
- /* Reset strange attraction. */
- sp->rcm = 0;
- sp->rcm_last = 0;
- }
-
- /* Make ex display to a special function. */
- if ((sp->stdfp = fwopen(sp, sp->s_ex_write)) == NULL) {
- msgq(sp, M_SYSERR, "ex output");
- return (1);
- }
-#ifdef MAKE_EX_OUTPUT_LINE_BUFFERED
- (void)setvbuf(sp->stdfp, NULL, _IOLBF, 0);
-#endif
-
- /* Display the status line. */
- return (msg_status(sp, ep, sp->lno, 0));
-}
-
-/*
- * v_end --
- * End vi session.
- */
-int
-v_end(sp)
- SCR *sp;
-{
- /* Close down ex output file descriptor. */
- (void)fclose(sp->stdfp);
-
- return (0);
-}
-
-/*
- * v_optchange --
- * Handle change of options for vi.
- */
-int
-v_optchange(sp, opt)
- SCR *sp;
- int opt;
-{
- switch (opt) {
- case O_PARAGRAPHS:
- case O_SECTIONS:
- return (v_buildps(sp));
- }
- return (0);
-}
-
-/*
- * v_comment --
- * Skip the first comment.
- */
-static int
-v_comment(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- recno_t lno;
- size_t len;
- char *p;
-
- for (lno = 1;
- (p = file_gline(sp, ep, lno, &len)) != NULL && len == 0; ++lno);
- if (p == NULL || len <= 1 || memcmp(p, "/*", 2))
- return (0);
- do {
- for (; len; --len, ++p)
- if (p[0] == '*' && len > 1 && p[1] == '/') {
- sp->lno = lno;
- return (0);
- }
- } while ((p = file_gline(sp, ep, ++lno, &len)) != NULL);
- return (0);
-}
diff --git a/usr.bin/vi/vi/v_left.c b/usr.bin/vi/vi/v_left.c
deleted file mode 100644
index ec57d9143091..000000000000
--- a/usr.bin/vi/vi/v_left.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_left.c 8.9 (Berkeley) 7/27/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-/*
- * v_left -- [count]^H, [count]h
- * Move left by columns.
- */
-int
-v_left(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t cnt;
-
- /*
- * !!!
- * The ^H and h commands always failed in the first column.
- */
- if (vp->m_start.cno == 0) {
- v_sol(sp);
- return (1);
- }
-
- /* Find the end of the range. */
- cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
- if (vp->m_start.cno > cnt)
- vp->m_stop.cno = vp->m_start.cno - cnt;
- else
- vp->m_stop.cno = 0;
-
- /*
- * VC_D and non-motion commands move to the end of the range,
- * VC_Y stays at the start. Ignore VC_C and VC_DEF. Motion
- * commands adjust the starting point to the character before
- * the current one.
- */
- vp->m_final = F_ISSET(vp, VC_Y) ? vp->m_start : vp->m_stop;
- if (ISMOTION(vp))
- --vp->m_start.cno;
- return (0);
-}
-
-/*
- * v_cfirst -- [count]_
- * Move to the first non-blank character in a line.
- */
-int
-v_cfirst(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t cnt;
-
- /*
- * !!!
- * If the _ is a motion component, it makes the command a line motion
- * e.g. "d_" deletes the line. It also means that the cursor doesn't
- * move.
- *
- * The _ command never failed in the first column.
- */
- if (ISMOTION(vp))
- F_SET(vp, VM_LMODE);
- /*
- * !!!
- * Historically a specified count makes _ move down count - 1
- * rows, so, "3_" is the same as "2j_".
- */
- cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
- if (cnt != 1) {
- --vp->count;
- return (v_down(sp, ep, vp));
- }
-
- /*
- * Move to the first non-blank.
- *
- * Can't just use RCM_SET_FNB, in case _ is used as the motion
- * component of another command.
- */
- vp->m_stop.cno = 0;
- if (nonblank(sp, ep, vp->m_stop.lno, &vp->m_stop.cno))
- return (1);
-
- /*
- * VC_D and non-motion commands move to the end of the range,
- * VC_Y stays at the start. Ignore VC_C and VC_DEF.
- */
- vp->m_final = F_ISSET(vp, VC_Y) ? vp->m_start : vp->m_stop;
- return (0);
-}
-
-/*
- * v_first -- ^
- * Move to the first non-blank character in this line.
- */
-int
-v_first(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- /*
- * !!!
- * Yielding to none in our quest for compatibility with every
- * historical blemish of vi, no matter how strange it might be,
- * we permit the user to enter a count and then ignore it.
- */
-
- /*
- * Move to the first non-blank.
- *
- * Can't just use RCM_SET_FNB, in case ^ is used as the motion
- * component of another command.
- */
- vp->m_stop.cno = 0;
- if (nonblank(sp, ep, vp->m_stop.lno, &vp->m_stop.cno))
- return (1);
-
- /*
- * !!!
- * The ^ command succeeded if used as a command without a whitespace
- * character preceding the cursor in the line, but failed if used as
- * a motion component in the same situation.
- */
- if (ISMOTION(vp) && vp->m_start.cno <= vp->m_stop.cno) {
- v_sol(sp);
- return (1);
- }
-
- /*
- * VC_D and non-motion commands move to the end of the range,
- * VC_Y stays at the start. Ignore VC_C and VC_DEF. Motion
- * commands adjust the starting point to the character before
- * the current one.
- */
- vp->m_final = F_ISSET(vp, VC_Y) ? vp->m_start : vp->m_stop;
- if (ISMOTION(vp))
- --vp->m_start.cno;
- return (0);
-}
-
-/*
- * v_ncol -- [count]|
- * Move to column count or the first column on this line. If the
- * requested column is past EOL, move to EOL. The nasty part is
- * that we have to know character column widths to make this work.
- */
-int
-v_ncol(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- if (F_ISSET(vp, VC_C1SET) && vp->count > 1) {
- --vp->count;
- vp->m_stop.cno =
- sp->s_colpos(sp, ep, vp->m_start.lno, (size_t)vp->count);
- /*
- * !!!
- * The | command succeeded if used as a command and the cursor
- * didn't move, but failed if used as a motion component in the
- * same situation.
- */
- if (ISMOTION(vp) && vp->m_stop.cno == vp->m_start.cno) {
- v_nomove(sp);
- return (1);
- }
- } else {
- /*
- * !!!
- * The | command succeeded if used as a command in column 0
- * without a count, but failed if used as a motion component
- * in the same situation.
- */
- if (ISMOTION(vp) && vp->m_start.cno == 0) {
- v_sol(sp);
- return (1);
- }
- vp->m_stop.cno = 0;
- }
-
- /*
- * If moving right, non-motion commands move to the end of the range.
- * VC_D and VC_Y stay at the start. If moving left, non-motion and
- * VC_D commands move to the end of the range. VC_Y remains at the
- * start. Ignore VC_C and VC_DEF. Motion left commands adjust the
- * starting point to the character before the current one.
- */
- if (vp->m_start.cno < vp->m_stop.cno)
- vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
- else {
- vp->m_final = vp->m_stop;
- if (ISMOTION(vp)) {
- if (F_ISSET(vp, VC_Y))
- vp->m_final = vp->m_start;
- --vp->m_start.cno;
- }
- }
- return (0);
-}
-
-/*
- * v_zero -- 0
- * Move to the first column on this line.
- */
-int
-v_zero(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- /*
- * !!!
- * The 0 command succeeded if used as a command in the first column
- * but failed if used as a motion component in the same situation.
- */
- if (ISMOTION(vp) && vp->m_start.cno == 0) {
- v_sol(sp);
- return (1);
- }
-
- /*
- * VC_D and non-motion commands move to the end of the range,
- * VC_Y stays at the start. Ignore VC_C and VC_DEF. Motion
- * commands adjust the starting point to the character before
- * the current one.
- */
- vp->m_stop.cno = 0;
- vp->m_final = F_ISSET(vp, VC_Y) ? vp->m_start : vp->m_stop;
- if (ISMOTION(vp))
- --vp->m_start.cno;
- return (0);
-}
diff --git a/usr.bin/vi/vi/v_mark.c b/usr.bin/vi/vi/v_mark.c
deleted file mode 100644
index 66dda1a7ff59..000000000000
--- a/usr.bin/vi/vi/v_mark.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_mark.c 8.8 (Berkeley) 7/27/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-/*
- * v_mark -- m[a-z]
- * Set a mark.
- */
-int
-v_mark(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- return (mark_set(sp, ep, vp->character, &vp->m_start, 1));
-}
-
-enum which {BMARK, FMARK};
-static int mark __P((SCR *, EXF *, VICMDARG *, enum which));
-
-
-/*
- * v_bmark -- `['`a-z]
- * Move to a mark.
- *
- * Moves to a mark, setting both row and column.
- *
- * !!!
- * Although not commonly known, the "'`" and "'`" forms are historically
- * valid. The behavior is determined by the first character, so "`'" is
- * the same as "``". Remember this fact -- you'll be amazed at how many
- * people don't know it and will be delighted that you are able to tell
- * them.
- */
-int
-v_bmark(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- return (mark(sp, ep, vp, BMARK));
-}
-
-/*
- * v_fmark -- '['`a-z]
- * Move to a mark.
- *
- * Move to the first nonblank character of the line containing the mark.
- */
-int
-v_fmark(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- return (mark(sp, ep, vp, FMARK));
-}
-
-static int
-mark(sp, ep, vp, cmd)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
- enum which cmd;
-{
- MARK m;
- size_t len;
- enum direction dir;
-
- if (mark_get(sp, ep, vp->character, &vp->m_stop))
- return (1);
-
- /* Forward marks move to the first non-blank. */
- if (cmd == FMARK) {
- vp->m_stop.cno = 0;
- if (nonblank(sp, ep, vp->m_stop.lno, &vp->m_stop.cno))
- return (1);
- }
-
- /* Non-motion commands move to the end of the range. */
- if (!ISMOTION(vp)) {
- vp->m_final = vp->m_stop;
- return (0);
- }
-
- /*
- * !!!
- * If a motion component, the cursor has to move.
- */
- if (vp->m_stop.lno == vp->m_start.lno &&
- vp->m_stop.cno == vp->m_start.cno) {
- v_nomove(sp);
- return (1);
- }
-
- /*
- * If the motion is in the reverse direction, switch the start and
- * stop MARK's so that it's in a forward direction. (There's no
- * reason for this other than to make the tests below easier. The
- * code in vi.c:vi() would have done the switch.) Both forward
- * and backward motions can happen for either kind of mark command.
- */
- if (vp->m_start.lno > vp->m_stop.lno ||
- vp->m_start.lno == vp->m_stop.lno &&
- vp->m_start.cno > vp->m_stop.cno) {
- dir = BACKWARD;
- m = vp->m_start;
- vp->m_start = vp->m_stop;
- vp->m_stop = m;
- } else
- dir = FORWARD;
-
- /*
- * BACKWARD:
- * VC_D commands move to the end of the range. VC_Y stays at
- * the start unless the end of the range is on a different line,
- * when it moves to the end of the range. Ignore VC_C and
- * VC_DEF.
- *
- * FORWARD:
- * VC_D and VC_Y commands don't move. Ignore VC_C and VC_DEF.
- */
- if (dir == BACKWARD)
- if (F_ISSET(vp, VC_D) ||
- F_ISSET(vp, VC_Y) && vp->m_start.lno != vp->m_stop.lno)
- vp->m_final = vp->m_start;
- else
- vp->m_final = vp->m_stop;
- else
- vp->m_final = vp->m_start;
-
- if (cmd == FMARK)
- return (0);
-
- /*
- * Forward marks are always line oriented, and it's set in the
- * vcmd.c table. Backward marks that start and stop at column
- * 0 of the line are also line mode commands.
- */
- if (vp->m_start.cno == 0 && vp->m_stop.cno == 0)
- F_SET(vp, VM_LMODE);
-
- /*
- * BMARK'S that move backward and start at column 0, or move forward
- * and end at column 0 are corrected to the last column of the previous
- * line. Else, adjust the starting/ending point to the character
- * before the current one (this is safe because we know the command had
- * to move to succeed).
- */
- if (vp->m_start.lno < vp->m_stop.lno && vp->m_stop.cno == 0) {
- if (file_gline(sp, ep, --vp->m_stop.lno, &len) == NULL) {
- GETLINE_ERR(sp, vp->m_stop.lno);
- return (1);
- }
- vp->m_stop.cno = len ? len - 1 : 0;
- } else
- --vp->m_stop.cno;
-
- return (0);
-}
diff --git a/usr.bin/vi/vi/v_match.c b/usr.bin/vi/vi/v_match.c
deleted file mode 100644
index b047a4431747..000000000000
--- a/usr.bin/vi/vi/v_match.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_match.c 8.14 (Berkeley) 7/27/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-/*
- * v_match -- %
- * Search to matching character.
- */
-int
-v_match(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- VCS cs;
- MARK *mp;
- recno_t lno;
- size_t cno, len, off;
- int cnt, matchc, startc, (*gc)__P((SCR *, EXF *, VCS *));
- char *p;
-
- /*
- * !!!
- * Historic practice; ignore the count.
- */
- if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno == 0)
- goto nomatch;
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
-
- /*
- * !!!
- * Historical practice was to search for the initial character
- * in the forward direction only.
- */
- for (off = vp->m_start.cno;; ++off) {
- if (off >= len) {
-nomatch: msgq(sp, M_BERR, "No match character on this line");
- return (1);
- }
- switch (startc = p[off]) {
- case '(':
- matchc = ')';
- gc = cs_next;
- break;
- case ')':
- matchc = '(';
- gc = cs_prev;
- break;
- case '[':
- matchc = ']';
- gc = cs_next;
- break;
- case ']':
- matchc = '[';
- gc = cs_prev;
- break;
- case '{':
- matchc = '}';
- gc = cs_next;
- break;
- case '}':
- matchc = '{';
- gc = cs_prev;
- break;
- default:
- continue;
- }
- break;
- }
-
- cs.cs_lno = vp->m_start.lno;
- cs.cs_cno = off;
- if (cs_init(sp, ep, &cs))
- return (1);
- for (cnt = 1;;) {
- if (gc(sp, ep, &cs))
- return (1);
- if (cs.cs_flags != 0) {
- if (cs.cs_flags == CS_EOF || cs.cs_flags == CS_SOF)
- break;
- continue;
- }
- if (cs.cs_ch == startc)
- ++cnt;
- else if (cs.cs_ch == matchc && --cnt == 0)
- break;
- }
- if (cnt) {
- msgq(sp, M_BERR, "Matching character not found");
- return (1);
- }
-
- vp->m_stop.lno = cs.cs_lno;
- vp->m_stop.cno = cs.cs_cno;
-
- /*
- * If moving right, non-motion commands move to the end of the range.
- * VC_D and VC_Y stay at the start. If moving left, non-motion and
- * VC_D commands move to the end of the range. VC_Y remains at the
- * start. Ignore VC_C and VC_DEF.
- *
- * !!!
- * Don't correct for leftward movement -- historic vi deleted the
- * starting cursor position when deleting to a match.
- */
- if (vp->m_start.lno < vp->m_stop.lno ||
- vp->m_start.lno == vp->m_stop.lno &&
- vp->m_start.cno < vp->m_stop.cno)
- vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
- else
- vp->m_final = ISMOTION(vp) &&
- F_ISSET(vp, VC_Y) ? vp->m_start : vp->m_stop;
-
- /*
- * !!!
- * If the motion is across lines, and the earliest cursor position
- * is at or before any non-blank characters in the line, i.e. the
- * movement is cutting all of the line's text, and the later cursor
- * position has nothing other than whitespace characters between it
- * and the end of its line, the buffer is in line mode.
- */
- if (!ISMOTION(vp) || vp->m_start.lno == vp->m_stop.lno)
- return (0);
- mp = vp->m_start.lno < vp->m_stop.lno ? &vp->m_start : &vp->m_stop;
- if (mp->cno != 0) {
- cno = 0;
- if (nonblank(sp, ep, mp->lno, &cno))
- return (1);
- if (cno < mp->cno)
- return (0);
- }
- mp = vp->m_start.lno < vp->m_stop.lno ? &vp->m_stop : &vp->m_start;
- if ((p = file_gline(sp, ep, mp->lno, &len)) == NULL) {
- GETLINE_ERR(sp, mp->lno);
- return (1);
- }
- for (p += mp->cno + 1, len -= mp->cno; --len; ++p)
- if (!isblank(*p))
- return (0);
- F_SET(vp, VM_LMODE);
- return (0);
-}
diff --git a/usr.bin/vi/vi/v_ntext.c b/usr.bin/vi/vi/v_ntext.c
deleted file mode 100644
index 5dcba3b2f967..000000000000
--- a/usr.bin/vi/vi/v_ntext.c
+++ /dev/null
@@ -1,1899 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_ntext.c 8.120 (Berkeley) 8/15/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-#include "excmd.h"
-
-static int txt_abbrev __P((SCR *, TEXT *, CHAR_T *, int, int *, int *));
-static void txt_ai_resolve __P((SCR *, TEXT *));
-static TEXT *txt_backup __P((SCR *, EXF *, TEXTH *, TEXT *, u_int *));
-static void txt_err __P((SCR *, EXF *, TEXTH *));
-static int txt_hex __P((SCR *, TEXT *));
-static int txt_indent __P((SCR *, TEXT *));
-static int txt_margin __P((SCR *,
- TEXT *, CHAR_T *, TEXT *, u_int, int *));
-static int txt_outdent __P((SCR *, TEXT *));
-static void txt_Rcleanup __P((SCR *,
- TEXTH *, TEXT *, const char *, const size_t));
-static int txt_resolve __P((SCR *, EXF *, TEXTH *, u_int));
-static void txt_showmatch __P((SCR *, EXF *));
-static void txt_unmap __P((SCR *, TEXT *, u_int *));
-
-/* Cursor character (space is hard to track on the screen). */
-#if defined(DEBUG) && 0
-#undef CH_CURSOR
-#define CH_CURSOR '+'
-#endif
-
-/*
- * v_ntext --
- * Read in text from the user.
- *
- * !!!
- * Historic vi did a special screen optimization for tab characters. For
- * the keystrokes "iabcd<esc>0C<tab>", the tab would overwrite the rest of
- * the string when it was displayed. Because this implementation redisplays
- * the entire line on each keystroke, the "bcd" gets pushed to the right as
- * we ignore that the user has "promised" to change the rest of the characters.
- * Users have noticed, but this isn't worth fixing, and, the way that the
- * historic vi did it results in an even worse bug. Given the keystrokes
- * "iabcd<esc>0R<tab><esc>", the "bcd" disappears, and magically reappears
- * on the second <esc> key.
- */
-int
-v_ntext(sp, ep, tiqh, tm, lp, len, rp, prompt, ai_line, flags)
- SCR *sp;
- EXF *ep;
- TEXTH *tiqh;
- MARK *tm; /* To MARK. */
- const char *lp; /* Input line. */
- const size_t len; /* Input line length. */
- MARK *rp; /* Return MARK. */
- ARG_CHAR_T prompt; /* Prompt to display. */
- recno_t ai_line; /* Line number to use for autoindent count. */
- u_int flags; /* TXT_ flags. */
-{
- /* State of abbreviation checks. */
- enum { A_NOTSET, A_NOTWORD, A_INWORD } abb;
- /* State of the "[^0]^D" sequences. */
- enum { C_NOTSET, C_CARATSET, C_NOCHANGE, C_ZEROSET } carat_st;
- /* State of the hex input character. */
- enum { H_NOTSET, H_NEXTCHAR, H_INHEX } hex;
- /* State of quotation. */
- enum { Q_NOTSET, Q_NEXTCHAR, Q_THISCHAR } quoted;
- enum input tval;
- struct termios t; /* Terminal characteristics. */
- CH ikey; /* Input character structure. */
- CHAR_T ch; /* Input character. */
- TEXT *tp, *ntp, ait; /* Input and autoindent text structures. */
- TEXT wmt; /* Wrapmargin text structure. */
- size_t owrite, insert; /* Temporary copies of TEXT fields. */
- size_t rcol; /* 0-N: insert offset in the replay buffer. */
- size_t col; /* Current column. */
- u_long margin; /* Wrapmargin value. */
- u_int iflags; /* Input flags. */
- int ab_cnt, ab_turnoff; /* Abbreviation count, if turned off. */
- int eval; /* Routine return value. */
- int replay; /* If replaying a set of input. */
- int showmatch; /* Showmatch set on this character. */
- int sig_ix, sig_reset; /* Signal information. */
- int testnr; /* Test first character for nul replay. */
- int max, tmp;
- int unmap_tst; /* Input map needs testing. */
- int wmset, wmskip; /* Wrapmargin happened, blank skip flags. */
- char *p;
-
- /*
- * Set the input flag, so tabs get displayed correctly
- * and everyone knows that the text buffer is in use.
- */
- F_SET(sp, S_INPUT);
-
- /* Local initialization. */
- eval = 0;
-
- /*
- * Get one TEXT structure with some initial buffer space, reusing
- * the last one if it's big enough. (All TEXT bookkeeping fields
- * default to 0 -- text_init() handles this.) If changing a line,
- * copy it into the TEXT buffer.
- */
- if (tiqh->cqh_first != (void *)tiqh) {
- tp = tiqh->cqh_first;
- if (tp->q.cqe_next != (void *)tiqh || tp->lb_len < len + 32) {
- text_lfree(tiqh);
- goto newtp;
- }
- tp->ai = tp->insert = tp->offset = tp->owrite = 0;
- if (lp != NULL) {
- tp->len = len;
- memmove(tp->lb, lp, len);
- } else
- tp->len = 0;
- } else {
-newtp: if ((tp = text_init(sp, lp, len, len + 32)) == NULL)
- return (1);
- CIRCLEQ_INSERT_HEAD(tiqh, tp, q);
- }
-
- /* Set the starting line number. */
- tp->lno = sp->lno;
-
- /*
- * Set the insert and overwrite counts. If overwriting characters,
- * do insertion afterward. If not overwriting characters, assume
- * doing insertion. If change is to a mark, emphasize it with an
- * CH_ENDMARK
- */
- if (len) {
- if (LF_ISSET(TXT_OVERWRITE)) {
- tp->owrite = (tm->cno - sp->cno) + 1;
- tp->insert = (len - tm->cno) - 1;
- } else
- tp->insert = len - sp->cno;
-
- if (LF_ISSET(TXT_EMARK))
- tp->lb[tm->cno] = CH_ENDMARK;
- }
-
- /*
- * Many of the special cases in this routine are to handle autoindent
- * support. Somebody decided that it would be a good idea if "^^D"
- * and "0^D" deleted all of the autoindented characters. In an editor
- * that takes single character input from the user, this beggars the
- * imagination. Note also, "^^D" resets the next lines' autoindent,
- * but "0^D" doesn't.
- *
- * We assume that autoindent only happens on empty lines, so insert
- * and overwrite will be zero. If doing autoindent, figure out how
- * much indentation we need and fill it in. Update input column and
- * screen cursor as necessary.
- */
- if (LF_ISSET(TXT_AUTOINDENT) && ai_line != OOBLNO) {
- if (txt_auto(sp, ep, ai_line, NULL, 0, tp))
- return (1);
- sp->cno = tp->ai;
- } else {
- /*
- * The cc and S commands have a special feature -- leading
- * <blank> characters are handled as autoindent characters.
- * Beauty!
- */
- if (LF_ISSET(TXT_AICHARS)) {
- tp->offset = 0;
- tp->ai = sp->cno;
- } else
- tp->offset = sp->cno;
- }
-
- /* If getting a command buffer from the user, there may be a prompt. */
- if (LF_ISSET(TXT_PROMPT)) {
- tp->lb[sp->cno++] = prompt;
- ++tp->len;
- ++tp->offset;
- }
-
- /*
- * If appending after the end-of-line, add a space into the buffer
- * and move the cursor right. This space is inserted, i.e. pushed
- * along, and then deleted when the line is resolved. Assumes that
- * the cursor is already positioned at the end of the line. This
- * avoids the nastiness of having the cursor reside on a magical
- * column, i.e. a column that doesn't really exist. The only down
- * side is that we may wrap lines or scroll the screen before it's
- * strictly necessary. Not a big deal.
- */
- if (LF_ISSET(TXT_APPENDEOL)) {
- tp->lb[sp->cno] = CH_CURSOR;
- ++tp->len;
- ++tp->insert;
- }
-
- /*
- * Historic practice is that the wrapmargin value was a distance
- * from the RIGHT-HAND column, not the left. It's more useful to
- * us as a distance from the left-hand column.
- *
- * !!!/XXX
- * Replay commands were not affected by the wrapmargin option in the
- * historic 4BSD vi. What I found surprising was that people depend
- * on it, as in this gem of a macro which centers lines:
- *
- * map #c $mq81a ^V^[81^V|D`qld0:s/ / /g^V^M$p
- *
- * Other historic versions of vi, notably Sun's, applied wrapmargin
- * to replay lines as well.
- *
- * XXX
- * Setting margin causes a significant performance hit. Normally
- * we don't update the screen if there are keys waiting, but we
- * have to if margin is set, otherwise the screen routines don't
- * know where the cursor is.
- *
- * !!!
- * One more special case. If an inserted <blank> character causes
- * wrapmargin to split the line, the next user entered character is
- * discarded if it's a <space> character.
- */
- if (LF_ISSET(TXT_REPLAY) || !LF_ISSET(TXT_WRAPMARGIN))
- margin = 0;
- else if ((margin = O_VAL(sp, O_WRAPMARGIN)) != 0)
- margin = sp->cols - margin;
- wmset = wmskip = 0;
-
- /* Initialize abbreviations checks. */
- if (F_ISSET(sp->gp, G_ABBREV) && LF_ISSET(TXT_MAPINPUT)) {
- abb = A_INWORD;
- ab_cnt = ab_turnoff = 0;
- } else
- abb = A_NOTSET;
-
- /*
- * Set up the dot command. Dot commands are done by saving the
- * actual characters and replaying the input. We have to push
- * the characters onto the key stack and then handle them normally,
- * otherwise things like wrapmargin will fail.
- *
- * XXX
- * It would be nice if we could swallow backspaces and such, but
- * it's not all that easy to do. Another possibility would be to
- * recognize full line insertions, which could be performed quickly,
- * without replay.
- */
-nullreplay:
- rcol = 0;
- if (replay = LF_ISSET(TXT_REPLAY)) {
- /*
- * !!!
- * Historically, it wasn't an error to replay non-existent
- * input. This test is necessary, we get here by the user
- * doing an input command followed by a nul.
- *
- * !!!
- * Historically, vi did not remap or reabbreviate replayed
- * input. It did, however, beep at you if you changed an
- * abbreviation and then replayed the input. We're not that
- * compatible.
- */
- if (VIP(sp)->rep == NULL)
- return (0);
- if (term_push(sp, VIP(sp)->rep, VIP(sp)->rep_cnt, CH_NOMAP))
- return (1);
- testnr = 0;
- abb = A_NOTSET;
- LF_CLR(TXT_RECORD);
- } else
- testnr = 1;
-
- unmap_tst = LF_ISSET(TXT_MAPINPUT) && LF_ISSET(TXT_INFOLINE);
- iflags = LF_ISSET(TXT_MAPCOMMAND | TXT_MAPINPUT);
- for (showmatch = 0, sig_reset = 0,
- carat_st = C_NOTSET, hex = H_NOTSET, quoted = Q_NOTSET;;) {
- /*
- * Reset the line and update the screen. (The txt_showmatch()
- * code refreshes the screen for us.) Don't refresh unless
- * we're about to wait on a character or we need to know where
- * the cursor really is.
- */
- if (showmatch || margin || !KEYS_WAITING(sp)) {
- if (sp->s_change(sp, ep, tp->lno, LINE_RESET))
- goto err;
- if (showmatch) {
- showmatch = 0;
- txt_showmatch(sp, ep);
- } else if (sp->s_refresh(sp, ep))
- goto err;
- }
-
- /* Get the next character. */
-next_ch: tval = term_key(sp, &ikey, quoted == Q_THISCHAR ?
- iflags & ~(TXT_MAPCOMMAND | TXT_MAPINPUT) : iflags);
- ch = ikey.ch;
-
- /* Restore the terminal state if it was modified. */
- if (sig_reset && !tcgetattr(STDIN_FILENO, &t)) {
- t.c_lflag |= ISIG;
- t.c_iflag |= sig_ix;
- sig_reset = 0;
- (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t);
- }
-
- /*
- * !!!
- * Historically, <interrupt> exited the user from text input
- * mode or cancelled a colon command, and returned to command
- * mode. It also beeped the terminal, but that seems a bit
- * excessive.
- */
- if (tval != INP_OK) {
- if (tval == INP_INTR)
- goto k_escape;
- goto err;
- }
-
- /* Abbreviation check. See comment in txt_abbrev(). */
-#define MAX_ABBREVIATION_EXPANSION 256
- if (ikey.flags & CH_ABBREVIATED) {
- if (++ab_cnt > MAX_ABBREVIATION_EXPANSION) {
- term_flush(sp,
- "Abbreviation exceeded maximum number of characters",
- CH_ABBREVIATED);
- ab_cnt = 0;
- continue;
- }
- } else
- ab_cnt = 0;
-
- /* Wrapmargin check. */
- if (wmskip) {
- wmskip = 0;
- if (ch == ' ')
- goto next_ch;
- }
-
- /*
- * !!!
- * Historic feature. If the first character of the input is
- * a nul, replay the previous input. This isn't documented
- * anywhere, and is a great test of vi clones.
- */
- if (ch == '\0' && testnr) {
- LF_SET(TXT_REPLAY);
- goto nullreplay;
- }
- testnr = 0;
-
- /*
- * Check to see if the character fits into the input (and
- * replay, if necessary) buffers. It isn't necessary to
- * have tp->len bytes, since it doesn't consider overwrite
- * characters, but not worth fixing.
- */
- if (LF_ISSET(TXT_RECORD)) {
- BINC_GOTO(sp, VIP(sp)->rep, VIP(sp)->rep_len, rcol + 1);
- VIP(sp)->rep[rcol++] = ch;
- }
- BINC_GOTO(sp, tp->lb, tp->lb_len, tp->len + 1);
-
- /*
- * If the character was quoted, replace the last character
- * (the literal mark) with the new character. If quoted
- * by someone else, simply insert the character.
- */
- if (ikey.flags & CH_QUOTED)
- goto insq_ch;
- if (quoted == Q_THISCHAR) {
- --sp->cno;
- ++tp->owrite;
- quoted = Q_NOTSET;
- goto insq_ch;
- }
- /*
- * !!!
- * Extension. If the user enters "<CH_HEX>[isxdigit()]*" we
- * will try to use the value as a character. Anything else
- * inserts the <CH_HEX> character, and resets hex mode.
- */
- if (hex == H_INHEX && !isxdigit(ch)) {
- if (txt_hex(sp, tp))
- goto err;
- hex = H_NOTSET;
- }
-
- switch (ikey.value) {
- case K_CR: /* Carriage return. */
- case K_NL: /* New line. */
- /* Return in script windows and the command line. */
-k_cr: if (LF_ISSET(TXT_CR)) {
- /*
- * If this was a map, we may have not displayed
- * the line. Display it, just in case.
- *
- * If a script window and not the colon line,
- * push a <cr> so it gets executed.
- */
- if (LF_ISSET(TXT_INFOLINE)) {
- if (sp->s_change(sp,
- ep, tp->lno, LINE_RESET))
- goto err;
- } else if (F_ISSET(sp, S_SCRIPT))
- (void)term_push(sp, "\r", 1, CH_NOMAP);
- goto k_escape;
- }
-
-#define LINE_RESOLVE { \
- /* \
- * Handle abbreviations. If there was one, \
- * discard the replay characters. \
- */ \
- if (abb == A_INWORD && !replay) { \
- if (txt_abbrev(sp, tp, &ch, \
- LF_ISSET(TXT_INFOLINE), &tmp, \
- &ab_turnoff)) \
- goto err; \
- if (tmp) { \
- if (LF_ISSET(TXT_RECORD)) \
- rcol -= tmp; \
- goto next_ch; \
- } \
- } \
- if (abb != A_NOTSET) \
- abb = A_NOTWORD; \
- if (unmap_tst) \
- txt_unmap(sp, tp, &iflags); \
- /* Delete any appended cursor. */ \
- if (LF_ISSET(TXT_APPENDEOL)) { \
- --tp->len; \
- --tp->insert; \
- } \
-}
- LINE_RESOLVE;
-
- /*
- * Save the current line information for restoration
- * in txt_backup(). Set the new line length.
- */
- tp->sv_len = tp->len;
- tp->sv_cno = sp->cno;
- tp->len = sp->cno;
-
- /* Update the old line. */
- if (sp->s_change(sp, ep, tp->lno, LINE_RESET))
- goto err;
-
- /*
- * Historic practice was to delete <blank> characters
- * following the inserted newline. This affected the
- * 'R', 'c', and 's' commands; 'c' and 's' retained
- * the insert characters only, 'R' moved overwrite and
- * insert characters into the next TEXT structure.
- * All other commands simply deleted the overwrite
- * characters. We have to keep track of the number of
- * characters erased for the 'R' command so that we
- * can get the final resolution of the line correct.
- */
- tp->R_erase = 0;
- owrite = tp->owrite;
- insert = tp->insert;
- if (LF_ISSET(TXT_REPLACE) && owrite != 0) {
- for (p = tp->lb + sp->cno;
- owrite > 0 && isblank(*p);
- ++p, --owrite, ++tp->R_erase);
- if (owrite == 0)
- for (; insert > 0 && isblank(*p);
- ++p, ++tp->R_erase, --insert);
- } else {
- for (p = tp->lb + sp->cno + owrite;
- insert > 0 && isblank(*p); ++p, --insert);
- owrite = 0;
- }
-
- /* Set up bookkeeping for the new line. */
- if ((ntp = text_init(sp, p,
- insert + owrite, insert + owrite + 32)) == NULL)
- goto err;
- ntp->insert = insert;
- ntp->owrite = owrite;
- ntp->lno = tp->lno + 1;
-
- /*
- * Reset the autoindent line value. 0^D keeps the ai
- * line from changing, ^D changes the level, even if
- * there are no characters in the old line. Note,
- * if using the current tp structure, use the cursor
- * as the length, the user may have erased autoindent
- * characters.
- */
- if (LF_ISSET(TXT_AUTOINDENT)) {
- if (carat_st == C_NOCHANGE) {
- if (txt_auto(sp, ep,
- OOBLNO, &ait, ait.ai, ntp))
- goto err;
- FREE_SPACE(sp, ait.lb, ait.lb_len);
- } else
- if (txt_auto(sp, ep,
- OOBLNO, tp, sp->cno, ntp))
- goto err;
- carat_st = C_NOTSET;
- }
-
- /* Reset the cursor. */
- sp->lno = ntp->lno;
- sp->cno = ntp->ai;
-
- /*
- * If we're here because wrapmargin was set and we've
- * broken a line, there may be additional information
- * (i.e. the start of a line) in the wmt structure.
- */
- if (wmset) {
- if (wmt.len != 0 ||
- wmt.insert != 0 || wmt.owrite != 0) {
- BINC_GOTO(sp, ntp->lb, ntp->lb_len,
- ntp->len + wmt.len + 32);
- memmove(ntp->lb + sp->cno, wmt.lb,
- wmt.len + wmt.insert + wmt.owrite);
- ntp->len +=
- wmt.len + wmt.insert + wmt.owrite;
- ntp->insert = wmt.insert;
- ntp->owrite = wmt.owrite;
- sp->cno += wmt.len;
- }
- wmset = 0;
- }
-
- /* New lines are TXT_APPENDEOL. */
- if (ntp->owrite == 0 && ntp->insert == 0) {
- BINC_GOTO(sp,
- ntp->lb, ntp->lb_len, ntp->len + 1);
- LF_SET(TXT_APPENDEOL);
- ntp->lb[sp->cno] = CH_CURSOR;
- ++ntp->insert;
- ++ntp->len;
- }
-
- /*
- * Swap old and new TEXT's, and insert the new TEXT
- * into the queue.
- *
- * !!!
- * DON'T insert until the old line has been updated,
- * or the inserted line count in line.c:file_gline()
- * will be wrong.
- */
- tp = ntp;
- CIRCLEQ_INSERT_TAIL(tiqh, tp, q);
-
- /* Update the new line. */
- if (sp->s_change(sp, ep, tp->lno, LINE_INSERT))
- goto err;
-
- /* Set the renumber bit. */
- F_SET(sp, S_RENUMBER);
-
- /* Refresh if nothing waiting. */
- if (margin || !KEYS_WAITING(sp))
- if (sp->s_refresh(sp, ep))
- goto err;
- goto next_ch;
- case K_ESCAPE: /* Escape. */
- if (!LF_ISSET(TXT_ESCAPE))
- goto ins_ch;
-k_escape: LINE_RESOLVE;
-
- /*
- * Clean up for the 'R' command, restoring overwrite
- * characters, and making them into insert characters.
- */
- if (LF_ISSET(TXT_REPLACE))
- txt_Rcleanup(sp, tiqh, tp, lp, len);
-
- /*
- * If there are any overwrite characters, copy down
- * any insert characters, and decrement the length.
- */
- if (tp->owrite) {
- if (tp->insert)
- memmove(tp->lb + sp->cno,
- tp->lb + sp->cno + tp->owrite,
- tp->insert);
- tp->len -= tp->owrite;
- }
-
- /*
- * Optionally resolve the lines into the file. Clear
- * the input flag, the look-aside buffer is no longer
- * valid. If not resolving the lines into the file,
- * end it with a nul.
- *
- * XXX
- * This is wrong, should pass back a length.
- */
- if (LF_ISSET(TXT_RESOLVE)) {
- if (txt_resolve(sp, ep, tiqh, flags))
- goto err;
- F_CLR(sp, S_INPUT);
- } else {
- BINC_GOTO(sp, tp->lb, tp->lb_len, tp->len + 1);
- tp->lb[tp->len] = '\0';
- }
-
- /*
- * Set the return cursor position to rest on the last
- * inserted character.
- */
- if (rp != NULL) {
- rp->lno = tp->lno;
- rp->cno = sp->cno ? sp->cno - 1 : 0;
- if (sp->s_change(sp, ep, rp->lno, LINE_RESET))
- goto err;
- }
- goto ret;
- case K_CARAT: /* Delete autoindent chars. */
- if (LF_ISSET(TXT_AUTOINDENT) && sp->cno <= tp->ai)
- carat_st = C_CARATSET;
- goto ins_ch;
- case K_ZERO: /* Delete autoindent chars. */
- if (LF_ISSET(TXT_AUTOINDENT) && sp->cno <= tp->ai)
- carat_st = C_ZEROSET;
- goto ins_ch;
- case K_CNTRLD: /* Delete autoindent char. */
- /*
- * If in the first column or no characters to erase,
- * ignore the ^D (this matches historic practice). If
- * not doing autoindent or already inserted non-ai
- * characters, it's a literal. The latter test is done
- * in the switch, as the CARAT forms are N + 1, not N.
- */
- if (!LF_ISSET(TXT_AUTOINDENT))
- goto ins_ch;
- if (sp->cno == 0)
- break;
- switch (carat_st) {
- case C_CARATSET: /* ^^D */
- if (sp->cno > tp->ai + tp->offset + 1)
- goto ins_ch;
- /* Save the ai string for later. */
- ait.lb = NULL;
- ait.lb_len = 0;
- BINC_GOTO(sp, ait.lb, ait.lb_len, tp->ai);
- memmove(ait.lb, tp->lb, tp->ai);
- ait.ai = ait.len = tp->ai;
-
- carat_st = C_NOCHANGE;
- goto leftmargin;
- case C_ZEROSET: /* 0^D */
- if (sp->cno > tp->ai + tp->offset + 1)
- goto ins_ch;
- carat_st = C_NOTSET;
-leftmargin: tp->lb[sp->cno - 1] = ' ';
- tp->owrite += sp->cno - tp->offset;
- tp->ai = 0;
- sp->cno = tp->offset;
- break;
- case C_NOTSET: /* ^D */
- if (sp->cno > tp->ai + tp->offset)
- goto ins_ch;
- (void)txt_outdent(sp, tp);
- break;
- default:
- abort();
- }
- break;
- case K_VERASE: /* Erase the last character. */
- /*
- * If can erase over the prompt, return. Len is 0
- * if backspaced over the prompt, 1 if only CR entered.
- */
- if (LF_ISSET(TXT_BS) && sp->cno <= tp->offset) {
- tp->len = 0;
- goto ret;
- }
-
- /*
- * If at the beginning of the line, try and drop back
- * to a previously inserted line.
- */
- if (sp->cno == 0) {
- if ((ntp = txt_backup(sp,
- ep, tiqh, tp, &flags)) == NULL)
- goto err;
- tp = ntp;
- break;
- }
-
- /* If nothing to erase, bell the user. */
- if (sp->cno <= tp->offset) {
- msgq(sp, M_BERR,
- "No more characters to erase");
- break;
- }
-
- /* Drop back one character. */
- --sp->cno;
-
- /*
- * Increment overwrite, decrement ai if deleted.
- *
- * !!!
- * Historic vi did not permit users to use erase
- * characters to delete autoindent characters.
- */
- ++tp->owrite;
- if (sp->cno < tp->ai)
- --tp->ai;
- break;
- case K_VWERASE: /* Skip back one word. */
- /*
- * If at the beginning of the line, try and drop back
- * to a previously inserted line.
- */
- if (sp->cno == 0) {
- if ((ntp = txt_backup(sp,
- ep, tiqh, tp, &flags)) == NULL)
- goto err;
- tp = ntp;
- }
-
- /*
- * If at offset, nothing to erase so bell the user.
- */
- if (sp->cno <= tp->offset) {
- msgq(sp, M_BERR,
- "No more characters to erase");
- break;
- }
-
- /*
- * First werase goes back to any autoindent
- * and second werase goes back to the offset.
- *
- * !!!
- * Historic vi did not permit users to use erase
- * characters to delete autoindent characters.
- */
- if (tp->ai && sp->cno > tp->ai)
- max = tp->ai;
- else {
- tp->ai = 0;
- max = tp->offset;
- }
-
- /* Skip over trailing space characters. */
- while (sp->cno > max && isblank(tp->lb[sp->cno - 1])) {
- --sp->cno;
- ++tp->owrite;
- }
- if (sp->cno == max)
- break;
- /*
- * There are three types of word erase found on UNIX
- * systems. They can be identified by how the string
- * /a/b/c is treated -- as 1, 3, or 6 words. Historic
- * vi had two classes of characters, and strings were
- * delimited by them and <blank>'s, so, 6 words. The
- * historic tty interface used <blank>'s to delimit
- * strings, so, 1 word. The algorithm offered in the
- * 4.4BSD tty interface (as stty altwerase) treats it
- * as 3 words -- there are two classes of characters,
- * and strings are delimited by them and <blank>'s.
- * The difference is that the type of the first erased
- * character erased is ignored, which is exactly right
- * when erasing pathname components. Here, the options
- * TXT_ALTWERASE and TXT_TTYWERASE specify the 4.4BSD
- * tty interface and the historic tty driver behavior,
- * respectively, and the default is the same as the
- * historic vi behavior.
- */
- if (LF_ISSET(TXT_TTYWERASE))
- while (sp->cno > max) {
- --sp->cno;
- ++tp->owrite;
- if (isblank(tp->lb[sp->cno - 1]))
- break;
- }
- else {
- if (LF_ISSET(TXT_ALTWERASE)) {
- --sp->cno;
- ++tp->owrite;
- if (isblank(tp->lb[sp->cno - 1]))
- break;
- }
- if (sp->cno > max)
- tmp = inword(tp->lb[sp->cno - 1]);
- while (sp->cno > max) {
- --sp->cno;
- ++tp->owrite;
- if (tmp != inword(tp->lb[sp->cno - 1])
- || isblank(tp->lb[sp->cno - 1]))
- break;
- }
- }
- break;
- case K_VKILL: /* Restart this line. */
- /*
- * If at the beginning of the line, try and drop back
- * to a previously inserted line.
- */
- if (sp->cno == 0) {
- if ((ntp = txt_backup(sp,
- ep, tiqh, tp, &flags)) == NULL)
- goto err;
- tp = ntp;
- }
-
- /* If at offset, nothing to erase so bell the user. */
- if (sp->cno <= tp->offset) {
- msgq(sp, M_BERR,
- "No more characters to erase");
- break;
- }
-
- /*
- * First kill goes back to any autoindent
- * and second kill goes back to the offset.
- *
- * !!!
- * Historic vi did not permit users to use erase
- * characters to delete autoindent characters.
- */
- if (tp->ai && sp->cno > tp->ai)
- max = tp->ai;
- else {
- tp->ai = 0;
- max = tp->offset;
- }
- tp->owrite += sp->cno - max;
- sp->cno = max;
- break;
- case K_CNTRLT: /* Add autoindent char. */
- if (!LF_ISSET(TXT_CNTRLT))
- goto ins_ch;
- if (txt_indent(sp, tp))
- goto err;
- goto ebuf_chk;
-#ifdef HISTORIC_PRACTICE_IS_TO_INSERT_NOT_SUSPEND
- case K_CNTRLZ:
- /*
- * XXX
- * Note, historically suspend triggered an autowrite.
- * That needs to be done to make this work correctly.
- */
- (void)sp->s_suspend(sp);
- break;
-#endif
-#ifdef HISTORIC_PRACTICE_IS_TO_INSERT_NOT_REPAINT
- case K_FORMFEED:
- F_SET(sp, S_REFRESH);
- break;
-#endif
- case K_RIGHTBRACE:
- case K_RIGHTPAREN:
- showmatch = LF_ISSET(TXT_SHOWMATCH);
- goto ins_ch;
- case K_VLNEXT: /* Quote the next character. */
- ch = '^';
- quoted = Q_NEXTCHAR;
- /*
- * If there are no keys in the queue, reset the tty
- * so that the user can enter a ^C, ^Q, ^S. There's
- * an obvious race here, if the user entered the ^C
- * already. There's nothing that we can do to fix
- * that problem.
- */
- if (!KEYS_WAITING(sp) && !tcgetattr(STDIN_FILENO, &t)) {
- t.c_lflag &= ~ISIG;
- sig_ix = t.c_iflag & (IXON | IXOFF);
- t.c_iflag &= ~(IXON | IXOFF);
- sig_reset = 1;
- (void)tcsetattr(STDIN_FILENO,
- TCSASOFT | TCSADRAIN, &t);
- }
- /*
- * XXX
- * Pass the tests for abbreviations, so ":ab xa XA",
- * "ixa^V<space>" works. Historic vi did something
- * weird here: ":ab x y", "ix\<space>" resulted in
- * "<space>x\", for some unknown reason. Had to be
- * a bug.
- */
- goto insl_ch;
- case K_HEXCHAR:
- hex = H_NEXTCHAR;
- goto insq_ch;
- default: /* Insert the character. */
-ins_ch: /*
- * Historically, vi eliminated nul's out of hand. If
- * the beautify option was set, it also deleted any
- * unknown ASCII value less than space (040) and the
- * del character (0177), except for tabs. Unknown is
- * a key word here. Most vi documentation claims that
- * it deleted everything but <tab>, <nl> and <ff>, as
- * that's what the original 4BSD documentation said.
- * This is obviously wrong, however, as <esc> would be
- * included in that list. What we do is eliminate any
- * unquoted, iscntrl() character that wasn't a replay
- * and wasn't handled specially, except <tab> or <ff>.
- */
- if (LF_ISSET(TXT_BEAUTIFY) && iscntrl(ch) &&
- ikey.value != K_FORMFEED && ikey.value != K_TAB) {
- msgq(sp, M_BERR,
- "Illegal character; quote to enter");
- break;
- }
-insq_ch: /*
- * If entering a non-word character after a word, check
- * for abbreviations. If there was one, discard the
- * replay characters. If entering a blank character,
- * check for unmap commands, as well.
- */
- if (!inword(ch)) {
- if (abb == A_INWORD && !replay) {
- if (txt_abbrev(sp, tp, &ch,
- LF_ISSET(TXT_INFOLINE),
- &tmp, &ab_turnoff))
- goto err;
- if (tmp) {
- if (LF_ISSET(TXT_RECORD))
- rcol -= tmp;
- goto next_ch;
- }
- }
- if (isblank(ch) && unmap_tst)
- txt_unmap(sp, tp, &iflags);
- }
- if (abb != A_NOTSET)
- abb = inword(ch) ? A_INWORD : A_NOTWORD;
-
-insl_ch: if (tp->owrite) /* Overwrite a character. */
- --tp->owrite;
- else if (tp->insert) { /* Insert a character. */
- ++tp->len;
- if (tp->insert == 1)
- tp->lb[sp->cno + 1] = tp->lb[sp->cno];
- else
- memmove(tp->lb + sp->cno + 1,
- tp->lb + sp->cno, tp->insert);
- }
-
- tp->lb[sp->cno++] = ch;
-
- /* Check to see if we've crossed the margin. */
- if (margin) {
- if (sp->s_column(sp, ep, &col))
- goto err;
- if (col >= margin) {
- if (txt_margin(sp,
- tp, &ch, &wmt, flags, &tmp))
- goto err;
- if (tmp) {
- if (isblank(ch))
- wmskip = 1;
- wmset = 1;
- goto k_cr;
- }
- }
- }
-
- /*
- * If we've reached the end of the buffer, then we
- * need to switch into insert mode. This happens
- * when there's a change to a mark and the user puts
- * in more characters than the length of the motion.
- */
-ebuf_chk: if (sp->cno >= tp->len) {
- BINC_GOTO(sp, tp->lb, tp->lb_len, tp->len + 1);
- LF_SET(TXT_APPENDEOL);
- tp->lb[sp->cno] = CH_CURSOR;
- ++tp->insert;
- ++tp->len;
- }
-
- if (hex == H_NEXTCHAR)
- hex = H_INHEX;
- if (quoted == Q_NEXTCHAR)
- quoted = Q_THISCHAR;
- break;
- }
-#if defined(DEBUG) && 1
- if (sp->cno + tp->insert + tp->owrite != tp->len)
- msgq(sp, M_ERR,
- "len %u != cno: %u ai: %u insert %u overwrite %u",
- tp->len, sp->cno, tp->ai, tp->insert, tp->owrite);
- tp->len = sp->cno + tp->insert + tp->owrite;
-#endif
- }
-
- /* Clear input flag. */
-ret: F_CLR(sp, S_INPUT);
-
- if (LF_ISSET(TXT_RECORD))
- VIP(sp)->rep_cnt = rcol;
- return (eval);
-
-err: /* Error jumps. */
-binc_err:
- eval = 1;
- txt_err(sp, ep, tiqh);
- goto ret;
-}
-
-/*
- * txt_abbrev --
- * Handle abbreviations.
- */
-static int
-txt_abbrev(sp, tp, pushcp, isinfoline, didsubp, turnoffp)
- SCR *sp;
- TEXT *tp;
- CHAR_T *pushcp;
- int isinfoline, *didsubp, *turnoffp;
-{
- CHAR_T ch;
- SEQ *qp;
- size_t len, off;
- char *p;
-
- /*
- * Find the start of the "word". Historically, abbreviations
- * could be preceded by any non-word character or the beginning
- * of the entry, .e.g inserting an abbreviated string in the
- * middle of another string triggered the replacement.
- */
- for (off = sp->cno - 1, p = tp->lb + off, len = 0;; --p, --off) {
- if (!inword(*p)) {
- ++p;
- break;
- }
- ++len;
- if (off == tp->ai || off == tp->offset)
- break;
- }
-
- /*
- * !!!
- * Historic vi exploded abbreviations on the command line. This has
- * obvious problems in that unabbreviating the string can be extremely
- * tricky, particularly if the string has, say, an embedded escape
- * character. Personally, I think it's a stunningly bad idea. Other
- * examples of problems this caused in historic vi are:
- * :ab foo bar
- * :ab foo baz
- * results in "bar" being abbreviated to "baz", which wasn't what the
- * user had in mind at all. Also, the commands:
- * :ab foo bar
- * :unab foo<space>
- * resulted in an error message that "bar" wasn't mapped. Finally,
- * since the string was already exploded by the time the unabbreviate
- * command got it, all it knew was that an abbreviation had occurred.
- * Cleverly, it checked the replacement string for its unabbreviation
- * match, which meant that the commands:
- * :ab foo1 bar
- * :ab foo2 bar
- * :unab foo2
- * unabbreviate "foo1", and the commands:
- * :ab foo bar
- * :ab bar baz
- * unabbreviate "foo"!
- *
- * Anyway, people neglected to first ask my opinion before they wrote
- * macros that depend on this stuff, so, we make this work as follows.
- * When checking for an abbreviation on the command line, if we get a
- * string which is <blank> terminated and which starts at the beginning
- * of the line, we check to see it is the abbreviate or unabbreviate
- * commands. If it is, turn abbreviations off and return as if no
- * abbreviation was found. Note also, minor trickiness, so that if
- * the user erases the line and starts another command, we turn the
- * abbreviations back on.
- *
- * This makes the layering look like a Nachos Supreme.
- */
- *didsubp = 0;
- if (isinfoline)
- if (off == tp->ai || off == tp->offset)
- if (ex_is_abbrev(p, len)) {
- *turnoffp = 1;
- return (0);
- } else
- *turnoffp = 0;
- else
- if (*turnoffp)
- return (0);
-
- /* Check for any abbreviations. */
- if ((qp = seq_find(sp, NULL, p, len, SEQ_ABBREV, NULL)) == NULL)
- return (0);
-
- /*
- * Push the abbreviation onto the tty stack. Historically, characters
- * resulting from an abbreviation expansion were themselves subject to
- * map expansions, O_SHOWMATCH matching etc. This means the expanded
- * characters will be re-tested for abbreviations. It's difficult to
- * know what historic practice in this case was, since abbreviations
- * were applied to :colon command lines, so entering abbreviations that
- * looped was tricky, although possible. In addition, obvious loops
- * didn't work as expected. (The command ':ab a b|ab b c|ab c a' will
- * silently only implement and/or display the last abbreviation.)
- *
- * This implementation doesn't recover well from such abbreviations.
- * The main input loop counts abbreviated characters, and, when it
- * reaches a limit, discards any abbreviated characters on the queue.
- * It's difficult to back up to the original position, as the replay
- * queue would have to be adjusted, and the line state when an initial
- * abbreviated character was received would have to be saved.
- */
- ch = *pushcp;
- if (term_push(sp, &ch, 1, CH_ABBREVIATED))
- return (1);
- if (term_push(sp, qp->output, qp->olen, CH_ABBREVIATED))
- return (1);
-
- /* Move to the start of the abbreviation, adjust the length. */
- sp->cno -= len;
- tp->len -= len;
-
- /* Copy any insert characters back. */
- if (tp->insert)
- memmove(tp->lb + sp->cno + tp->owrite,
- tp->lb + sp->cno + tp->owrite + len, tp->insert);
-
- /*
- * We return the length of the abbreviated characters. This is so
- * the calling routine can replace the replay characters with the
- * abbreviation. This means that subsequent '.' commands will produce
- * the same text, regardless of intervening :[un]abbreviate commands.
- * This is historic practice.
- */
- *didsubp = len;
- return (0);
-}
-
-/*
- * txt_unmap --
- * Handle the unmap command.
- */
-static void
-txt_unmap(sp, tp, iflagsp)
- SCR *sp;
- TEXT *tp;
- u_int *iflagsp;
-{
- size_t len, off;
- char *p;
-
- /* Find the beginning of this "word". */
- for (off = sp->cno - 1, p = tp->lb + off, len = 0;; --p, --off) {
- if (isblank(*p)) {
- ++p;
- break;
- }
- ++len;
- if (off == tp->ai || off == tp->offset)
- break;
- }
-
- /*
- * !!!
- * Historic vi exploded input mappings on the command line. See the
- * txt_abbrev() routine for an explanation of the problems inherent
- * in this.
- *
- * We make this work as follows. If we get a string which is <blank>
- * terminated and which starts at the beginning of the line, we check
- * to see it is the unmap command. If it is, we return that the input
- * mapping should be turned off. Note also, minor trickiness, so that
- * if the user erases the line and starts another command, we go ahead
- * an turn mapping back on.
- */
- if ((off == tp->ai || off == tp->offset) && ex_is_unmap(p, len))
- *iflagsp &= ~TXT_MAPINPUT;
- else
- *iflagsp |= TXT_MAPINPUT;
-}
-
-/*
- * txt_ai_resolve --
- * When a line is resolved by <esc> or <cr>, review autoindent
- * characters.
- */
-static void
-txt_ai_resolve(sp, tp)
- SCR *sp;
- TEXT *tp;
-{
- u_long ts;
- int del;
- size_t cno, len, new, old, scno, spaces, tab_after_sp, tabs;
- char *p;
-
- /*
- * If the line is empty, has an offset, or no autoindent
- * characters, we're done.
- */
- if (!tp->len || tp->offset || !tp->ai)
- return;
-
- /*
- * If the length is less than or equal to the autoindent
- * characters, delete them.
- */
- if (tp->len <= tp->ai) {
- tp->len = tp->ai = 0;
- if (tp->lno == sp->lno)
- sp->cno = 0;
- return;
- }
-
- /*
- * The autoindent characters plus any leading <blank> characters
- * in the line are resolved into the minimum number of characters.
- * Historic practice.
- */
- ts = O_VAL(sp, O_TABSTOP);
-
- /* Figure out the last <blank> screen column. */
- for (p = tp->lb, scno = 0, len = tp->len,
- spaces = tab_after_sp = 0; len-- && isblank(*p); ++p)
- if (*p == '\t') {
- if (spaces)
- tab_after_sp = 1;
- scno += STOP_OFF(scno, ts);
- } else {
- ++spaces;
- ++scno;
- }
-
- /*
- * If there are no spaces, or no tabs after spaces and less than
- * ts spaces, it's already minimal.
- */
- if (!spaces || !tab_after_sp && spaces < ts)
- return;
-
- /* Count up spaces/tabs needed to get to the target. */
- for (cno = 0, tabs = 0; cno + STOP_OFF(cno, ts) <= scno; ++tabs)
- cno += STOP_OFF(cno, ts);
- spaces = scno - cno;
-
- /*
- * Figure out how many characters we're dropping -- if we're not
- * dropping any, it's already minimal, we're done.
- */
- old = p - tp->lb;
- new = spaces + tabs;
- if (old == new)
- return;
-
- /* Shift the rest of the characters down, adjust the counts. */
- del = old - new;
- memmove(p - del, p, tp->len - old);
- tp->len -= del;
-
- /* If the cursor was on this line, adjust it as well. */
- if (sp->lno == tp->lno)
- sp->cno -= del;
-
- /* Fill in space/tab characters. */
- for (p = tp->lb; tabs--;)
- *p++ = '\t';
- while (spaces--)
- *p++ = ' ';
-}
-
-/*
- * txt_auto --
- * Handle autoindent. If aitp isn't NULL, use it, otherwise,
- * retrieve the line.
- */
-int
-txt_auto(sp, ep, lno, aitp, len, tp)
- SCR *sp;
- EXF *ep;
- recno_t lno;
- size_t len;
- TEXT *aitp, *tp;
-{
- size_t nlen;
- char *p, *t;
-
- if (aitp == NULL) {
- /*
- * If the ex append command is executed with an address of 0,
- * it's possible to get here with a line number of 0. Return
- * an indent of 0.
- */
- if (lno == 0) {
- tp->ai = 0;
- return (0);
- }
- if ((t = file_gline(sp, ep, lno, &len)) == NULL)
- return (1);
- } else
- t = aitp->lb;
-
- /* Count whitespace characters. */
- for (p = t; len > 0; ++p, --len)
- if (!isblank(*p))
- break;
-
- /* Set count, check for no indentation. */
- if ((nlen = (p - t)) == 0)
- return (0);
-
- /* Make sure the buffer's big enough. */
- BINC_RET(sp, tp->lb, tp->lb_len, tp->len + nlen);
-
- /* Copy the buffer's current contents up. */
- if (tp->len != 0)
- memmove(tp->lb + nlen, tp->lb, tp->len);
- tp->len += nlen;
-
- /* Copy the indentation into the new buffer. */
- memmove(tp->lb, t, nlen);
-
- /* Set the autoindent count. */
- tp->ai = nlen;
- return (0);
-}
-
-/*
- * txt_backup --
- * Back up to the previously edited line.
- */
-static TEXT *
-txt_backup(sp, ep, tiqh, tp, flagsp)
- SCR *sp;
- EXF *ep;
- TEXTH *tiqh;
- TEXT *tp;
- u_int *flagsp;
-{
- TEXT *ntp;
- u_int flags;
-
- /* Get a handle on the previous TEXT structure. */
- if ((ntp = tp->q.cqe_prev) == (void *)tiqh) {
- msgq(sp, M_BERR, "Already at the beginning of the insert");
- return (tp);
- }
-
- /* Reset the cursor, bookkeeping. */
- sp->lno = ntp->lno;
- sp->cno = ntp->sv_cno;
- ntp->len = ntp->sv_len;
-
- /* Handle appending to the line. */
- flags = *flagsp;
- if (ntp->owrite == 0 && ntp->insert == 0) {
- ntp->lb[ntp->len] = CH_CURSOR;
- ++ntp->insert;
- ++ntp->len;
- LF_SET(TXT_APPENDEOL);
- } else
- LF_CLR(TXT_APPENDEOL);
- *flagsp = flags;
-
- /* Release the current TEXT. */
- CIRCLEQ_REMOVE(tiqh, tp, q);
- text_free(tp);
-
- /* Update the old line on the screen. */
- if (sp->s_change(sp, ep, ntp->lno + 1, LINE_DELETE))
- return (NULL);
-
- /* Return the new/current TEXT. */
- return (ntp);
-}
-
-/*
- * txt_err --
- * Handle an error during input processing.
- */
-static void
-txt_err(sp, ep, tiqh)
- SCR *sp;
- EXF *ep;
- TEXTH *tiqh;
-{
- recno_t lno;
- size_t len;
-
- /*
- * The problem with input processing is that the cursor is at an
- * indeterminate position since some input may have been lost due
- * to a malloc error. So, try to go back to the place from which
- * the cursor started, knowing that it may no longer be available.
- *
- * We depend on at least one line number being set in the text
- * chain.
- */
- for (lno = tiqh->cqh_first->lno;
- file_gline(sp, ep, lno, &len) == NULL && lno > 0; --lno);
-
- sp->lno = lno == 0 ? 1 : lno;
- sp->cno = 0;
-
- /* Redraw the screen, just in case. */
- F_SET(sp, S_REDRAW);
-}
-
-/*
- * txt_hex --
- * Let the user insert any character value they want.
- *
- * !!!
- * This is an extension. The pattern "^X[0-9a-fA-F]*" is a way
- * for the user to specify a character value which their keyboard
- * may not be able to enter.
- */
-static int
-txt_hex(sp, tp)
- SCR *sp;
- TEXT *tp;
-{
- CHAR_T savec;
- size_t len, off;
- u_long value;
- char *p, *wp;
-
- /*
- * Null-terminate the string. Since nul isn't a legal hex value,
- * this should be okay, and lets us use a local routine, which
- * presumably understands the character set, to convert the value.
- */
- savec = tp->lb[sp->cno];
- tp->lb[sp->cno] = 0;
-
- /* Find the previous CH_HEX character. */
- for (off = sp->cno - 1, p = tp->lb + off, len = 0;; --p, --off, ++len) {
- if (*p == CH_HEX) {
- wp = p + 1;
- break;
- }
- /* Not on this line? Shouldn't happen. */
- if (off == tp->ai || off == tp->offset)
- goto nothex;
- }
-
- /* If length of 0, then it wasn't a hex value. */
- if (len == 0)
- goto nothex;
-
- /* Get the value. */
- errno = 0;
- value = strtol(wp, NULL, 16);
- if (errno || value > MAX_CHAR_T) {
-nothex: tp->lb[sp->cno] = savec;
- return (0);
- }
-
- /* Restore the original character. */
- tp->lb[sp->cno] = savec;
-
- /* Adjust the bookkeeping. */
- sp->cno -= len;
- tp->len -= len;
- tp->lb[sp->cno - 1] = value;
-
- /* Copy down any overwrite characters. */
- if (tp->owrite)
- memmove(tp->lb + sp->cno,
- tp->lb + sp->cno + len, tp->owrite);
-
- /* Copy down any insert characters. */
- if (tp->insert)
- memmove(tp->lb + sp->cno + tp->owrite,
- tp->lb + sp->cno + tp->owrite + len, tp->insert);
-
- return (0);
-}
-
-/*
- * Txt_indent and txt_outdent are truly strange. ^T and ^D do movements
- * to the next or previous shiftwidth value, i.e. for a 1-based numbering,
- * with shiftwidth=3, ^T moves a cursor on the 7th, 8th or 9th column to
- * the 10th column, and ^D moves it back.
- *
- * !!!
- * The ^T and ^D characters in historical vi only had special meaning when
- * they were the first characters typed after entering text input mode.
- * Since normal erase characters couldn't erase autoindent (in this case
- * ^T) characters, this meant that inserting text into previously existing
- * text was quite strange, ^T only worked if it was the first keystroke,
- * and then it could only be erased by using ^D. This implementation treats
- * ^T specially anywhere it occurs in the input, and permits the standard
- * erase characters to erase characters inserted using it.
- *
- * XXX
- * Technically, txt_indent, txt_outdent should part of the screen interface,
- * as they require knowledge of the size of a space character on the screen.
- * (Not the size of tabs, because tabs are logically composed of spaces.)
- * They're left in the text code because they're complicated, not to mention
- * the gruesome awareness that if spaces aren't a single column on the screen
- * for any language, we're into some serious, ah, for lack of a better word,
- * "issues".
- */
-
-/*
- * txt_indent --
- * Handle ^T indents.
- */
-static int
-txt_indent(sp, tp)
- SCR *sp;
- TEXT *tp;
-{
- u_long sw, ts;
- size_t cno, off, scno, spaces, tabs;
-
- ts = O_VAL(sp, O_TABSTOP);
- sw = O_VAL(sp, O_SHIFTWIDTH);
-
- /* Get the current screen column. */
- for (off = scno = 0; off < sp->cno; ++off)
- if (tp->lb[off] == '\t')
- scno += STOP_OFF(scno, ts);
- else
- ++scno;
-
- /* Count up spaces/tabs needed to get to the target. */
- for (cno = scno, scno += STOP_OFF(scno, sw), tabs = 0;
- cno + STOP_OFF(cno, ts) <= scno; ++tabs)
- cno += STOP_OFF(cno, ts);
- spaces = scno - cno;
-
- /* Put space/tab characters in place of any overwrite characters. */
- for (; tp->owrite && tabs; --tp->owrite, --tabs, ++tp->ai)
- tp->lb[sp->cno++] = '\t';
- for (; tp->owrite && spaces; --tp->owrite, --spaces, ++tp->ai)
- tp->lb[sp->cno++] = ' ';
-
- if (!tabs && !spaces)
- return (0);
-
- /* Make sure there's enough room. */
- BINC_RET(sp, tp->lb, tp->lb_len, tp->len + spaces + tabs);
-
- /* Move the insert characters out of the way. */
- if (tp->insert)
- memmove(tp->lb + sp->cno + spaces + tabs,
- tp->lb + sp->cno, tp->insert);
-
- /* Add new space/tab characters. */
- for (; tabs--; ++tp->len, ++tp->ai)
- tp->lb[sp->cno++] = '\t';
- for (; spaces--; ++tp->len, ++tp->ai)
- tp->lb[sp->cno++] = ' ';
- return (0);
-}
-
-/*
- * txt_outdent --
- * Handle ^D outdents.
- *
- */
-static int
-txt_outdent(sp, tp)
- SCR *sp;
- TEXT *tp;
-{
- u_long sw, ts;
- size_t cno, off, scno, spaces;
-
- ts = O_VAL(sp, O_TABSTOP);
- sw = O_VAL(sp, O_SHIFTWIDTH);
-
- /* Get the current screen column. */
- for (off = scno = 0; off < sp->cno; ++off)
- if (tp->lb[off] == '\t')
- scno += STOP_OFF(scno, ts);
- else
- ++scno;
-
- /* Get the previous shiftwidth column. */
- for (cno = scno; --scno % sw != 0;);
-
- /* Decrement characters until less than or equal to that slot. */
- for (; cno > scno; --sp->cno, --tp->ai, ++tp->owrite)
- if (tp->lb[--off] == '\t')
- cno -= STOP_OFF(cno, ts);
- else
- --cno;
-
- /* Spaces needed to get to the target. */
- spaces = scno - cno;
-
- /* Maybe just a delete. */
- if (spaces == 0)
- return (0);
-
- /* Make sure there's enough room. */
- BINC_RET(sp, tp->lb, tp->lb_len, tp->len + spaces);
-
- /* Use up any overwrite characters. */
- for (; tp->owrite && spaces; --spaces, ++tp->ai, --tp->owrite)
- tp->lb[sp->cno++] = ' ';
-
- /* Maybe that was enough. */
- if (spaces == 0)
- return (0);
-
- /* Move the insert characters out of the way. */
- if (tp->insert)
- memmove(tp->lb + sp->cno + spaces,
- tp->lb + sp->cno, tp->insert);
-
- /* Add new space characters. */
- for (; spaces--; ++tp->len, ++tp->ai)
- tp->lb[sp->cno++] = ' ';
- return (0);
-}
-
-/*
- * txt_resolve --
- * Resolve the input text chain into the file.
- */
-static int
-txt_resolve(sp, ep, tiqh, flags)
- SCR *sp;
- EXF *ep;
- TEXTH *tiqh;
- u_int flags;
-{
- TEXT *tp;
- recno_t lno;
-
- /*
- * The first line replaces a current line, and all subsequent lines
- * are appended into the file. Resolve autoindented characters for
- * each line before committing it.
- */
- tp = tiqh->cqh_first;
- if (LF_ISSET(TXT_AUTOINDENT))
- txt_ai_resolve(sp, tp);
- if (file_sline(sp, ep, tp->lno, tp->lb, tp->len))
- return (1);
-
- for (lno = tp->lno; (tp = tp->q.cqe_next) != (void *)sp->tiqp; ++lno) {
- if (LF_ISSET(TXT_AUTOINDENT))
- txt_ai_resolve(sp, tp);
- if (file_aline(sp, ep, 0, lno, tp->lb, tp->len))
- return (1);
- }
- return (0);
-}
-
-/*
- * txt_showmatch --
- * Show a character match.
- *
- * !!!
- * Historic vi tried to display matches even in the :colon command line.
- * I think not.
- */
-static void
-txt_showmatch(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- struct timeval second;
- VCS cs;
- MARK m;
- fd_set zero;
- int cnt, endc, startc;
-
- /*
- * Do a refresh first, in case the v_ntext() code hasn't done
- * one in awhile, so the user can see what we're complaining
- * about.
- */
- if (sp->s_refresh(sp, ep))
- return;
- /*
- * We don't display the match if it's not on the screen. Find
- * out what the first character on the screen is.
- */
- if (sp->s_position(sp, ep, &m, 0, P_TOP))
- return;
-
- /* Initialize the getc() interface. */
- cs.cs_lno = sp->lno;
- cs.cs_cno = sp->cno - 1;
- if (cs_init(sp, ep, &cs))
- return;
- startc = (endc = cs.cs_ch) == ')' ? '(' : '{';
-
- /* Search for the match. */
- for (cnt = 1;;) {
- if (cs_prev(sp, ep, &cs))
- return;
- if (cs.cs_lno < m.lno ||
- cs.cs_lno == m.lno && cs.cs_cno < m.cno)
- return;
- if (cs.cs_flags != 0) {
- if (cs.cs_flags == CS_EOF || cs.cs_flags == CS_SOF) {
- (void)sp->s_bell(sp);
- return;
- }
- continue;
- }
- if (cs.cs_ch == endc)
- ++cnt;
- else if (cs.cs_ch == startc && --cnt == 0)
- break;
- }
-
- /* Move to the match. */
- m.lno = sp->lno;
- m.cno = sp->cno;
- sp->lno = cs.cs_lno;
- sp->cno = cs.cs_cno;
- (void)sp->s_refresh(sp, ep);
-
- /*
- * Sleep(3) is eight system calls. Do it fast -- besides,
- * I don't want to wait an entire second.
- */
- FD_ZERO(&zero);
- second.tv_sec = O_VAL(sp, O_MATCHTIME) / 10;
- second.tv_usec = (O_VAL(sp, O_MATCHTIME) % 10) * 100000L;
- (void)select(0, &zero, &zero, &zero, &second);
-
- /* Return to the current location. */
- sp->lno = m.lno;
- sp->cno = m.cno;
- (void)sp->s_refresh(sp, ep);
-}
-
-/*
- * txt_margin --
- * Handle margin wrap.
- */
-static int
-txt_margin(sp, tp, chp, wmtp, flags, didbreak)
- SCR *sp;
- TEXT *tp, *wmtp;
- CHAR_T *chp;
- int *didbreak;
- u_int flags;
-{
- size_t len, off;
- char *p, *wp;
-
- /* Find the nearest previous blank. */
- for (off = sp->cno - 1, p = tp->lb + off, len = 0;; --off, --p, ++len) {
- if (isblank(*p)) {
- wp = p + 1;
- break;
- }
-
- /*
- * If reach the start of the line, there's nowhere to break.
- *
- * !!!
- * Historic vi belled each time a character was entered after
- * crossing the margin until a space was entered which could
- * be used to break the line. I don't as it tends to wake the
- * cats.
- */
- if (off == tp->ai || off == tp->offset) {
- *didbreak = 0;
- return (0);
- }
- }
-
- /*
- * Store saved information about the rest of the line in the
- * wrapmargin TEXT structure.
- */
- wmtp->lb = p + 1;
- wmtp->len = len;
- wmtp->insert = LF_ISSET(TXT_APPENDEOL) ? tp->insert - 1 : tp->insert;
- wmtp->owrite = tp->owrite;
-
- /* Correct current bookkeeping information. */
- sp->cno -= len;
- if (LF_ISSET(TXT_APPENDEOL)) {
- tp->len -= len + tp->owrite + (tp->insert - 1);
- tp->insert = 1;
- } else {
- tp->len -= len + tp->owrite + tp->insert;
- tp->insert = 0;
- }
- tp->owrite = 0;
-
- /*
- * !!!
- * Delete any trailing whitespace from the current line.
- */
- for (;; --p, --off) {
- if (!isblank(*p))
- break;
- --sp->cno;
- --tp->len;
- if (off == tp->ai || off == tp->offset)
- break;
- }
- *didbreak = 1;
- return (0);
-}
-
-/*
- * txt_Rcleanup --
- * Resolve the input line for the 'R' command.
- */
-static void
-txt_Rcleanup(sp, tiqh, tp, lp, olen)
- SCR *sp;
- TEXTH *tiqh;
- TEXT *tp;
- const char *lp;
- const size_t olen;
-{
- TEXT *ttp;
- size_t ilen, tmp;
-
- /*
- * Check to make sure that the cursor hasn't moved beyond
- * the end of the line.
- */
- if (tp->owrite == 0)
- return;
-
- /*
- * Calculate how many characters the user has entered,
- * plus the blanks erased by <carriage-return>/<newline>s.
- */
- for (ttp = tiqh->cqh_first, ilen = 0;;) {
- ilen += ttp == tp ? sp->cno : ttp->len + ttp->R_erase;
- if ((ttp = ttp->q.cqe_next) == (void *)sp->tiqp)
- break;
- }
-
- /*
- * If the user has entered less characters than the original line
- * was long, restore any overwriteable characters to the original
- * characters, and make them insert characters. We don't copy them
- * anywhere, because the 'R' command doesn't have insert characters.
- */
- if (ilen < olen) {
- tmp = MIN(tp->owrite, olen - ilen);
- memmove(tp->lb + sp->cno, lp + ilen, tmp);
- tp->owrite -= tmp;
- tp->insert += tmp;
- }
-}
diff --git a/usr.bin/vi/vi/v_replace.c b/usr.bin/vi/vi/v_replace.c
deleted file mode 100644
index 92540242bd51..000000000000
--- a/usr.bin/vi/vi/v_replace.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_replace.c 8.18 (Berkeley) 5/21/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-/*
- * v_replace -- [count]rc
- *
- * !!!
- * The r command in historic vi was almost beautiful in its badness. For
- * example, "r<erase>" and "r<word erase>" beeped the terminal and deleted
- * a single character. "Nr<carriage return>", where N was greater than 1,
- * inserted a single carriage return. This may not be right, but at least
- * it's not insane.
- */
-int
-v_replace(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- CH ikey;
- TEXT *tp;
- recno_t lno;
- size_t blen, len;
- u_long cnt;
- int rval;
- char *bp, *p;
-
- /*
- * If the line doesn't exist, or it's empty, replacement isn't
- * allowed. It's not hard to implement, but:
- *
- * 1: It's historic practice.
- * 2: For consistency, this change would require that the more
- * general case, "Nr", when the user is < N characters from
- * the end of the line, also work.
- * 3: Replacing a newline has somewhat odd semantics.
- */
- if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno != 0) {
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
- goto nochar;
- }
- if (len == 0) {
-nochar: msgq(sp, M_BERR, "No characters to replace");
- return (1);
- }
-
- /*
- * Figure out how many characters to be replace. For no particular
- * reason (other than that the semantics of replacing the newline
- * are confusing) only permit the replacement of the characters in
- * the current line. I suppose we could append replacement characters
- * to the line, but I see no compelling reason to do so.
- */
- cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
- vp->m_stop.lno = vp->m_start.lno;
- vp->m_stop.cno = vp->m_start.cno + cnt - 1;
- if (vp->m_stop.cno > len - 1) {
- v_eol(sp, ep, &vp->m_start);
- return (1);
- }
-
- /*
- * Get the character. Literal escapes escape any character,
- * single escapes return.
- */
- if (F_ISSET(vp, VC_ISDOT)) {
- ikey.ch = VIP(sp)->rlast;
- ikey.value = KEY_VAL(sp, ikey.ch);
- } else {
- sp->showmode = "Replace char";
- (void)sp->s_refresh(sp, ep);
-
- if (term_key(sp, &ikey, 0) != INP_OK)
- return (1);
- switch (ikey.value) {
- case K_ESCAPE:
- return (0);
- case K_VLNEXT:
- if (term_key(sp, &ikey, 0) != INP_OK)
- return (1);
- break;
- }
- VIP(sp)->rlast = ikey.ch;
- }
-
- /* Copy the line. */
- GET_SPACE_RET(sp, bp, blen, len);
- memmove(bp, p, len);
- p = bp;
-
- if (ikey.value == K_CR || ikey.value == K_NL) {
- /* Set return line. */
- vp->m_stop.lno = vp->m_start.lno + cnt;
- vp->m_stop.cno = 0;
-
- /* The first part of the current line. */
- if (file_sline(sp, ep, vp->m_start.lno, p, vp->m_start.cno))
- goto err_ret;
-
- /*
- * The rest of the current line. And, of course, now it gets
- * tricky. Any white space after the replaced character is
- * stripped, and autoindent is applied. Put the cursor on the
- * last indent character as did historic vi.
- */
- for (p += vp->m_start.cno + cnt, len -= vp->m_start.cno + cnt;
- len && isblank(*p); --len, ++p);
-
- if ((tp = text_init(sp, p, len, len)) == NULL)
- goto err_ret;
- if (txt_auto(sp, ep, vp->m_start.lno, NULL, 0, tp))
- goto err_ret;
- vp->m_stop.cno = tp->ai ? tp->ai - 1 : 0;
- if (file_aline(sp, ep, 1, vp->m_start.lno, tp->lb, tp->len))
- goto err_ret;
- text_free(tp);
-
- rval = 0;
-
- /* All of the middle lines. */
- while (--cnt)
- if (file_aline(sp, ep, 1, vp->m_start.lno, "", 0)) {
-err_ret: rval = 1;
- break;
- }
- } else {
- memset(bp + vp->m_start.cno, ikey.ch, cnt);
- rval = file_sline(sp, ep, vp->m_start.lno, bp, len);
- }
- FREE_SPACE(sp, bp, blen);
-
- vp->m_final = vp->m_stop;
- return (rval);
-}
diff --git a/usr.bin/vi/vi/v_right.c b/usr.bin/vi/vi/v_right.c
deleted file mode 100644
index df7c85ca9fc8..000000000000
--- a/usr.bin/vi/vi/v_right.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_right.c 8.8 (Berkeley) 7/27/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-/*
- * v_right -- [count]' ', [count]l
- * Move right by columns.
- */
-int
-v_right(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t lno;
- size_t len;
-
- if (file_gline(sp, ep, vp->m_start.lno, &len) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno == 0)
- v_eol(sp, ep, NULL);
- else
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
-
- /* It's always illegal to move right on empty lines. */
- if (len == 0) {
- v_eol(sp, ep, NULL);
- return (1);
- }
-
- /*
- * Non-motion commands move to the end of the range. VC_D and
- * VC_Y stay at the start. Ignore VC_C and VC_DEF. Adjust the
- * end of the range for motion commands.
- *
- * !!!
- * Historically, "[cdsy]l" worked at the end of a line. Also,
- * EOL is a count sink.
- */
- vp->m_stop.cno = vp->m_start.cno +
- (F_ISSET(vp, VC_C1SET) ? vp->count : 1);
- if (vp->m_start.cno == len - 1 && !ISMOTION(vp)) {
- v_eol(sp, ep, NULL);
- return (1);
- }
- if (vp->m_stop.cno >= len) {
- vp->m_stop.cno = len - 1;
- vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
- } else if (ISMOTION(vp)) {
- --vp->m_stop.cno;
- vp->m_final = vp->m_start;
- } else
- vp->m_final = vp->m_stop;
- return (0);
-}
-
-/*
- * v_dollar -- [count]$
- * Move to the last column.
- */
-int
-v_dollar(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t lno;
- size_t len;
-
- /*
- * !!!
- * A count moves down count - 1 rows, so, "3$" is the same as "2j$".
- */
- if ((F_ISSET(vp, VC_C1SET) ? vp->count : 1) != 1) {
- /*
- * !!!
- * Historically, if the $ is a motion, and deleting from
- * at or before the first non-blank of the line, it's a
- * line motion, and the line motion flag is set.
- */
- vp->m_stop.cno = 0;
- if (nonblank(sp, ep, vp->m_start.lno, &vp->m_stop.cno))
- return (1);
- if (ISMOTION(vp) && vp->m_start.cno <= vp->m_stop.cno)
- F_SET(vp, VM_LMODE);
-
- --vp->count;
- if (v_down(sp, ep, vp))
- return (1);
- }
-
- if (file_gline(sp, ep, vp->m_stop.lno, &len) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno == 0)
- v_eol(sp, ep, NULL);
- else
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
-
- /*
- * Non-motion commands move to the end of the range. VC_D
- * and VC_Y stay at the start. Ignore VC_C and VC_DEF.
- */
- vp->m_stop.cno = len ? len - 1 : 0;
- vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
- return (0);
-}
diff --git a/usr.bin/vi/vi/v_screen.c b/usr.bin/vi/vi/v_screen.c
deleted file mode 100644
index 20ca6ba67a30..000000000000
--- a/usr.bin/vi/vi/v_screen.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_screen.c 8.12 (Berkeley) 8/8/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-/*
- * v_screen -- ^W
- * Switch screens.
- */
-int
-v_screen(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- /*
- * Try for the next lower screen, or, go back to the first
- * screen on the stack.
- */
- if (sp->q.cqe_next != (void *)&sp->gp->dq)
- sp->nextdisp = sp->q.cqe_next;
- else if (sp->gp->dq.cqh_first == sp) {
- msgq(sp, M_ERR, "No other screen to switch to");
- return (1);
- } else
- sp->nextdisp = sp->gp->dq.cqh_first;
-
- /*
- * Display the old screen's status line so the user can
- * find the screen they want.
- */
- (void)msg_status(sp, ep, vp->m_start.lno, 0);
-
- /* Save the old screen's cursor information. */
- sp->frp->lno = sp->lno;
- sp->frp->cno = sp->cno;
- F_SET(sp->frp, FR_CURSORSET);
-
- F_SET(sp, S_SSWITCH);
- return (0);
-}
diff --git a/usr.bin/vi/vi/v_search.c b/usr.bin/vi/vi/v_search.c
deleted file mode 100644
index 2ba013ae91f2..000000000000
--- a/usr.bin/vi/vi/v_search.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_search.c 8.32 (Berkeley) 7/27/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-static int correct __P((SCR *, EXF *, VICMDARG *, u_int));
-static int getptrn __P((SCR *, EXF *, ARG_CHAR_T, char **, size_t *));
-static int search __P((SCR *,
- EXF *, VICMDARG *, char *, size_t, u_int, enum direction));
-
-/*
- * v_searchn -- n
- * Repeat last search.
- */
-int
-v_searchn(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- return (search(sp, ep, vp, NULL, 0, SEARCH_MSG, sp->searchdir));
-}
-
-/*
- * v_searchN -- N
- * Reverse last search.
- */
-int
-v_searchN(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- enum direction dir;
-
- switch (sp->searchdir) {
- case BACKWARD:
- dir = FORWARD;
- break;
- case FORWARD:
- dir = BACKWARD;
- break;
- default: /* NOTSET handled in search(). */
- dir = sp->searchdir;
- break;
- }
- return (search(sp, ep, vp, NULL, 0, SEARCH_MSG, dir));
-}
-
-/*
- * v_searchb -- [count]?RE[? offset]
- * Search backward.
- */
-int
-v_searchb(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- size_t len;
- char *ptrn;
-
- if (F_ISSET(vp, VC_ISDOT))
- ptrn = NULL;
- else {
- if (getptrn(sp, ep, CH_BSEARCH, &ptrn, &len))
- return (1);
- if (len == 0) {
- F_SET(vp, VM_NOMOTION);
- return (0);
- }
- }
- return (search(sp, ep, vp, ptrn, len,
- SEARCH_MSG | SEARCH_PARSE | SEARCH_SET, BACKWARD));
-}
-
-/*
- * v_searchf -- [count]/RE[/ offset]
- * Search forward.
- */
-int
-v_searchf(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- size_t len;
- char *ptrn;
-
- if (F_ISSET(vp, VC_ISDOT))
- ptrn = NULL;
- else {
- if (getptrn(sp, ep, CH_FSEARCH, &ptrn, &len))
- return (1);
- if (len == 0) {
- F_SET(vp, VM_NOMOTION);
- return (0);
- }
- }
- return (search(sp, ep, vp, ptrn, len,
- SEARCH_MSG | SEARCH_PARSE | SEARCH_SET, FORWARD));
-}
-
-/*
- * v_searchw -- [count]^A
- * Search for the word under the cursor.
- */
-int
-v_searchw(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- size_t blen, len;
- int rval;
- char *bp;
-
- len = vp->kbuflen + sizeof(RE_WSTART) + sizeof(RE_WSTOP);
- GET_SPACE_RET(sp, bp, blen, len);
- (void)snprintf(bp, blen, "%s%s%s", RE_WSTART, vp->keyword, RE_WSTOP);
-
- rval = search(sp, ep, vp, bp, 0, SEARCH_MSG | SEARCH_TERM, FORWARD);
-
- FREE_SPACE(sp, bp, blen);
- return (rval);
-}
-
-static int
-search(sp, ep, vp, ptrn, len, flags, dir)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
- u_int flags;
- char *ptrn;
- size_t len;
- enum direction dir;
-{
- char *eptrn;
-
- if (ISMOTION(vp))
- flags |= SEARCH_EOL;
-
- for (;;) {
- switch (dir) {
- case BACKWARD:
- if (b_search(sp, ep,
- &vp->m_start, &vp->m_stop, ptrn, &eptrn, &flags))
- return (1);
- break;
- case FORWARD:
- if (f_search(sp, ep,
- &vp->m_start, &vp->m_stop, ptrn, &eptrn, &flags))
- return (1);
- break;
- case NOTSET:
- msgq(sp, M_ERR, "No previous search pattern");
- return (1);
- default:
- abort();
- }
-
- /*
- * !!!
- * Historically, vi permitted trailing <blank>'s, multiple
- * search strings (separated by semi-colons) and full-blown
- * z commands after / and ? search strings. In the case of
- * multiple search strings, leading <blank>'s on the second
- * and subsequent strings was eaten as well.
- *
- * !!!
- * However, the command "/STRING/; " failed, apparently it
- * confused the parser. We're not *that* compatible.
- *
- * The N, n, and ^A commands also get to here, but they've
- * set ptrn to NULL, len to 0, or the SEARCH_TERM flag, or
- * some combination thereof.
- */
- if (ptrn == NULL || len == 0)
- break;
- len -= eptrn - ptrn;
- for (; len > 0 && isblank(*eptrn); ++eptrn, --len);
- if (len == 0)
- break;
-
- switch (*eptrn) {
- case ';':
- for (++eptrn; --len > 0 && isblank(*eptrn); ++eptrn);
- ptrn = eptrn;
- switch (*eptrn) {
- case '/':
- dir = FORWARD;
- break;
- case '?':
- dir = BACKWARD;
- break;
- default:
- goto usage;
- }
- ptrn = eptrn;
- vp->m_start = vp->m_stop;
- continue;
- case 'z':
- if (term_push(sp, eptrn, len, CH_NOMAP | CH_QUOTED))
- return (1);
- goto ret;
- default:
-usage: msgq(sp, M_ERR,
- "Characters after search string and/or delta");
- return (1);
- }
- }
-
- /* Non-motion commands move to the end of the range. */
-ret: if (ISMOTION(vp)) {
- if (correct(sp, ep, vp, flags))
- return (1);
- } else
- vp->m_final = vp->m_stop;
- return (0);
-}
-
-/*
- * getptrn --
- * Get the search pattern.
- */
-static int
-getptrn(sp, ep, prompt, ptrnp, lenp)
- SCR *sp;
- EXF *ep;
- ARG_CHAR_T prompt;
- char **ptrnp;
- size_t *lenp;
-{
- TEXT *tp;
-
- if (sp->s_get(sp, ep, sp->tiqp, prompt,
- TXT_BS | TXT_CR | TXT_ESCAPE | TXT_PROMPT) != INP_OK)
- return (1);
-
- /* Len is 0 if backspaced over the prompt, 1 if only CR entered. */
- tp = sp->tiqp->cqh_first;
- *ptrnp = tp->lb;
- *lenp = tp->len;
- return (0);
-}
-
-/*
- * correct --
- * Handle command with a search as the motion.
- *
- * !!!
- * Historically, commands didn't affect the line searched to/from if the
- * motion command was a search and the final position was the start/end
- * of the line. There were some special cases and vi was not consistent;
- * it was fairly easy to confuse it. For example, given the two lines:
- *
- * abcdefghi
- * ABCDEFGHI
- *
- * placing the cursor on the 'A' and doing y?$ would so confuse it that 'h'
- * 'k' and put would no longer work correctly. In any case, we try to do
- * the right thing, but it's not going to exactly match historic practice.
- */
-static int
-correct(sp, ep, vp, flags)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
- u_int flags;
-{
- enum direction dir;
- MARK m;
- size_t len;
-
- /*
- * !!!
- * We may have wrapped if wrapscan was set, and we may have returned
- * to the position where the cursor started. Historic vi didn't cope
- * with this well. Yank wouldn't beep, but the first put after the
- * yank would move the cursor right one column (without adding any
- * text) and the second would put a copy of the current line. The
- * change and delete commands would beep, but would leave the cursor
- * on the colon command line. I believe that there are macros that
- * depend on delete, at least, failing. For now, commands that use
- * search as a motion component fail when the search returns to the
- * original cursor position.
- */
- if (vp->m_start.lno == vp->m_stop.lno &&
- vp->m_start.cno == vp->m_stop.cno) {
- msgq(sp, M_BERR, "Search wrapped to original position");
- return (1);
- }
-
- /*
- * !!!
- * Searches become line mode operations if there was a delta
- * specified to the search pattern.
- */
- if (LF_ISSET(SEARCH_DELTA))
- F_SET(vp, VM_LMODE);
-
- /*
- * If the motion is in the reverse direction, switch the start and
- * stop MARK's so that it's in a forward direction. (There's no
- * reason for this other than to make the tests below easier. The
- * code in vi.c:vi() would have done the switch.) Both forward
- * and backward motions can happen for any kind of search command
- * because of the wrapscan option.
- */
- if (vp->m_start.lno > vp->m_stop.lno ||
- vp->m_start.lno == vp->m_stop.lno &&
- vp->m_start.cno > vp->m_stop.cno) {
- dir = BACKWARD;
- m = vp->m_start;
- vp->m_start = vp->m_stop;
- vp->m_stop = m;
- } else
- dir = FORWARD;
-
- /*
- * BACKWARD:
- * VC_D commands move to the end of the range. VC_Y stays at
- * the start unless the end of the range is on a different line,
- * when it moves to the end of the range. Ignore VC_C and
- * VC_DEF.
- *
- * FORWARD:
- * VC_D and VC_Y commands don't move. Ignore VC_C and VC_DEF.
- */
- if (dir == BACKWARD)
- if (F_ISSET(vp, VC_D) ||
- F_ISSET(vp, VC_Y) && vp->m_start.lno != vp->m_stop.lno)
- vp->m_final = vp->m_start;
- else
- vp->m_final = vp->m_stop;
- else
- vp->m_final = vp->m_start;
-
- /*
- * !!!
- * Backward searches starting at column 0, and forward searches ending
- * at column 0 are corrected to the last column of the previous line.
- * Otherwise, adjust the starting/ending point to the character before
- * the current one (this is safe because we know the search had to move
- * to succeed).
- *
- * Searches become line mode operations if they start at column 0 and
- * end at column 0 of another line.
- */
- if (vp->m_start.lno < vp->m_stop.lno && vp->m_stop.cno == 0) {
- if (file_gline(sp, ep, --vp->m_stop.lno, &len) == NULL) {
- GETLINE_ERR(sp, vp->m_stop.lno);
- return (1);
- }
- if (vp->m_start.cno == 0)
- F_SET(vp, VM_LMODE);
- vp->m_stop.cno = len ? len - 1 : 0;
- } else
- --vp->m_stop.cno;
-
- return (0);
-}
diff --git a/usr.bin/vi/vi/v_status.c b/usr.bin/vi/vi/v_status.c
deleted file mode 100644
index 5ea544c7e2a8..000000000000
--- a/usr.bin/vi/vi/v_status.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_status.c 8.16 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-/*
- * v_status -- ^G
- * Show the file status.
- */
-int
-v_status(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
-
- /*
- * ^G in historic vi reset the cursor column to the first
- * non-blank character in the line. This doesn't seem of
- * any usefulness whatsoever, so I don't bother.
- */
- return (msg_status(sp, ep, vp->m_start.lno, 1));
-}
diff --git a/usr.bin/vi/vi/v_text.c b/usr.bin/vi/vi/v_text.c
deleted file mode 100644
index e6c940a7bf93..000000000000
--- a/usr.bin/vi/vi/v_text.c
+++ /dev/null
@@ -1,883 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_text.c 8.40 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-/*
- * !!!
- * Repeated input in the historic vi is mostly wrong and this isn't very
- * backward compatible. For example, if the user entered "3Aab\ncd" in
- * the historic vi, the "ab" was repeated 3 times, and the "\ncd" was then
- * appended to the result. There was also a hack which I don't remember
- * right now, where "3o" would open 3 lines and then let the user fill them
- * in, to make screen movements on 300 baud modems more tolerable. I don't
- * think it's going to be missed.
- *
- * !!!
- * There's a problem with the way that we do logging for change commands with
- * implied motions (e.g. A, I, O, cc, etc.). Since the main vi loop logs the
- * starting cursor position before the change command "moves" the cursor, the
- * cursor position to which we return on undo will be where the user entered
- * the change command, not the start of the change. Several of the following
- * routines re-log the cursor to make this work correctly. Historic vi tried
- * to do the same thing, and mostly got it right. (The only spectacular way
- * it fails is if the user entered 'o' from anywhere but the last character of
- * the line, the undo returned the cursor to the start of the line. If the
- * user was on the last character of the line, the cursor returned to that
- * position.) We also check for mapped keys waiting, i.e. if we're in the
- * middle of a map, don't bother logging the cursor.
- */
-#define LOG_CORRECT { \
- if (!MAPPED_KEYS_WAITING(sp)) \
- (void)log_cursor(sp, ep); \
-}
-#define LOG_CORRECT_FIRST { \
- if (first == 1) { \
- LOG_CORRECT; \
- first = 0; \
- } \
-}
-
-static u_int set_txt_std __P((SCR *, VICMDARG *, u_int));
-static int v_CS __P((SCR *, EXF *, VICMDARG *, u_int));
-
-/*
- * v_iA -- [count]A
- * Append text to the end of the line.
- */
-int
-v_iA(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t lno;
- u_long cnt;
- size_t len;
- u_int flags;
- int first;
- char *p;
-
- sp->showmode = "Append";
- flags = set_txt_std(sp, vp, TXT_APPENDEOL);
- for (first = 1, lno = vp->m_start.lno,
- cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
- /* Move the cursor to the end of the line + 1. */
- if ((p = file_gline(sp, ep, lno, &len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno != 0) {
- GETLINE_ERR(sp, lno);
- return (1);
- }
- lno = 1;
- len = 0;
- } else {
- /* Correct logging for implied cursor motion. */
- if (first == 1) {
- sp->cno = len == 0 ? 0 : len - 1;
- LOG_CORRECT;
- first = 0;
- }
-
- /* Start the change after the line. */
- sp->cno = len;
- }
-
- if (v_ntext(sp, ep,
- sp->tiqp, NULL, p, len, &vp->m_final, 0, OOBLNO, flags))
- return (1);
-
- flags = set_txt_std(sp, vp, TXT_APPENDEOL | TXT_REPLAY);
- sp->lno = lno = vp->m_final.lno;
- sp->cno = vp->m_final.cno;
- }
- return (0);
-}
-
-/*
- * v_ia -- [count]a
- * Append text to the cursor position.
- */
-int
-v_ia(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t lno;
- u_long cnt;
- u_int flags;
- size_t len;
- char *p;
-
- sp->showmode = "Append";
- flags = set_txt_std(sp, vp, 0);
- for (lno = vp->m_start.lno,
- cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
- /*
- * Move the cursor one column to the right and
- * repaint the screen.
- */
- if ((p = file_gline(sp, ep, lno, &len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno != 0) {
- GETLINE_ERR(sp, lno);
- return (1);
- }
- lno = 1;
- len = 0;
- LF_SET(TXT_APPENDEOL);
- } else if (len) {
- if (len == sp->cno + 1) {
- sp->cno = len;
- LF_SET(TXT_APPENDEOL);
- } else
- ++sp->cno;
- } else
- LF_SET(TXT_APPENDEOL);
-
- if (v_ntext(sp, ep,
- sp->tiqp, NULL, p, len, &vp->m_final, 0, OOBLNO, flags))
- return (1);
-
- flags = set_txt_std(sp, vp, TXT_REPLAY);
- sp->lno = lno = vp->m_final.lno;
- sp->cno = vp->m_final.cno;
- }
- return (0);
-}
-
-/*
- * v_iI -- [count]I
- * Insert text at the first non-blank character in the line.
- */
-int
-v_iI(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t lno;
- u_long cnt;
- size_t len;
- u_int flags;
- int first;
- char *p;
-
- sp->showmode = "Insert";
- flags = set_txt_std(sp, vp, 0);
- for (first = 1, lno = vp->m_start.lno,
- cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
- /*
- * Move the cursor to the start of the line and repaint
- * the screen.
- */
- if ((p = file_gline(sp, ep, lno, &len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno != 0) {
- GETLINE_ERR(sp, lno);
- return (1);
- }
- lno = 1;
- len = 0;
- } else {
- sp->cno = 0;
- if (nonblank(sp, ep, lno, &sp->cno))
- return (1);
-
- /* Correct logging for implied cursor motion. */
- LOG_CORRECT_FIRST;
- }
- if (len == 0)
- LF_SET(TXT_APPENDEOL);
-
- if (v_ntext(sp, ep,
- sp->tiqp, NULL, p, len, &vp->m_final, 0, OOBLNO, flags))
- return (1);
-
- flags = set_txt_std(sp, vp, TXT_REPLAY);
- sp->lno = lno = vp->m_final.lno;
- sp->cno = vp->m_final.cno;
- }
- return (0);
-}
-
-/*
- * v_ii -- [count]i
- * Insert text at the cursor position.
- */
-int
-v_ii(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t lno;
- u_long cnt;
- size_t len;
- u_int flags;
- char *p;
-
- sp->showmode = "Insert";
- flags = set_txt_std(sp, vp, 0);
- for (lno = vp->m_start.lno,
- cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
- if ((p = file_gline(sp, ep, lno, &len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno != 0) {
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
- lno = 1;
- len = 0;
- }
- /* If len == sp->cno, it's a replay caused by a count. */
- if (len == 0 || len == sp->cno)
- LF_SET(TXT_APPENDEOL);
-
- if (v_ntext(sp, ep,
- sp->tiqp, NULL, p, len, &vp->m_final, 0, OOBLNO, flags))
- return (1);
-
- /*
- * On replay, if the line isn't empty, advance the insert
- * by one (make it an append).
- */
- flags = set_txt_std(sp, vp, TXT_REPLAY);
- sp->lno = lno = vp->m_final.lno;
- if ((sp->cno = vp->m_final.cno) != 0)
- ++sp->cno;
- }
- return (0);
-}
-
-/*
- * v_iO -- [count]O
- * Insert text above this line.
- */
-int
-v_iO(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t ai_line, lno;
- size_t len;
- u_long cnt;
- u_int flags;
- int first;
- char *p;
-
- sp->showmode = "Insert";
- flags = set_txt_std(sp, vp, TXT_APPENDEOL);
- for (first = 1, cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
- if (sp->lno == 1) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno != 0)
- goto insert;
- p = NULL;
- len = 0;
- ai_line = OOBLNO;
- } else {
-insert: p = "";
- sp->cno = 0;
-
- /* Correct logging for implied cursor motion. */
- LOG_CORRECT_FIRST;
-
- if (file_iline(sp, ep, sp->lno, p, 0))
- return (1);
- if ((p = file_gline(sp, ep, sp->lno, &len)) == NULL) {
- GETLINE_ERR(sp, sp->lno);
- return (1);
- }
- ai_line = sp->lno + 1;
- }
-
- if (v_ntext(sp, ep,
- sp->tiqp, NULL, p, len, &vp->m_final, 0, ai_line, flags))
- return (1);
-
- flags = set_txt_std(sp, vp, TXT_APPENDEOL | TXT_REPLAY);
- sp->lno = lno = vp->m_final.lno;
- sp->cno = vp->m_final.cno;
- }
- return (0);
-}
-
-/*
- * v_io -- [count]o
- * Insert text after this line.
- */
-int
-v_io(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t ai_line, lno;
- size_t len;
- u_long cnt;
- u_int flags;
- int first;
- char *p;
-
- sp->showmode = "Insert";
- flags = set_txt_std(sp, vp, TXT_APPENDEOL);
- for (first = 1,
- cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
- if (sp->lno == 1) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno != 0)
- goto insert;
- p = NULL;
- len = 0;
- ai_line = OOBLNO;
- } else {
-insert: p = "";
- sp->cno = 0;
-
- /* Correct logging for implied cursor motion. */
- LOG_CORRECT_FIRST;
-
- len = 0;
- if (file_aline(sp, ep, 1, sp->lno, p, len))
- return (1);
- if ((p = file_gline(sp, ep, ++sp->lno, &len)) == NULL) {
- GETLINE_ERR(sp, sp->lno);
- return (1);
- }
- ai_line = sp->lno - 1;
- }
-
- if (v_ntext(sp, ep,
- sp->tiqp, NULL, p, len, &vp->m_final, 0, ai_line, flags))
- return (1);
-
- flags = set_txt_std(sp, vp, TXT_APPENDEOL | TXT_REPLAY);
- sp->lno = lno = vp->m_final.lno;
- sp->cno = vp->m_final.cno;
- }
- return (0);
-}
-
-/*
- * v_Change -- [buffer][count]C
- * Change line command.
- */
-int
-v_Change(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- return (v_CS(sp, ep, vp, 0));
-}
-
-/*
- * v_Subst -- [buffer][count]S
- * Line substitute command.
- */
-int
-v_Subst(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- u_int flags;
-
- /*
- * The S command is the same as a 'C' command from the beginning
- * of the line. This is hard to do in the parser, so do it here.
- *
- * If autoindent is on, the change is from the first *non-blank*
- * character of the line, not the first character. And, to make
- * it just a bit more exciting, the initial space is handled as
- * auto-indent characters.
- */
- LF_INIT(0);
- if (O_ISSET(sp, O_AUTOINDENT)) {
- vp->m_start.cno = 0;
- if (nonblank(sp, ep, vp->m_start.lno, &vp->m_start.cno))
- return (1);
- LF_SET(TXT_AICHARS);
- } else
- vp->m_start.cno = 0;
- sp->cno = vp->m_start.cno;
- return (v_CS(sp, ep, vp, flags));
-}
-
-/*
- * v_CS --
- * C and S commands.
- */
-static int
-v_CS(sp, ep, vp, iflags)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
- u_int iflags;
-{
- MARK *tm;
- recno_t lno;
- size_t len;
- char *p;
- u_int flags;
-
- sp->showmode = "Change";
- flags = set_txt_std(sp, vp, iflags);
-
- /*
- * There are two cases -- if a count is supplied, we do a line
- * mode change where we delete the lines and then insert text
- * into a new line. Otherwise, we replace the current line.
- */
- vp->m_stop.lno =
- vp->m_start.lno + (F_ISSET(vp, VC_C1SET) ? vp->count - 1 : 0);
- if (vp->m_start.lno != vp->m_stop.lno) {
- /* Make sure that the to line is real. */
- if (file_gline(sp, ep,
- vp->m_stop.lno, &vp->m_stop.cno) == NULL) {
- v_eof(sp, ep, &vp->m_start);
- return (1);
- }
- if (vp->m_stop.cno != 0)
- --vp->m_stop.cno;
-
- /*
- * Cut the lines.
- *
- * !!!
- * Historic practice, C and S did not cut into the numeric
- * buffers, only the unnamed one.
- */
- if (cut(sp, ep,
- F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
- &vp->m_start, &vp->m_stop, CUT_LINEMODE))
- return (1);
-
- /* Insert a line while we still can... */
- if (file_iline(sp, ep, vp->m_start.lno, "", 0))
- return (1);
- ++vp->m_start.lno;
- ++vp->m_stop.lno;
-
- /* Delete the lines. */
- if (delete(sp, ep, &vp->m_start, &vp->m_stop, 1))
- return (1);
-
- /* Get the inserted line. */
- if ((p = file_gline(sp, ep, --vp->m_start.lno, &len)) == NULL) {
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
- tm = NULL;
- sp->lno = vp->m_start.lno;
- sp->cno = 0;
- LF_SET(TXT_APPENDEOL);
- } else {
- /* The line may be empty, but that's okay. */
- if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno != 0) {
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
- vp->m_stop.cno = len = 0;
- LF_SET(TXT_APPENDEOL);
- } else {
- if (len == 0) {
- vp->m_stop.cno = 0;
- LF_SET(TXT_APPENDEOL);
- } else
- vp->m_stop.cno = len - 1;
- /*
- * !!!
- * Historic practice, C and S did not cut into the
- * numeric buffers, only the unnamed one.
- */
- if (cut(sp, ep,
- F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
- &vp->m_start, &vp->m_stop, CUT_LINEMODE))
- return (1);
- LF_SET(TXT_EMARK | TXT_OVERWRITE);
- }
- tm = &vp->m_stop;
- }
-
- /* Correct logging for implied cursor motion. */
- LOG_CORRECT;
-
- return (v_ntext(sp, ep,
- sp->tiqp, tm, p, len, &vp->m_final, 0, OOBLNO, flags));
-}
-
-/*
- * v_change -- [buffer][count]c[count]motion
- * Change command.
- */
-int
-v_change(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t lno;
- size_t blen, len;
- u_int flags;
- int lmode, rval;
- char *bp, *p;
-
- sp->showmode = "Change";
- flags = set_txt_std(sp, vp, 0);
-
- /*
- * Move the cursor to the start of the change. Note, if autoindent
- * is turned on, the cc command in line mode changes from the first
- * *non-blank* character of the line, not the first character. And,
- * to make it just a bit more exciting, the initial space is handled
- * as auto-indent characters.
- */
- lmode = F_ISSET(vp, VM_LMODE) ? CUT_LINEMODE : 0;
- if (lmode) {
- vp->m_start.cno = 0;
- if (O_ISSET(sp, O_AUTOINDENT)) {
- if (nonblank(sp, ep, vp->m_start.lno, &vp->m_start.cno))
- return (1);
- LF_SET(TXT_AICHARS);
- }
- }
- sp->lno = vp->m_start.lno;
- sp->cno = vp->m_start.cno;
-
- /* Correct logging for implied cursor motion. */
- LOG_CORRECT;
-
- /*
- * Turn off the VM_RCM flags, inserting text has its own rules for
- * cursor positioning.
- */
- F_CLR(vp, VM_RCM_MASK);
-
- /*
- * If not in line mode and changing within a single line, the line
- * either currently has text or it doesn't. If it doesn't, insert
- * some. Otherwise, copy it and overwrite it.
- */
- if (!lmode && vp->m_start.lno == vp->m_stop.lno) {
- if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) {
- if (p == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno != 0) {
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
- }
- vp->m_stop.cno = len = 0;
- LF_SET(TXT_APPENDEOL);
- } else {
- /*
- * !!!
- * Historic practice, c cut into the numeric buffers,
- * as well as the unnamed one.
- */
- if (cut(sp, ep,
- F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
- &vp->m_start, &vp->m_stop, lmode | CUT_NUMOPT))
- return (1);
- if (len == 0)
- LF_SET(TXT_APPENDEOL);
- LF_SET(TXT_EMARK | TXT_OVERWRITE);
- }
- return (v_ntext(sp, ep, sp->tiqp,
- &vp->m_stop, p, len, &vp->m_final, 0, OOBLNO, flags));
- }
-
- /*
- * It's trickier if changing over multiple lines. If we're in
- * line mode we delete all of the lines and insert a replacement
- * line which the user edits. If there was leading whitespace
- * in the first line being changed, we copy it and use it as the
- * replacement. If we're not in line mode, we just delete the
- * text and start inserting.
- *
- * !!!
- * Historic practice, c cut into the numeric buffers, as well as the
- * unnamed one.
- *
- * Copy the text.
- */
- if (cut(sp, ep,
- F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
- &vp->m_start, &vp->m_stop, lmode | CUT_NUMOPT))
- return (1);
-
- /* If replacing entire lines and there's leading text. */
- if (lmode && vp->m_start.cno) {
- /* Get a copy of the first line changed. */
- if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) {
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
- /* Copy the leading text elsewhere. */
- GET_SPACE_RET(sp, bp, blen, vp->m_start.cno);
- memmove(bp, p, vp->m_start.cno);
- } else
- bp = NULL;
-
- /* Delete the text. */
- if (delete(sp, ep, &vp->m_start, &vp->m_stop, lmode))
- return (1);
-
- /* If replacing entire lines, insert a replacement line. */
- if (lmode) {
- if (file_iline(sp, ep, vp->m_start.lno, bp, vp->m_start.cno))
- return (1);
- sp->lno = vp->m_start.lno;
- len = sp->cno = vp->m_start.cno;
- }
-
- /* Get the line we're editing. */
- if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno != 0) {
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
- len = 0;
- }
-
- /* Check to see if we're appending to the line. */
- if (vp->m_start.cno >= len)
- LF_SET(TXT_APPENDEOL);
-
- rval = v_ntext(sp, ep,
- sp->tiqp, NULL, p, len, &vp->m_final, 0, OOBLNO, flags);
-
- if (bp != NULL)
- FREE_SPACE(sp, bp, blen);
- return (rval);
-}
-
-/*
- * v_Replace -- [count]R
- * Overwrite multiple characters.
- */
-int
-v_Replace(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t lno;
- u_long cnt;
- size_t len;
- u_int flags;
- char *p;
-
- sp->showmode = "Replace";
- flags = set_txt_std(sp, vp, 0);
-
- cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
- if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno != 0) {
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
- len = 0;
- LF_SET(TXT_APPENDEOL);
- } else {
- if (len == 0)
- LF_SET(TXT_APPENDEOL);
- LF_SET(TXT_OVERWRITE | TXT_REPLACE);
- }
- vp->m_stop.lno = vp->m_start.lno;
- vp->m_stop.cno = len ? len - 1 : 0;
- if (v_ntext(sp, ep, sp->tiqp,
- &vp->m_stop, p, len, &vp->m_final, 0, OOBLNO, flags))
- return (1);
-
- /*
- * Special case. The historic vi handled [count]R badly, in that R
- * would replace some number of characters, and then the count would
- * append count-1 copies of the replacing chars to the replaced space.
- * This seems wrong, so this version counts R commands. There is some
- * trickiness in moving back to where the user stopped replacing after
- * each R command. Basically, if the user ended with a newline, we
- * want to use vp->m_final.cno (which will be 0). Otherwise, use the
- * column after the returned cursor, unless it would be past the end of
- * the line, in which case we append to the line.
- */
- while (--cnt) {
- if ((p = file_gline(sp, ep, vp->m_final.lno, &len)) == NULL)
- GETLINE_ERR(sp, vp->m_final.lno);
- flags = set_txt_std(sp, vp, TXT_REPLAY);
-
- sp->lno = vp->m_final.lno;
-
- if (len == 0 || vp->m_final.cno == len - 1) {
- sp->cno = len;
- LF_SET(TXT_APPENDEOL);
- } else {
- sp->cno = vp->m_final.cno;
- if (vp->m_final.cno != 0)
- ++sp->cno;
- LF_SET(TXT_OVERWRITE | TXT_REPLACE);
- }
-
- vp->m_stop.lno = sp->lno;
- vp->m_stop.cno = sp->cno;
- if (v_ntext(sp, ep, sp->tiqp,
- &vp->m_stop, p, len, &vp->m_final, 0, OOBLNO, flags))
- return (1);
- }
- return (0);
-}
-
-/*
- * v_subst -- [buffer][count]s
- * Substitute characters.
- */
-int
-v_subst(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t lno;
- size_t len;
- u_int flags;
- char *p;
-
- sp->showmode = "Change";
- flags = set_txt_std(sp, vp, 0);
- if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno != 0) {
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
- len = 0;
- LF_SET(TXT_APPENDEOL);
- } else {
- if (len == 0)
- LF_SET(TXT_APPENDEOL);
- LF_SET(TXT_EMARK | TXT_OVERWRITE);
- }
-
- vp->m_stop.lno = vp->m_start.lno;
- vp->m_stop.cno =
- vp->m_start.cno + (F_ISSET(vp, VC_C1SET) ? vp->count - 1 : 0);
- if (vp->m_stop.cno > len - 1)
- vp->m_stop.cno = len - 1;
-
- if (p != NULL && cut(sp, ep,
- F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
- &vp->m_start, &vp->m_stop, 0))
- return (1);
-
- return (v_ntext(sp, ep, sp->tiqp,
- &vp->m_stop, p, len, &vp->m_final, 0, OOBLNO, flags));
-}
-
-/*
- * set_txt_std --
- * Initialize text processing flags.
- */
-static u_int
-set_txt_std(sp, vp, init)
- SCR *sp;
- VICMDARG *vp;
- u_int init;
-{
- u_int flags;
-
- /* Text operations are all interruptible. */
- F_SET(sp, S_INTERRUPTIBLE);
-
- LF_INIT(init);
- LF_SET(TXT_CNTRLT |
- TXT_ESCAPE | TXT_MAPINPUT | TXT_RECORD | TXT_RESOLVE);
- if (O_ISSET(sp, O_ALTWERASE))
- LF_SET(TXT_ALTWERASE);
- if (O_ISSET(sp, O_AUTOINDENT))
- LF_SET(TXT_AUTOINDENT);
- if (O_ISSET(sp, O_BEAUTIFY))
- LF_SET(TXT_BEAUTIFY);
- if (O_ISSET(sp, O_SHOWMATCH))
- LF_SET(TXT_SHOWMATCH);
- if (O_ISSET(sp, O_WRAPMARGIN))
- LF_SET(TXT_WRAPMARGIN);
- if (F_ISSET(sp, S_SCRIPT))
- LF_SET(TXT_CR);
- if (O_ISSET(sp, O_TTYWERASE))
- LF_SET(TXT_TTYWERASE);
- if (F_ISSET(vp, VC_ISDOT))
- LF_SET(TXT_REPLAY);
- return (flags);
-}
diff --git a/usr.bin/vi/vi/v_ulcase.c b/usr.bin/vi/vi/v_ulcase.c
deleted file mode 100644
index 684a7f5a73d8..000000000000
--- a/usr.bin/vi/vi/v_ulcase.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_ulcase.c 8.10 (Berkeley) 8/17/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-static int ulcase __P((SCR *, EXF *,
- recno_t, CHAR_T *, size_t, size_t, size_t));
-
-/*
- * v_ulcase -- [count]~
- * Toggle upper & lower case letters.
- *
- * !!!
- * Historic vi didn't permit ~ to cross newline boundaries. I can
- * think of no reason why it shouldn't, which at least lets the user
- * auto-repeat through a paragraph.
- *
- * !!!
- * In historic vi, the count was ignored. It would have been better
- * if there had been an associated motion, but it's too late to make
- * that the default now.
- */
-int
-v_ulcase(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t lno;
- size_t cno, lcnt, len;
- u_long cnt;
- char *p;
-
- len = 0;
- lno = vp->m_start.lno;
- cno = vp->m_start.cno;
-
- /* EOF is an infinite count sink. */
- for (cnt =
- F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt > 0; cno = 0, ++lno) {
- if ((p = file_gline(sp, ep, lno, &len)) == NULL)
- break;
-
- /* Empty lines decrement the count by one. */
- if (len == 0) {
- --cnt;
- vp->m_final.lno = lno + 1;
- vp->m_final.cno = 0;
- } else {
- if (cno + cnt >= len) {
- lcnt = len - 1;
- cnt -= len - cno;
-
- vp->m_final.lno = lno + 1;
- vp->m_final.cno = 0;
- } else {
- lcnt = cno + cnt - 1;
- cnt = 0;
-
- vp->m_final.lno = lno;
- vp->m_final.cno = lcnt + 1;
- }
-
- if (ulcase(sp, ep, lno, p, len, cno, lcnt))
- return (1);
- }
- }
-
- /* Check to see if we tried to move past EOF. */
- if (file_gline(sp, ep, vp->m_final.lno, &len) == NULL) {
- /* line number start with 1, lno zero is illegal */
- if (vp->m_final.lno > 1)
- --vp->m_final.lno;
- (void)file_gline(sp, ep, vp->m_final.lno, &len);
- vp->m_final.cno = len == 0 ? 0 : len - 1;
- }
- return (0);
-}
-
-/*
- * v_mulcase -- [count]~[count]motion
- * Toggle upper & lower case letters over a range.
- */
-int
-v_mulcase(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- CHAR_T *p;
- size_t len;
- recno_t lno;
-
- for (lno = vp->m_start.lno;;) {
- if ((p = file_gline(sp, ep, lno, &len)) == NULL) {
- GETLINE_ERR(sp, lno);
- return (1);
- }
- if (len != 0 &&
- ulcase(sp, ep, lno, p, len,
- lno == vp->m_start.lno ? vp->m_start.cno : 0,
- !F_ISSET(vp, VM_LMODE) &&
- lno == vp->m_stop.lno ? vp->m_stop.cno : len))
- return (1);
-
- if (++lno > vp->m_stop.lno)
- break;
- }
-
- /*
- * XXX
- * I didn't create a new motion command when I added motion semantics
- * for ~. While that's the correct way to do it, that choice would
- * have required changes all over the vi directory for little gain.
- * Instead, we pretend it's a yank command. Note, this means that we
- * follow the cursor motion rules for yank commands, but that seems
- * reasonable to me.
- */
- return (0);
-}
-
-/*
- * ulcase --
- * Change part of a line's case.
- */
-static int
-ulcase(sp, ep, lno, lp, len, scno, ecno)
- SCR *sp;
- EXF *ep;
- recno_t lno;
- CHAR_T *lp;
- size_t len, scno, ecno;
-{
- size_t blen;
- int change, rval;
- CHAR_T ch, *p, *t;
- char *bp;
-
- GET_SPACE_RET(sp, bp, blen, len);
- memmove(bp, lp, len);
-
- change = rval = 0;
- for (p = bp + scno, t = bp + ecno + 1; p < t; ++p) {
- ch = *(u_char *)p;
- if (islower(ch)) {
- *p = toupper(ch);
- change = 1;
- } else if (isupper(ch)) {
- *p = tolower(ch);
- change = 1;
- }
- }
-
- if (change && file_sline(sp, ep, lno, bp, len))
- rval = 1;
-
- FREE_SPACE(sp, bp, blen);
- return (rval);
-}
diff --git a/usr.bin/vi/vi/v_util.c b/usr.bin/vi/vi/v_util.c
deleted file mode 100644
index d7defa8c3db4..000000000000
--- a/usr.bin/vi/vi/v_util.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_util.c 8.10 (Berkeley) 7/18/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-/*
- * v_eof --
- * Vi end-of-file error.
- */
-void
-v_eof(sp, ep, mp)
- SCR *sp;
- EXF *ep;
- MARK *mp;
-{
- recno_t lno;
-
- if (mp == NULL)
- msgq(sp, M_BERR, "Already at end-of-file");
- else {
- if (file_lline(sp, ep, &lno))
- return;
- if (mp->lno >= lno)
- msgq(sp, M_BERR, "Already at end-of-file");
- else
- msgq(sp, M_BERR, "Movement past the end-of-file");
- }
-}
-
-/*
- * v_eol --
- * Vi end-of-line error.
- */
-void
-v_eol(sp, ep, mp)
- SCR *sp;
- EXF *ep;
- MARK *mp;
-{
- size_t len;
-
- if (mp == NULL)
- msgq(sp, M_BERR, "Already at end-of-line");
- else {
- if (file_gline(sp, ep, mp->lno, &len) == NULL) {
- GETLINE_ERR(sp, mp->lno);
- return;
- }
- if (mp->cno == len - 1)
- msgq(sp, M_BERR, "Already at end-of-line");
- else
- msgq(sp, M_BERR, "Movement past the end-of-line");
- }
-}
-
-/*
- * v_nomove --
- * Vi no cursor movement error.
- */
-void
-v_nomove(sp)
- SCR *sp;
-{
- msgq(sp, M_BERR, "No cursor movement made");
-}
-
-/*
- * v_sof --
- * Vi start-of-file error.
- */
-void
-v_sof(sp, mp)
- SCR *sp;
- MARK *mp;
-{
- if (mp == NULL || mp->lno == 1)
- msgq(sp, M_BERR, "Already at the beginning of the file");
- else
- msgq(sp, M_BERR, "Movement past the beginning of the file");
-}
-
-/*
- * v_sol --
- * Vi start-of-line error.
- */
-void
-v_sol(sp)
- SCR *sp;
-{
- msgq(sp, M_BERR, "Already in the first column");
-}
-
-/*
- * v_isempty --
- * Return if the line contains nothing but white-space characters.
- */
-int
-v_isempty(p, len)
- char *p;
- size_t len;
-{
- for (; len--; ++p)
- if (!isblank(*p))
- return (0);
- return (1);
-}
diff --git a/usr.bin/vi/vi/v_xchar.c b/usr.bin/vi/vi/v_xchar.c
deleted file mode 100644
index 6bb317cd5f73..000000000000
--- a/usr.bin/vi/vi/v_xchar.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_xchar.c 8.8 (Berkeley) 5/21/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-/*
- * v_xchar -- [count]x
- * Deletes the character(s) on which the cursor sits.
- */
-int
-v_xchar(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t lno;
- size_t len;
-
- if (file_gline(sp, ep, vp->m_start.lno, &len) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno == 0)
- goto nodel;
- GETLINE_ERR(sp, vp->m_start.lno);
- return (1);
- }
- if (len == 0) {
-nodel: msgq(sp, M_BERR, "No characters to delete");
- return (1);
- }
-
- /*
- * Delete from the cursor toward the end of line, w/o moving the
- * cursor.
- *
- * !!!
- * Note, "2x" at EOL isn't the same as "xx" because the left movement
- * of the cursor as part of the 'x' command isn't taken into account.
- * Historically correct.
- */
- if (F_ISSET(vp, VC_C1SET))
- vp->m_stop.cno += vp->count - 1;
- if (vp->m_stop.cno >= len - 1) {
- vp->m_stop.cno = len - 1;
- vp->m_final.cno = vp->m_start.cno ? vp->m_start.cno - 1 : 0;
- } else
- vp->m_final.cno = vp->m_start.cno;
-
- if (cut(sp, ep,
- F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
- &vp->m_start, &vp->m_stop, 0))
- return (1);
- return (delete(sp, ep, &vp->m_start, &vp->m_stop, 0));
-}
-
-/*
- * v_Xchar -- [count]X
- * Deletes the character(s) immediately before the current cursor
- * position.
- */
-int
-v_Xchar(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- u_long cnt;
-
- if (vp->m_start.cno == 0) {
- v_sol(sp);
- return (1);
- }
-
- cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
- if (cnt >= vp->m_start.cno)
- vp->m_start.cno = 0;
- else
- vp->m_start.cno -= cnt;
- --vp->m_stop.cno;
- vp->m_final.cno = vp->m_start.cno;
-
- if (cut(sp, ep,
- F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
- &vp->m_start, &vp->m_stop, 0))
- return (1);
- return (delete(sp, ep, &vp->m_start, &vp->m_stop, 0));
-}
diff --git a/usr.bin/vi/vi/v_yank.c b/usr.bin/vi/vi/v_yank.c
deleted file mode 100644
index 14f99f57ce47..000000000000
--- a/usr.bin/vi/vi/v_yank.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_yank.c 8.14 (Berkeley) 5/17/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-/*
- * v_yank -- [buffer][count]Y
- * [buffer][count]y[count][motion]
- * Yank text (or lines of text) into a cut buffer.
- *
- * !!!
- * Historic vi moved the cursor to the from MARK if it was before the current
- * cursor and on a different line, e.g., "yj" moves the cursor but "yk" and
- * "yh" do not. Unfortunately, it's too late to change this now. Matching
- * the historic semantics isn't easy. The line number was always changed and
- * column movement was usually relative. However, "y'a" moved the cursor to
- * the first non-blank of the line marked by a, while "y`a" moved the cursor
- * to the line and column marked by a. Hopefully, the motion component code
- * got it right... Unlike delete, we make no adjustments here.
- */
-int
-v_yank(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- int lmode;
-
- /* The line may not exist in line mode cuts, check to be sure. */
- if (F_ISSET(vp, VM_LMODE)) {
- if (file_gline(sp, ep, vp->m_stop.lno, NULL) == NULL) {
- v_eof(sp, ep, &vp->m_start);
- return (1);
- }
- lmode = CUT_LINEMODE;
- } else
- lmode = 0;
- if (cut(sp, ep,
- F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
- &vp->m_start, &vp->m_stop, lmode))
- return (1);
-
- sp->rptlines[L_YANKED] += (vp->m_stop.lno - vp->m_start.lno) + 1;
- return (0);
-}
diff --git a/usr.bin/vi/vi/v_z.c b/usr.bin/vi/vi/v_z.c
deleted file mode 100644
index ca780f400055..000000000000
--- a/usr.bin/vi/vi/v_z.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_z.c 8.16 (Berkeley) 7/17/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-/*
- * v_z -- [count]z[count][-.+^<CR>]
- * Move the screen.
- */
-int
-v_z(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- recno_t last, lno;
- u_int value;
-
- /*
- * The first count is the line to use. If the value doesn't
- * exist, use the last line.
- */
- if (F_ISSET(vp, VC_C1SET)) {
- lno = vp->count;
- if (file_lline(sp, ep, &last))
- return (1);
- if (lno > last)
- lno = last;
- } else
- lno = vp->m_start.lno;
-
- /* Set default return cursor values. */
- vp->m_final.lno = lno;
- vp->m_final.cno = vp->m_start.cno;
-
- /*
- * The second count is the displayed window size, i.e. the 'z'
- * command is another way to get artificially small windows.
- *
- * !!!
- * A window size of 0 was historically allowed, and simply ignored.
- * Also, this could be much more simply done by modifying the value
- * of the O_WINDOW option, but that's not how it worked historically.
- */
- if (F_ISSET(vp, VC_C2SET) &&
- vp->count2 != 0 && sp->s_crel(sp, vp->count2))
- return (1);
-
- switch (vp->character) {
- case '-': /* Put the line at the bottom. */
- if (sp->s_fill(sp, ep, lno, P_BOTTOM))
- return (1);
- break;
- case '.': /* Put the line in the middle. */
- if (sp->s_fill(sp, ep, lno, P_MIDDLE))
- return (1);
- break;
- case '+':
- /*
- * If the user specified a line number, put that line at the
- * top and move the cursor to it. Otherwise, scroll forward
- * a screen from the current screen.
- */
- if (F_ISSET(vp, VC_C1SET)) {
- if (sp->s_fill(sp, ep, lno, P_TOP))
- return (1);
- if (sp->s_position(sp, ep, &vp->m_final, 0, P_TOP))
- return (1);
- } else
- if (sp->s_scroll(sp, ep,
- &vp->m_final, sp->t_rows, Z_PLUS))
- return (1);
- break;
- case '^':
- /*
- * If the user specified a line number, put that line at the
- * bottom, move the cursor to it, and then display the screen
- * before that one. Otherwise, scroll backward a screen from
- * the current screen.
- *
- * !!!
- * Note, we match the off-by-one characteristics of historic
- * vi, here.
- */
- if (F_ISSET(vp, VC_C1SET)) {
- if (sp->s_fill(sp, ep, lno, P_BOTTOM))
- return (1);
- if (sp->s_position(sp, ep, &vp->m_final, 0, P_TOP))
- return (1);
- if (sp->s_fill(sp, ep, vp->m_final.lno, P_BOTTOM))
- return (1);
- } else
- if (sp->s_scroll(sp, ep,
- &vp->m_final, sp->t_rows, Z_CARAT))
- return (1);
- break;
- default: /* Put the line at the top for <cr>. */
- value = KEY_VAL(sp, vp->character);
- if (value != K_CR && value != K_NL) {
- msgq(sp, M_ERR, "usage: %s", vp->kp->usage);
- return (1);
- }
- if (sp->s_fill(sp, ep, lno, P_TOP))
- return (1);
- break;
- }
-
-
- return (0);
-}
diff --git a/usr.bin/vi/vi/v_zexit.c b/usr.bin/vi/vi/v_zexit.c
deleted file mode 100644
index cd4aac715a35..000000000000
--- a/usr.bin/vi/vi/v_zexit.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)v_zexit.c 8.11 (Berkeley) 8/4/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "excmd.h"
-#include "vcmd.h"
-
-/*
- * v_zexit -- ZZ
- * Save the file and exit.
- */
-int
-v_zexit(sp, ep, vp)
- SCR *sp;
- EXF *ep;
- VICMDARG *vp;
-{
- /* Write back any modifications. */
- if (F_ISSET(ep, F_MODIFIED) &&
- file_write(sp, ep, NULL, NULL, NULL, FS_ALL))
- return (1);
-
- /* Check to make sure it's not a temporary file. */
- if (file_m3(sp, ep, 0))
- return (1);
-
- /* Check for more files to edit. */
- if (ex_ncheck(sp, 0))
- return (1);
-
- F_SET(sp, S_EXIT);
- return (0);
-}
diff --git a/usr.bin/vi/vi/vcmd.h b/usr.bin/vi/vi/vcmd.h
deleted file mode 100644
index 4c13076b4e5d..000000000000
--- a/usr.bin/vi/vi/vcmd.h
+++ /dev/null
@@ -1,346 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)vcmd.h 8.40 (Berkeley) 8/5/94
- */
-
-typedef struct _vikeys VIKEYS;
-
-/* Structure passed around to functions implementing vi commands. */
-typedef struct _vicmdarg {
-#define vp_startzero buffer /* START ZERO OUT. */
- CHAR_T key; /* Command key. */
- CHAR_T buffer; /* Buffer. */
- CHAR_T character; /* Character. */
- u_long count; /* Count. */
- u_long count2; /* Second count (only used by z). */
- VIKEYS const *kp; /* VIKEYS key. */
- size_t klen; /* Keyword length. */
-
- /*
- * Historic vi allowed "dl" when the cursor was on the last column,
- * deleting the last character, and similarly allowed "dw" when
- * the cursor was on the last column of the file. It didn't allow
- * "dh" when the cursor was on column 1, although these cases are
- * not strictly analogous. The point is that some movements would
- * succeed if they were associated with a motion command, and fail
- * otherwise. This is part of the off-by-1 schizophrenia that
- * plagued vi. Other examples are that "dfb" deleted everything
- * up to and including the next 'b' character, while "d/b" deleted
- * everything up to the next 'b' character. While this implementation
- * regularizes the interface to the extent possible, there are many
- * special cases that can't be fixed. The special cases are handled
- * by setting flags per command so that the underlying command and
- * motion routines know what's really going on.
- *
- * The VC_* and VM_* flags are set in the vikeys array, and the VM_*
- * flags may be set by the underlying functions (motion component or
- * command) as well. For this reason, the flags in the VICMDARG and
- * VIKEYS structures live in the same name space.
- */
-#define VC_C 0x00000001 /* The 'c' command. */
-#define VC_D 0x00000002 /* The 'd' command. */
-#define VC_DEF 0x00000004 /* The '<', '>' and '!' commands. */
-#define VC_Y 0x00000008 /* The 'y' command. */
-#define VC_COMMASK 0x0000000f /* Mask for VC flags. */
-#define ISMOTION(vp) F_ISSET(vp, VC_COMMASK)
-
-#define VM_CUTREQ 0x00000010 /* Always cut into numeric buffers. */
-#define VM_LDOUBLE 0x00000020 /* Doubled command for line mode. */
-#define VM_LMODE 0x00000040 /* Motion is line oriented. */
-#define VM_NOMOTION 0x00000080 /* Motion command not entered. */
-#define VM_COMMASK 0x000000f0 /* Mask for VM flags. */
-
- /*
- * The VM_RCM_* flags are single usage, i.e. if you set one, you have
- * to clear the others.
- */
-#define VM_RCM 0x00000100 /* Use relative cursor movment (RCM). */
-#define VM_RCM_SET 0x00000200 /* RCM: set to current position. */
-#define VM_RCM_SETFNB 0x00000400 /* RCM: set to first non-blank (FNB). */
-#define VM_RCM_SETLAST 0x00000800 /* RCM: set to last character. */
-#define VM_RCM_SETNNB 0x00001000 /* RCM: set to next non-blank. */
-#define VM_RCM_MASK 0x00001f00 /* Mask for RCM flags. */
-
- /* Flags for the underlying function. */
-#define VC_BUFFER 0x00002000 /* The buffer was set. */
-#define VC_C1RESET 0x00004000 /* Reset C1SET flag for dot commands. */
-#define VC_C1SET 0x00008000 /* Count 1 was set. */
-#define VC_C2SET 0x00010000 /* Count 2 was set. */
-#define VC_ISDOT 0x00020000 /* Command was the dot command. */
- u_int32_t flags;
-
-#define vp_endzero keyword /* END ZERO OUT. */
- char *keyword; /* Keyword. */
- size_t kbuflen; /* Keyword buffer length. */
- /*
- * There are four cursor locations that we worry about: the initial
- * cursor position, the start of the range, the end of the range,
- * and the final cursor position. The initial cursor position and
- * the start of the range are both m_start, and are always the same.
- * All locations are initialized to the starting cursor position by
- * the main vi routines, and the underlying functions depend on this.
- *
- * Commands that can be motion components set the end of the range
- * cursor position, m_stop. All commands must set the ending cursor
- * position, m_final. The reason that m_stop isn't the same as m_final
- * is that there are situations where the final position of the cursor
- * is outside of the cut/delete range (e.g. 'd[[' from the first column
- * of a line). The final cursor position often varies based on the
- * direction of the movement, as well as the command. The only special
- * case that the delete code handles is that it will make adjustments
- * if the final cursor position is deleted.
- *
- * The reason for all of this is that the historic vi semantics were
- * defined command-by-command. Every function has to roll its own
- * starting and stopping positions, and adjust them if it's being used
- * as a motion component. The general rules are as follows:
- * 1: If not a motion component, the final cursor is at the end
- * of the range.
- * 2: If moving backward in the file:
- * a: VC_D moves to the end of the range.
- * b: If the line hasn't changed, VC_Y doesn't move, else it
- * moves to the end of the range.
- * 3: If moving forward in the file, VC_D and VC_Y stay at the
- * start of the range.
- *
- * Usually, if moving backward in the file and it's a motion component,
- * the starting cursor is decremented by a single character (or, in a
- * few cases, to the end of the previous line) so that the starting
- * cursor character isn't cut or deleted. No cursor adjustment is
- * needed for moving forward, because the cut/delete routines handle
- * m_stop inclusively, i.e. the last character in the range is cut or
- * deleted. This makes cutting to the EOF/EOL reasonable.
- *
- * The 'c', '<', '>', and '!' commands are special cases. We ignore
- * the final cursor position for all of them: for 'c', the text input
- * routines set the cursor to the last character inserted; for '<',
- * '>' and '!', the underlying ex commands that do the operation will
- * set the cursor for us. We still need a VC_C flag because there are
- * special motion semantics that are associated with the 'c' command.
- * We don't need VC_ flags for the others, because, as far as I know,
- * there are no special semantics associated with their motions. So,
- * we group them under a single VC_ flag so that the standard motion
- * adjustments get done.
- */
- MARK m_start; /* mark: initial cursor, range start. */
- MARK m_stop; /* mark: range end. */
- MARK m_final; /* mark: final cursor position. */
-} VICMDARG;
-
-/* Vi command structure. */
-struct _vikeys { /* Underlying function. */
- int (*func) __P((SCR *, EXF *, VICMDARG *));
-#define V_ABS 0x00040000 /* Absolute movement, set '' mark. */
-#define V_ABS_C 0x00080000 /* V_ABS: if the line/column changed. */
-#define V_ABS_L 0x00100000 /* V_ABS: if the line changed. */
-#define V_CHAR 0x00200000 /* Character (required, trailing). */
-#define V_CNT 0x00400000 /* Count (optional, leading). */
-#define V_DOT 0x00800000 /* On success, sets dot command. */
-#define V_KEYNUM 0x01000000 /* Cursor referenced number. */
-#define V_KEYW 0x02000000 /* Cursor referenced word. */
-#define V_MOTION 0x04000000 /* Motion (required, trailing). */
-#define V_MOVE 0x08000000 /* Command defines movement. */
-#define V_OBUF 0x10000000 /* Buffer (optional, leading). */
-#define V_RBUF 0x20000000 /* Buffer (required, trailing). */
- u_int32_t flags;
- char *usage; /* Usage line. */
- char *help; /* Help line. */
-};
-#define MAXVIKEY 126 /* List of vi commands. */
-extern VIKEYS const vikeys[MAXVIKEY + 1];
-extern VIKEYS const tmotion; /* XXX Hacked ~ command. */
-
-/* Definition of a vi "word". */
-#define inword(ch) (isalnum(ch) || (ch) == '_')
-
-/* Offset to next column of stop size. */
-#define STOP_OFF(c, stop) (stop - (c) % stop)
-
-/* Character stream structure, prototypes. */
-typedef struct _vcs {
- recno_t cs_lno; /* Line. */
- size_t cs_cno; /* Column. */
- CHAR_T *cs_bp; /* Buffer. */
- size_t cs_len; /* Length. */
- CHAR_T cs_ch; /* Character. */
-#define CS_EMP 1 /* Empty line. */
-#define CS_EOF 2 /* End-of-file. */
-#define CS_EOL 3 /* End-of-line. */
-#define CS_SOF 4 /* Start-of-file. */
- int cs_flags; /* Return flags. */
-} VCS;
-
-int cs_bblank __P((SCR *, EXF *, VCS *));
-int cs_fblank __P((SCR *, EXF *, VCS *));
-int cs_fspace __P((SCR *, EXF *, VCS *));
-int cs_init __P((SCR *, EXF *, VCS *));
-int cs_next __P((SCR *, EXF *, VCS *));
-int cs_prev __P((SCR *, EXF *, VCS *));
-
- /* Character search information. */
-enum cdirection { CNOTSET, FSEARCH, fSEARCH, TSEARCH, tSEARCH };
-
-/* Vi private, per-screen memory. */
-typedef struct _vi_private {
- VICMDARG sdot; /* Saved dot, motion command. */
- VICMDARG sdotmotion;
-
- CHAR_T rlast; /* Last 'r' command character. */
-
- char *rep; /* Input replay buffer. */
- size_t rep_len; /* Input replay buffer length. */
- size_t rep_cnt; /* Input replay buffer characters. */
-
- CHAR_T inc_lastch; /* Last increment character. */
- long inc_lastval; /* Last increment value. */
-
- char *ps; /* Paragraph plus section list. */
-
- u_long u_ccnt; /* Undo command count. */
-
- CHAR_T lastckey; /* Last search character. */
- enum cdirection csearchdir; /* Character search direction. */
-} VI_PRIVATE;
-
-#define VIP(sp) ((VI_PRIVATE *)((sp)->vi_private))
-
-/* Vi function prototypes. */
-int txt_auto __P((SCR *, EXF *, recno_t, TEXT *, size_t, TEXT *));
-int v_buildps __P((SCR *));
-int v_end __P((SCR *));
-void v_eof __P((SCR *, EXF *, MARK *));
-void v_eol __P((SCR *, EXF *, MARK *));
-int v_exwrite __P((void *, const char *, int));
-int v_init __P((SCR *, EXF *));
-int v_isempty __P((char *, size_t));
-int v_msgflush __P((SCR *));
-void v_nomove __P((SCR *));
-int v_ntext __P((SCR *, EXF *, TEXTH *, MARK *,
- const char *, const size_t, MARK *, ARG_CHAR_T, recno_t, u_int));
-int v_optchange __P((SCR *, int));
-int v_screen_copy __P((SCR *, SCR *));
-int v_screen_end __P((SCR *));
-void v_sof __P((SCR *, MARK *));
-void v_sol __P((SCR *));
-int vi __P((SCR *, EXF *));
-
-#define VIPROTO(name) int name __P((SCR *, EXF *, VICMDARG *))
-VIPROTO(v_again);
-VIPROTO(v_at);
-VIPROTO(v_bmark);
-VIPROTO(v_bottom);
-VIPROTO(v_cfirst);
-VIPROTO(v_Change);
-VIPROTO(v_change);
-VIPROTO(v_chF);
-VIPROTO(v_chf);
-VIPROTO(v_chrepeat);
-VIPROTO(v_chrrepeat);
-VIPROTO(v_chT);
-VIPROTO(v_cht);
-VIPROTO(v_cr);
-VIPROTO(v_Delete);
-VIPROTO(v_delete);
-VIPROTO(v_dollar);
-VIPROTO(v_down);
-VIPROTO(v_ex);
-VIPROTO(v_exmode);
-VIPROTO(v_filter);
-VIPROTO(v_first);
-VIPROTO(v_fmark);
-VIPROTO(v_home);
-VIPROTO(v_hpagedown);
-VIPROTO(v_hpageup);
-VIPROTO(v_iA);
-VIPROTO(v_ia);
-VIPROTO(v_iI);
-VIPROTO(v_ii);
-VIPROTO(v_increment);
-VIPROTO(v_iO);
-VIPROTO(v_io);
-VIPROTO(v_join);
-VIPROTO(v_left);
-VIPROTO(v_lgoto);
-VIPROTO(v_linedown);
-VIPROTO(v_lineup);
-VIPROTO(v_mark);
-VIPROTO(v_match);
-VIPROTO(v_middle);
-VIPROTO(v_mulcase);
-VIPROTO(v_ncol);
-VIPROTO(v_pagedown);
-VIPROTO(v_pageup);
-VIPROTO(v_paragraphb);
-VIPROTO(v_paragraphf);
-VIPROTO(v_Put);
-VIPROTO(v_put);
-VIPROTO(v_redraw);
-VIPROTO(v_Replace);
-VIPROTO(v_replace);
-VIPROTO(v_right);
-VIPROTO(v_screen);
-VIPROTO(v_searchb);
-VIPROTO(v_searchf);
-VIPROTO(v_searchN);
-VIPROTO(v_searchn);
-VIPROTO(v_searchw);
-VIPROTO(v_sectionb);
-VIPROTO(v_sectionf);
-VIPROTO(v_sentenceb);
-VIPROTO(v_sentencef);
-VIPROTO(v_shiftl);
-VIPROTO(v_shiftr);
-VIPROTO(v_status);
-VIPROTO(v_stop);
-VIPROTO(v_Subst);
-VIPROTO(v_subst);
-VIPROTO(v_switch);
-VIPROTO(v_tagpop);
-VIPROTO(v_tagpush);
-VIPROTO(v_ulcase);
-VIPROTO(v_Undo);
-VIPROTO(v_undo);
-VIPROTO(v_up);
-VIPROTO(v_wordB);
-VIPROTO(v_wordb);
-VIPROTO(v_wordE);
-VIPROTO(v_worde);
-VIPROTO(v_wordW);
-VIPROTO(v_wordw);
-VIPROTO(v_Xchar);
-VIPROTO(v_xchar);
-VIPROTO(v_Yank);
-VIPROTO(v_yank);
-VIPROTO(v_z);
-VIPROTO(v_zero);
-VIPROTO(v_zexit);
diff --git a/usr.bin/vi/vi/vi.c b/usr.bin/vi/vi/vi.c
deleted file mode 100644
index 9e52eb1c8884..000000000000
--- a/usr.bin/vi/vi/vi.c
+++ /dev/null
@@ -1,937 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)vi.c 8.89 (Berkeley) 8/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-#include "vcmd.h"
-
-static int getcmd __P((SCR *, EXF *,
- VICMDARG *, VICMDARG *, VICMDARG *, int *, int *));
-static __inline int
- getcount __P((SCR *, ARG_CHAR_T, u_long *));
-static __inline int
- getkey __P((SCR *, CH *, u_int));
-static int getkeyword __P((SCR *, EXF *, VICMDARG *, u_int));
-static int getmotion __P((SCR *, EXF *, VICMDARG *, VICMDARG *, int *));
-
-/*
- * Side-effect:
- * The dot structure can be set by the underlying vi functions,
- * see v_Put() and v_put().
- */
-#define DOT (&VIP(sp)->sdot)
-#define DOTMOTION (&VIP(sp)->sdotmotion)
-
-/*
- * vi --
- * Main vi command loop.
- */
-int
-vi(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- MARK abs;
- VICMDARG cmd, *vp;
- u_int flags, saved_mode;
- int comcount, eval, mapped;
-
- /* Start vi and paint the screen. */
- if (v_init(sp, ep))
- return (1);
-
- /* Command initialization. */
- memset(&cmd, 0, sizeof(VICMDARG));
-
- for (eval = 0, vp = &cmd;;) {
- /* Refresh the screen. */
- sp->showmode = "Command";
- if (sp->s_refresh(sp, ep)) {
- eval = 1;
- break;
- }
-
- /* Set the new favorite position. */
- if (F_ISSET(vp, VM_RCM_SET | VM_RCM_SETFNB | VM_RCM_SETNNB)) {
- sp->rcm_last = 0;
- (void)sp->s_column(sp, ep, &sp->rcm);
- }
-
- /*
- * If not currently in a map, log the cursor position,
- * and set a flag so that this command can become the
- * DOT command.
- */
- if (MAPPED_KEYS_WAITING(sp))
- mapped = 1;
- else {
- if (log_cursor(sp, ep))
- goto err;
- mapped = 0;
- }
-
- /*
- * We get a command, which may or may not have an associated
- * motion. If it does, we get it too, calling its underlying
- * function to get the resulting mark. We then call the
- * command setting the cursor to the resulting mark.
- */
- if (getcmd(sp, ep, DOT, vp, NULL, &comcount, &mapped))
- goto err;
-
- /*
- * Historical practice: if a dot command gets a new count,
- * any motion component goes away, i.e. "d3w2." deletes a
- * total of 5 words.
- */
- if (F_ISSET(vp, VC_ISDOT) && comcount)
- DOTMOTION->count = 1;
-
- /* Copy the key flags into the local structure. */
- F_SET(vp, vp->kp->flags);
-
- /* Get any associated keyword. */
- if (F_ISSET(vp, V_KEYNUM | V_KEYW) &&
- getkeyword(sp, ep, vp, vp->flags))
- goto err;
-
- /* Prepare to set the previous context. */
- if (F_ISSET(vp, V_ABS | V_ABS_C | V_ABS_L)) {
- abs.lno = sp->lno;
- abs.cno = sp->cno;
- }
-
- /*
- * Set the three cursor locations to the current cursor. The
- * underlying routines don't bother if the cursor doesn't move.
- * This also handles line commands (e.g. Y) defaulting to the
- * current line.
- */
- vp->m_start.lno = vp->m_stop.lno = vp->m_final.lno = sp->lno;
- vp->m_start.cno = vp->m_stop.cno = vp->m_final.cno = sp->cno;
-
- /*
- * Do any required motion; getmotion sets the from MARK and the
- * line mode flag. We save off the RCM mask and only restore
- * it if it no RCM flags are set by the motion command. This
- * means that the motion command is expected to determine where
- * the cursor ends up!
- */
- if (F_ISSET(vp, V_MOTION)) {
- flags = F_ISSET(vp, VM_RCM_MASK);
- F_CLR(vp, VM_RCM_MASK);
- if (getmotion(sp, ep, DOTMOTION, vp, &mapped))
- goto err;
- if (F_ISSET(vp, VM_NOMOTION))
- goto err;
- if (!F_ISSET(vp, VM_RCM_MASK))
- F_SET(vp, flags);
- }
-
- /*
- * If a count is set and the command is line oriented, set the
- * to MARK here relative to the cursor/from MARK. This is for
- * commands that take both counts and motions, i.e. "4yy" and
- * "y%". As there's no way the command can know which the user
- * did, we have to do it here. (There are commands that are
- * line oriented and that take counts ("#G", "#H"), for which
- * this calculation is either completely meaningless or wrong.
- * Each command must validate the value for itself.
- */
- if (F_ISSET(vp, VC_C1SET) && F_ISSET(vp, VM_LMODE))
- vp->m_stop.lno += vp->count - 1;
-
- /* Increment the command count. */
- ++sp->ccnt;
-
- /* Save the mode and call the function. */
- saved_mode = F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE);
- if ((vp->kp->func)(sp, ep, vp))
- goto err;
-#ifdef DEBUG
- /* Make sure no function left the temporary space locked. */
- if (F_ISSET(sp->gp, G_TMP_INUSE)) {
- msgq(sp, M_ERR,
- "Error: vi: temporary buffer not released");
- return (1);
- }
-#endif
- /*
- * If that command took us out of vi or changed the screen,
- * then exit the loop without further action.
- */
- if (saved_mode != F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE))
- break;
-
- /*
- * Set the dot command structure.
- *
- * !!!
- * Historically, no command which used any mapped keys became
- * the dot command.
- */
- if (F_ISSET(vp, V_DOT) && !mapped) {
- *DOT = cmd;
- F_SET(DOT, VC_ISDOT);
-
- /*
- * If a count was supplied for both the command and
- * its motion, the count was used only for the motion.
- * Turn the count back on for the dot structure.
- */
- if (F_ISSET(vp, VC_C1RESET))
- F_SET(DOT, VC_C1SET);
-
- /* VM flags aren't retained. */
- F_CLR(DOT, VM_COMMASK | VM_RCM_MASK);
- }
-
- /*
- * Some vi row movements are "attracted" to the last position
- * set, i.e. the VM_RCM commands are moths to the VM_RCM_SET
- * commands' candle. It's broken into two parts. Here we deal
- * with the command flags. In sp->relative(), we deal with the
- * screen flags. If the movement is to the EOL the vi command
- * handles it. If it's to the beginning, we handle it here.
- *
- * Note, some commands (e.g. _, ^) don't set the VM_RCM_SETFNB
- * flag, but do the work themselves. The reason is that they
- * have to modify the column in case they're being used as a
- * motion component. Other similar commands (e.g. +, -) don't
- * have to modify the column because they are always line mode
- * operations when used as motions, so the column number isn't
- * of any interest.
- *
- * Does this totally violate the screen and editor layering?
- * You betcha. As they say, if you think you understand it,
- * you don't.
- */
- switch (F_ISSET(vp, VM_RCM_MASK)) {
- case 0:
- case VM_RCM_SET:
- break;
- case VM_RCM:
- vp->m_final.cno = sp->s_rcm(sp, ep, vp->m_final.lno);
- break;
- case VM_RCM_SETLAST:
- sp->rcm_last = 1;
- break;
- case VM_RCM_SETFNB:
- vp->m_final.cno = 0;
- /* FALLTHROUGH */
- case VM_RCM_SETNNB:
- if (nonblank(sp, ep, vp->m_final.lno, &vp->m_final.cno))
- goto err;
- break;
- default:
- abort();
- }
-
- /* Update the cursor. */
- sp->lno = vp->m_final.lno;
- sp->cno = vp->m_final.cno;
-
- /*
- * Set the absolute mark -- set even if a tags or similar
- * command, since the tag may be moving to the same file.
- */
- if ((F_ISSET(vp, V_ABS) ||
- F_ISSET(vp, V_ABS_L) && sp->lno != abs.lno ||
- F_ISSET(vp, V_ABS_C) &&
- (sp->lno != abs.lno || sp->cno != abs.cno)) &&
- mark_set(sp, ep, ABSMARK1, &abs, 1))
- goto err;
-
- if (!MAPPED_KEYS_WAITING(sp))
- (void)msg_rpt(sp, 1);
-
- /*
- * Check and clear the interrupts. There's an obvious race,
- * but it's not worth cleaning up. This is done after the
- * err: lable, so that if the "error" was an interupt it gets
- * cleaned up.
- *
- * !!!
- * Previous versions of nvi cleared mapped characters on error,
- * even if it wasn't an interrupt. This feature was removed as
- * users complained that it wasn't historic practice and that
- * they used leading (illegal) <escape> characters in the map
- * to clean up vi state before the map was interpreted.
- */
-err: if (INTERRUPTED(sp))
- term_flush(sp, "Interrupted", CH_MAPPED);
- CLR_INTERRUPT(sp);
- }
-
- /* Free allocated keyword memory. */
- if (cmd.keyword != NULL)
- free(cmd.keyword);
-
- return (v_end(sp) || eval);
-}
-
-#define KEY(key, map) { \
- if (getkey(sp, &ikey, map)) \
- return (1); \
- if (ikey.value == K_ESCAPE) \
- goto esc; \
- if (F_ISSET(&ikey, CH_MAPPED)) \
- *mappedp = 1; \
- key = ikey.ch; \
-}
-
-/*
- * The O_TILDEOP option makes the ~ command take a motion instead
- * of a straight count. This is the replacement structure we use
- * instead of the one currently in the VIKEYS table.
- *
- * XXX
- * Note, I used VC_Y instead of creating a new motion command, it's
- * a lot easier.
- */
-VIKEYS const tmotion = {
- v_mulcase, V_CNT|V_DOT|V_MOTION|VC_Y|VM_RCM_SET,
- "[count]~[count]motion",
- " ~ change case to motion"
-};
-
-/*
- * getcmd --
- *
- * The command structure for vi is less complex than ex (and don't think
- * I'm not grateful!) The command syntax is:
- *
- * [count] [buffer] [count] key [[motion] | [buffer] [character]]
- *
- * and there are several special cases. The motion value is itself a vi
- * command, with the syntax:
- *
- * [count] key [character]
- */
-static int
-getcmd(sp, ep, dp, vp, ismotion, comcountp, mappedp)
- SCR *sp;
- EXF *ep;
- VICMDARG *dp, *vp;
- VICMDARG *ismotion; /* Previous key if getting motion component. */
- int *comcountp, *mappedp;
-{
- enum { COMMANDMODE, ISPARTIAL, NOTPARTIAL } cpart;
- VIKEYS const *kp;
- u_int flags;
- CH ikey;
- CHAR_T key;
- char *s;
-
- /* Refresh the command structure. */
- memset(&vp->vp_startzero, 0,
- (char *)&vp->vp_endzero - (char *)&vp->vp_startzero);
-
- /*
- * Get a key.
- *
- * <escape> cancels partial commands, i.e. a command where at least
- * one non-numeric character has been entered. Otherwise, it beeps
- * the terminal.
- *
- * !!!
- * POSIX 1003.2-1992 explicitly disallows cancelling commands where
- * all that's been entered is a number, requiring that the terminal
- * be alerted.
- */
- cpart = ismotion == NULL ? COMMANDMODE : ISPARTIAL;
- KEY(key, TXT_MAPCOMMAND);
- if (ismotion == NULL)
- cpart = NOTPARTIAL;
-
- /* Pick up optional buffer. */
- if (key == '"') {
- cpart = ISPARTIAL;
- if (ismotion != NULL) {
- msgq(sp, M_BERR,
- "Buffers should be specified before the command");
- return (1);
- }
- KEY(vp->buffer, 0);
- F_SET(vp, VC_BUFFER);
-
- KEY(key, TXT_MAPCOMMAND);
- }
-
- /*
- * Pick up optional count, where a leading 0 is not a count,
- * it's a command.
- */
- if (isdigit(key) && key != '0') {
- if (getcount(sp, key, &vp->count))
- return (1);
- F_SET(vp, VC_C1SET);
- *comcountp = 1;
-
- KEY(key, TXT_MAPCOMMAND);
- } else
- *comcountp = 0;
-
- /* Pick up optional buffer. */
- if (key == '"') {
- cpart = ISPARTIAL;
- if (F_ISSET(vp, VC_BUFFER)) {
- msgq(sp, M_ERR, "Only one buffer can be specified");
- return (1);
- }
- if (ismotion != NULL) {
- msgq(sp, M_BERR,
- "Buffers should be specified before the command");
- return (1);
- }
- KEY(vp->buffer, 0);
- F_SET(vp, VC_BUFFER);
-
- KEY(key, TXT_MAPCOMMAND);
- }
-
- /* Check for an OOB command key. */
- cpart = ISPARTIAL;
- if (key > MAXVIKEY) {
- msgq(sp, M_BERR, "%s isn't a vi command", KEY_NAME(sp, key));
- return (1);
- }
- kp = &vikeys[vp->key = key];
-
- /* The tildeop option makes the ~ command take a motion. */
- if (key == '~' && O_ISSET(sp, O_TILDEOP))
- kp = &tmotion;
-
- vp->kp = kp;
-
- /*
- * Find the command. The only legal command with no underlying
- * function is dot. It's historic practice that <escape> doesn't
- * just erase the preceding number, it beeps the terminal as well.
- * It's a common problem, so just beep the terminal unless verbose
- * was set.
- */
- if (kp->func == NULL) {
- if (key != '.') {
- msgq(sp, ikey.value == K_ESCAPE ? M_BERR : M_ERR,
- "%s isn't a vi command", KEY_NAME(sp, key));
- return (1);
- }
-
- /* If called for a motion command, stop now. */
- if (dp == NULL)
- goto usage;
-
- /* A repeatable command must have been executed. */
- if (!F_ISSET(dp, VC_ISDOT)) {
- msgq(sp, M_ERR, "No command to repeat");
- return (1);
- }
-
- /*
- * !!!
- * If a '.' is immediately entered after an undo command, we
- * replay the log instead of redoing the last command. This
- * is necessary because 'u' can't set the dot command -- see
- * vi/v_undo.c:v_undo for details.
- */
- if (VIP(sp)->u_ccnt == sp->ccnt) {
- vp->kp = &vikeys['u'];
- F_SET(vp, VC_ISDOT);
- return (0);
- }
-
- /* Set new count/buffer, if any, and return. */
- if (F_ISSET(vp, VC_C1SET)) {
- F_SET(dp, VC_C1SET);
- dp->count = vp->count;
- }
- if (F_ISSET(vp, VC_BUFFER))
- dp->buffer = vp->buffer;
- *vp = *dp;
- return (0);
- }
-
- /* Set the flags based on the command flags. */
- flags = kp->flags;
-
- /* Check for illegal count. */
- if (F_ISSET(vp, VC_C1SET) && !LF_ISSET(V_CNT))
- goto usage;
-
- /* Illegal motion command. */
- if (ismotion == NULL) {
- /* Illegal buffer. */
- if (!LF_ISSET(V_OBUF) && F_ISSET(vp, VC_BUFFER))
- goto usage;
-
- /* Required buffer. */
- if (LF_ISSET(V_RBUF)) {
- KEY(vp->buffer, 0);
- F_SET(vp, VC_BUFFER);
- }
- }
-
- /*
- * Special case: '[', ']' and 'Z' commands. Doesn't the fact that
- * the *single* characters don't mean anything but the *doubled*
- * characters do just frost your shorts?
- */
- if (vp->key == '[' || vp->key == ']' || vp->key == 'Z') {
- /*
- * Historically, half entered [[, ]] or Z commands weren't
- * cancelled by <escape>, the terminal was beeped instead.
- * POSIX.2-1992 probably didn't notice, and requires that
- * they be cancelled instead of beeping. Seems fine to me.
- */
- KEY(key, TXT_MAPCOMMAND);
-
- if (vp->key != key) {
-usage: if (ismotion == NULL)
- s = kp->usage;
- else if (ismotion->key == '~' && O_ISSET(sp, O_TILDEOP))
- s = tmotion.usage;
- else
- s = vikeys[ismotion->key].usage;
- msgq(sp, M_ERR, "Usage: %s", s);
- return (1);
- }
- }
- /* Special case: 'z' command. */
- if (vp->key == 'z') {
- KEY(vp->character, 0);
- if (isdigit(vp->character)) {
- if (getcount(sp, vp->character, &vp->count2))
- return (1);
- F_SET(vp, VC_C2SET);
- KEY(vp->character, 0);
- }
- }
-
- /*
- * Commands that have motion components can be doubled to
- * imply the current line.
- */
- if (ismotion != NULL && ismotion->key != key && !LF_ISSET(V_MOVE)) {
- msgq(sp, M_ERR, "%s may not be used as a motion command",
- KEY_NAME(sp, key));
- return (1);
- }
-
- /* Required character. */
- if (LF_ISSET(V_CHAR))
- KEY(vp->character, 0);
-
- return (0);
-
-esc: switch (cpart) {
- case COMMANDMODE:
- msgq(sp, M_BERR, "Already in command mode");
- break;
- case ISPARTIAL:
- break;
- case NOTPARTIAL:
- (void)sp->s_bell(sp);
- break;
- }
- return (1);
-}
-
-/*
- * getmotion --
- *
- * Get resulting motion mark.
- */
-static int
-getmotion(sp, ep, dm, vp, mappedp)
- SCR *sp;
- EXF *ep;
- VICMDARG *dm, *vp;
- int *mappedp;
-{
- MARK m;
- VICMDARG motion;
- size_t len;
- u_long cnt;
- int notused;
-
- /*
- * If '.' command, use the dot motion, else get the motion command.
- * Clear any line motion flags, the subsequent motion isn't always
- * the same, i.e. "/aaa" may or may not be a line motion.
- */
- if (F_ISSET(vp, VC_ISDOT)) {
- motion = *dm;
- F_SET(&motion, VC_ISDOT);
- F_CLR(&motion, VM_COMMASK);
- } else if (getcmd(sp, ep, NULL, &motion, vp, &notused, mappedp))
- return (1);
-
- /*
- * A count may be provided both to the command and to the motion, in
- * which case the count is multiplicative. For example, "3y4y" is the
- * same as "12yy". This count is provided to the motion command and
- * not to the regular function.
- */
- cnt = motion.count = F_ISSET(&motion, VC_C1SET) ? motion.count : 1;
- if (F_ISSET(vp, VC_C1SET)) {
- motion.count *= vp->count;
- F_SET(&motion, VC_C1SET);
-
- /*
- * Set flags to restore the original values of the command
- * structure so dot commands can change the count values,
- * e.g. "2dw" "3." deletes a total of five words.
- */
- F_CLR(vp, VC_C1SET);
- F_SET(vp, VC_C1RESET);
- }
-
- /*
- * Some commands can be repeated to indicate the current line. In
- * this case, or if the command is a "line command", set the flags
- * appropriately. If not a doubled command, run the function to get
- * the resulting mark.
- */
- if (vp->key == motion.key) {
- F_SET(vp, VM_LDOUBLE | VM_LMODE);
-
- /* Set the origin of the command. */
- vp->m_start.lno = sp->lno;
- vp->m_start.cno = 0;
-
- /*
- * Set the end of the command.
- *
- * If the current line is missing, i.e. the file is empty,
- * historic vi permitted a "cc" or "!!" command to insert
- * text.
- */
- vp->m_stop.lno = sp->lno + motion.count - 1;
- if (file_gline(sp, ep, vp->m_stop.lno, &len) == NULL) {
- if (vp->m_stop.lno != 1 ||
- vp->key != 'c' && vp->key != '!') {
- m.lno = sp->lno;
- m.cno = sp->cno;
- v_eof(sp, ep, &m);
- return (1);
- }
- vp->m_stop.cno = 0;
- } else
- vp->m_stop.cno = len ? len - 1 : 0;
- } else {
- /*
- * Motion commands change the underlying movement (*snarl*).
- * For example, "l" is illegal at the end of a line, but "dl"
- * is not. Set flags so the function knows the situation.
- */
- F_SET(&motion, vp->kp->flags & VC_COMMASK);
-
- /*
- * Copy the key flags into the local structure, except for
- * the RCM flags, the motion command will set the RCM flags
- * in the vp structure as necessary.
- */
- F_SET(&motion, motion.kp->flags & ~VM_RCM_MASK);
-
- /*
- * Set the three cursor locations to the current cursor. This
- * permits commands like 'j' and 'k', that are line oriented
- * motions and have special cursor suck semantics when they are
- * used as standalone commands, to ignore column positioning.
- */
- motion.m_final.lno =
- motion.m_stop.lno = motion.m_start.lno = sp->lno;
- motion.m_final.cno =
- motion.m_stop.cno = motion.m_start.cno = sp->cno;
-
- /* Run the function. */
- if ((motion.kp->func)(sp, ep, &motion))
- return (1);
-
- /*
- * Copy cut buffer, line mode and cursor position information
- * from the motion command structure, i.e. anything that the
- * motion command can set for us. The commands can flag the
- * movement as a line motion (see v_sentence) as well as set
- * the VM_RCM_* flags explicitly.
- */
- F_SET(vp, F_ISSET(&motion, VM_COMMASK | VM_RCM_MASK));
-
- /*
- * Motion commands can reset all of the cursor information.
- * If the motion is in the reverse direction, switch the
- * from and to MARK's so that it's in a forward direction.
- * Motions are from the from MARK to the to MARK (inclusive).
- */
- if (motion.m_start.lno > motion.m_stop.lno ||
- motion.m_start.lno == motion.m_stop.lno &&
- motion.m_start.cno > motion.m_stop.cno) {
- vp->m_start = motion.m_stop;
- vp->m_stop = motion.m_start;
- } else {
- vp->m_start = motion.m_start;
- vp->m_stop = motion.m_stop;
- }
- vp->m_final = motion.m_final;
- }
-
- /*
- * If the command sets dot, save the motion structure. The motion
- * count was changed above and needs to be reset, that's why this
- * is done here, and not in the calling routine.
- */
- if (F_ISSET(vp->kp, V_DOT)) {
- *dm = motion;
- dm->count = cnt;
- }
- return (0);
-}
-
-#define innum(c) (isdigit(c) || strchr("abcdefABCDEF", c))
-
-/*
- * getkeyword --
- * Get the "word" the cursor is on.
- */
-static int
-getkeyword(sp, ep, kp, flags)
- SCR *sp;
- EXF *ep;
- VICMDARG *kp;
- u_int flags;
-{
- recno_t lno;
- size_t beg, end, len;
- char *p;
-
- if ((p = file_gline(sp, ep, sp->lno, &len)) == NULL) {
- if (file_lline(sp, ep, &lno))
- return (1);
- if (lno == 0)
- v_eof(sp, ep, NULL);
- else
- GETLINE_ERR(sp, sp->lno);
- return (1);
- }
-
- /*
- * !!!
- * Historically, tag commands skipped over any leading whitespace
- * characters.
- */
- for (beg = sp->cno; beg < len && isspace(p[beg]); ++beg);
-
- if (beg >= len ||
- LF_ISSET(V_KEYW) && !inword(p[beg]) ||
- LF_ISSET(V_KEYNUM) && !innum(p[beg]) &&
- p[beg] != '-' && p[beg] != '+')
- goto noword;
-
- /*
- * !!!
- * Find the beginning/end of the keyword. Keywords (V_KEYW) are
- * used for cursor-word searching and for tags. Historical vi
- * only used the word in a tag search from the cursor to the end
- * of the word, i.e. if the cursor was on the 'b' in " abc ", the
- * tag was "bc". For no particular reason, we make the cursor
- * word searches follow the same rule.
- */
- if (beg != 0)
- if (LF_ISSET(V_KEYW)) {
-#ifdef MOVE_TO_KEYWORD_BEGINNING
- for (;;) {
- --beg;
- if (!inword(p[beg])) {
- ++beg;
- break;
- }
- if (beg == 0)
- break;
- }
-#endif
- } else {
- for (;;) {
- --beg;
- if (!innum(p[beg])) {
- if (beg > 0 && p[beg - 1] == '0' &&
- (p[beg] == 'X' || p[beg] == 'x'))
- --beg;
- else
- ++beg;
- break;
- }
- if (beg == 0)
- break;
- }
-
- /* Skip possible leading sign. */
- if (beg != 0 && p[beg] != '0' &&
- (p[beg - 1] == '+' || p[beg - 1] == '-'))
- --beg;
- }
-
- if (LF_ISSET(V_KEYW)) {
- for (end = beg; ++end < len && inword(p[end]););
- --end;
- } else {
- for (end = beg; ++end < len;) {
- if (p[end] == 'X' || p[end] == 'x') {
- if (end != beg + 1 || p[beg] != '0')
- break;
- continue;
- }
- if (!innum(p[end]))
- break;
- }
-
- /* Just a sign isn't a number. */
- if (end == beg && (p[beg] == '+' || p[beg] == '-')) {
-noword: msgq(sp, M_BERR, "Cursor not in a %s",
- LF_ISSET(V_KEYW) ? "word" : "number");
- return (1);
- }
- --end;
- }
-
- /*
- * Getting a keyword implies moving the cursor to its beginning.
- * Refresh now.
- */
- if (beg != sp->cno) {
- sp->cno = beg;
- sp->s_refresh(sp, ep);
- }
-
- /*
- * XXX
- * 8-bit clean problem. Numeric keywords are handled using strtol(3)
- * and friends. This would have to be fixed in v_increment and here
- * to not depend on a trailing NULL.
- */
- len = (end - beg) + 2; /* XXX */
- kp->klen = (end - beg) + 1;
- BINC_RET(sp, kp->keyword, kp->kbuflen, len);
- memmove(kp->keyword, p + beg, kp->klen);
- kp->keyword[kp->klen] = '\0'; /* XXX */
- return (0);
-}
-
-/*
- * getcount --
- * Return the next count.
- */
-static __inline int
-getcount(sp, fkey, countp)
- SCR *sp;
- ARG_CHAR_T fkey;
- u_long *countp;
-{
- u_long count, tc;
- CH ikey;
-
- ikey.ch = fkey;
- count = tc = 0;
- do {
- /* Assume that overflow results in a smaller number. */
- tc = count * 10 + ikey.ch - '0';
- if (count > tc) {
- /* Toss to the next non-digit. */
- do {
- if (getkey(sp, &ikey,
- TXT_MAPCOMMAND | TXT_MAPNODIGIT))
- return (1);
- } while (isdigit(ikey.ch));
- msgq(sp, M_ERR, "Number larger than %lu", ULONG_MAX);
- return (1);
- }
- count = tc;
- if (getkey(sp, &ikey, TXT_MAPCOMMAND | TXT_MAPNODIGIT))
- return (1);
- } while (isdigit(ikey.ch));
- *countp = count;
- return (0);
-}
-
-/*
- * getkey --
- * Return the next key.
- */
-static __inline int
-getkey(sp, ikeyp, map)
- SCR *sp;
- CH *ikeyp;
- u_int map;
-{
- switch (term_key(sp, ikeyp, map)) {
- case INP_EOF:
- case INP_ERR:
- F_SET(sp, S_EXIT_FORCE);
- return (1);
- case INP_INTR:
- /*
- * !!!
- * Historically, vi beeped on command level interrupts.
- *
- * Historically, vi exited to ex mode if no file was named
- * on the command line, and two interrupts were generated
- * in a row. (Just figured you might want to know that.)
- */
- (void)sp->s_bell(sp);
- return (1);
- case INP_OK:
- return (0);
- }
- /* NOTREACHED */
-}
diff --git a/usr.bin/vi/xaw/xaw_screen.c b/usr.bin/vi/xaw/xaw_screen.c
deleted file mode 100644
index 14a9674ffefe..000000000000
--- a/usr.bin/vi/xaw/xaw_screen.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)xaw_screen.c 8.6 (Berkeley) 5/21/94";
-#endif /* not lint */
-
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-
-/*
- * xaw_init --
- * Athena widget screen initialization.
- */
-int
-xaw_screen_init(sp)
- SCR *sp;
-{
- msgq(sp, M_ERR, "The Athena widget screen not yet implemented");
- return (1);
-}
-
-/*
- * xaw_screen_copy --
- * Copy to a new screen.
- */
-int
-xaw_screen_copy(orig, sp)
- SCR *orig, *sp;
-{
- return (0);
-}
-
-/*
- * xaw_screen_end --
- * End a screen.
- */
-int
-xaw_screen_end(sp)
- SCR *sp;
-{
- return (0);
-}
-
-/*
- * xaw --
- * Main vi Athena widget screen loop.
- */
-int
-xaw(sp, ep, spp)
- SCR *sp, **spp;
- EXF *ep;
-{
- *spp = NULL;
- return (0);
-}