home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD1.bin
/
useful
/
text
/
show
/
less
/
source
/
source.lha
/
command.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-21
|
25KB
|
805 lines
/*
* User-level command processor.
*/
#include "less.h"
#include "position.h"
#include <setjmp.h>
extern jmp_buf main_loop;
extern int erase_char, kill_char;
extern int pr_type;
extern int sigs;
extern int ispipe;
extern int quit_at_eof;
extern int hit_eof;
extern int sc_width, sc_height;
extern int sc_window;
extern char *first_cmd;
extern char *every_first_cmd;
extern char version[];
extern char current_file[];
extern char *editor;
#ifdef AMIGA
extern int scroll;
extern curr_ac, ac; /* local argc for file names */
extern char **av;
int user_errors = 0;
#endif
static char cmdbuf[90]; /* Buffer for holding a multi-char command */
#if SHELL_ESCAPE
static char shellcmd[200]; /* For holding last shell command for "!!" */
#endif
static char *cp; /* Pointer into cmdbuf */
static int cmd_col; /* Current column of the multi-char command */
static char mcc; /* The multi-char command letter (e.g. '/') */
static char last_mcc; /* The previous mcc */
#ifdef AMIGA
int screen_trashed; /* The screen has been overwritten */
#else
static int screen_trashed; /* The screen has been overwritten */
#endif
/* Prototypes for functions defined in command.c */
static int cmd_erase __PROTO((void));
static int cmd_char __PROTO((int c));
static int cmd_int __PROTO((void));
static void cmd_exec __PROTO((void));
static void prompt __PROTO((void));
static int getcc __PROTO((void));
/*
* Reset command buffer (to empty).
*/
#ifdef __STDC__
void cmd_reset (void)
#else
cmd_reset()
#endif
{
cp = cmdbuf;
}
/*
* Backspace in command buffer.
*/
#ifdef __STDC__
static int cmd_erase (void)
#else
static int
cmd_erase()
#endif
{
if (cp == cmdbuf)
/*
* Backspace past beginning of the string:
* this usually means abort the command.
*/
return (1);
if (control_char(*--cp))
{
/*
* Erase an extra character, for the carat.
*/
backspace();
cmd_col--;
}
backspace();
cmd_col--;
return (0);
}
/*
* Set up the display to start a new multi-character command.
*/
#ifdef __STDC__
void start_mcc (int c)
#else
start_mcc(c)
int c;
#endif
{
mcc = c;
lower_left();
clear_eol();
putchr(mcc);
cmd_col = 1;
}
/*
* Process a single character of a multi-character command, such as
* a number, or the pattern of a search command.
*/
#ifdef __STDC__
static int cmd_char (int c)
#else
static int
cmd_char(c)
int c;
#endif
{
if (c == erase_char)
{
if (cmd_erase())
return (1);
} else if (c == kill_char)
{
/* {{ Could do this faster, but who cares? }} */
while (cmd_erase() == 0)
;
} else
{
/*
* Append the character to the string,
* if there is room in the buffer and on the screen.
*/
if (cp < &cmdbuf[sizeof(cmdbuf)-1] && cmd_col < sc_width-3)
{
*cp++ = c;
if (control_char(c))
{
putchr('^');
cmd_col++;
c = carat_char(c);
}
putchr(c);
cmd_col++;
} else
bell();
}
return (0);
}
/*
* Return the number currently in the command buffer.
*/
#ifdef __STDC__
static int cmd_int (void)
#else
static int
cmd_int()
#endif
{
*cp = '\0';
cp = cmdbuf;
return (atoi(cmdbuf));
}
/*
* Move the cursor to lower left before executing a command.
* This looks nicer if the command takes a long time before
* updating the screen.
*/
#ifdef __STDC__
static void cmd_exec (void)
#else
static void
cmd_exec()
#endif
{
lower_left();
flush();
}
/*
* Display the appropriate prompt.
*/
#ifdef __STDC__
static void prompt (void)
#else
static void
prompt()
#endif
{
register char *p;
if (first_cmd != NULL && *first_cmd != '\0')
/*
* No prompt necessary if commands are from first_cmd
* rather than from the user.
*/
return;
/*
* If nothing is displayed yet, display starting from line 1.
*/
if (position(TOP) == NULL_POSITION)
jump_back(1);
else if (screen_trashed)
repaint();
screen_trashed = 0;
/*
* Select the proper prompt and display it.
*/
lower_left();
clear_eol();
p = pr_string();
if (p == NULL)
putchr(':');
else
{
#ifdef AMIGA
if ( strlen(p) > sc_width )
screen_trashed = 1;
#endif
so_enter();
putstr(p);
so_exit();
}
}
/*
* Get command character.
* The character normally comes from the keyboard,
* but may come from the "first_cmd" string.
*/
#ifdef __STDC__
static int getcc (void)
#else
static int
getcc()
#endif
{
if (first_cmd == NULL)
return (getchr());
if (*first_cmd == '\0')
{
/*
* Reached end of first_cmd input.
*/
first_cmd = NULL;
if (cp > cmdbuf && position(TOP) == NULL_POSITION)
{
/*
* Command is incomplete, so try to complete it.
* There are only two cases:
* 1. We have "/string" but no newline. Add the \n.
* 2. We have a number but no command. Treat as #g.
* (This is all pretty hokey.)
*/
if (mcc != ':')
/* Not a number; must be search string */
return ('\n');
else
/* A number; append a 'g' */
return ('g');
}
return (getchr());
}
return (int)(*first_cmd++);
}
/*
* Main command processor.
* Accept and execute commands until a quit command, then return.
*/
#ifdef __STDC__
void commands (void)
#else
public void
commands()
#endif
{
register int c;
register int n;
#ifndef AMIGA
register int scroll = 10;
#endif
last_mcc = 0;
n = 0;
setjmp(main_loop);
mcc = 0;
for (;;)
{
/*
* Display prompt and accept a character.
*/
psignals(); /* See if any signals need processing */
#ifdef AMIGA
if (quit_at_eof == 2 && hit_eof > 1)
#else
if (quit_at_eof && (quit_at_eof + hit_eof) > 2)
#endif
/*
* After hitting end-of-file for the second time,
* automatically advance to the next file.
* If there are no more files, quit.
*/
next_file(1);
cmd_reset();
prompt();
c = getcc();
again:
if (sigs)
continue;
if (mcc)
{
/*
* We are in a multi-character command.
* All chars until newline go into the command buffer.
* (Note that mcc == ':' is a special case that
* means a number is being entered.)
*/
if (mcc != ':' && (c == '\n' || c == '\r