Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Import Elvis 2.1_3 (written by Steve Kirkendall)

  • Loading branch information...
commit 3a9bb556847cf2f6907d8ccc45224727a917ad36 1 parent 8d1ac0c
@mbert authored
Showing with 4,121 additions and 2,083 deletions.
  1. +155 −4 BUGS
  2. +15 −8 Makefile.in
  3. +243 −15 README.html
  4. +32 −29 buffer.c
  5. +108 −15 calc.c
  6. +34 −4 configure
  7. +2 −2 ctags.c
  8. +6 −2 display.c
  9. +6 −2 display2.h
  10. +559 −236 dmmarkup.c
  11. +3 −3 dmnormal.c
  12. +8 −0 elvis.h
  13. +6 −5 elvis.lsm
  14. +12 −3 event.c
  15. +135 −10 ex.c
  16. +4 −2 ex.h
  17. +8 −4 exaction.c
  18. +7 −7 exconfig.c
  19. +18 −2 exedit.c
  20. +12 −2 exmake.c
  21. +2 −2 exsubst.c
  22. +88 −19 ftp.c
  23. +2 −2 guicurs.c
  24. +2 −2 guiopen.c
  25. +33 −5 guitcap.c
  26. BIN  guiwin32/elvisold.ico
  27. +42 −1 guiwin32/guiwin.c
  28. +2 −2 guiwin32/gwcmd.c
  29. +2 −1  guiwin32/gwdlgs.c
  30. +2 −2 guiwin32/gwmsg.c
  31. +1 −1  guiwin32/gwopts.c
  32. +1 −2  guiwin32/gwprint.c
  33. +1 −1  guiwin32/gwstatb.c
  34. +1 −1  guiwin32/gwtoolb.c
  35. +2 −2 guiwin32/gwutil.c
  36. +1 −1  guiwin32/winelvis.c
  37. +1 −1  guiwin32/wintags.c
  38. +1 −1  guiwin32/wintools.c
  39. +12 −0 guix11/Elvis.kdelnk
  40. +17 −11 guix11/guix11.c
  41. +1 −0  guix11/guix11.h
  42. +57 −0 guix11/kde.xpm
  43. +4 −2 guix11/xdialog.c
  44. +2 −2 guix11/xevent.c
  45. +4 −1 input.c
  46. +8 −6 lib/ctags.man
  47. +96 −7 lib/elvis.ali
  48. +6 −2 lib/elvis.arf
  49. +1 −1  lib/elvis.html
  50. +35 −3 lib/elvis.syn
  51. +3 −1 lib/elvis.x11
  52. +2 −2 lib/elvisdm.html
  53. +61 −18 lib/elvisex.html
  54. +23 −3 lib/elvisexp.html
  55. +60 −12 lib/elvisgui.html
  56. +1 −1  lib/elvisinp.html
  57. +12 −2 lib/elvisnet.html
  58. +9 −32 lib/elvisopt.html
  59. +75 −23 lib/elvisos.html
  60. +1 −1  lib/elvisre.html
  61. +7 −1 lib/elvisses.html
  62. +7 −6 lib/elvistag.html
  63. +149 −41 lib/elvistip.html
  64. +8 −3 lib/fmt.man
  65. +82 −9 lib/howto.html
  66. +112 −86 lib/ref.man
  67. +3 −3 main.c
  68. +7 −1 makwin32.bat
  69. +81 −6 message.c
  70. +1 −1  message.h
  71. +5 −0 message2.h
  72. +5 −1 more.c
  73. +1 −0  more.h
  74. +2 −4 optglob.c
  75. +62 −63 optglob.h
  76. +4 −1 osmsdos/osconfig.h
  77. +44 −29 osos2/Makefile.os2
  78. +0 −58 osos2/README.os2
  79. +6 −3 osos2/config-no-tcp.h
  80. +6 −3 osos2/config-with-tcp.h
  81. +2 −0  osos2/manual/ctags.man.ed
  82. +2 −0  osos2/manual/elvis.ali.ed
  83. +6 −0 osos2/manual/elvis.html.ed
  84. +2 −0  osos2/manual/elvis.ini.ed
  85. +16 −0 osos2/manual/elvis.ipf.ed
  86. +2 −0  osos2/manual/elvis.man.ed
  87. +2 −0  osos2/manual/elvis.syn.ed
  88. +5 −0 osos2/manual/elvismsg.html.ed
  89. +2 −0  osos2/manual/elvistrs.msg.ed
  90. +12 −0 osos2/manual/fixhtml.cmd
  91. +2 −0  osos2/manual/fmt.man.ed
  92. +46 −0 osos2/manual/h2i-guide.cmd
  93. +6 −0 osos2/manual/others.html.ed
  94. +2 −0  osos2/manual/ref.man.ed
  95. +5 −4 osos2/osconfig.h
  96. +3 −1 osos2/osnet.c
  97. +2 −2 osunix/osblock.c
  98. +5 −3 osunix/osnet.c
  99. +2 −2 oswin32/elvis.mak
  100. +4 −1 oswin32/osconfig.h
  101. +3 −1 oswin32/osnet.c
  102. +126 −1,166 oswin32/osprg.c
  103. +1 −1  ref.c
  104. +3 −2 regexp.c
  105. +2 −2 state.c
  106. +7 −2 tag.c
  107. +16 −20 tagelvis.c
  108. +1,149 −0 tcaphelp.c
  109. +1 −1  url.c
  110. +2 −2 version.h
  111. +14 −3 vi.c
  112. +20 −17 vicmd.c
  113. +10 −3 window.c
View
159 BUGS
@@ -11,15 +11,166 @@ NOTE: Not all of these are truly bugs. This file also serves as my "to do"
list, so some items are just unimplemented features that sounded like a good
idea at one time or another.
-* The [[ and ]] commands shouldn't be line-mode moves. I.e., from the middle
+* There appears to be a bug in scanning -- a scanned block is not necessarily
+ being locked for the whole time that it should be, which means that it may
+ be removed from the block cache, in which case NULL may be returned by some
+ of the blkXXXX() functions. Also, on at least one occasion elvis appeared
+ to be trying to free a block which wasn't allocated.
+
+ This may have something to do with the FEATURE_LITRE feature, or my
+ recent attempts to make searches run faster by keeping at least one
+ scan context for the current location at all times.
+
+/ One user reported crashes in WinElvis when the "Options->syntax" menu item
+ is activated while in "syntax" display mode.
+
+* One user reported that elvis was sensitive to keystrokes during quitting.
+ I suspect that gui->poll was being called while the file was being written
+ (possibly just when written via FTP). That write should not be quittable.
+
+* Under MS-DOS with TERM=nansi (and NANSI.SYS installed, of course) the screen
+ is shifted up one line. TERM=ansi works, but doesn't use nansi efficiently.
+
+/ Can't identify tags whose whose contains a new-style comment. Apparently
+ the tag-selector can't parse \/\/ in an regular expression.
+
+/ Make elvis assume "-Gopen" if termcap can't be used.
+
+? The :make command is still slightly weird. "elvis +make" waits until after
+ a keystroke to display the first error message.
+
+/ Document the ftp://host/~user/resource URL notation.
+
+/ The :mark command should save the column number as well as the line number.
+ (I.e., if no explicit address was given, then use the cursor position instead
+ of the start of the cursor's line.)
+
+/ Add a :cbshow alias which displays cut buffers. To do this right, elvis
+ will need a text() function for fetching text lines...
+ text() return the current line of the current buffer
+ text(n) return line #n of the current buffer
+ text(b,n) return line #n of buffer (b)
+
+/ ":map ^H visual X" doesn't work when the cursor is at the end of the line.
+ It deletes the last character, but then moves the cursor back two characters
+ instead of just one.
+
+/ Assertion fails at buffer.c:1206 when attempting to write an empty buffer.
+
+? dmmarkup.c:1066: htmlinit: Assertion `first == True && col == 0' failed.
+
+/ "Dead keys" don't work in "x11" gui.
+
+/ If the .elvisrc file contains "set wrapmargin=0" then that option is
+ displayed by a later ":set" command. It shouldn't be.
+
+ This is a complication arising from the fact that wrapmargin is
+ actually implemented via the textwidth option. Wrapmargin doesn't
+ exist until a buffer is shown in a window, but defaults are normally
+ recorded before that.
+
+/ If there is no tags file in the current directory and inputtab=tagname
+ then there is a long delay each time <Tab> is hit.
+
+/ Is this a good time to fix the bug where :make outputs the first error
+ message *before* prompting the user to hit <Enter>, when it should be after?
+
+/ Add a "howto" describing Perl's error messages.
+
+/ The "noanyerror" option shouldn't prevent the cursor from moving into locked
+ files in the current directory -- only unwritables in some other directory.
+
+/ It's back: Sometimes in "man" mode the cursor can't move up. This appears
+ to happen only for .IP or .TP commands with long labels. I should probably
+ change that code anyway, so the labels are considered to be separate lines
+ in that situation.
+
+/ It would be nice if FTP URLs supported user names as in ftp:host/~user/...
+ in addition to just ftp:host/~/... When a user name is specified, the
+ ~/.netrc file is searched for an account at that host which has that login
+ name; the password is then taken from that entry.
+
+? More importantly, it has been reported that the Windows versions don't
+ read "elvis.ftp" correctly. (It works under Unix; I've tested it.)
+
+ This appears to work under Win32, as far as I can tell. Perhaps
+ the user who reported it didn't have "elvis.ftp" in a directory
+ where elvis could find it? Or maybe the other changes I made to
+ that file (to support ~user) had the side-effect of fixing this?
+
+/ Add support for backticks in filenames -- the text between backticks is
+ interpreted as a shell command, and the command's first line of output
+ is substituted into the line.
+
+ The main reason for supporting backticks is to do things like
+ ":n `grep -l sometext *.c`". The backtick expression would return
+ multiple file names. Because of this, it must be done at a fairly
+ high level in the ex command-line parser.
+
+ It would also be handy to have a "shell" function which runs a
+ command string and returns its output. That function would be
+ handy when implementing backtick support, and could also be used
+ for things like...
+
+ :let d=shell("date")
+
+/ Under Win32, can't always redirect an external program's stdin. For example,
+ ":%!\windows\command\sort" fails, but ":%!\usr\bin\sort" works.
+
+ This is ridiculously difficult. I/O redirection depends on whether
+ the program being run is 16-bit or 32-bit, whether you're running
+ it from WinElvis or elvis, whether you're running Win95/98 or
+ WinNT, and... something else that I haven't figured out yet.
+ I give up. Instead of trying to do it the efficient way (with
+ pipes when possible, and always using Win32 stdio redirection
+ facilities), I decided to rewrite it from scratch to do it the
+ brain-dead way: By constructing a shell script, and invoking
+ COMMAND.COM to run that script. This sucks, but it appears to
+ work reliably.
+
+? On some systems, elvis sometimes reports "# is illegal during initialization"
+ and then it skips some initialization steps for the first file. Later files
+ will be initialized correctly; it only affects the first file. This has been
+ reported under SCO and (I think) Irix. Unfortunately, it seems to interfere
+ with the "-VVV" vebose feedback.
+
+ I've improved error messages -- they now include the filename and
+ line number where the problem was detected. Hopefully that'll allow
+ me to get a little more feedback.
+
+ I just tried the newest code under SCO, and this didn't happen.
+ It worked fine. This is definitely a change in its behavior, and
+ that's good... but I wish I knew why it started, and why it may
+ have stopped.
+
+/ Add a "digraph" topic to the howto file, and improve the documentation of
+ digraphs in the main manual.
+
+/ Lose the "tagprgonce" option; the :local command offers a cleaner solution.
+ You can just say "local tagprg=..." in the alias, and be done with it.
+
+/ The [[ and ]] commands shouldn't be line-mode moves. I.e., from the middle
of a line, d]] should not delete the entire current line.
-* It would be handy if, in a :tag command line, the % character was expanded
- to the current file name.
+/ When a character-mode deletion ends at a newline, that newline should not
+ be deleted. The same goes for yanking.
-* The tagprg option (or something similar) should be used when reading tags
+? The tagprg option (or something similar) should be used when reading tags
for tag name completion. Apparently it isn't.
+ Actually I think it is, but maybe not quite correctly. The code
+ assumes the typed part of the tag name is always going to match the
+ initial part of each match. If the tagprg program doesn't do that,
+ then name completion gets confused. Changing this behavior will be
+ hard.
+
+/ In a shell command, file name completion should match binary files.
+
+/ After a repeated insert such as 25i*<Esc>, typing <.> will only repeat 24
+ insertions, not 25.
+------------------------------------------------------------------------------
+ELvis 2.1, official released version
+
/ Some HTTP sites require a "Host:" line in the GET request. The argument
to "Host:" is the site name and port of the URL elvis is trying to download.
View
23 Makefile.in
@@ -1,5 +1,5 @@
# Makefile.in
-# $Id: Makefile.in,v 2.58 1998/12/10 01:02:47 steve Exp $
+# $Id: Makefile.in,v 2.62 1999/06/19 01:06:23 steve Exp $
#
# Makefile.in should not be modified! The "configure" script reads Makefile.in
# and writes a customized Makefile by editing the values of the following
@@ -67,10 +67,11 @@ FLAGI=-I
################################################################################
# This is a list of programs to be created by "make all". The possible list
-# includes elvis$(EXE), ref$(EXE), ctags$(EXE), and fmt$(EXE). The $(EXE) on
+# includes elvis$(EXE), ref$(EXE), ctags$(EXE), elvtags$(EXE), and fmt$(EXE).
+# ctags and elvtags are the same program under different names. The $(EXE) on
# the end is just in case this Makefile is reconfigured for an operating
# system which requires the EXE macro to be something like ".exe".
-ALL=elvis$(EXE) ref$(EXE)
+ALL=elvis$(EXE) ref$(EXE) elvtags$(EXE)
################################################################################
# This is the directory where "make install" will place the executable programs
@@ -121,10 +122,10 @@ LPSRCS= lpescape.c lpovrtyp.c lpps.c
LPOBJS= lpescape$(OBJ) lpovrtyp$(OBJ) lpps$(OBJ)
HDRS= $(OSHDRS) buffer.h buffer2.h calc.h cut.h digraph.h display.h\
display2.h draw.h draw2.h elvis.h elvisio.h event.h ex.h gui.h gui2.h\
- input.h lowbuf.h lp.h map.h mark.h message.h misc.h more.h move.h\
- need.h operator.h opsys.h optglob.h options.h regexp.h safe.h scan.h\
- session.h state.h state2.h tag.h tagsrch.h tagelvis.h version.h vi.h\
- vicmd.h window.h config.h
+ input.h lowbuf.h lp.h map.h mark.h message.h message2.h misc.h more.h\
+ move.h need.h operator.h opsys.h optglob.h options.h regexp.h safe.h\
+ scan.h session.h state.h state2.h tag.h tagsrch.h tagelvis.h version.h\
+ vi.h vicmd.h window.h config.h
SRCS= $(OSSRCS) $(GUISRCS) $(LPSRCS) buffer.c calc.c cut.c digraph.c\
display.c dmhex.c dmmarkup.c dmnormal.c dmsyntax.c draw.c\
event.c ex.c exaction.c exconfig.c exedit.c exmake.c exsubst.c ftp.c\
@@ -149,7 +150,7 @@ CFLAGS= $(FLAGI)os$(OS)
EVERY= $(ALL) verify$(EXE) elvdump$(EXE) calc$(EXE)
SHELL= /bin/sh
-DISTRIB=elvis-2.1
+DISTRIB=elvis-2.1_3
DOSEXE=exedos
WIN32EXE=exewin32
OS2EXE=exeos2
@@ -164,6 +165,10 @@ elvis$(EXE): $(HDRS) main$(OBJ) $(OBJS) $(GUIOBJS) $(LPOBJS)
ctags$(EXE): $(CTOBJS)
$(CC) $(CFLAGS) $(CTOBJS) -o ctags$(EXE)
+elvtags$(EXE): ctags$(EXE)
+ $(CP) ctags$(EXE) elvtags$(EXE)
+ sed 's/\<CTAGS\>/ELVTAGS/g; s/\<ctags\>/elvtags/g' lib/ctags.man >lib/elvtags.man
+
ref$(EXE): $(REFOBJS)
$(CC) $(CFLAGS) $(REFOBJS) -o ref$(EXE)
@@ -243,6 +248,7 @@ clean.unix:
$(RM) errlist
$(RM) verify.elv
$(RM) $(DISTRIB).tar.gz
+ $(RM) lib/elvtags.man
clean.msdos:
$(RM) *$(OBJ)
@@ -291,6 +297,7 @@ $(DISTRIB).tar.gz:
rm -f $(DISTRIB)/osunix/osconfig.h
rm -f $(DISTRIB)/config.h
rm -f $(DISTRIB)/Makefile
+ rm -f $(DISTRIB)/lib/elvtags.man
tar czf $(DISTRIB).tar.gz $(DISTRIB)
rm -rf $(DISTRIB)
View
258 README.html
@@ -19,9 +19,10 @@
<li><a HREF="#functions">3.3 New functions</a>
<li><a HREF="#gui">3.4 New ports and GUI features</a>
<li><a HREF="#misc">3.5 Miscellany</a>
+ <li><a HREF="#revision">3.6 Revisions since the original 2.1 release</a>
</menu>
-<li><a HREF="#future">3. The future of elvis</a>
-<li><a HREF="#links">4. Links to related files</a>
+<li><a HREF="#future">4. The future of elvis</a>
+<li><a HREF="#links">5. Links to related files</a>
</menu>
<hr>
@@ -191,7 +192,7 @@
buffername.
<pre>
:e #1
- :1,20 cop (1)$
+ :1,20 copy (1)$
</pre>
<dt>locked, lock
@@ -219,7 +220,7 @@
<dt>putstyle, ps
<dd>This is only meaningful for cut buffers, not normal edit buffers.
-It indicates whether the cutr buffer's contents should be pasted as
+It indicates whether the cut buffer's contents should be pasted as
a series of characters, as a rectangular block, or as whole lines.
(Previously this information was stored in the first line of a cut buffer,
but that made cut buffers hard to edit.)
@@ -288,7 +289,7 @@
<br>italicstyle, ifn
<br>fixedstyle, ffn
<br>emphasizedstyle, efn
-<br>underlinedstyle, nfn
+<br>underlinedstyle, ufn
<dd>These control the appearance of text in the "windows" interface (for
Windows95/98/NT).
<code>font</code> stores the base font, and the other options tell elvis
@@ -467,7 +468,222 @@
</dl>
-<h1><a name="future"></a>3. The future of elvis</h1>
+<h2><a name="revision"></a>3.6 Revisions since the first 2.1 release</h2>
+
+This version of elvis is 2.1_3 (pronounced "two point one patch-level 3").
+It may also be written as 2.1.3; however, the "2.1_3" notation was chosen for a reason:
+the directory name "elvis-2.1_3" is a valid MS-DOS directory name, but
+"elvis-2.1.3" is not.
+
+<p>Many bugs and annoyances have been fixed since the first 2.1 release
+a couple months ago.
+The highlights are:
+<dl>
+
+<dt>Portability
+<dd>The "configure" script has been tweaked to support some Unix variants better.
+In particular, you should now be able to compile elvis under Linux systems that
+use libc-6, such as Red Hat, without doing anything except "configure;make".
+The same goes for SCO Unix.
+
+<p>Elvis' version of ctags will now be installed as "<strong>elvtags</strong>"
+on all Unix systems, including Linux.
+Previously for Linux it was installed as "ctags", which made sense because
+originally most versions of Linux used elvis 1.8's "ctags", but now most
+Linux systems ship with Exuberant Ctags as their default ctags.
+Previously, other versions of Unix skipped elvis' ctags
+because they already had their own.
+The new name for elvis' ctags should allow you to keep the old ctags and
+still have access to elvis' ctags when you want it.
+(Elvis' version can generate the "ln" attribute, which makes the
+<code>showtag</code> option load files faster, but Exuberant Ctags is
+better in just about every other way.)
+
+<p>Elvis' "fmt" program is no longer included in the default program list
+for any version of Unix.
+Previously it was installed under Linux, and skipped for other versions of Unix.
+
+<dt>Vi commands
+<dd>The [[ and ]] commands were acting like line-mode commands; i.e.,
+even with the cursor in the middle of a line, an operator such as d]] would
+delete whole lines.
+The real vi doesn't behave that way, so this was a bug.
+It has been fixed.
+
+<p>In fixing that bug, I noticed a problem in the way elvis was handling
+character-mode operations which happen to end at the start of a line.
+In certain circumstances, elvis was including the final newline character
+as part of the affected text, where the real vi would exclude it.
+This has been fixed.
+
+<p>Another minor bug: After a command such as "<kbd>25i*^[</kbd>" (to insert
+25 asterisks), attempting to repeat the command via "<kbd>.</kbd>" would only
+insert 24 asterisks. This has been fixed.
+
+<dt>Name completion
+<dd>The behavior of name completion is now slightly different. In 2.1_3,
+even if you've left the <code>completebinary</code> option turned off, elvis
+will still complete binary files' names when you're entering a shell command.
+This is handy when you're trying to enter an ex command such as...
+<pre>
+ :r !uuencode elvis-2.1_3.tar.gz &lt;elvis-2.1_3.tar.gz
+</pre>
+... in which you're running a program which takes a binary file as input. In any
+other context, the <code>completebinary</code> option will continue to work
+as before.
+
+<p>If you normally have <code>inputtab=identifier</code> set,
+elvis will ignore that (treat it like <code>inputtab=tab</code>)
+unless there is a "tags" file in the current directory.
+Without this rule, there could be a long delay if you're editing a
+non-source file and you hit the <kbd>&lt;Tab&gt;</kbd> key, because
+elvis would search through the whole tag path for the word before the tab.
+(A better solution is to only set <code>inputtab=identifier</code> if the
+file is in a known programming language, as detected by the
+<code>knownsyntax(</code><var>file</var><code>)</code> function.
+You can add that to your ~/.exrc file.)
+
+<dt>Tags (other than name completion)
+<dd>The <code>tagprgonce</code> option has been removed because the
+<code>:local</code> command offers a cleaner way to achieve the same effect.
+In any alias or script, you can simply replace ":set tagprgonce=..." with
+":local tagprg=...".
+
+<p>Also, there was a bug which prevented elvis from recognizing tags
+whose address contained a C++ comment.
+(In other words, "//" confused the tag file parser.)
+This bug is now fixed.
+
+<dt>Error reporting
+<dd>When there's an error in a script file or an alias, elvis 2.1_3 will
+now (usually) tell you the name of the script and the line number within it,
+where the error occurred.
+It only does this if the verbose option is set to 1 or higher
+(i.e., you give at least one uppercase -V flag on the command line).
+
+<p>I added this mostly because users on some Unix platforms have reported
+that elvis says "# is illegal during initialization". It doesn't happen on
+any system I use, and none of the standard scripts contain a "#" command,
+so I'm hoping this will allow users to give me more information.
+
+<p>Also, the <code>:cc</code> and <code>:make</code> commands used to output
+the first error message before the user hit <kbd>&lt;Enter&gt;</kbd>, but
+now it will show that message afterward.
+
+<dt>Networking
+<dd>The notation for FTP URLs has been extended.
+The original release of elvis 2.1 supported the standard
+<strong>ftp://</strong><var>host</var><strong>/</strong><var>resource</var>
+notation for anonymous FTP, and elvis' own
+<strong>ftp://</strong><var>host</var><strong>/~/</strong><var>resource</var>
+notation for accessing your own FTP account.
+Elvis 2.1_3 now adds
+<strong>ftp://</strong><var>host</var><strong>/~</strong><var>user</var><strong>/</strong><var>resource</var>
+to access some other user's account.
+
+<p>The format of the <code>~/.netrc</code> file or <code>elvis.ftp</code> file
+remains the same, but the way elvis interprets it has changed.
+It now allows multiple entries for the same machine, with different user names.
+When you use the
+<strong>ftp://</strong><var>host</var><strong>/~</strong><var>user</var><strong>/</strong><var>resource</var>
+notation to access a given user's account,
+elvis will search for an entry with a matching <var>host</var> and <var>user</var>, and use the password from that entry.
+
+<p>Elvis' implementation of HTTP was having trouble talking to some sites that
+run older server software.
+This should be fixed now.
+
+<dt>Windows95/98/NT
+<dd>The font selection dialog was listing all fonts, even though elvis can
+only use fixed-pitch fonts correctly. This has been changed, so the dialog
+will now list only the fixed-pitch fonts.
+
+<p>Many fixed-pitch fonts were being displayed with a large gap between the
+characters. For example, although "Courier" looked good, "Courier New" was
+unusable. This has been corrected by making elvis use the average character
+width instead of the maximum width.
+(Shouldn't those two values be the same for fixed-pitch fonts?
+Apparently they aren't.)
+
+<p>You can now define your own colors, in addition to the named colors, by
+using the notation #RRGGBB anywhere a color name is expected. The "RR", "GG",
+and "BB" are any pairs of hex digits, giving the amount of of red, green, and
+blue in the color. For example, "#c0d0ff" is a nice sky-blue color.
+(This is the same notation that X-windows uses for non-standard colors.)
+Presently this feature is limited to defining one extra foreground color plus
+one extra background color, and it only works correctly on "high color" or
+"true color" displays (<em>not 16-color or 256-color</em>); these limitations
+should be lifted in later versions of elvis.
+
+<p>Sometimes, for some programs, elvis was unable to redirect a program's stdin.
+This messed up attempts to filter text through an external program.
+Typically, the <code>fmt</code> program included with elvis worked correctly,
+but the standard MS-DOS <code>sort</code> program didn't.
+I've spent probably 10 whole days trying to get the Win32 I/O redirection
+functions to work consistently, and failed.
+I suspect that Serge has had the same bad luck.
+Elvis 2.1_3 has a totally rewritten module for running programs, which
+simply creates a batch file and runs it.
+If there is filtering to be done, then the batch file redirects stdin and/or
+stdout to temporary files.
+This is a kludge, but it seems to work reliably.
+
+<p>There were a couple of bugs in the "Options-&gt;Syntax" menu item.
+It wasn't always enabled for all syntaxes, and if it was enabled then
+selecting it would occasionally cause elvis to crash.
+Both of these should be fixed now.
+
+<dt>Miscellaneous Annoyances
+
+<dd>In filenames, you can now use the backtick notation to run an external
+program and have its output be parsed as part or all of the filename list.
+E.g., <code>:n `grep -l sometext *.c`</code>.
+While I was at it, I added a new <code>shell("command")</code> function which
+runs an external program and returns its output, so you can do things like
+<code>:let d=shell("date")</code>.
+(These features are omitted from the MS-DOS version to help elvis fit in
+the lower 640k.)
+
+<p>The <code>:mark</code> command, when invoked without any addresses, will
+now set the mark to the exact cursor position; previously it was just setting
+it to the start of the cursor's line.
+
+<p>I added a <code>:kwic</code> alias, which greps for a given word anywhere
+in elvis' documentation and builds a table table of all matches, with links
+to their locations.
+This gives you yet another way to search through elvis' documentation
+(in addition to the <code>:howto</code> alias and the <code>:help</code>
+built-in command).
+For non-Unix systems, you must find a grep utility somewhere for this to work.
+
+<p>If your ~/.exrc file contained <code>:set wrapmargin=0</code> then
+wrapmargin would be listed by <code>:set</code>, but it shouldn't be.
+And now it won't be.
+
+<p>It has been reported that "dead keys" (for entering accented letters)
+don't work under X11.
+It appears that my big mistake here was failing to #include
+&lt;X11/Intrinsics.h&gt;, so elvis' source code didn't know that
+the multi-character input methods were available.
+That's fixed, but now the multi-byte input code is being compiled for
+the first time, and new bugs may turn up.
+
+<p>If the TERM environment variable is unset and there is no reasonable default,
+then elvis will use the "open" user interface instead of "termcap".
+Previously you had to give an explicit "-Gopen" flag to make this happen.
+The new behavior is more like the traditional vi.
+
+<p>The markup display modes (html, man, and tex) can now be configured in or
+out separately, via DISPLAY_HTML, DISPLAY_MAN, and DISPLAY_TEX macros in the
+config.h file.
+Previously, there was a single DISPLAY_MARKUP macro which controlled all of
+them.
+This change was made mostly so that "tex" could be omitted from the MS-DOS
+version.
+
+</dl>
+
+<h1><a name="future"></a>4. The future of elvis</h1>
One of the biggest tasks on my list is to rewrite the ctags program
so that it will be able to parse C++ code better.
@@ -481,13 +697,25 @@
sometimes it would be nice if they could be attached to the existing window,
as a horizontal or vertical pane.
-<p>I intend to add a true extension language to elvis someday, but it
-isn't in 2.1.
+<p>More colors will be supported.
+The syntax of the <code>:color</code> command will change to allow you
+to specify colors and other attributes by the type of text, instead of
+defining colors by attributes.
+For example, "<code>:color link=underlined green</code>" will define the
+appearance of HTML links.
+
+<p>I intend to add a true extension language to elvis.
The language interface will be general enough to support a variety of
-languages. The first language supported will probably be PERL, followed
-rapidly by Python and TCL.
+languages.
+The first language supported will probably be PERL,
+followed rapidly by Python and TCL.
+
+<p>I'm thinking of modifying the markup display modes (man, tex, and html)
+to store the list of supported markups, and their effects, in a separate file.
+That way, you could create your own markups to display nroff -ms, RTF, SGML,
+and MIME "rich text" documents.
-<h1><a name="links"></a>4. Links to related files</H1>
+<h1><a name="links"></a>5. Links to related files</H1>
If the main site (<a href="ftp://ftp.cs.pdx.edu/pub/elvis/README.html">ftp.cs.pdx.edu</a>) is too slow, try the mirror site at
<a href="ftp://ftp.false.com/pub/elvis/README.html">
@@ -535,21 +763,21 @@
For brief instructions on how to use <code>untaros2,</code>
run it with no arguments.
-<dt><a href="elvis-2.1.tar.gz">elvis-2.1.tar.gz</a>
+<dt><a href="elvis-2.1_3.tar.gz">elvis-2.1_3.tar.gz</a>
<dd>This is a gzipped tar archive of the source code and documentation for
Elvis 2.1 and its related programs.
-<dt><a href="elvis-2.1-msdos.tar.gz">elvis-2.1-msdos.tar.gz</a>
+<dt><a href="elvis-2.1_3-msdos.tar.gz">elvis-2.1_3-msdos.tar.gz</a>
<dd>This archive contains the documentation and MS-DOS executables
for Elvis 2.1.
-<dt><a href="elvis-2.1-win32.tar.gz">elvis-2.1-win32.tar.gz</a>
+<dt><a href="elvis-2.1_3-win32.tar.gz">elvis-2.1_3-win32.tar.gz</a>
<dd>This archive contains the documentation and Win32 executables
for Elvis 2.1.
These were compiled and tested under Windows95, but should work under
WindowsNT 3.51 (or later) as well.
-<dt><a href="elvis-2.1-os2.tar.gz">elvis-2.1-os2.tar.gz</a>
+<dt><a href="elvis-2.1_3-os2.tar.gz">elvis-2.1_3-os2.tar.gz</a>
<dd>This archive contains the documentation and OS/2 executables
for Elvis 2.1.
View
61 buffer.c
@@ -1,7 +1,7 @@
/* buffer.c */
/* Copyright 1995 by Steve Kirkendall */
-char id_buffer[] = "$Id: buffer.c,v 2.92 1998/11/29 18:53:51 steve Exp $";
+char id_buffer[] = "$Id: buffer.c,v 2.94 1999/06/15 04:21:43 steve Exp $";
#include "elvis.h"
@@ -1202,36 +1202,39 @@ BOOLEAN bufwrite(from, to, wfile, force)
msg(MSG_STATUS, "[s]writing $1", wfile);
}
next = *from;
- scanalloc(&cp, &next);
- assert(cp);
- bytes = 1;
- do
+ if (o_bufchars(markbuffer(from)) > 0L)
{
- /* check for ^C */
- if (guipoll(False))
+ scanalloc(&cp, &next);
+ assert(cp);
+ bytes = 1;
+ do
{
- ioclose();
- scanfree(&cp);
- return False;
- }
+ /* check for ^C */
+ if (guipoll(False))
+ {
+ ioclose();
+ scanfree(&cp);
+ return False;
+ }
- bytes = scanright(&cp);
- if (markoffset(&next) + bytes > markoffset(to))
- {
- bytes = (int)(markoffset(to) - markoffset(&next));
- }
- if (iowrite(cp, bytes) < bytes)
- {
- msg(MSG_ERROR, (wfile[0] == '!') ? "broken pipe" : "disk full");
- ioclose();
- scanfree(&cp);
- return False;
- }
- markaddoffset(&next, bytes);
- scanseek(&cp, &next);
- } while (cp != NULL && markoffset(&next) < markoffset(to));
+ bytes = scanright(&cp);
+ if (markoffset(&next) + bytes > markoffset(to))
+ {
+ bytes = (int)(markoffset(to) - markoffset(&next));
+ }
+ if (iowrite(cp, bytes) < bytes)
+ {
+ msg(MSG_ERROR, (wfile[0] == '!') ? "broken pipe" : "disk full");
+ ioclose();
+ scanfree(&cp);
+ return False;
+ }
+ markaddoffset(&next, bytes);
+ scanseek(&cp, &next);
+ } while (cp != NULL && markoffset(&next) < markoffset(to));
+ scanfree(&cp);
+ }
ioclose();
- scanfree(&cp);
if (!filter)
{
@@ -1647,7 +1650,7 @@ long bufundo(cursor, back)
namedmark[i] = markalloc(buffer, undo->offset[i]);
}
}
-#ifdef DISPLAY_MARKUP
+#ifdef DISPLAY_ANYMARKUP
dmmuadjust(marktmp(from, buffer, 0), marktmp(to, buffer, o_bufchars(buffer)), 0);
#endif
@@ -1732,7 +1735,7 @@ void bufreplace(from, to, newp, newlen)
markbuffer(from)->changes++;
/* adjust the marks */
-#ifdef DISPLAY_MARKUP
+#ifdef DISPLAY_ANYMARKUP
dmmuadjust(from, to, chgchars);
#endif
markadjust(from, to, chgchars);
View
123 calc.c
@@ -1,7 +1,7 @@
/* calc.c */
/* Copyright 1995 by Steve Kirkendall */
-char id_calc[] = "$Id: calc.c,v 2.61 1998/12/04 23:12:25 steve Exp $";
+char id_calc[] = "$Id: calc.c,v 2.65 1999/04/08 22:09:25 steve Exp $";
#include "elvis.h"
#include <setjmp.h>
@@ -62,6 +62,9 @@ static CHAR *feature[] =
# ifdef FEATURE_RAM
toCHAR("ram"),
# endif
+# ifdef FEATURE_BACKTICK
+ toCHAR("backtick"),
+# endif
NULL
};
#endif
@@ -175,7 +178,8 @@ BOOLEAN calcbase10(str)
case '0': num = 0; break;
case 'a': num = '\007'; break;
case 'b': num = '\b'; break;
- case 'E': num = '\033'; break;
+ case 'E':
+ case 'e': num = '\033'; break;
case 'f': num = '\f'; break;
case 'n': num = '\n'; break;
case 'r': num = '\r'; break;
@@ -186,7 +190,7 @@ BOOLEAN calcbase10(str)
}
else
{
- if (str[1] == '\'' || !str[1] || str[2] != '\'')
+ if (str[1] == '\\' || !str[1] || str[2] != '\'')
return False;
num = str[1];
i = 3;
@@ -722,7 +726,81 @@ static BOOLEAN func(name, arg)
}
return True;
}
-#endif
+ else if (!CHARcmp(name, toCHAR("line")))
+ {
+ if (!*arg)
+ {
+ /* no arguments, use current line of current file */
+ if (!windefault)
+ goto NeedWindefault;
+ begin = markdup(windefault->cursor);
+ (void)marksetline(begin, markline(begin));
+ }
+ else if (calcnumber(arg))
+ {
+ /* just a number, use given line of current file */
+ if (!windefault)
+ goto NeedWindefault;
+ begin = markdup(windefault->cursor);
+ if (marksetline(begin, atol(tochar8(arg))) == NULL)
+ goto BadArgs;
+ }
+ else
+ {
+ /* given name & number, I hope! */
+ tmp = CHARrchr(arg, ',');
+ if (!tmp)
+ goto BadArgs;
+ *tmp++ = '\0';
+ end.buffer = buffind(arg);
+ if (!end.buffer
+ || !calcnumber(tmp)
+ || marksetline(&end, atol(tochar8(tmp))) == NULL)
+
+ goto BadArgs;
+ begin = markdup(&end);
+ }
+
+ /* one way or another, "begin" is now set to the start of the
+ * line. Copy it into the buffer (or as much of it as will fit)
+ */
+ for (scanalloc(&tmp, begin);
+ tmp && *tmp != '\n' && RESULT_AVAIL(name) > 10;
+ scannext(&tmp))
+ {
+ *name++ = *tmp;
+ }
+ scanfree(&tmp);
+ *name = '\0';
+ return True;
+ }
+ else if (!CHARcmp(name, toCHAR("shell")))
+ {
+ /* Insert a '!' at the front of arg. (This is safe
+ * since we know that "shell\0" appears before it.)
+ */
+ *--arg = '!';
+
+ /* Run the command and read its output */
+ if (ioopen(tochar8(arg), 'r', False, False, 't'))
+ {
+ arg = name;
+ while ((i = ioread(arg,RESULT_AVAIL(name))) > 0)
+ {
+ if (RESULT_OVERFLOW(arg, i + 1))
+ goto Overflow;
+ arg += i;
+ }
+ ioclose();
+ }
+
+ /* Remove the last newline */
+ if (arg != name && arg[-1] == '\n')
+ arg--;
+ *arg = '\0';
+ return True;
+ }
+#endif /* not TRY */
#ifdef TRY
msg(MSG_ERROR, "unknown function %s", name);
@@ -748,6 +826,16 @@ static BOOLEAN func(name, arg)
Overflow:
msg(MSG_ERROR, "result too long");
return False;
+
+#ifndef TRY
+NeedWindefault:
+ msg(MSG_ERROR, "[S]$1 requires both a buffer name and a line number when there is no window", name);
+ return False;
+
+BadArgs:
+ msg(MSG_ERROR, "[S]$1 called with bad arguments", name);
+ return False;
+#endif
}
/* This function applies a single operator. Returns False on error. Its
@@ -1298,24 +1386,29 @@ CHAR *calculate(expr, arg, asmsg)
/* may be a character constant, as in '\t' */
if (expr[0] == '\'')
{
- build[0] = expr[0];
- build[1] = expr[1];
- build[2] = expr[2];
- if (expr[1] == '\\')
- {
- build[3] = expr[3];
- build[4] = '\0';
- }
- else
+ /* copy it into build[] */
+ build[0] = *expr++;
+ for (i = 1; *expr && *expr != '\''; )
{
- build[3] = '\0';
+ build[i] = *expr++;
+ if (build[i++] == '\\' && *expr)
+ build[i++] = *expr++;
}
+ if (*expr == '\'')
+ build[i++] = *expr++;
+ build[i] = '\0';
+
+ /* convert to number */
if (calcbase10(build))
{
build += CHARlen(build);
- expr += (expr[1] == '\\' ? 4 : 3);
break;
}
+ else
+ {
+ msg(MSG_ERROR, "bad character literal");
+ return (CHAR *)0;
+ }
}
/* try to identify an operator. This is slightly
View
38 configure
@@ -324,36 +324,50 @@ if [ -f /usr/include/sys/ptem.h ]
then
why "This system has a <sys/ptem.h> file so I assume elvis needs it"
NEED_WINSIZE=define
+else
+ why "This system has no <sys/ptem.h> file so I assume elvis doesn't need it"
fi
if [ -f /usr/include/termcap.h ]
then
why "This system has a <termcap.h> file so I assume elvis needs it"
NEED_SPEED_T=define
+else
+ why "This system has no <termcap.h> file so I assume elvis doesn't need it"
fi
if [ -f /usr/include/sys/wait.h ]
then
why "This system has a <sys/wait.h> file so I assume elvis needs it"
NEED_WAIT_H=define
+else
+ why "This system has no <sys/wait.h> file so I assume elvis doesn't need it"
fi
if [ -f /usr/include/sys/select.h ]
then
why "This system has a <sys/select.h> file so I assume elvis needs it"
NEED_SELECT_H=define
+else
+ why "This system has no <sys/select.h> file so I assume elvis doesn't need it"
fi
if [ -f /usr/include/sys/ioctl.h ]
then
why "This system has a <sys/ioctl.h> file so I assume elvis needs it"
NEED_IOCTL_H=define
+else
+ why "This system has no <sys/ioctl.h> file so I assume elvis doesn't need it"
fi
if [ -f /usr/include/netinet/in.h ]
then
why "This system has a <netinet/in.h> file so I assume elvis needs it"
NEED_IN_H=define
+else
+ why "This system has no <netinet/in.h> file so I assume elvis doesn't need it"
fi
if [ -f /usr/include/sys/socket.h ]
then
why "This system has a <sys/socket.h> file so I assume elvis needs it"
NEED_SOCKET_H=define
+else
+ why "This system has no <sys/socket.h> file so I assume elvis doesn't need it"
fi
if [ X"$xinc" != X ]
then
@@ -361,6 +375,8 @@ then
then
why "This system has a <X11/Xos.h> file so I assume elvis needs it"
NEED_XOS_H=define
+ else
+ why "This system has no <X11/Xos.h> file so I assume elvis doesn't need it"
fi
fi
why "Does this system support setpgid()?"
@@ -449,6 +465,11 @@ case "$SYS" in
else
why "For Linux, we're using termcap because I prefer it over curses/terminfo"
fi
+ if [ "$NEED_SELECT_H" = "define" ]
+ then
+ why "For Linux, elvis never needs <sys/select.h> so I'm ignoring it on your system"
+ NEED_SELECT_H=undef
+ fi
;;
*osf*)
why "OSF is configured to use the bogus 'tinytcap.c' file instead of a real termcap"
@@ -498,6 +519,12 @@ case "$SYS" in
xlibdir=`dirname "$xlib"`
XLIBS=" -R$xlibdir$XLIBS"
fi
+ if [ -f /usr/ccs/lib/libtermcap.a ]
+ then
+ why "For Solaris2, -ltermcap is usually not necessary but since you have and and"
+ why " it is harmless, I'll add it."
+ TLIBS="$TLIBS -ltermcap"
+ fi
;;
*solaris*)
why "For Solaris 1, no really wacky tricks are needed. A -Dconst= flag is added"
@@ -531,7 +558,7 @@ case "$SYS" in
elif [ X"$inet" != X ]
then
why "For SCO, any network access needs -lsocket"
- LIBS="$LIBS -lsocket"
+ TLIBS="$TLIBS -lsocket"
fi
;;
*xenix*)
@@ -543,7 +570,8 @@ case "$SYS" in
fi
;;
*freebsd*)
- why "For FreeBSD, no tweaks are required"
+ why "For FreeBSD, we ignore the <sys/select.h> file"
+ NEED_SELECT_H="undef"
;;
*bsd*)
why "For BSD we like to use shlicc2 because it supports shared libraries"
@@ -676,7 +704,9 @@ cat >config.h <<eof-config
* mode. #define to enable the mode, #undef to exclude it.
*/
#define DISPLAY_HEX /* hex interactive hex dump */
-#define DISPLAY_MARKUP /* html/man/tex formatted text */
+#define DISPLAY_HTML /* html formatted text */
+#define DISPLAY_MAN /* man formatted text */
+#define DISPLAY_TEX /* tex formatted text */
#define DISPLAY_SYNTAX /* syntax generic syntax coloring */
#${PROTOCOL_HTTP} PROTOCOL_HTTP /* define to enable HTTP; undef to disable */
#${PROTOCOL_FTP} PROTOCOL_FTP /* define to enable FTP; undef to disable */
@@ -687,6 +717,7 @@ cat >config.h <<eof-config
#define FEATURE_COMPLETE /* filename completion */
#define FEATURE_LITRE /* accelerate searches for literal strings */
#undef FEATURE_RAM /* store edit buffer in RAM if "-f ram" */
+#define FEATURE_BACKTICK /* the \`program\` notation in file names */
/* The following provide custom implementation of some common functions which
@@ -779,7 +810,6 @@ eof-hp-ux
cat >$tmp <<eof-linux
s!^# Makefile.in\$!# Makefile - configured for $SYS!
s!^CC=.*!CC=$CC!
-s!^ALL=.*!ALL=elvis\$(EXE) ref\$(EXE) ctags\$(EXE) fmt\$(EXE)!
eof-linux
;;
View
4 ctags.c
@@ -1,6 +1,6 @@
/* ctags.c */
-char id_ctags[] = "$Id: ctags.c,v 2.22 1998/11/14 01:36:51 steve Exp $";
+char id_ctags[] = "$Id: ctags.c,v 2.23 1999/02/26 21:31:41 steve Exp $";
/* This is a reimplementation of the ctags(1) program. It supports ANSI C,
* and has heaps o' flags. It is meant to be distributed with elvis.
@@ -228,7 +228,7 @@ void file_copyline(seek, fp, buf)
fseek(file_fp, seek, 0);
/* write everything up to, but not including, the newline */
- for (ch = getc(file_fp); ch != '\n'; ch = next)
+ for (ch = getc(file_fp); ch != '\n' && ch != EOF; ch = next)
{
/* preread the next character from this file */
next = getc(file_fp);
View
8 display.c
@@ -1,7 +1,7 @@
/* display.c */
/* Copyright 1995 by Steve Kirkendall */
-char id_display[] = "$Id: display.c,v 2.17 1997/02/09 22:15:56 steve Exp $";
+char id_display[] = "$Id: display.c,v 2.18 1999/03/11 17:55:46 steve Exp $";
#include "elvis.h"
@@ -11,9 +11,13 @@ DISPMODE *allmodes[] =
#ifdef DISPLAY_HEX
&dmhex,
#endif
-#ifdef DISPLAY_MARKUP
+#ifdef DISPLAY_HTML
&dmhtml,
+#endif
+#ifdef DISPLAY_MAN
&dmman,
+#endif
+#ifdef DISPLAY_TEX
&dmtex,
#endif
#ifdef DISPLAY_SYNTAX
View
8 display2.h
@@ -33,9 +33,13 @@ extern DISPMODE dmnormal;
#ifdef DISPLAY_HEX
extern DISPMODE dmhex;
#endif
-#ifdef DISPLAY_MARKUP
+#ifdef DISPLAY_HTML
extern DISPMODE dmhtml;
+#endif
+#ifdef DISPLAY_MAN
extern DISPMODE dmman;
+#endif
+#ifdef DISPLAY_TEX
extern DISPMODE dmtex;
#endif
#ifdef DISPLAY_SYNTAX
@@ -52,7 +56,7 @@ extern MARK dispmove P_((WINDOW win, long linedelta, long wantcol));
extern long dispmark2col P_((WINDOW win));
extern void dispindent P_((WINDOW w, MARK line, long linedelta));
-#ifdef DISPLAY_MARKUP
+#ifdef DISPLAY_ANYMARKUP
extern void dmmuadjust P_((MARK from, MARK to, long delta));
#endif
#ifdef DISPLAY_SYNTAX
View
795 dmmarkup.c
@@ -1,27 +1,29 @@
/* dmmarkup.c */
/* Copyright 1995 by Steve Kirkendall */
-char id_dmmarkup[] = "$Id: dmmarkup.c,v 2.79 1998/11/28 05:12:02 steve Exp $";
+char id_dmmarkup[] = "$Id: dmmarkup.c,v 2.85 1999/06/15 04:18:16 steve Exp $";
/* This file contains some fairly generic text formatting code -- generic
* in the sense that it can be easily tweaked to format a variety of types
- * marked-up text. Currently, it supports useful subsets of NROFF and HTML
- * instructions.
+ * marked-up text. Currently, it supports useful subsets of NROFF, HTML,
+ * and TeX instructions.
*/
#include "elvis.h"
-#ifdef DISPLAY_MARKUP
+#ifdef DISPLAY_ANYMARKUP
+#undef SGML_HACK
#define GRANULARITY 64 /* number of LINEINFOs to allocate at a time */
+typedef enum { TWRAP_NO, TWRAP_AFTER, TWRAP_BEFORE } twrap_t;
typedef struct
{
- CHAR text[200]; /* raw text of token */
- long offset[200]; /* offsets of characters */
+ CHAR text[256]; /* raw text of token */
+ long offset[256]; /* offsets of characters */
int nchars; /* number of characters in text[] */
int width; /* normal displayed width of text[] */
struct markup_s *markup;/* info about markup token */
@@ -31,13 +33,13 @@ typedef struct markup_s
{
char *name; /* name of the markup */
char attr[8]; /* attributes of markup */
- BOOLEAN (*fn)P_((TOKEN *));/* ptr to special function */
+ twrap_t (*fn)P_((TOKEN *));/* ptr to special function */
} MARKUP;
#define TITLE attr[0] /* in title: -, N, Y */
#define BREAKLN attr[1] /* line break: -, 0, 1, 2, c, or p */
#define INDENT attr[2] /* -, <, >, or a number */
#define LIST attr[3] /* in list: -, N, Y, # */
-#define FONT attr[4] /* font: -, =, n, b, u, i, f, e, N, B, U, I, F, E */
+#define FONT attr[4] /* font: -,=,n,b,u,i,f,e,N,B,U,I,F,E */
#define FILL attr[5] /* Y=fill, N=preformatted, -=no chg. */
#define DEST attr[6] /* S=section, P=paragraph, T=<tab> key */
@@ -67,6 +69,9 @@ typedef struct
long endtitle; /* offset of the end of the title */
CHAR *title; /* title of document, or NULL */
CHAR **defs; /* macros within the text */
+#ifdef SGML_HACK
+ int flavor; /* which macro package to emulate */
+#endif
} MUINFO;
static BOOLEAN first; /* is this the first token on this line? */
@@ -100,52 +105,76 @@ static CHAR mantext[80]; /* buffer, holds args from .XX macro */
static long manoffset[80]; /* holds offsets of mantext[] chars */
static char manfont[80]; /* holds fonts of mantext[] chars */
+#ifdef SGML_HACK
+/* This stores the text of an expected terminator tag. SGML allows the use of
+ * "<tt/some text/" as a shorthand for "<tt>some text</tt>", so if this var
+ * is set to a non-empty string then the next "/" character is interpreted
+ * as this string.
+ */
+static CHAR sgmltag[20];
+#endif /* SGML_HACK */
+
/* Forward declarations of some functions which are static to this file */
+#ifdef DISPLAY_HTML
static void htmlescape P_((TOKEN *tok));
-static BOOLEAN htmlhr P_((TOKEN *token));
-static BOOLEAN htmlimg P_((TOKEN *token));
-static BOOLEAN htmlpre P_((TOKEN *token));
-static BOOLEAN htmlli P_((TOKEN *token));
-static BOOLEAN htmlinput P_((TOKEN *token));
-static BOOLEAN htmla P_((TOKEN *token));
-static void htmlmarkup P_((TOKEN *token));
+static twrap_t htmlimg P_((TOKEN *token));
+static twrap_t htmlpre P_((TOKEN *token));
+static twrap_t htmlli P_((TOKEN *token));
+static twrap_t htmlinput P_((TOKEN *token));
+static twrap_t htmla P_((TOKEN *token));
+static int htmlmarkup P_((TOKEN *token));
static TOKEN *htmlget P_((CHAR **refp));
static DMINFO *htmlinit P_((WINDOW win));
static CHAR *htmltagatcursor P_((WINDOW win, MARK cursor));
static MARK htmltagload P_((CHAR *tagname, MARK from));
static MARK htmltagnext P_((MARK cursor));
+#endif /* defined(DISPLAY_HTML) */
+
+#if defined(DISPLAY_HTML) || defined(DISPLAY_TEX)
+static twrap_t htmlhr P_((TOKEN *token));
+#endif
+
+#if defined(DISPLAY_HTML) || defined(DISPLAY_MAN)
+static twrap_t manput P_((void));
+#endif
+
+#ifdef DISPLAY_MAN
static void manescape P_((TOKEN *tok));
static int manarg P_((TOKEN *token, int start, _char_ font, BOOLEAN spc));
-static BOOLEAN manput P_((void));
-static BOOLEAN manTH P_((TOKEN *token));
-static BOOLEAN manSH P_((TOKEN *token));
-static BOOLEAN manBI P_((TOKEN *token));
-static BOOLEAN manIP P_((TOKEN *token));
+static twrap_t manTH P_((TOKEN *token));
+static twrap_t manSH P_((TOKEN *token));
+static twrap_t manBI P_((TOKEN *token));
+static twrap_t manIP P_((TOKEN *token));
static void manmarkup P_((TOKEN *token));
static TOKEN *manget P_((CHAR **refp));
static DMINFO *maninit P_((WINDOW win));
+#endif /* defined(DISPLAY_MAN) */
+
+#ifdef DISPLAY_TEX
static void texescape P_((TOKEN *tok));
-static BOOLEAN texscope P_((TOKEN *token));
-static BOOLEAN texoutput P_((TOKEN *token));
-static BOOLEAN texitem P_((TOKEN *token));
-static BOOLEAN textitle P_((TOKEN *token));
-static BOOLEAN texdigraph P_((TOKEN *token));
+static twrap_t texscope P_((TOKEN *token));
+static twrap_t texoutput P_((TOKEN *token));
+static twrap_t texitem P_((TOKEN *token));
+static twrap_t textitle P_((TOKEN *token));
+static twrap_t texdigraph P_((TOKEN *token));
static long texpair P_((CHAR **refp, TOKEN *token));
static TOKEN *texget P_((CHAR **refp));
static DMINFO *texinit P_((WINDOW win));
+#endif /* defined(DISPLAY_TEX) */
+
static void countchar P_((CHAR *p, long qty, _char_ font, long offset));
-static BOOLEAN put P_((TOKEN *token));
+static twrap_t put P_((TOKEN *token));
static void term P_((DMINFO *info));
static long mark2col P_((WINDOW w, MARK mark, BOOLEAN cmd));
static MARK move P_((WINDOW w, MARK from, long linedelta, long column, BOOLEAN cmd));
static MARK setup P_((WINDOW win, MARK top, long cursor, MARK bottom, DMINFO *info));
static MARK image P_((WINDOW w, MARK line, DMINFO *info, void (*draw)(CHAR *p, long qty, _char_ font, long offset)));
-#ifdef FEATURE_LPR
-static void header P_((WINDOW w, int pagenum, DMINFO *info, void (*draw)(CHAR *p, long qty, _char_ font, long offset)));
-#endif
static int start P_((WINDOW win, MARK from, void (*draw)(CHAR *p, long qty, _char_ font, long offset)));
static void storestate P_((long offset, LINEINFO *dest));
static void findtitle P_((BUFFER buf));
+#ifdef FEATURE_LPR
+static void header P_((WINDOW w, int pagenum, DMINFO *info, void (*draw)(CHAR *p, long qty, _char_ font, long offset)));
+#endif
/* Only a single TOKEN is ever really needed at one time */
static TOKEN rettok;
@@ -174,6 +203,7 @@ static CHAR space = ' ';
static CHAR bullet = '*';
+#ifdef DISPLAY_HTML
/*----------------------------------------------------------------------------*/
/* HTML-specific functions and variables */
@@ -340,31 +370,15 @@ static struct {
token->width = width;
}
-/* output a horizontal rule */
-static BOOLEAN htmlhr(token)
- TOKEN *token;
-{
- int len;
-
- assert(col == 0 && textwidth > 0);
-
- len = textwidth - indent * 3 / 2;
- if (len < 3)
- len = 3;
-
- /* draw the hrule */
- (*drawchar)(&space, -indent, 'g', (anyspc ? spcoffset : 1));
- (*drawchar)(&hyphen, -len, 'g', token->offset[0]);
- col = indent + len;
- anyspc = False;
- return False;
-}
-
/* Output the "alt" text from an <img> tag */
-static BOOLEAN htmlimg(token)
+static twrap_t htmlimg(token)
TOKEN *token;
{
int i, j;
+ BOOLEAN htmlurl;
+
+ /* detect whether this is an SGML <htmlurl> or <ulink> tag */
+ htmlurl = (token->text[1] == 'h' || token->text[1] == 'u');
/* look for an "alt=..." argument */
for (i = 5; i < token->nchars && CHARncmp(&token->text[i - 5], toCHAR(" alt="), 5); i++)
@@ -379,10 +393,14 @@ static BOOLEAN htmlimg(token)
}
}
- /* if we still have no "alt=" then try "src=" */
+ /* if we still have no "alt=" then try "src=" or "url=" */
if (i >= token->nchars)
{
- for (i = 5; i < token->nchars && CHARncmp(&token->text[i - 5], toCHAR(" src="), 5); i++)
+ for (i = 5;
+ i < token->nchars
+ && CHARncmp(&token->text[i - 5], toCHAR(" src="), 5)
+ && CHARncmp(&token->text[i - 5], toCHAR(" url="), 5);
+ i++)
{
}
@@ -425,7 +443,7 @@ static BOOLEAN htmlimg(token)
}
/* limit length to 14 characters -- tables look better that way */
- if (j > i + 14)
+ if (!htmlurl && j > i + 14)
j = i + 14;
/* Insert a little arrow in front of the label, pointing to the label.
@@ -435,23 +453,28 @@ static BOOLEAN htmlimg(token)
* And it gives the user an obvious place to double-click, to download
* the image.
*/
- mantext[0] = '>';
- manoffset[0] = token->offset[0];
- manfont[0] = 'u';
+ manlen = 0;
+ if (!htmlurl)
+ {
+ mantext[0] = '>';
+ manoffset[0] = token->offset[0];
+ manfont[0] = 'u';
+ manlen++;
+ }
/* copy it into the manput() arguments, and then put it. */
- for (manlen = 1; i < j && manlen < QTY(mantext); i++, manlen++)
+ for ( ; i < j && manlen < QTY(mantext); i++, manlen++)
{
mantext[manlen] = token->text[i];
manoffset[manlen] = token->offset[i];
- manfont[manlen] = 'N';
+ manfont[manlen] = htmlurl ? 'u' : 'N';
}
return manput();
}
/* Set the modeinfo's "graphic" flag if <pre graphic> */
-static BOOLEAN htmlpre(token)
+static twrap_t htmlpre(token)
TOKEN *token;
{
int i;
@@ -464,11 +487,11 @@ static BOOLEAN htmlpre(token)
break;
}
}
- return False;
+ return TWRAP_NO;
}
/* List items are preceded by a less-indented number or bullet */
-static BOOLEAN htmlli(token)
+static twrap_t htmlli(token)
TOKEN *token;
{
CHAR buf[10];
@@ -513,11 +536,11 @@ static BOOLEAN htmlli(token)
* here, but if the number/bullet doesn't fit within the indentation
* space then our indentation might be off. So we won't.
*/
- return False;
+ return TWRAP_NO;
}
/* Form elements are shown as reverse-video areas */
-static BOOLEAN htmlinput(token)
+static twrap_t htmlinput(token)
TOKEN *token;
{
int height; /* 1 for input, 2 for textarea */
@@ -551,7 +574,7 @@ static BOOLEAN htmlinput(token)
else
{
validx = i;
- for (vallen = i; i < token->nchars && !isspace(token->text[i]); i++)
+ for (vallen = i; i < token->nchars && isalnum(token->text[i]); i++)
{
}
}
@@ -579,7 +602,7 @@ static BOOLEAN htmlinput(token)
|| !CHARncmp(&token->text[i], toCHAR("HIDDEN"), 6))
{
/* HIDDEN field -- do nothing with it */
- return False;
+ return TWRAP_NO;
}
else if (!CHARncmp(&token->text[i], toCHAR("radio"), 5)
|| !CHARncmp(&token->text[i], toCHAR("RADIO"), 5))
@@ -630,7 +653,7 @@ static BOOLEAN htmlinput(token)
/* no it won't */
(*drawchar)(&newline, 1, 'n', -1);
col = 0;
- return True;
+ return TWRAP_BEFORE;
}
/* output the image */
@@ -647,19 +670,22 @@ static BOOLEAN htmlinput(token)
col = mycol;
}
if (vallen > 0)
- (*drawchar)(&token->text[validx], vallen, font, token->offset[validx]);
- (*drawchar)(&space, vallen - width, font, token->offset[token->nchars - 1]);
+ (*drawchar)(&token->text[validx], vallen,
+ font, token->offset[validx]);
+ if (width > vallen)
+ (*drawchar)(&space, vallen - width, /* <- negative! */
+ font, token->offset[token->nchars - 1]);
col += width;
}
anyspc = False;
- return False;
+ return TWRAP_NO;
}
/* switch to underline if this is an href anchor (else leave the font unchanged
* for name anchor).
*/
-static BOOLEAN htmla(token)
+static twrap_t htmla(token)
TOKEN *token;
{
/* whether we set the font or not, </a> will reset it so we always
@@ -672,11 +698,11 @@ static BOOLEAN htmla(token)
curfont = 'u';
/* zero width, always fits on line */
- return False;
+ return TWRAP_NO;
}
/* Look up an html markup token in a table */
-static void htmlmarkup(token)
+static int htmlmarkup(token)
TOKEN *token; /* the token to lookup */
{
static MARKUP tbl[] =
@@ -684,6 +710,64 @@ static void htmlmarkup(token)
/* Tag Effects Function */
/* TBILFFD */
+
+#ifdef SGML_HACK
+ /* These are SGML tags. We only consider using these when
+ * the display mode is "html sgml".
+ */
+ { "title", "N---b--" },
+ { "/title", "N-|-=--" },
+ { "/", "N---=--" },
+ { "author", "N0--I--" },
+ { "date", "N0--N--" },
+ { "sect", "Np0-BYS" }, /* <h1> */
+ { "sect1", "Nc1-BYS" }, /* <h2> */
+ { "sect2", "N12-BYS" }, /* <h3> */
+ { "para", "N1|-NYP" }, /* <p> */
+ { "simpara", "N1--NYP" }, /* <p> */
+ { "orderedlist","N->#-YP" }, /* <ol> */
+ { "/orderedlist","N0<N-Y-" }, /* </ol> */
+ { "itemizedlist","N->Y-YP" }, /* <ul> */
+ { "/itemizedlist","N0<N-Y-" }, /* </ul> */
+ { "listitem", "N0-----", htmlli }, /* <li> */
+ { "enum", "N->#-YP" }, /* <ol> */
+ { "/enum", "N0<N-Y-" }, /* </ol> */
+ { "itemize", "N->Y-YP" }, /* <ul> */
+ { "/itemize", "N0<N-Y-" }, /* </ul> */
+ { "item", "N0-----", htmlli }, /* <li> */
+ { "abstract", "N14-NYP" }, /* </blockquote> */
+ { "/abstract", "N12-NY-" }, /* </blockquote> */
+ { "verb", "N0---NP" },
+ { "/verb", "N0---Y-" },
+ { "tscreen", "N0>-F--", htmlpre },
+ { "/tscreen", "N0<-N--" },
+ { "descrip", "N-2-NYS" }, /* <dl> */
+ { "/descrip", "N02-NY-" }, /* </dl> */
+ { "tag", "N12-BYP" }, /* <dt> */
+ { "/tag", "N03-NY-" }, /* <dd> */
+ { "variablelist","N-2-NYS" }, /* <dl> */
+ { "/variablelist","N02-NY-" }, /* </dl> */
+ { "term", "N12-BYP" }, /* <dt> */
+ { "/term", "N03-NY-" }, /* <dd> */
+ { "htmlurl", "N-----T", htmlimg }, /* <img> */
+ { "url", "N-----T", htmlimg }, /* <img> */
+ { "ulink", "N---u-T" }, /* <a> */
+ { "/ulink", "N---=--" }, /* </a> */
+ { "replaceable","N---i--" }, /* <var> */
+ { "/replaceable","N---=--" }, /* </var> */
+ { "bf", "N---b--" }, /* <b> */
+ { "/bf", "N---=--" }, /* </b> */
+ { "sf", "N---b--" }, /* <strong> */
+ { "/sf", "N---=--" }, /* </strong> */
+ { "it", "N---i--" }, /* <i> */
+ { "/it", "N---=--" }, /* </i> */
+ { "sl", "N---i--" }, /* <i> */
+ { "/sl", "N---=--" }, /* </i> */
+ { "row", "N02--Y-" }, /* <tr> */
+ { "entry", "N-=-NY-" }, /* <td> */
+#endif /* SGML_HACK */
+
+ /* These are HTML tags */
{ "html", "Y-2-NY-" },
{ "/html", "N-2-NY-" },
{ "head", "Y-2-NY-" },
@@ -704,7 +788,7 @@ static void htmlmarkup(token)
{ "/h5", "N02-NY-" },
{ "h6", "N12-IY-" },
{ "/h6", "N02-NY-" },
- { "p", "N1--NYP" },
+ { "p", "N1|-NYP" },
{ "hr", "N0-----", htmlhr },
{ "img", "N------", htmlimg },
{ "frame", "N-----T", htmlimg },
@@ -761,6 +845,7 @@ static void htmlmarkup(token)
{ "/u", "N---=--" },
{ "tt", "N---f--" },
{ "/tt", "N---=--" },
+
{ (char *)0, "N------" }
};
MARKUP *scan; /* used for scanning the tbl[] array */
@@ -777,7 +862,11 @@ static void htmlmarkup(token)
len--; /* since we started at 1 */
/* look it up in the table */
+#ifdef SGML_HACK
+ for (scan = &tbl[mui->flavor];
+#else
for (scan = tbl;
+#endif
scan->name &&
(strlen(scan->name) != (unsigned)len ||
strncmp(scan->name, (char *)token->text + 1, (size_t)len));
@@ -787,6 +876,9 @@ static void htmlmarkup(token)
/* remember it */
token->markup = scan;
+
+ /* return the index of the markup in tbl[] */
+ return (int)(scan - tbl);
}
/* Read the next token. */
@@ -794,7 +886,7 @@ static TOKEN *htmlget(refp)
CHAR **refp; /* address of a (CHAR *) used for scanning */
{
long offset;
- BOOLEAN lower;
+ BOOLEAN lower, nameonly;
/* if the CHAR pointer is NULL, then return NULL */
if (!*refp)
@@ -808,16 +900,51 @@ static TOKEN *htmlget(refp)
rettok.markup = NULL;
scannext(refp);
+#ifdef SGML_HACK
+ /* If '/' and we were expecting '/' to be interpreted as an SGML-style
+ * terminator, then do that.
+ */
+ if (rettok.text[0] == '/' && *sgmltag)
+ {
+ /* replace the '/' with the SGML terminator tag name */
+ CHARcpy(rettok.text, sgmltag);
+ for ( ; rettok.text[rettok.nchars]; rettok.nchars++)
+ rettok.offset[rettok.nchars] = rettok.offset[0];
+
+ /* lookup the markup */
+ (void)htmlmarkup(&rettok);
+
+ /* when computing line breaks, assume this markup is hidden */
+ rettok.width = 0;
+
+ /* clear the sgmltag variable... unless this tag forces a
+ * newline before it is processed, in which case we need to
+ * return the same tag twice so we can't clobber it the first
+ * time.
+ */
+ if (rettok.markup->BREAKLN == '-' || first)
+ *sgmltag = '\0';
+
+ return &rettok;
+ }
+#endif /* SGML_HACK */
+
/* If '<' then token is a markup */
if (rettok.text[0] == '<')
{
/* This is a markup. Collect characters up to next '>' */
- for (lower = True; *refp && **refp != '>'; offset++, scannext(refp))
+ for (lower = nameonly = True;
+ *refp && **refp != '>' && !(**refp == '/' && nameonly && rettok.nchars > 1);
+ offset++, scannext(refp))
{
/* if token text is full, then skip this char */
if (rettok.nchars >= QTY(rettok.text) - 2)
continue;
+ /* if not alphanumeric, then clear nameonly */
+ if (nameonly && !isalnum(**refp))
+ nameonly = False;
+
/* Store the character. This is a little complex
* because we want to convert uppercase tags and
* parameter names to lowercase, but leave parameter
@@ -838,6 +965,19 @@ static TOKEN *htmlget(refp)
rettok.offset[rettok.nchars++] = offset;
}
+#ifdef SGML_HACK
+ /* if terminated with / then remember that the next / should be
+ * the ternminator. So "<tt/some text/" is interpreted as
+ * "<tt>some text</tt>". (This is an SGML thing.)
+ */
+ if (*refp && **refp == '/')
+ {
+ CHARncpy(sgmltag, toCHAR("</"), sizeof sgmltag);
+ CHARncpy(sgmltag + 2, rettok.text + 1, rettok.nchars - 1);
+ CHARcat(sgmltag, toCHAR(">"));
+ }
+#endif /* SGML_HACK */
+
/* store the terminating '>' */
rettok.text[rettok.nchars] = '>';
rettok.offset[rettok.nchars] = offset;
@@ -847,7 +987,7 @@ static TOKEN *htmlget(refp)
scannext(refp);
/* lookup the markup */
- htmlmarkup(&rettok);
+ (void)htmlmarkup(&rettok);
/* when computing line breaks, assume this markup is hidden */
rettok.width = 0;
@@ -873,6 +1013,9 @@ static TOKEN *htmlget(refp)
*refp
&& rettok.nchars < QTY(rettok.text) - 1
&& **refp > ' ' /* !isspace(**refp) */
+#ifdef SGML_HACK
+ && !(**refp == '/' && *sgmltag)
+#endif
&& **refp != '<';
offset++, scannext(refp))
{
@@ -902,6 +1045,7 @@ static DMINFO *htmlinit(win)
TOKEN *token;
MARKBUF top;
CHAR *p;
+ twrap_t result;
/* inherit some functions from dmnormal */
dmhtml.wordmove = dmnormal.wordmove;
@@ -913,6 +1057,17 @@ static DMINFO *htmlinit(win)
mui->line = (LINEINFO *)safealloc(GRANULARITY, sizeof(LINEINFO));
mui->nlines = 1; /* every buffer has at least one line */
+ /* decide which tags we should use -- HTML or SGML */
+#ifdef SGML_HACK
+ mui->flavor = 0;
+ if (CHARcmp(o_display(win), toCHAR("html sgml")))
+ {
+ /* we want plain HTML -- find the first HTML tag */
+ CHARcpy(rettok.text, toCHAR("<html>"));
+ mui->flavor = htmlmarkup(&rettok);
+ }
+#endif /* SGML_HACK */
+
/* temporarily move the cursor someplace harmless */
cursoffset = markoffset(win->cursor);
marksetoffset(win->cursor, o_bufchars(markbuffer(win->cursor)));
@@ -921,10 +1076,20 @@ static DMINFO *htmlinit(win)
win->mi = (DMINFO *)mui;
(void)start(win, marktmp(top, markbuffer(win->cursor), 0), NULL);
p = scanalloc(&p, &top);
+ result = TWRAP_NO;
for (token = (*mui->get)(&p);
token;
token = (*mui->get)(&p))
{
+ /* if previous token forced a newline after it, then this token
+ * is the start of the next line.
+ */
+ if (result == TWRAP_AFTER)
+ {
+ /* assert(first == True && col == 0); */
+ storestate(token->offset[0], NULL);
+ }
+
/* if cursor is at position 0, and this is a text token,
* then move the cursor here. This is done because otherwise
* the cursor would always start on an ugly formatting code.
@@ -940,7 +1105,8 @@ static DMINFO *htmlinit(win)
/* output the token. If it forces a new line, remember where
* that new line started.
*/
- if (put(token))
+ result = put(token);
+ if (result == TWRAP_BEFORE)
{
assert(first == True && col == 0);
storestate(token->offset[0], NULL);
@@ -1015,6 +1181,8 @@ static CHAR *htmltagatcursor(win, cursor)
if (!CHARncmp(token->text, toCHAR("<a "), 3)
|| !CHARcmp(token->text, toCHAR("</a>"))
|| !CHARncmp(token->text, toCHAR("<frame "), 7)
+ || !CHARncmp(token->text, toCHAR("<htmlurl "), 9)
+ || !CHARncmp(token->text, toCHAR("<ulink "), 7)
|| (anchor.text[1] == '/' && !CHARncmp(token->text, toCHAR("<img "), 5)))
{
anchor = *token;
@@ -1033,9 +1201,11 @@ static CHAR *htmltagatcursor(win, cursor)
ret = NULL;
if (anchor.text[1] != '/')
{
- /* search for an HREF=... or SRC=... parameter */
+ /* search for an HREF=, SRC=, or URL= parameter */
for (p = &anchor.text[3];
- CHARncmp(p, toCHAR("href="), 5) && CHARncmp(p, toCHAR("src="), 4);
+ CHARncmp(p, toCHAR("href="), 5)
+ && CHARncmp(p, toCHAR("src="), 4)
+ && CHARncmp(p, toCHAR("url="), 4);
p++)
{
if (*p == '>' || !*p)
@@ -1353,7 +1523,83 @@ static MARK htmltagnext(cursor)
/* else construct a mark for the start of the last token */
return marktmp(ret, markbuffer(cursor), token->offset[0]);
}
+#endif /* defined(DISPLAY_HTML) */
+
+#if defined(DISPLAY_HTML) || defined(DISPLAY_TEX)
+/* output a horizontal rule */
+static twrap_t htmlhr(token)
+ TOKEN *token;
+{
+ int len;
+
+ assert(col == 0 && textwidth > 0);
+
+ len = textwidth - indent * 3 / 2;
+ if (len < 3)
+ len = 3;
+
+ /* draw the hrule */
+ (*drawchar)(&space, -indent, 'g', (anyspc ? spcoffset : 1));
+ (*drawchar)(&hyphen, -len, 'g', token->offset[0]);
+ col = indent + len;
+ anyspc = False;
+ return TWRAP_NO;
+}
+#endif /* defined(DISPLAY_HTML) || defined(DISPLAY_TEX) */
+
+#if defined(DISPLAY_HTML) || defined(DISPLAY_MAN)
+/* This function either outputs mantext[] and returns False, or (if mantext[]
+ * is too wide to fit on this line) it outputs a newline and returns True.
+ */
+static twrap_t manput()
+{
+ int i, start;
+ /* if it won't fit, then output a newline instead */
+ if (!first && col > indent && col + manlen > textwidth - listind)
+ {
+ /* output a newline */
+ (*drawchar)(&newline, 1, 'n', anyspc ? spcoffset : -1);
+ col = 0;
+ first = True;
+ return TWRAP_BEFORE;
+ }
+
+ /* It will fit. If we need to adjust our indent, do it now */
+ if (col < indent)
+ {
+ (*drawchar)(&space, col - indent, 'n', anyspc ? spcoffset : -1);
+ col = indent;
+ anyspc = False;
+ }
+
+ /* Output a space between tokens, usually. */
+ if (anyspc)
+ {
+ (*drawchar)(&space, 1, 'n', spcoffset);
+ col++;
+ anyspc = False;
+ }
+
+ /* Output mantext[] in as few chunks as possible */
+ for (start = 0; start < manlen; start = i)
+ {
+ for (i = start + 1;
+ i < manlen
+ && manfont[i] == manfont[start]
+ && manoffset[i] == manoffset[i - 1] + 1;
+ i++)
+ {
+ }
+ (*drawchar)(&mantext[start], (long)(i - start), manfont[start], manoffset[start]);
+ }
+ col += manlen;
+
+ return TWRAP_NO;
+}
+#endif /* defined(DISPLAY_HTML) || defined(DISPLAY_MAN) */
+
+#ifdef DISPLAY_MAN
/*----------------------------------------------------------------------------*/
/* "man" mode functions */
@@ -1557,58 +1803,8 @@ static int manarg(token, start, font, spc)
}
-/* This function either outputs mantext[] and returns False, or (if mantext[]
- * is too wide to fit on this line) it outputs a newline and returns True.
- */
-static BOOLEAN manput()
-{
- int i, start;
-
- /* if it won't fit, then output a newline instead */
- if (!first && col > indent && col + manlen > textwidth - listind)
- {
- /* output a newline */
- (*drawchar)(&newline, 1, 'n', anyspc ? spcoffset : -1);
- col = 0;
- first = True;
- return True;
- }
-
- /* It will fit. If we need to adjust our indent, do it now */
- if (col < indent)
- {
- (*drawchar)(&space, col - indent, 'n', anyspc ? spcoffset : -1);
- col = indent;
- anyspc = False;
- }
-
- /* Output a space between tokens, usually. */
- if (anyspc)
- {
- (*drawchar)(&space, 1, 'n', spcoffset);
- col++;
- anyspc = False;
- }
-
- /* Output mantext[] in as few chunks as possible */
- for (start = 0; start < manlen; start = i)
- {
- for (i = start + 1;
- i < manlen
- && manfont[i] == manfont[start]
- && manoffset[i] == manoffset[i - 1] + 1;
- i++)
- {
- }
- (*drawchar)(&mantext[start], (long)(i - start), manfont[start], manoffset[start]);
- }
- col += manlen;
-
- return False;
-}
-
/* This function implements the .TH macro, which declares the page's title */
-static BOOLEAN manTH(token)
+static twrap_t manTH(token)
TOKEN *token;
{
int i;
@@ -1629,11 +1825,11 @@ static BOOLEAN manTH(token)
mui->title = CHARdup(mantext);
}
- return False;
+ return TWRAP_NO;
}
/* This function implements the .SH and .SS macros */
-static BOOLEAN manSH(token)
+static twrap_t manSH(token)
TOKEN *token;
{
long nloff; /* offset of newline */
@@ -1671,18 +1867,18 @@ static BOOLEAN manSH(token)
/* force the indentation to be the default */
indent = listind * 2;
- /* Return False even though we did output a newline. The newline
- * (and the text before it) is considered to be part of the same
- * "line" as far as movement is concerned.
+ /* Force the line to end after this title; this affects movement,
+ * not the appearance of the title since we already output a newline
+ * here.
*/
- return False;
+ return TWRAP_AFTER;
}
/* This function implements the font-changing macros such as .BI, .RB, and
* so on. The resulting text is treated as a single word; if it can't fit
* on the current line, then this function merely outputs a newline.
*/
-static BOOLEAN manBI(token)
+static twrap_t manBI(token)
TOKEN *token;
{
char font1, font2;
@@ -1719,17 +1915,17 @@ static BOOLEAN manBI(token)
if (list || (o_showmarkups && token->offset[0] <= cursoff && cursoff <= token->offset[token->nchars - 1]))
{
token->width = manlen + 1; /* "+ 1" to allow for whitespace */
- return False;
+ return TWRAP_NO;
}
- else if (manput())
+ else if (manput() != TWRAP_NO)
{
- return True;
+ return TWRAP_BEFORE;
}
/* assume there should be some whitespace after this */
anyspc = True;
spcoffset = token->offset[token->nchars - 1];
- return False;
+ return TWRAP_NO;
}
/* This function implements the .IP macro. It outputs its first argument,
@@ -1738,7 +1934,7 @@ static BOOLEAN manBI(token)
* the end of "line" as far as moving the cursor is concerned; it is just
* a funny type of wrapping.
*/
-static BOOLEAN manIP(token)
+static twrap_t manIP(token)
TOKEN *token;
{
int i, start;
@@ -1748,7 +1944,7 @@ static BOOLEAN manIP(token)
* performing its output.
*/
if (list || (o_showmarkups && token->offset[0] <= cursoff && cursoff <= token->offset[token->nchars - 1]))
- return False;
+ return TWRAP_NO;
/* get the first arg, as the paragraph tag */
manlen = 0;
@@ -1802,10 +1998,9 @@ static BOOLEAN manIP(token)
{
(*drawchar)(&newline, 1, 'n', token->offset[token->nchars - 1]);
col = 0;
+ return TWRAP_AFTER;
}
-
- /* return False, even if we output a newline */
- return False;
+ return TWRAP_NO;
}
/* Look up a man markup token in a table */
@@ -1880,7 +2075,12 @@ static TOKEN *manget(refp)
/* if the CHAR pointer is NULL, then return NULL */
if (!*refp)
+ {
+#ifdef DEBUG_MARKUP
+ fprintf(stderr, "manget() returning NULL\n");
+#endif
return NULL;
+ }
/* Get first character of token */
offset = markoffset(scanmark(refp));
@@ -1912,7 +2112,12 @@ static TOKEN *manget(refp)
back = scanmark(refp);
next = manget(refp);
if (next && next->markup && next->markup->BREAKLN != '-')
+ {
+#ifdef DEBUG_MARKUP
+ fprintf(stderr, "manget() returning \"%s\", offset=%ld, BREAKLN\n", next->text[0] == '\n' ? "\\n" : (char *)next->text, next->offset[0]);
+#endif
return next;
+ }
scanseek(refp, back);
rettok = tmp;
}
@@ -1932,6 +2137,9 @@ static TOKEN *manget(refp)
rettok.nchars = 5;
manmarkup(&rettok);
midline = False;
+#ifdef DEBUG_MARKUP
+ fprintf(stderr, "manget() returning constructed \"%s\", offset=%ld\n", rettok.text[0] == '\n' ? "\\n" : (char *)rettok.text, rettok.offset[0]);
+#endif
return &rettok;
}
@@ -2074,6 +2282,9 @@ static TOKEN *manget(refp)
/* Mark the end of the text, and return the token */
rettok.text[rettok.nchars] = '\0';
+#ifdef DEBUG_MARKUP
+ fprintf(stderr, "manget() returning \"%s\", offset=%ld\n", rettok.text[0] == '\n' ? "\\n" : (char *)rettok.text, rettok.offset[0]);
+#endif
return &rettok;
}
@@ -2084,6 +2295,7 @@ static DMINFO *maninit(win)
MARKBUF top;
CHAR *p;
long cursoffset;
+ twrap_t result;
/* inherit some functions from dmnormal */
dmman.wordmove = dmnormal.wordmove;
@@ -2103,13 +2315,29 @@ static DMINFO *maninit(win)
marksetoffset(win->cursor, o_bufchars(markbuffer(win->cursor)));
/* format the buffer */
+#ifdef DEBUG_MARKUP
+ fprintf(stderr, "maninit() starting\n");
+#endif
win->mi = (DMINFO *)mui;
(void)start(win, marktmp(top, markbuffer(win->cursor), 0), NULL);
p = scanalloc(&p, &top);
+ result = TWRAP_NO;
for (token = (*mui->get)(&p);
token;
token = (*mui->get)(&p))
{
+ /* if previous token forced a newline after it, then this token
+ * is the start of the next line.
+ */
+ if (result == TWRAP_AFTER)
+ {
+#ifdef DEBUG_MARKUP
+ fprintf(stderr, "maninit() storing line %ld, offset=%ld, result=TWRAP_AFTER\n", mui->nlines + 1, token->offset[0]);
+#endif
+ assert(first == True && col == 0);
+ storestate(token->offset[0], NULL);
+ }
+
/* if cursor is at position 0, and this is a text token,
* then move the cursor here. This is done because otherwise
* the cursor would always start on an ugly formatting code.
@@ -2125,14 +2353,24 @@ static DMINFO *maninit(win)
/* output the token. If it forces a new line, remember where
* that new line started.
*/
- if (put(token))
+ result = put(token);
+ if (result == TWRAP_BEFORE)
{
+#ifdef DEBUG_MARKUP
+ fprintf(stderr, "maninit() storing line %ld, offset=%ld, result=TWRAP_BEFORE\n", mui->nlines + 1, token->offset[0]);
+#endif
assert(first == True && col == 0);
storestate(token->offset[0], NULL);
- (void)put(token);
+ result = put(token);
+#ifdef DEBUG_MARKUP
+ fprintf(stderr, "maninit() after 2nd put(), result=TWRAP_%s\n", result==TWRAP_BEFORE ? "BEFORE" : "AFTER");
+#endif
}
}
scanfree(&p);
+#ifdef DEBUG_MARKUP
+ fprintf(stderr, "maninit() finished\n");
+#endif
/* restore th