* Copyright (c) 1988 Mark Nudleman
* Copyright (c) 1988 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Mark Nudleman and the University of California, Berkeley. The
* name of Mark Nudleman or the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
static char sccsid
[] = "@(#)option.c 5.5 (Berkeley) %G%";
* Process command line options.
* Each option is a single letter which controls a program variable.
* The options have defaults which may be changed via
* the command line option, or toggled via the "-" command.
#define toupper(c) ((c)-'a'+'A')
#define END_OPTION_STRING ('$')
#define BOOL 01 /* Boolean option: 0 or 1 */
#define TRIPLE 02 /* Triple-valued option: 0, 1 or 2 */
#define NUMBER 04 /* Numeric option */
#define REPAINT 040 /* Repaint screen after toggling option */
#define NO_TOGGLE 0100 /* Option cannot be toggled with "-" cmd */
* Variables controlled by command line options.
public int clean_data
; /* Can we assume the data is "clean"?
(That is, free of nulls, etc) */
public int quiet
; /* Should we suppress the audible bell? */
public int how_search
; /* Where should forward searches start? */
public int top_scroll
; /* Repaint screen from top?
(alternative is scroll from bottom) */
public int pr_type
; /* Type of prompt (short, medium, long) */
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 */
public int twiddle
; /* Display "~" for lines after EOF */
public int caseless
; /* Do "caseless" searches */
public int linenums
; /* Use line numbers */
public int cbufs
; /* Current number of buffers */
extern char *every_first_cmd
;
public int tagoption
= 0;
char oletter
; /* The controlling letter (a-z) */
char otype
; /* Type of the option */
int odefault
; /* Default value */
int *ovar
; /* Pointer to the associated variable */
char *odesc
[3]; /* Description of each value */
{ 'a', TRIPLE
, 0, &how_search
,
{ "Forward search starts at second REAL line displayed",
"Forward search starts at bottom of screen",
"Forward search starts at second SCREEN line displayed"
{ 'b', NUMBER
, 10, &cbufs
,
{ 'B', BOOL
, 1, &autobuf
,
{ "Don't automatically allocate buffers",
"Automatically allocate buffers when needed",
{ 'c', TRIPLE
, 0, &top_scroll
,
{ "Repaint by scrolling from bottom of screen",
"Repaint by clearing each line",
"Repaint by painting from top of screen"
{ 'd', BOOL
|NO_TOGGLE
, 0, &know_dumb
,
{ 'e', TRIPLE
, 0, &quit_at_eof
,
{ "Don't quit at end-of-file",
"Quit immediately at end-of-file"
{ 'h', NUMBER
, -1, &back_scroll
,
{ "Backwards scroll limit is %d lines",
{ 'i', BOOL
, 0, &caseless
,
{ "Case is significant in searches",
"Ignore case in searches",
{ 'm', TRIPLE
, 0, &pr_type
,
{ 'n', BOOL
, 1, &linenums
,
{ "Don't use line numbers",
{ 'q', TRIPLE
, 0, &quiet
,
{ "Ring the bell for errors AND at eof/bof",
"Ring the bell for errors but not at eof/bof",
{ 's', BOOL
|REPAINT
, 0, &squeeze
,
{ "Don't squeeze multiple blank lines",
"Squeeze multiple blank lines",
{ 'u', TRIPLE
|REPAINT
, 0, &bs_mode
,
{ "Underlined text displayed in underline mode",
"Backspaces cause overstrike",
{ 'w', BOOL
|REPAINT
, 1, &twiddle
,
{ "Display nothing for lines after end-of-file",
"Display ~ for lines after end-of-file",
{ 'x', NUMBER
|REPAINT
, 8, &tabstop
,
{ "Tab stops every %d spaces",
{ 'z', NUMBER
|REPAINT
, -1, &sc_window
,
{ "Scroll window size is %d lines",
* Initialize each option to its default value.
register struct option
*o
;
first_cmd
= every_first_cmd
= NULL
;
for (o
= option
; o
->oletter
!= '\0'; o
++)
* Set each variable to its default.
*(o
->ovar
) = o
->odefault
;
* Toggle command line flags from within the program.
* Used by the "-" and "_" commands.
* If do_toggle is zero, just report the current setting, without changing it.
toggle_option(s
, do_toggle
)
register struct option
*o
;
char message
[100], *strcat();
for (o
= option
; o
->oletter
!= '\0'; o
++)
if (o
->otype
& NO_TOGGLE
)
dorepaint
= (o
->otype
& REPAINT
);
if ((o
->otype
& BOOL
) && (o
->oletter
== c
))
*(o
->ovar
) = ! *(o
->ovar
);
} else if ((o
->otype
& TRIPLE
) && (o
->oletter
== c
))
* Triple-valued option with lower case letter:
* make it 1 unless already 1, then make it 0.
*(o
->ovar
) = (*(o
->ovar
) == 1) ? 0 : 1;
} else if ((o
->otype
& TRIPLE
) && (toupper(o
->oletter
) == c
))
* Triple-valued option with upper case letter:
* make it 2 unless already 2, then make it 0.
*(o
->ovar
) = (*(o
->ovar
) == 2) ? 0 : 2;
} else if ((o
->otype
& NUMBER
) && (o
->oletter
== c
))
* No number; just a query.
* No need to repaint screen.
* Number follows the option letter.
* Set the variable to that number.
* Call ch_init to set new number of buffers.
(void)sprintf(message
, o
->odesc
[0],
(o
->ovar
== &back_scroll
) ?
get_back_scroll() : *(o
->ovar
));
* Print a message describing the new setting.
msg
= o
->odesc
[*(o
->ovar
)];
if (do_toggle
&& dorepaint
)
(void)sprintf(message
, "-^%c", carat_char(c
));
(void)sprintf(message
, "-%c", c
);
(void)strcat(message
, ": no such flag.");
* Determine if an option is a single character option (BOOL or TRIPLE),
* or if it a multi-character option (NUMBER).
register struct option
*o
;
for (o
= option
; o
->oletter
!= '\0'; o
++)
return (o
->otype
& (BOOL
|TRIPLE
));
* Scan to end of string or to an END_OPTION_STRING character.
* In the latter case, replace the char with a null char.
* Return a pointer to the remainder of the string, if any.
(void)sprintf(message
, "string is required after -%c", c
);
for (p
= s
; *p
!= '\0'; p
++)
if (*p
== END_OPTION_STRING
)
* Scan an argument (either from command line or from LESS environment
* variable) and process it.
register struct option
*o
;
if (set_default
= (*s
== '+'))
every_first_cmd
= save(++s
);
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
* Handle special "more" compatibility form "-number"
* (instead of -znumber) to set the scrolling window size.
for (o
= option
; o
->oletter
!= '\0'; o
++)
if ((o
->otype
& BOOL
) && (o
->oletter
== c
))
*(o
->ovar
) = o
->odefault
;
*(o
->ovar
) = ! o
->odefault
;
} else if ((o
->otype
& TRIPLE
) && (o
->oletter
== c
))
*(o
->ovar
) = o
->odefault
;
*(o
->ovar
) = (o
->odefault
== 1) ? 0 : 1;
} else if ((o
->otype
& TRIPLE
) && (toupper(o
->oletter
) == c
))
*(o
->ovar
) = o
->odefault
;
*(o
->ovar
) = (o
->odefault
== 2) ? 0 : 2;
} else if ((o
->otype
& NUMBER
) && (o
->oletter
== c
))
*(o
->ovar
) = getnum(&s
, c
);
(void)sprintf(message
, "\"-%c\": invalid flag", c
);
* Figure out which prototype string should be changed.
case 'm': proto
= &prproto
[PR_MEDIUM
]; s
++; break;
case 'M': proto
= &prproto
[PR_LONG
]; s
++; break;
case '=': proto
= &eqproto
; s
++; break;
default: proto
= &prproto
[pr_type
]; break;
* Translate a string into a number.
* Like atoi(), but takes a pointer to a char *, and updates
* the char * to point after the translated number.
if (*s
< '0' || *s
> '9')
(void)sprintf(message
, "number is required after -%c", c
);
while (*s
>= '0' && *s
<= '9')