version 1.1.1.1, 1996/09/21 05:39:41 |
version 1.1.1.2, 2003/04/13 18:21:21 |
|
|
/* |
/* |
* Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman |
* Copyright (C) 1984-2002 Mark Nudelman |
* All rights reserved. |
|
* |
* |
* Redistribution and use in source and binary forms, with or without |
* You may distribute under the terms of either the GNU General Public |
* modification, are permitted provided that the following conditions |
* License or the Less License, as specified in the README file. |
* are met: |
|
* 1. Redistributions of source code must retain the above copyright |
|
* notice, this list of conditions and the following disclaimer. |
|
* 2. Redistributions in binary form must reproduce the above copyright |
|
* notice in the documentation and/or other materials provided with |
|
* the distribution. |
|
* |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY |
* For more information about less, or for information on how to |
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* contact the author, see the README file. |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE |
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
|
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
*/ |
*/ |
|
|
|
|
|
|
|
|
extern int sc_width; |
extern int sc_width; |
|
|
static char cmdbuf[120]; /* Buffer for holding a multi-char command */ |
static char cmdbuf[CMDBUF_SIZE]; /* Buffer for holding a multi-char command */ |
static int cmd_col; /* Current column of the multi-char command */ |
static int cmd_col; /* Current column of the cursor */ |
|
static int prompt_col; /* Column of cursor just after prompt */ |
static char *cp; /* Pointer into cmdbuf */ |
static char *cp; /* Pointer into cmdbuf */ |
static int literal; |
static int cmd_offset; /* Index into cmdbuf of first displayed char */ |
|
static int literal; /* Next input char should not be interpreted */ |
|
|
#if TAB_COMPLETE_FILENAME |
#if TAB_COMPLETE_FILENAME |
static int cmd_complete(); |
static int cmd_complete(); |
|
|
static struct textlist tk_tlist; |
static struct textlist tk_tlist; |
#endif |
#endif |
|
|
|
static int cmd_left(); |
|
static int cmd_right(); |
|
|
|
#if SPACES_IN_FILENAMES |
|
public char openquote = '"'; |
|
public char closequote = '"'; |
|
#endif |
|
|
#if CMD_HISTORY |
#if CMD_HISTORY |
/* |
/* |
* A mlist structure represents a command history. |
* A mlist structure represents a command history. |
|
|
*/ |
*/ |
struct mlist mlist_search = |
struct mlist mlist_search = |
{ &mlist_search, &mlist_search, &mlist_search, NULL }; |
{ &mlist_search, &mlist_search, &mlist_search, NULL }; |
public void *ml_search = (void *) &mlist_search; |
public void * constant ml_search = (void *) &mlist_search; |
|
|
struct mlist mlist_examine = |
struct mlist mlist_examine = |
{ &mlist_examine, &mlist_examine, &mlist_examine, NULL }; |
{ &mlist_examine, &mlist_examine, &mlist_examine, NULL }; |
public void *ml_examine = (void *) &mlist_examine; |
public void * constant ml_examine = (void *) &mlist_examine; |
|
|
#if SHELL_ESCAPE || PIPEC |
#if SHELL_ESCAPE || PIPEC |
struct mlist mlist_shell = |
struct mlist mlist_shell = |
{ &mlist_shell, &mlist_shell, &mlist_shell, NULL }; |
{ &mlist_shell, &mlist_shell, &mlist_shell, NULL }; |
public void *ml_shell = (void *) &mlist_shell; |
public void * constant ml_shell = (void *) &mlist_shell; |
#endif /* SHELL_ESCAPE || PIPEC */ |
#endif |
|
|
|
#else /* CMD_HISTORY */ |
|
|
|
/* If CMD_HISTORY is off, these are just flags. */ |
|
public void * constant ml_search = (void *)1; |
|
public void * constant ml_examine = (void *)2; |
|
#if SHELL_ESCAPE || PIPEC |
|
public void * constant ml_shell = (void *)3; |
|
#endif |
|
|
|
#endif /* CMD_HISTORY */ |
|
|
/* |
/* |
* History for the current command. |
* History for the current command. |
*/ |
*/ |
static struct mlist *curr_mlist = NULL; |
static struct mlist *curr_mlist = NULL; |
|
static int curr_cmdflags; |
|
|
#endif /* CMD_HISTORY */ |
|
|
|
/* |
/* |
* Reset command buffer (to empty). |
* Reset command buffer (to empty). |
|
|
cp = cmdbuf; |
cp = cmdbuf; |
*cp = '\0'; |
*cp = '\0'; |
cmd_col = 0; |
cmd_col = 0; |
|
cmd_offset = 0; |
literal = 0; |
literal = 0; |
} |
} |
|
|
/* |
/* |
|
* Clear command line on display. |
|
*/ |
|
public void |
|
clear_cmd() |
|
{ |
|
clear_bot(); |
|
cmd_col = prompt_col = 0; |
|
} |
|
|
|
/* |
|
* Display a string, usually as a prompt for input into the command buffer. |
|
*/ |
|
public void |
|
cmd_putstr(s) |
|
char *s; |
|
{ |
|
putstr(s); |
|
cmd_col += strlen(s); |
|
prompt_col += strlen(s); |
|
} |
|
|
|
/* |
* How many characters are in the command buffer? |
* How many characters are in the command buffer? |
*/ |
*/ |
public int |
public int |
|
|
} |
} |
|
|
/* |
/* |
|
* Repaint the line from cp onwards. |
|
* Then position the cursor just after the char old_cp (a pointer into cmdbuf). |
|
*/ |
|
static void |
|
cmd_repaint(old_cp) |
|
char *old_cp; |
|
{ |
|
char *p; |
|
|
|
/* |
|
* Repaint the line from the current position. |
|
*/ |
|
clear_eol(); |
|
for ( ; *cp != '\0'; cp++) |
|
{ |
|
p = prchar(*cp); |
|
if (cmd_col + (int)strlen(p) >= sc_width) |
|
break; |
|
putstr(p); |
|
cmd_col += strlen(p); |
|
} |
|
|
|
/* |
|
* Back up the cursor to the correct position. |
|
*/ |
|
while (cp > old_cp) |
|
cmd_left(); |
|
} |
|
|
|
/* |
|
* Put the cursor at "home" (just after the prompt), |
|
* and set cp to the corresponding char in cmdbuf. |
|
*/ |
|
static void |
|
cmd_home() |
|
{ |
|
while (cmd_col > prompt_col) |
|
{ |
|
putbs(); |
|
cmd_col--; |
|
} |
|
|
|
cp = &cmdbuf[cmd_offset]; |
|
} |
|
|
|
/* |
|
* Shift the cmdbuf display left a half-screen. |
|
*/ |
|
static void |
|
cmd_lshift() |
|
{ |
|
char *s; |
|
char *save_cp; |
|
int cols; |
|
|
|
/* |
|
* Start at the first displayed char, count how far to the |
|
* right we'd have to move to reach the center of the screen. |
|
*/ |
|
s = cmdbuf + cmd_offset; |
|
cols = 0; |
|
while (cols < (sc_width - prompt_col) / 2 && *s != '\0') |
|
cols += strlen(prchar(*s++)); |
|
|
|
cmd_offset = s - cmdbuf; |
|
save_cp = cp; |
|
cmd_home(); |
|
cmd_repaint(save_cp); |
|
} |
|
|
|
/* |
|
* Shift the cmdbuf display right a half-screen. |
|
*/ |
|
static void |
|
cmd_rshift() |
|
{ |
|
char *s; |
|
char *p; |
|
char *save_cp; |
|
int cols; |
|
|
|
/* |
|
* Start at the first displayed char, count how far to the |
|
* left we'd have to move to traverse a half-screen width |
|
* of displayed characters. |
|
*/ |
|
s = cmdbuf + cmd_offset; |
|
cols = 0; |
|
while (cols < (sc_width - prompt_col) / 2 && s > cmdbuf) |
|
{ |
|
p = prchar(*--s); |
|
cols += strlen(p); |
|
} |
|
|
|
cmd_offset = s - cmdbuf; |
|
save_cp = cp; |
|
cmd_home(); |
|
cmd_repaint(save_cp); |
|
} |
|
|
|
/* |
|
* Move cursor right one character. |
|
*/ |
|
static int |
|
cmd_right() |
|
{ |
|
char *p; |
|
|
|
if (*cp == '\0') |
|
{ |
|
/* |
|
* Already at the end of the line. |
|
*/ |
|
return (CC_OK); |
|
} |
|
p = prchar(*cp); |
|
if (cmd_col + (int)strlen(p) >= sc_width) |
|
cmd_lshift(); |
|
else if (cmd_col + (int)strlen(p) == sc_width - 1 && cp[1] != '\0') |
|
cmd_lshift(); |
|
cp++; |
|
putstr(p); |
|
cmd_col += strlen(p); |
|
return (CC_OK); |
|
} |
|
|
|
/* |
|
* Move cursor left one character. |
|
*/ |
|
static int |
|
cmd_left() |
|
{ |
|
char *p; |
|
|
|
if (cp <= cmdbuf) |
|
{ |
|
/* Already at the beginning of the line */ |
|
return (CC_OK); |
|
} |
|
p = prchar(cp[-1]); |
|
if (cmd_col < prompt_col + (int)strlen(p)) |
|
cmd_rshift(); |
|
cp--; |
|
cmd_col -= strlen(p); |
|
while (*p++ != '\0') |
|
putbs(); |
|
return (CC_OK); |
|
} |
|
|
|
/* |
|
* Insert a char into the command buffer, at the current position. |
|
*/ |
|
static int |
|
cmd_ichar(c) |
|
int c; |
|
{ |
|
char *s; |
|
|
|
if (strlen(cmdbuf) >= sizeof(cmdbuf)-2) |
|
{ |
|
/* |
|
* No room in the command buffer for another char. |
|
*/ |
|
bell(); |
|
return (CC_ERROR); |
|
} |
|
|
|
/* |
|
* Insert the character into the buffer. |
|
*/ |
|
for (s = &cmdbuf[strlen(cmdbuf)]; s >= cp; s--) |
|
s[1] = s[0]; |
|
*cp = c; |
|
/* |
|
* Reprint the tail of the line from the inserted char. |
|
*/ |
|
cmd_repaint(cp); |
|
cmd_right(); |
|
return (CC_OK); |
|
} |
|
|
|
/* |
* Backspace in the command buffer. |
* Backspace in the command buffer. |
* Delete the char to the left of the cursor. |
* Delete the char to the left of the cursor. |
*/ |
*/ |
|
|
cmd_erase() |
cmd_erase() |
{ |
{ |
register char *s; |
register char *s; |
char *p; |
|
int col; |
|
|
|
if (cp == cmdbuf) |
if (cp == cmdbuf) |
{ |
{ |
|
|
return (CC_QUIT); |
return (CC_QUIT); |
} |
} |
/* |
/* |
* Back up the pointer. |
* Move cursor left (to the char being erased). |
*/ |
*/ |
--cp; |
cmd_left(); |
/* |
/* |
* Remember the current cursor column and |
* Remove the char from the buffer (shift the buffer left). |
* set it back the width of the char being erased. |
|
*/ |
*/ |
col = cmd_col; |
|
p = prchar(*cp); |
|
cmd_col -= strlen(p); |
|
/* |
|
* Shift left the buffer after the erased char. |
|
*/ |
|
for (s = cp; *s != '\0'; s++) |
for (s = cp; *s != '\0'; s++) |
s[0] = s[1]; |
s[0] = s[1]; |
/* |
/* |
* Back up the cursor to the position of the erased char, |
* Repaint the buffer after the erased char. |
* clear the tail of the line, |
|
* and reprint the line after the erased char. |
|
*/ |
*/ |
while (col > cmd_col) |
cmd_repaint(cp); |
{ |
|
putbs(); |
|
col--; |
|
} |
|
clear_eol(); |
|
for (s = cp; *s != '\0'; s++) |
|
{ |
|
p = prchar(*s); |
|
putstr(p); |
|
col += strlen(p); |
|
} |
|
/* |
|
* Back up the cursor again. |
|
*/ |
|
while (col > cmd_col) |
|
{ |
|
putbs(); |
|
col--; |
|
} |
|
|
|
/* |
/* |
* This is rather weird. |
|
* We say that erasing the entire command string causes us |
* We say that erasing the entire command string causes us |
* to abort the current command, BUT ONLY IF there is no history |
* to abort the current command, if CF_QUIT_ON_ERASE is set. |
* for this type of command. This causes commands like search (/) |
|
* and edit (:e) to stay active even if we erase the entire string, |
|
* but commands like <digit> and - go away when we erase the string. |
|
* (See same thing in cmd_kill.) |
|
*/ |
*/ |
if (curr_mlist == NULL && cp == cmdbuf && *cp == '\0') |
if ((curr_cmdflags & CF_QUIT_ON_ERASE) && cp == cmdbuf && *cp == '\0') |
return (CC_QUIT); |
return (CC_QUIT); |
return (CC_OK); |
return (CC_OK); |
} |
} |
|
|
static int |
static int |
cmd_delete() |
cmd_delete() |
{ |
{ |
char *p; |
|
|
|
if (*cp == '\0') |
if (*cp == '\0') |
{ |
{ |
/* |
/* |
|
|
/* |
/* |
* Move right, then use cmd_erase. |
* Move right, then use cmd_erase. |
*/ |
*/ |
p = prchar(*cp); |
cmd_right(); |
cp++; |
|
putstr(p); |
|
cmd_col += strlen(p); |
|
cmd_erase(); |
cmd_erase(); |
return (CC_OK); |
return (CC_OK); |
} |
} |
|
|
} |
} |
|
|
/* |
/* |
* Move cursor to start of command buffer. |
|
*/ |
|
static int |
|
cmd_home() |
|
{ |
|
char *p; |
|
|
|
/* |
|
* Back up until we hit start of buffer. |
|
*/ |
|
while (cp > cmdbuf) |
|
{ |
|
cp--; |
|
p = prchar(*cp); |
|
cmd_col -= strlen(p); |
|
while (*p++ != '\0') |
|
putbs(); |
|
} |
|
return (CC_OK); |
|
} |
|
|
|
/* |
|
* Delete all chars in the command buffer. |
* Delete all chars in the command buffer. |
*/ |
*/ |
static int |
static int |
|
|
*/ |
*/ |
return (CC_QUIT); |
return (CC_QUIT); |
} |
} |
(void) cmd_home(); |
cmd_offset = 0; |
|
cmd_home(); |
*cp = '\0'; |
*cp = '\0'; |
clear_eol(); |
cmd_repaint(cp); |
|
|
/* |
/* |
* Same weirdness as in cmd_erase. |
* We say that erasing the entire command string causes us |
* If the current command has no history, abort the current command. |
* to abort the current command, if CF_QUIT_ON_ERASE is set. |
*/ |
*/ |
if (curr_mlist == NULL) |
if (curr_cmdflags & CF_QUIT_ON_ERASE) |
return (CC_QUIT); |
return (CC_QUIT); |
return (CC_OK); |
return (CC_OK); |
} |
} |
|
|
/* |
/* |
* Move cursor right one character. |
|
*/ |
|
static int |
|
cmd_right() |
|
{ |
|
char *p; |
|
|
|
if (*cp == '\0') |
|
{ |
|
/* |
|
* Already at the end of the line. |
|
*/ |
|
return (CC_OK); |
|
} |
|
p = prchar(*cp); |
|
cp++; |
|
putstr(p); |
|
cmd_col += strlen(p); |
|
return (CC_OK); |
|
} |
|
|
|
/* |
|
* Move cursor left one character. |
|
*/ |
|
static int |
|
cmd_left() |
|
{ |
|
char *p; |
|
|
|
if (cp <= cmdbuf) |
|
{ |
|
/* Already at the beginning of the line */ |
|
return (CC_OK); |
|
} |
|
cp--; |
|
p = prchar(*cp); |
|
cmd_col -= strlen(p); |
|
while (*p++ != '\0') |
|
putbs(); |
|
return (CC_OK); |
|
} |
|
|
|
#if CMD_HISTORY |
|
/* |
|
* Select an mlist structure to be the current command history. |
* Select an mlist structure to be the current command history. |
*/ |
*/ |
public void |
public void |
set_mlist(mlist) |
set_mlist(mlist, cmdflags) |
void *mlist; |
void *mlist; |
|
int cmdflags; |
{ |
{ |
curr_mlist = (struct mlist *) mlist; |
curr_mlist = (struct mlist *) mlist; |
|
curr_cmdflags = cmdflags; |
} |
} |
|
|
|
#if CMD_HISTORY |
/* |
/* |
* Move up or down in the currently selected command history list. |
* Move up or down in the currently selected command history list. |
*/ |
*/ |
|
|
cmd_updown(action) |
cmd_updown(action) |
int action; |
int action; |
{ |
{ |
char *p; |
|
char *s; |
char *s; |
|
|
if (curr_mlist == NULL) |
if (curr_mlist == NULL) |
|
|
s = curr_mlist->curr_mp->string; |
s = curr_mlist->curr_mp->string; |
if (s == NULL) |
if (s == NULL) |
s = ""; |
s = ""; |
for (cp = cmdbuf; *s != '\0'; s++, cp++) |
for (cp = cmdbuf; *s != '\0'; s++) |
{ |
{ |
*cp = *s; |
*cp = *s; |
p = prchar(*cp); |
cmd_right(); |
cmd_col += strlen(p); |
|
putstr(p); |
|
} |
} |
*cp = '\0'; |
*cp = '\0'; |
return (CC_OK); |
return (CC_OK); |
} |
} |
|
#endif |
|
|
/* |
/* |
* Accept the command in the command buffer. |
* Add a string to a history list. |
* Add it to the currently selected history list. |
|
*/ |
*/ |
public void |
public void |
cmd_accept() |
cmd_addhist(mlist, cmd) |
|
struct mlist *mlist; |
|
char *cmd; |
{ |
{ |
|
#if CMD_HISTORY |
struct mlist *ml; |
struct mlist *ml; |
|
|
/* |
/* |
* Nothing to do if there is no currently selected history list. |
|
*/ |
|
if (curr_mlist == NULL) |
|
return; |
|
/* |
|
* Don't save a trivial command. |
* Don't save a trivial command. |
*/ |
*/ |
if (strlen(cmdbuf) == 0) |
if (strlen(cmd) == 0) |
return; |
return; |
/* |
/* |
* Don't save if a duplicate of a command which is already in the history. |
* Don't save if a duplicate of a command which is already |
|
* in the history. |
* But select the one already in the history to be current. |
* But select the one already in the history to be current. |
*/ |
*/ |
for (ml = curr_mlist->next; ml != curr_mlist; ml = ml->next) |
for (ml = mlist->next; ml != mlist; ml = ml->next) |
{ |
{ |
if (strcmp(ml->string, cmdbuf) == 0) |
if (strcmp(ml->string, cmd) == 0) |
break; |
break; |
} |
} |
if (ml == curr_mlist) |
if (ml == mlist) |
{ |
{ |
/* |
/* |
* Did not find command in history. |
* Did not find command in history. |
* Save the command and put it at the end of the history list. |
* Save the command and put it at the end of the history list. |
*/ |
*/ |
ml = (struct mlist *) ecalloc(1, sizeof(struct mlist)); |
ml = (struct mlist *) ecalloc(1, sizeof(struct mlist)); |
ml->string = save(cmdbuf); |
ml->string = save(cmd); |
ml->next = curr_mlist; |
ml->next = mlist; |
ml->prev = curr_mlist->prev; |
ml->prev = mlist->prev; |
curr_mlist->prev->next = ml; |
mlist->prev->next = ml; |
curr_mlist->prev = ml; |
mlist->prev = ml; |
} |
} |
/* |
/* |
* Point to the cmd just after the just-accepted command. |
* Point to the cmd just after the just-accepted command. |
* Thus, an UPARROW will always retrieve the previous command. |
* Thus, an UPARROW will always retrieve the previous command. |
*/ |
*/ |
curr_mlist->curr_mp = ml->next; |
mlist->curr_mp = ml->next; |
|
#endif |
} |
} |
|
|
|
/* |
|
* Accept the command in the command buffer. |
|
* Add it to the currently selected history list. |
|
*/ |
|
public void |
|
cmd_accept() |
|
{ |
|
#if CMD_HISTORY |
|
/* |
|
* Nothing to do if there is no currently selected history list. |
|
*/ |
|
if (curr_mlist == NULL) |
|
return; |
|
cmd_addhist(curr_mlist, cmdbuf); |
#endif |
#endif |
|
} |
|
|
/* |
/* |
* Try to perform a line-edit function on the command buffer, |
* Try to perform a line-edit function on the command buffer, |
|
|
* See if the char is indeed a line-editing command. |
* See if the char is indeed a line-editing command. |
*/ |
*/ |
flags = 0; |
flags = 0; |
|
#if CMD_HISTORY |
if (curr_mlist == NULL) |
if (curr_mlist == NULL) |
/* |
/* |
* No current history; don't accept history manipulation cmds. |
* No current history; don't accept history manipulation cmds. |
*/ |
*/ |
flags |= EC_NOHISTORY; |
flags |= EC_NOHISTORY; |
if (curr_mlist == &mlist_search) |
#endif |
|
#if TAB_COMPLETE_FILENAME |
|
if (curr_mlist == ml_search) |
/* |
/* |
* In a search command; don't accept file-completion cmds. |
* In a search command; don't accept file-completion cmds. |
*/ |
*/ |
flags |= EC_NOCOMPLETE; |
flags |= EC_NOCOMPLETE; |
|
#endif |
|
|
action = editchar(c, flags); |
action = editchar(c, flags); |
|
|
|
|
return (CC_OK); |
return (CC_OK); |
case EC_HOME: |
case EC_HOME: |
not_in_completion(); |
not_in_completion(); |
return (cmd_home()); |
cmd_offset = 0; |
|
cmd_home(); |
|
cmd_repaint(cp); |
|
return (CC_OK); |
case EC_END: |
case EC_END: |
not_in_completion(); |
not_in_completion(); |
while (*cp != '\0') |
while (*cp != '\0') |
|
|
case EC_EXPAND: |
case EC_EXPAND: |
return (cmd_complete(action)); |
return (cmd_complete(action)); |
#endif |
#endif |
|
case EC_NOACTION: |
|
return (CC_OK); |
default: |
default: |
not_in_completion(); |
not_in_completion(); |
return (CC_PASS); |
return (CC_PASS); |
} |
} |
} |
} |
|
|
/* |
|
* Insert a char into the command buffer, at the current position. |
|
*/ |
|
static int |
|
cmd_ichar(c) |
|
int c; |
|
{ |
|
int col; |
|
char *p; |
|
char *s; |
|
|
|
if (strlen(cmdbuf) >= sizeof(cmdbuf)-2) |
|
{ |
|
/* |
|
* No room in the command buffer for another char. |
|
*/ |
|
bell(); |
|
return (CC_ERROR); |
|
} |
|
|
|
/* |
|
* Remember the current cursor column and |
|
* move it forward the width of the char being inserted. |
|
*/ |
|
col = cmd_col; |
|
p = prchar(c); |
|
cmd_col += strlen(p); |
|
if (cmd_col >= sc_width-1) |
|
{ |
|
cmd_col -= strlen(p); |
|
bell(); |
|
return (CC_ERROR); |
|
} |
|
/* |
|
* Insert the character in the string. |
|
* First, make room for the new char. |
|
*/ |
|
for (s = &cmdbuf[strlen(cmdbuf)]; s >= cp; s--) |
|
s[1] = s[0]; |
|
*cp++ = c; |
|
/* |
|
* Reprint the tail of the line after the inserted char. |
|
*/ |
|
clear_eol(); |
|
for (s = cp-1; *s != '\0'; s++) |
|
{ |
|
p = prchar(*s); |
|
col += strlen(p); |
|
if (col >= sc_width-1) |
|
{ |
|
/* |
|
* Oops. There is no room on the screen |
|
* for the new char. Back up the cursor to |
|
* just after the inserted char and erase it. |
|
*/ |
|
col -= strlen(p); |
|
while (col > cmd_col) |
|
{ |
|
putbs(); |
|
col--; |
|
} |
|
(void) cmd_erase(); |
|
bell(); |
|
return (CC_ERROR); |
|
} |
|
putstr(p); |
|
} |
|
/* |
|
* Back up the cursor to just after the inserted char. |
|
*/ |
|
while (col > cmd_col) |
|
{ |
|
putbs(); |
|
col--; |
|
} |
|
return (CC_OK); |
|
} |
|
|
|
#if TAB_COMPLETE_FILENAME |
#if TAB_COMPLETE_FILENAME |
/* |
/* |
* Insert a string into the command buffer, at the current position. |
* Insert a string into the command buffer, at the current position. |
|
|
delimit_word() |
delimit_word() |
{ |
{ |
char *word; |
char *word; |
|
#if SPACES_IN_FILENAMES |
|
char *p; |
|
int delim_quoted = 0; |
|
int meta_quoted = 0; |
|
char *esc = get_meta_escape(); |
|
int esclen = strlen(esc); |
|
#endif |
|
|
/* |
/* |
* Move cursor to end of word. |
* Move cursor to end of word. |
|
|
* We're already at the end of the word. |
* We're already at the end of the word. |
*/ |
*/ |
; |
; |
|
#if 0 |
} else |
} else |
{ |
{ |
/* |
/* |
|
|
* Huh? There's no word here. |
* Huh? There's no word here. |
*/ |
*/ |
return (NULL); |
return (NULL); |
|
#endif |
} |
} |
/* |
/* |
* Search backwards for beginning of the word. |
* Find the beginning of the word which the cursor is in. |
*/ |
*/ |
if (cp == cmdbuf) |
if (cp == cmdbuf) |
return (NULL); |
return (NULL); |
for (word = cp-1; word > cmdbuf; word--) |
#if SPACES_IN_FILENAMES |
if (word[-1] == ' ') |
/* |
|
* If we have an unbalanced quote (that is, an open quote |
|
* without a corresponding close quote), we return everything |
|
* from the open quote, including spaces. |
|
*/ |
|
for (word = cmdbuf; word < cp; word++) |
|
if (*word != ' ') |
break; |
break; |
|
if (word >= cp) |
|
return (cp); |
|
for (p = cmdbuf; p < cp; p++) |
|
{ |
|
if (meta_quoted) |
|
{ |
|
meta_quoted = 0; |
|
} else if (esclen > 0 && p + esclen < cp && |
|
strncmp(p, esc, esclen) == 0) |
|
{ |
|
meta_quoted = 1; |
|
p += esclen - 1; |
|
} else if (delim_quoted) |
|
{ |
|
if (*p == closequote) |
|
delim_quoted = 0; |
|
} else /* (!delim_quoted) */ |
|
{ |
|
if (*p == openquote) |
|
delim_quoted = 1; |
|
else if (*p == ' ') |
|
word = p+1; |
|
} |
|
} |
|
#endif |
return (word); |
return (word); |
} |
} |
|
|
|
|
*/ |
*/ |
c = *cp; |
c = *cp; |
*cp = '\0'; |
*cp = '\0'; |
tk_text = fcomplete(word); |
if (*word != openquote) |
|
{ |
|
tk_text = fcomplete(word); |
|
} else |
|
{ |
|
char *qword = shell_quote(word+1); |
|
if (qword == NULL) |
|
tk_text = fcomplete(word+1); |
|
else |
|
{ |
|
tk_text = fcomplete(qword); |
|
free(qword); |
|
} |
|
} |
*cp = c; |
*cp = c; |
} |
} |
|
|
|
|
*/ |
*/ |
static char * |
static char * |
next_compl(action, prev) |
next_compl(action, prev) |
int action; |
int action; |
char *prev; |
char *prev; |
{ |
{ |
switch (action) |
switch (action) |
|
|
return (forw_textlist(&tk_tlist, prev)); |
return (forw_textlist(&tk_tlist, prev)); |
case EC_B_COMPLETE: |
case EC_B_COMPLETE: |
return (back_textlist(&tk_tlist, prev)); |
return (back_textlist(&tk_tlist, prev)); |
default: |
|
/* Cannot happen */ |
|
return ("?"); |
|
} |
} |
|
/* Cannot happen */ |
|
return ("?"); |
} |
} |
|
|
/* |
/* |
|
|
cmd_complete(action) |
cmd_complete(action) |
int action; |
int action; |
{ |
{ |
|
char *s; |
|
|
if (!in_completion || action == EC_EXPAND) |
if (!in_completion || action == EC_EXPAND) |
{ |
{ |
|
|
*/ |
*/ |
if (cmd_istr(tk_trial) != CC_OK) |
if (cmd_istr(tk_trial) != CC_OK) |
goto fail; |
goto fail; |
|
/* |
|
* If it is a directory, append a slash. |
|
*/ |
|
if (is_dir(tk_trial)) |
|
{ |
|
if (cp > cmdbuf && cp[-1] == closequote) |
|
(void) cmd_erase(); |
|
s = lgetenv("LESSSEPARATOR"); |
|
if (s == NULL) |
|
s = PATHNAME_SEP; |
|
if (cmd_istr(s) != CC_OK) |
|
goto fail; |
|
} |
} |
} |
|
|
return (CC_OK); |
return (CC_OK); |
|
|
/* |
/* |
* Insert the char into the command buffer. |
* Insert the char into the command buffer. |
*/ |
*/ |
action = cmd_ichar(c); |
return (cmd_ichar(c)); |
if (action != CC_OK) |
|
return (action); |
|
return (CC_OK); |
|
} |
} |
|
|
/* |
/* |
* Return the number currently in the command buffer. |
* Return the number currently in the command buffer. |
*/ |
*/ |
public int |
public LINENUM |
cmd_int() |
cmd_int() |
{ |
{ |
return (atoi(cmdbuf)); |
register char *p; |
} |
LINENUM n = 0; |
|
|
/* |
for (p = cmdbuf; *p != '\0'; p++) |
* Display a string, usually as a prompt for input into the command buffer. |
n = (10 * n) + (*p - '0'); |
*/ |
return (n); |
public void |
|
cmd_putstr(s) |
|
char *s; |
|
{ |
|
putstr(s); |
|
cmd_col += strlen(s); |
|
} |
} |
|
|
/* |
/* |