[comp.sources.bugs] adding feature to LESS V5

pwolfe@kailand.KAI.COM (09/25/88)

Okay, I'll try again.

Version 73 of less had a feature that was eliminated in the recent posting.
The "e" option still quits the second time you reach end of file, but now if
a single file being displayed that is less than one screen length, less
doesn't exit immediately, but displays it's prompt instead.

I prefered the old action (which was similar to the way "more" works), but I
found out from the original author that workstation users have problems with
this action causing windows to disappear as soon as they appear, so I made it
a separate option, -f.

This patch does not fix any bugs, so it is not really neccessary for you to
install it, but on the other hand, it shouldn't hurt either.


Patrick J. Wolfe  (pwolfe@kai.com,  uunet!kailand!pwolfe)
System Manager, Kuck and Associates Inc.



*** /tmp/,RCSt1006768	Sat Sep 24 13:23:42 1988
--- less.nro	Sat Sep 24 13:20:55 1988
***************
*** 291,296
  the second time it reaches end-of-file.
  .IP -E
  The -E flag causes less to exit the first time it reaches end-of-file.
  .IP -h
  Normally,
  .I less

--- 291,301 -----
  the second time it reaches end-of-file.
  .IP -E
  The -E flag causes less to exit the first time it reaches end-of-file.
+ .IP -f
+ When used with the -e option and the display is shorter than one screen,
+ less will exit immediately when it reaches end-of-file.
+ Workstations where less creates a window should NOT use this, or
+ the window will disappear immediately.
  .IP -h
  Normally,
  .I less
*** /tmp/,RCSt1006789	Sat Sep 24 13:24:12 1988
--- option.c	Sat Sep 24 12:43:17 1988
***************
*** 33,38
  public int bs_mode;		/* How to process backspaces */
  public int know_dumb;		/* Don't complain about dumb terminals */
  public int quit_at_eof;		/* Quit after hitting end of file twice */
  public int squeeze;		/* Squeeze multiple blank lines into one */
  public int tabstop;		/* Tab settings */
  public int back_scroll;		/* Repaint screen on backwards movement */

--- 33,39 -----
  public int bs_mode;		/* How to process backspaces */
  public int know_dumb;		/* Don't complain about dumb terminals */
  public int quit_at_eof;		/* Quit after hitting end of file twice */
+ public int exit_if_short;	/* Quit immediately if file is short */
  public int squeeze;		/* Squeeze multiple blank lines into one */
  public int tabstop;		/* Tab settings */
  public int back_scroll;		/* Repaint screen on backwards movement */
***************
*** 102,107
  		{ "Don't quit at end-of-file",
  		  "Quit at end-of-file",
  		  "Quit immediately at end-of-file"
  		}
  	},
  	{ 'h', NUMBER, -1, &back_scroll,

--- 103,114 -----
  		{ "Don't quit at end-of-file",
  		  "Quit at end-of-file",
  		  "Quit immediately at end-of-file"
+ 		}
+ 	},
+ 	{ 'f', BOOL, 0, &exit_if_short,
+ 		{ "Don't quit at end-of-file if file is short",
+ 		  "Quit immediately at end-of-file if file is short",
+ 		  NULL
  		}
  	},
  	{ 'h', NUMBER, -1, &back_scroll,
*** /tmp/,RCSt1007557	Sat Sep 24 14:54:06 1988
--- prim.c	Sat Sep 24 14:53:44 1988
***************
*** 21,26
  extern int linenums;
  extern int plusoption;
  extern char *line;
  extern char *first_cmd;
  #if TAGS
  extern int tagoption;

--- 21,28 -----
  extern int linenums;
  extern int plusoption;
  extern char *line;
+ extern int ac;
+ extern int exit_if_short;
  extern char *first_cmd;
  #if TAGS
  extern int tagoption;
***************
*** 198,203
  		eof_bell();
  	else if (do_repaint)
  		repaint();
  	first_time = 0;
  	(void) currline(BOTTOM);
  }

--- 200,208 -----
  		eof_bell();
  	else if (do_repaint)
  		repaint();
+   	if (exit_if_short && first_time && hit_eof && quit_at_eof && ac <= 1) {
+   		quit ();
+   		}
  	first_time = 0;
  	(void) currline(BOTTOM);
  }

dupuy@douglass.columbia.edu (Alexander Dupuy) (09/25/88)

Before people go and add incompatible flags to their versions of less, there is
a better way....

Here are my local patches to less.  I had planned to finish reapplying all my
local patches to the last version, and post them all at once.  But since the
fifth patch does what Patrick Wolfe wants, without causing problems for users
of terminals with a special termcap mode (like xterm, cmdtool, or multi-page
terminals) and since there is a problem with the HP display fixes that Julian
Perry posted which causes terminals which have clear-eol but not clear-eos to
exhibit the symptoms the HP used to have, I'm posting them now.  When I finish
the rest, I'll post them as well, and send the whole shebang to Mark Nudelman.

If you have a recent version of patch, and a virgin copy of less, you can just
feed patch the entire article.  Otherwise, unshar it, and feed patch the pieces
which are relevant.  There's a brief description at the beginning of each one.

: This is a shar archive.  Extract with sh, not csh.
: The rest of this file will extract: 
:
:	PATCH.1
:	PATCH.2
:	PATCH.3
:	PATCH.3a
:	PATCH.4
:	PATCH.5
:	PATCH.6
:
echo x - PATCH.1
sed 's/^X//' > PATCH.1 << '//go.sysin dd *'
X
XSince it isn't always possible to get people to install the latest and greatest
Xversion of less, it's sometimes nice to allow less to work with some old flags.
XI use LESS=pc to get my preferred behavior on both old and new versions.
X
X*** /tmp/,RCSt1a10424	Mon Sep 19 18:02:21 1988
X--- option.c	Mon Sep 19 16:59:44 1988
X***************
X*** 477,482 ****
X--- 477,484 ----
X  		s--;
X  		c = 'z';
X  		break;
X+ 	case 'p':
X+ 		c = 'C';		/* compatibility with old less */
X  	}
X  
X  	for (o = option;  o->oletter != '\0';  o++)
//go.sysin dd *
echo x - PATCH.2
sed 's/^X//' > PATCH.2 << '//go.sysin dd *'
X
XAnother compatibility issue is the -t flag, which is now -a.  Since the new use
Xof -t requires a string argument, we can be compatible when it's the last char
Xin an option cluster.  This allows LESS=emct and similar uses.
X
X*** /tmp/,RCSt1a10951	Mon Sep 19 19:10:30 1988
X--- option.c	Mon Sep 19 19:08:32 1988
X***************
X*** 458,463 ****
X--- 458,468 ----
X  	case 't':
X  	{
X  		char *p;
X+ 		if (*s == ' ' || *s == '\t' || *s == '\0')
X+ 		{
X+ 			c = 'a';	/* some compatibility with old less */
X+ 			break;
X+ 		}
X  		tagoption = 1;
X  		p = s;
X  		s = optstring(s, c);
X***************
X*** 464,469 ****
X--- 469,478 ----
X  		findtag(p);
X  		goto next;
X  	}
X+ #else
X+ 	case 't':
X+ 		c = 'a';		/* compatibility with old less */
X+ 		break;
X  #endif
X  	case 'P':
X  		s = opt_P(s);
//go.sysin dd *
echo x - PATCH.3
sed 's/^X//' > PATCH.3 << '//go.sysin dd *'
X
XIt is sometimes useful to be able to look at a character special file (like a
Xtape).  There's also no reason why you shouldn't be able to look at a fifo.
X
X*** /tmp/,RCSt1a11210	Mon Sep 19 19:25:20 1988
X--- os.c	Mon Sep 19 19:25:04 1988
X***************
X*** 245,250 ****
X--- 245,252 ----
X  #include <sys/types.h>
X  #include <sys/stat.h>
X  
X+ extern int	ispipe;
X+ 
X  	public char *
X  bad_file(filename, message, len)
X  	char *filename;
X***************
X*** 253,258 ****
X--- 255,262 ----
X  {
X  	struct stat statbuf;
X  
X+ 	ispipe = 0;
X+ 
X  	if (stat(filename, &statbuf) < 0)
X  		return (errno_message(filename, message, len));
X  
X***************
X*** 263,268 ****
X--- 267,284 ----
X  		strcat(message, is_dir);
X  		return (message);
X  	}
X+ 	if ((statbuf.st_mode & S_IFMT) == S_IFCHR)
X+ 	{
X+ 		ispipe = 1;
X+ 		return (NULL);
X+ 	}
X+ #ifdef S_IFIFO
X+ 	if ((statbuf.st_mode & S_IFMT) == S_IFIFO)
X+ 	{
X+ 		ispipe = 1;
X+ 		return (NULL);
X+ 	}
X+ #endif
X  	if ((statbuf.st_mode & S_IFMT) != S_IFREG)
X  	{
X  		static char not_reg[] = " is not a regular file";
X*** /tmp/,RCSt1a11228	Mon Sep 19 19:31:49 1988
X--- main.c	Mon Sep 19 19:31:36 1988
X***************
X*** 133,140 ****
X  	previous_file = current_file;
X  	current_file = filename;
X  	prev_pos = position(TOP);
X! 	ispipe = (f == 0);
X! 	if (ispipe)
X  		didpipe = 1;
X  	file = f;
X  	ch_init(cbufs, 0);
X--- 133,140 ----
X  	previous_file = current_file;
X  	current_file = filename;
X  	prev_pos = position(TOP);
X! 	ispipe |= (f == 0);
X! 	if (f == 0)
X  		didpipe = 1;
X  	file = f;
X  	ch_init(cbufs, 0);
//go.sysin dd *
echo x - PATCH.3a
sed 's/^X//' > PATCH.3a << '//go.sysin dd *'
X*** /tmp/,RCSt1a03252	Sun Sep 25 00:04:19 1988
X--- /tmp/,RCSt2a03252	Sun Sep 25 00:04:20 1988
X***************
X*** 201,207 ****
X  		/*
X  		 * Read the output of <$SHELL -c "echo filename">.
X  		 */
X! 		cmd = calloc(strlen(p)+12);
X  		if (cmd == NULL)
X  			return (filename);
X  		sprintf(cmd, "%s -c \"echo %s\"", p, filename);
X--- 201,207 ----
X  		/*
X  		 * Read the output of <$SHELL -c "echo filename">.
X  		 */
X! 		cmd = calloc(strlen(p)+strlen(filename)+12, sizeof(char));
X  		if (cmd == NULL)
X  			return (filename);
X  		sprintf(cmd, "%s -c \"echo %s\"", p, filename);
//go.sysin dd *
echo x - PATCH.4
sed 's/^X//' > PATCH.4 << '//go.sysin dd *'
XBugfix for underlining from David MacKenzie (edf@rocky2.rockefeller.edu).
X
X*** /tmp/,RCSt1a08977	Wed Sep 21 13:31:15 1988
X--- less.h	Wed Sep 21 12:33:00 1988
X***************
X*** 59,68 ****
X  #define	BS_CONTROL	2	/* \b treated as control char; prints as ^H */
X  
X  /* Special chars used to tell put_line() to do something special */
X! #define	UL_CHAR		'\201'	/* Enter underline mode */
X! #define	UE_CHAR		'\202'	/* Exit underline mode */
X! #define	BO_CHAR		'\203'	/* Enter boldface mode */
X! #define	BE_CHAR		'\204'	/* Exit boldface mode */
X  
X  #define	CONTROL(c)		((c)&037)
X  #define	SIGNAL(sig,func)	signal(sig,func)
X--- 59,68 ----
X  #define	BS_CONTROL	2	/* \b treated as control char; prints as ^H */
X  
X  /* Special chars used to tell put_line() to do something special */
X! #define	UL_CHAR		(unsigned) 0201	/* Enter underline mode */
X! #define	UE_CHAR		(unsigned) 0202	/* Exit underline mode */
X! #define	BO_CHAR		(unsigned) 0203	/* Enter boldface mode */
X! #define	BE_CHAR		(unsigned) 0204	/* Exit boldface mode */
X  
X  #define	CONTROL(c)		((c)&037)
X  #define	SIGNAL(sig,func)	signal(sig,func)
X*** /tmp/,RCSt1a08977	Wed Sep 21 13:31:16 1988
X--- output.c	Wed Sep 21 12:33:02 1988
X***************
X*** 44,50 ****
X  	column = 0;
X  	for (p = line;  *p != '\0';  p++)
X  	{
X! 		switch (c = *p)
X  		{
X  		case UL_CHAR:
X  			ul_enter();
X--- 44,50 ----
X  	column = 0;
X  	for (p = line;  *p != '\0';  p++)
X  	{
X! 		switch (c = *p & 0377)
X  		{
X  		case UL_CHAR:
X  			ul_enter();
X*** /tmp/,RCSt1a08977	Wed Sep 21 13:31:17 1988
X--- os.c	Wed Sep 21 12:42:09 1988
X***************
X*** 201,207 ****
X  		/*
X  		 * Read the output of <$SHELL -c "echo filename">.
X  		 */
X! 		cmd = calloc(strlen(p)+12);
X  		if (cmd == NULL)
X  			return (filename);
X  		sprintf(cmd, "%s -c \"echo %s\"", p, filename);
X--- 201,207 ----
X  		/*
X  		 * Read the output of <$SHELL -c "echo filename">.
X  		 */
X! 		cmd = calloc(strlen(p)+strlen(filename)+12, sizeof(char));
X  		if (cmd == NULL)
X  			return (filename);
X  		sprintf(cmd, "%s -c \"echo %s\"", p, filename);
//go.sysin dd *
echo x - PATCH.5
sed 's/^X//' > PATCH.5 << '//go.sysin dd *'
XPatrick J. Wolfe (pwolfe@kai.com) posted a patch which reimplemented a feature
Xof less I sent to Casey Leedom and which might have been found in one of his
X"unofficial" distributions of less.  
X
XSpecifically, it caused less to automatically exit at the end of the first and
Xonly file, if it was less than one page (the idea being that you can see the
Xwhole thing without a pager).
X
XIt was pointed out that this causes some problems for people on workstations,
Xor more generally anyone whose terminal goes into a special mode for termcap
Xusing terminals.
X
XThe right way to fix this problem is to automatically disable the feature when
Xless is running on a terminal with a special termcap mode.
X
X*** /tmp/,RCSt1a02865	Sat Sep 24 23:10:58 1988
X--- screen.c	Sat Sep 24 23:10:13 1988
X***************
X*** 55,60 ****
X--- 55,61 ----
X  
X  public int auto_wrap;		/* Terminal does \r\n when write past margin */
X  public int ignaw;		/* Terminal ignores \n immediately after wrap */
X+ public int te_init;		/* Terminal uses ti and/or te for screen mode */
X  public int erase_char, kill_char; /* The user's erase and line-kill chars */
X  public int sc_width, sc_height;	/* Height & width of screen */
X  public int sc_window = -1;	/* window size for forward and backward */
X***************
X*** 267,276 ****
X--- 268,281 ----
X  	sc_init = tgetstr("ti", &sp);
X  	if (sc_init == NULL)
X  		sc_init = "";
X+ 	else
X+ 		te_init = 1;
X  
X  	sc_deinit= tgetstr("te", &sp);
X  	if (sc_deinit == NULL)
X  		sc_deinit = "";
X+ 	else
X+ 		te_init = 1;
X  
X  	sc_eol_clear = tgetstr("ce", &sp);
X  	if (hard || sc_eol_clear == NULL || *sc_eol_clear == '\0')
X*** /tmp/,RCSt1a02865	Sat Sep 24 23:10:59 1988
X--- prim.c	Sat Sep 24 23:10:11 1988
X***************
X*** 16,22 ****
X--- 16,24 ----
X  extern int top_scroll;
X  extern int back_scroll;
X  extern int sc_width, sc_height;
X+ extern int te_init;
X  extern int quit_at_eof;
X+ extern int ac;
X  extern int caseless;
X  extern int linenums;
X  extern int plusoption;
X***************
X*** 198,203 ****
X--- 200,208 ----
X  		eof_bell();
X  	else if (do_repaint)
X  		repaint();
X+ 	if (first_time && hit_eof && quit_at_eof && ac <= 1 &&
X+ 		(!te_init || quit_at_eof > 1))
X+   		quit();
X  	first_time = 0;
X  	(void) currline(BOTTOM);
X  }
//go.sysin dd *
echo x - PATCH.6
sed 's/^X//' > PATCH.6 << '//go.sysin dd *'
XJulian Perry's (jules@zen.co.uk) fixes for HP terminals, with one change.  His
Xversion would complain about not being able to clear to end of screen, when for
Xeverything except HP terminals, clear to end of line suffices.
X
X*** /tmp/,RCSt1a03276	Sun Sep 25 00:08:41 1988
X--- command.c	Sat Sep 24 23:42:38 1988
X***************
X*** 699,705 ****
X  			 * Help.
X  			 */
X  			lower_left();
X! 			clear_eol();
X  			putstr("help");
X  			cmd_exec();
X  			help();
X--- 699,705 ----
X  			 * Help.
X  			 */
X  			lower_left();
X! 			clear_eos();
X  			putstr("help");
X  			cmd_exec();
X  			help();
X*** /tmp/,RCSt1a03276	Sun Sep 25 00:08:42 1988
X--- main.c	Sat Sep 24 23:42:41 1988
X***************
X*** 446,452 ****
X  	end_logfile();
X  #endif
X  	lower_left();
X! 	clear_eol();
X  	deinit();
X  	flush();
X  	raw_mode(0);
X--- 446,452 ----
X  	end_logfile();
X  #endif
X  	lower_left();
X! 	clear_eos();
X  	deinit();
X  	flush();
X  	raw_mode(0);
X*** /tmp/,RCSt1a03276	Sun Sep 25 00:08:43 1988
X--- os.c	Sat Sep 24 23:42:43 1988
X***************
X*** 44,50 ****
X  	else
X  	{
X  		lower_left();
X! 		clear_eol();
X  		putstr("!");
X  		putstr(cmd);
X  		putstr("\n");
X--- 44,50 ----
X  	else
X  	{
X  		lower_left();
X! 		clear_eos();
X  		putstr("!");
X  		putstr(cmd);
X  		putstr("\n");
X*** /tmp/,RCSt1a03276	Sun Sep 25 00:08:44 1988
X--- prim.c	Sat Sep 24 23:42:46 1988
X***************
X*** 118,124 ****
X  		} else
X  		{
X  			lower_left();
X! 			clear_eol();
X  		}
X  
X  		if (pos != position(BOTTOM_PLUS_ONE))
X--- 118,124 ----
X  		} else
X  		{
X  			lower_left();
X! 			clear_eos();
X  		}
X  
X  		if (pos != position(BOTTOM_PLUS_ONE))
X*** /tmp/,RCSt1a03276	Sun Sep 25 00:08:45 1988
X--- screen.c	Sat Sep 24 23:42:49 1988
X***************
X*** 42,47 ****
X--- 42,48 ----
X  	*sc_move,		/* General cursor positioning */
X  	*sc_clear,		/* Clear screen */
X  	*sc_eol_clear,		/* Clear to end of line */
X+ 	*sc_eos_clear,		/* Clear to end of screen */
X  	*sc_s_in,		/* Enter standout (highlighted) mode */
X  	*sc_s_out,		/* Exit standout mode */
X  	*sc_u_in,		/* Enter underline mode */
X***************
X*** 284,289 ****
X--- 285,294 ----
X  		sc_eol_clear = "";
X  	}
X  
X+ 	sc_eos_clear = tgetstr("cd", &sp);
X+ 	if (sc_eos_clear == NULL || *sc_eos_clear == '\0')
X+ 		sc_eos_clear = sc_eol_clear;
X+ 
X  	sc_clear = tgetstr("cl", &sp);
X  	if (hard || sc_clear == NULL || *sc_clear == '\0')
X  	{
X***************
X*** 498,503 ****
X--- 503,518 ----
X  clear_eol()
X  {
X  	tputs(sc_eol_clear, 1, putchr);
X+ }
X+ 
X+ /*
X+  * Clear from the cursor to the end of the screen (memory).
X+  * {{ This must not move the cursor. }}
X+  */
X+ 	public void
X+ clear_eos()
X+ {
X+ 	tputs(sc_eos_clear, 1, putchr);
X  }
X  
X  /*
X*** /tmp/,RCSt1a03276	Sun Sep 25 00:08:46 1988
X--- signal.c	Sat Sep 24 23:42:52 1988
X***************
X*** 166,172 ****
X  		SIGNAL(SIGTTOU, SIG_IGN);
X  #endif
X  		lower_left();
X! 		clear_eol();
X  		deinit();
X  		flush();
X  		raw_mode(0);
X--- 166,172 ----
X  		SIGNAL(SIGTTOU, SIG_IGN);
X  #endif
X  		lower_left();
X! 		clear_eos();
X  		deinit();
X  		flush();
X  		raw_mode(0);
//go.sysin dd *
exit
-- 
inet: dupuy@columbia.edu
uucp: ...!rutgers!columbia!dupuy

dupuy@douglass.columbia.edu (Alexander Dupuy) (09/26/88)

In my last set of patches, I inadvertently included two copies of the patch for
filename globbing.  This may have produced complaints from patch about reversed
patches.  You probably knew enough to ignore that..

As I promised, here are the rest of my less patches.  If you have a recent
version of patch, you can just feed patch the entire article.  Otherwise,
unshar it, and feed patch the pieces which are relevant.  There's a brief
description at the beginning of each one.

@alex

: This is a shar archive.  Extract with sh, not csh.
: The rest of this file will extract: 
:
:	PATCH.7
:	PATCH.8
:	PATCH.9
:
echo x - PATCH.7
sed 's/^X//' > PATCH.7 << '//go.sysin dd *'
XIt is often the case that one wants to look at a typescript (from the script(1)
Xcommand, for example) where there are trailing carriage returns at the end of
Xeach line.  Less frequently, one wants to look at a document which has been
Xformatted for a printer using CR rather than BS to underline a whole line.
X
XThis patch deals with this by creating a new option: -o/O (for overstrike),
Xwhich parallels the -u/U option that controls the BS mode.  The default is to
Xignore CRs at ends of lines, and to print ^M elsewhere.  With -o, CRs are
Xalways output as is (the behavior of more), and with -O, they are always output
Xas ^M (less' current behavior).
X
X*** /tmp/,RCSt1a04332	Sun Sep 25 02:57:20 1988
X--- less.h	Sun Sep 25 02:56:47 1988
X***************
X*** 58,63 ****
X--- 58,68 ----
X  #define	BS_NORMAL	1	/* \b treated as normal char; actually output */
X  #define	BS_CONTROL	2	/* \b treated as control char; prints as ^H */
X  
X+ /* How should we handle carriage returns? */
X+ #define	CR_SPECIAL	0	/* Ignore at end of line, ^M elsewhere */
X+ #define	CR_NORMAL	1	/* \r treated as normal char; actually output */
X+ #define	CR_CONTROL	2	/* \r treated as control char; prints as ^H */
X+ 
X  /* Special chars used to tell put_line() to do something special */
X  #define	UL_CHAR		(unsigned) 0201	/* Enter underline mode */
X  #define	UE_CHAR		(unsigned) 0202	/* Exit underline mode */
X*** /tmp/,RCSt1a04332	Sun Sep 25 02:57:21 1988
X--- less.nro	Sun Sep 25 02:56:50 1988
X***************
X*** 2,8 ****
X  .SH NAME
X  less \- opposite of more
X  .SH SYNOPSIS
X! .B "less [-[+]aABcCdeEimMnqQuUsw] [-b\fIN\fB] [-h\fIN\fB] [-x\fIN\fB] [-[z]\fIN\fB]"
X  .br
X  .B "     [-P[mM=]\fIstring\fB] [-[lL]\fIlogfile\fB] [+\fIcmd\fB]"
X  .br
X--- 2,8 ----
X  .SH NAME
X  less \- opposite of more
X  .SH SYNOPSIS
X! .B "less [-[+]aABcCdeEimMnoOqQuUsw] [-b\fIN\fB] [-h\fIN\fB] [-x\fIN\fB] [-[z]\fIN\fB]"
X  .br
X  .B "     [-P[mM=]\fIstring\fB] [-[lL]\fIlogfile\fB] [+\fIcmd\fB]"
X  .br
X***************
X*** 343,348 ****
X--- 343,359 ----
X  Using line numbers means: the line number will be displayed in the verbose
X  prompt and in the = command,
X  and the v command will pass the current line number to the editor.
X+ .IP -o
X+ If the -o option is given, 
X+ carriage returns are treated as printable characters;
X+ that is, they are sent to the terminal when they appear in the input.
X+ .IP -O
X+ If the -O option is given,
X+ carriage returns are printed as the two character sequence "^M".
X+ .sp
X+ If neither -o nor -O is given,
X+ carriage returns at the end of a line are ignored, and
X+ carriage returns elsewhere are printed as the two character sequence "^M".
X  .IP -P
X  The -P option provides a way to tailor the three prompt
X  styles to your own preference.
X*** /tmp/,RCSt1a04332	Sun Sep 25 02:57:22 1988
X--- line.c	Sun Sep 25 02:56:53 1988
X***************
X*** 47,56 ****
X--- 47,66 ----
X  #define	LN_BO_X		5	/* In boldface, got char, need \b */
X  #define	LN_BO_XB	6	/* In boldface, got char & \b, need same char */
X  
X+ /*
X+  * An extremely simple state machine takes care of carriage returns
X+  * when in CR_SPECIAL mode.  We put carriage returns into the line buffer,
X+  * and backpatch them if something else comes in before we start a new line.
X+  */
X+ static int cr_seen;		/* Was the last character a carriage return? */
X+ #define CR_NOTSEEN	0
X+ #define CR_SEEN		1
X+ 
X  public char *line;		/* Pointer to the current line.
X  				   Usually points to linebuf. */
X  
X  extern int bs_mode;
X+ extern int cr_mode;
X  extern int tabstop;
X  extern int bo_width, be_width;
X  extern int ul_width, ue_width;
X***************
X*** 64,69 ****
X--- 74,80 ----
X  {
X  	line = curr = linebuf;
X  	ln_state = LN_NORMAL;
X+ 	cr_seen = CR_NOTSEEN;
X  	column = 0;
X  }
X  
X***************
X*** 108,113 ****
X--- 119,125 ----
X  			break;
X  		}
X  		ln_state = LN_NORMAL;
X+ 		cr_seen = CR_NOTSEEN;
X  		*curr = '\0';
X  		return (0);
X  	}
X***************
X*** 122,127 ****
X--- 134,165 ----
X  		 */
X  		return (1);
X  
X+ 	if (cr_mode == CR_SPECIAL)
X+ 	{
X+ 		if (cr_seen == CR_SEEN)
X+ 		{
X+ 			/*
X+ 			 * Multiple carriage returns can be treated as one
X+ 			 */
X+ 			if (c == '\r')
X+ 				return (0);
X+ 			/*
X+ 			 * Patch the old carriage return to display as "^M"
X+ 			 */
X+ 			cr_seen = CR_NOTSEEN;
X+ 			curr[-1] = ('M' | 0200);
X+ 		} else if (c == '\r')
X+ 		{
X+ 			/*
X+ 			 * Leave a carriage return in the buffer for now
X+ 			 */
X+ 			NEW_COLUMN(column+2);
X+ 			cr_seen = CR_SEEN;
X+ 			*curr++ = '\r';
X+ 			return (0);
X+ 		}
X+ 	}
X+ 	
X  	if (bs_mode == BS_SPECIAL)
X  	{
X  		/*
X***************
X*** 357,362 ****
X--- 395,420 ----
X  			 */
X  			column--;
X  			*curr++ = '\b';
X+ 		}
X+ 		return (0);
X+ 	} 
X+ 
X+ 	if (c == '\r')
X+ 	{
X+ 		if (cr_mode == CR_CONTROL)
X+ 		{
X+ 			/*
X+ 			 * Treat carriage return as control char: output "^M".
X+ 			 */
X+ 			NEW_COLUMN(column+2);
X+ 			*curr++ = ('M' | 0200);
X+ 		} else
X+ 		{
X+ 			/*
X+ 			 * Output a real carriage return
X+ 			 */
X+ 			column = 0;
X+ 			*curr++ = '\r';
X  		}
X  		return (0);
X  	} 
X*** /tmp/,RCSt1a04332	Sun Sep 25 02:57:23 1988
X--- option.c	Sun Sep 25 02:56:55 1988
X***************
X*** 31,36 ****
X--- 31,37 ----
X  				   (alternative is scroll from bottom) */
X  public int pr_type;		/* Type of prompt (short, medium, long) */
X  public int bs_mode;		/* How to process backspaces */
X+ public int cr_mode;		/* How to process carriage returns */
X  public int know_dumb;		/* Don't complain about dumb terminals */
X  public int quit_at_eof;		/* Quit after hitting end of file twice */
X  public int squeeze;		/* Squeeze multiple blank lines into one */
X***************
X*** 125,130 ****
X--- 126,137 ----
X  		{ "Don't use line numbers",
X  		  "Use line numbers",
X  		  NULL
X+ 		}
X+ 	},
X+ 	{ 'o', TRIPLE|REPAINT, 0, &cr_mode,
X+ 		{ "Ignore CR at end of line, print as ^M elsewhere",
X+ 		  "Carriage Returns cause overstrike",
X+ 		  "Carriage Returns print as ^M"
X  		}
X  	},
X  	{ 'q', TRIPLE, 0, &quiet,
X*** /tmp/,RCSt1a04332	Sun Sep 25 02:57:24 1988
X--- output.c	Sun Sep 25 02:56:58 1988
X***************
X*** 73,78 ****
X--- 73,82 ----
X  			putbs();
X  			column--;
X  			break;
X+ 		case '\r':
X+ 			putchr('\r');
X+ 			column = 0;
X+ 			break;
X  		default:
X  			if (c & 0200)
X  			{
//go.sysin dd *
echo x - PATCH.8
sed 's/^X//' > PATCH.8 << '//go.sysin dd *'
XWhile "Can't take input from a terminal" is a perfectly reasonable and correct
Xerror message, it is not the most illuminating when you type "less" and have
Xno idea what sorts of arguments it expects.  This patch modifies the behavior
Xof less so that it prints a more conventional usage message if called with no
Xarguments.
X
XNow, if you type "less < /dev/tty", the error message may be less illuminating,
Xbut you probably deserve it.  More does the same thing in this case.
X
X*** /tmp/,RCSt1a04937	Sun Sep 25 04:08:55 1988
X--- main.c	Sun Sep 25 04:08:21 1988
X***************
X*** 19,24 ****
X--- 19,25 ----
X  public char **	av;
X  public int 	curr_ac;
X  public int	quitting;
X+ public int	usage[128];
X  
X  extern int	file;
X  extern int	quit_at_eof;
X***************
X*** 108,115 ****
X  		 * but if the control terminal (for commands)
X  		 * and the input file (for data) are the same,
X  		 * we get weird results at best.
X  		 */
X! 		error("Can't take input from a terminal");
X  		if (f > 0)
X  			close(f);
X  		free(filename);
X--- 109,120 ----
X  		 * but if the control terminal (for commands)
X  		 * and the input file (for data) are the same,
X  		 * we get weird results at best.
X+ 		 * If there were no arguments, print a usage note.
X  		 */
X! 		if (ac == 0)
X! 			error(usage);
X! 		else
X! 			error("Can't take input from a terminal");
X  		if (f > 0)
X  			close(f);
X  		free(filename);
X***************
X*** 289,294 ****
X--- 294,303 ----
X  {
X  	char *getenv();
X  
X+ 	sprintf(usage, "Usage: %s %s\n\t%s\n\t%s", *argv,
X+ 		"[-[+]aABcCdeEimMnoOqQuUsw] [-b #] [-h #] [-x #] [-[z] #]",
X+ 		"[-P[mM=] string] [-[lL] logfile] [+ cmd]",
X+ 		"[-t tag] [filename]...");
X  
X  	/*
X  	 * Process command line arguments and LESS environment arguments.
X*** /tmp/,RCSt1a04937	Sun Sep 25 04:08:59 1988
X--- option.c	Sun Sep 25 04:08:24 1988
X***************
X*** 44,49 ****
X--- 44,50 ----
X  public int autobuf;
X  public int plusoption;
X  
X+ extern char usage[];
X  extern char *prproto[];
X  extern char *eqproto;
X  extern int nbufs;
X***************
X*** 529,534 ****
X--- 530,536 ----
X  
X  	sprintf(message, "\"-%c\": invalid flag", c);
X  	error(message);
X+ 	error(usage);
X  	exit(1);
X  }
X  
//go.sysin dd *
echo x - PATCH.9
sed 's/^X//' > PATCH.9 << '//go.sysin dd *'
XAlong with the patch that restores the old less behavior of quitting at the
Xendof of the first and only file if it is on a single screen (ala more), this
Xpatch makes less even "more" convenient for empty files.  If there is nothing
Xto display (since the first and only file is empty) this patch causes less to
Xquit before it displays anything, and to leave the cursor where it already is.
XThis last feature will also take effect if there are errors reading all files.
X
X*** /tmp/,RCSt1a01139	Sun Sep 25 12:06:01 1988
X--- main.c	Sun Sep 25 04:37:10 1988
X***************
X*** 145,150 ****
X--- 145,161 ----
X  	ch_init(cbufs, 0);
X  	init_mark();
X  
X+ 	/*
X+ 	 * Ignore a single empty file if we quit at eof.
X+ 	 */
X+ 	if (quit_at_eof && ac <= 1)
X+ 		if (ch_forw_get() == EOI)
X+ 		{
X+ 			file = -1;
X+ 			return;
X+ 		}
X+ 		else (void) ch_back_get();
X+ 
X  	if (every_first_cmd != NULL)
X  		first_cmd = every_first_cmd;
X  
X***************
X*** 454,461 ****
X  #if LOGFILE
X  	end_logfile();
X  #endif
X! 	lower_left();
X! 	clear_eos();
X  	deinit();
X  	flush();
X  	raw_mode(0);
X--- 465,475 ----
X  #if LOGFILE
X  	end_logfile();
X  #endif
X! 	if (any_display)
X! 	{
X! 		lower_left();
X! 		clear_eos();
X! 	}
X  	deinit();
X  	flush();
X  	raw_mode(0);
//go.sysin dd *
exit
-- 
inet: dupuy@columbia.edu
uucp: ...!rutgers!columbia!dupuy