* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS 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
#if !defined(lint) && !defined(SCCSID)
static char sccsid
[] = "@(#)common.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
* common.c: Common Editor functions
*el
->el_line
.lastchar
= '\0';
* Add character to the line
* Insert a character [bound to all insert keys]
if (el
->el_line
.lastchar
+ el
->el_state
.argument
>=
return CC_ERROR
; /* end of buffer space */
if (el
->el_state
.argument
== 1) {
if (el
->el_state
.inputmode
!= MODE_INSERT
) {
el
->el_chared
.c_undo
.buf
[el
->el_chared
.c_undo
.isize
++] =
el
->el_chared
.c_undo
.buf
[el
->el_chared
.c_undo
.isize
] = '\0';
*el
->el_line
.cursor
++ = c
;
el
->el_state
.doingarg
= 0; /* just in case */
re_fastaddc(el
); /* fast refresh for one char. */
if (el
->el_state
.inputmode
!= MODE_INSERT
) {
for(i
= 0;i
< el
->el_state
.argument
; i
++)
el
->el_chared
.c_undo
.buf
[el
->el_chared
.c_undo
.isize
++] =
el
->el_chared
.c_undo
.buf
[el
->el_chared
.c_undo
.isize
] = '\0';
c_delafter(el
, el
->el_state
.argument
);
c_insert(el
, el
->el_state
.argument
);
while (el
->el_state
.argument
--)
*el
->el_line
.cursor
++ = c
;
if (el
->el_state
.inputmode
== MODE_REPLACE_1
)
(void) vi_command_mode(el
, 0);
/* ed_delete_prev_word():
* Delete from beginning of current word to cursor
ed_delete_prev_word(el
, c
)
if (el
->el_line
.cursor
== el
->el_line
.buffer
)
cp
= c__prev_word(el
->el_line
.cursor
, el
->el_line
.buffer
,
el
->el_state
.argument
, ce__isword
);
for (p
= cp
, kp
= el
->el_chared
.c_kill
.buf
; p
< el
->el_line
.cursor
; p
++)
el
->el_chared
.c_kill
.last
= kp
;
c_delbefore(el
, el
->el_line
.cursor
- cp
); /* delete before dot */
if (el
->el_line
.cursor
< el
->el_line
.buffer
)
el
->el_line
.cursor
= el
->el_line
.buffer
; /* bounds check */
/* ed_delete_next_char():
* Delete character under cursor
ed_delete_next_char(el
, c
)
fprintf(stderr
, "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n",
EL
.buffer
, EL
.buffer
, EL
.cursor
, EL
.cursor
, EL
.lastchar
, EL
.lastchar
, EL
.limit
, EL
.limit
);
if (el
->el_line
.cursor
== el
->el_line
.lastchar
) {/* if I'm at the end */
if (el
->el_map
.type
== MAP_VI
) {
if (el
->el_line
.cursor
== el
->el_line
.buffer
) {
/* if I'm also at the beginning */
term_overwrite(el
, STReof
, 4);/* then do a EOF */
if (el
->el_line
.cursor
!= el
->el_line
.buffer
)
c_delafter(el
, el
->el_state
.argument
); /* delete after dot */
if (el
->el_line
.cursor
>= el
->el_line
.lastchar
&& el
->el_line
.cursor
> el
->el_line
.buffer
)
el
->el_line
.cursor
= el
->el_line
.lastchar
- 1; /* bounds check */
kp
= el
->el_chared
.c_kill
.buf
;
while (cp
< el
->el_line
.lastchar
)
*kp
++ = *cp
++; /* copy it */
el
->el_chared
.c_kill
.last
= kp
;
el
->el_line
.lastchar
= el
->el_line
.cursor
; /* zap! -- delete to end */
* Move cursor to the end of line
el
->el_line
.cursor
= el
->el_line
.lastchar
;
if (el
->el_map
.type
== MAP_VI
) {
if (el
->el_chared
.c_vcmd
.action
& DELETE
) {
* Move cursor to the beginning of line
el
->el_line
.cursor
= el
->el_line
.buffer
;
if (el
->el_map
.type
== MAP_VI
) {
/* We want FIRST non space character */
while (isspace(*el
->el_line
.cursor
))
if (el
->el_chared
.c_vcmd
.action
& DELETE
) {
* Exchange the character to the left of the cursor with the one under it
ed_transpose_chars(el
, c
)
if (el
->el_line
.cursor
< el
->el_line
.lastchar
) {
if (el
->el_line
.lastchar
<= &el
->el_line
.buffer
[1])
if (el
->el_line
.cursor
> &el
->el_line
.buffer
[1]) {
/* must have at least two chars entered */
c
= el
->el_line
.cursor
[-2];
el
->el_line
.cursor
[-2] = el
->el_line
.cursor
[-1];
el
->el_line
.cursor
[-1] = c
;
* Move to the right one character
if (el
->el_line
.cursor
>= el
->el_line
.lastchar
)
el
->el_line
.cursor
+= el
->el_state
.argument
;
if (el
->el_line
.cursor
> el
->el_line
.lastchar
)
el
->el_line
.cursor
= el
->el_line
.lastchar
;
if (el
->el_map
.type
== MAP_VI
)
if (el
->el_chared
.c_vcmd
.action
& DELETE
) {
* Move to the beginning of the current word
if (el
->el_line
.cursor
== el
->el_line
.buffer
)
el
->el_line
.cursor
= c__prev_word(el
->el_line
.cursor
, el
->el_line
.buffer
,
if (el
->el_map
.type
== MAP_VI
)
if (el
->el_chared
.c_vcmd
.action
& DELETE
) {
* Move to the left one character
if (el
->el_line
.cursor
> el
->el_line
.buffer
) {
el
->el_line
.cursor
-= el
->el_state
.argument
;
if (el
->el_line
.cursor
< el
->el_line
.buffer
)
el
->el_line
.cursor
= el
->el_line
.buffer
;
if (el
->el_map
.type
== MAP_VI
)
if (el
->el_chared
.c_vcmd
.action
& DELETE
) {
* Add the next character typed verbatim
return ed_end_of_file(el
, 0);
* Adds to argument or enters a digit
if (el
->el_state
.doingarg
) {
/* if doing an arg, add this in... */
if (el
->el_state
.lastcmd
== EM_UNIVERSAL_ARGUMENT
)
el
->el_state
.argument
= c
- '0';
if (el
->el_state
.argument
> 1000000)
(el
->el_state
.argument
* 10) + (c
- '0');
if (el
->el_line
.lastchar
+ 1 >= el
->el_line
.limit
)
if (el
->el_state
.inputmode
!= MODE_INSERT
) {
el
->el_chared
.c_undo
.buf
[el
->el_chared
.c_undo
.isize
++] =
el
->el_chared
.c_undo
.buf
[el
->el_chared
.c_undo
.isize
] = '\0';
*el
->el_line
.cursor
++ = c
;
el
->el_state
.doingarg
= 0;
* Digit that starts argument
if (el
->el_state
.doingarg
) {
if (el
->el_state
.argument
> 1000000)
el
->el_state
.argument
= (el
->el_state
.argument
* 10) + (c
- '0');
else { /* else starting an argument */
el
->el_state
.argument
= c
- '0';
el
->el_state
.doingarg
= 1;
* Indicates unbound character
* Bound to keys that are not assigned
* Tty interrupt character
* Tty delayed suspend character
/* ed_tty_flush_output():
* Tty flush output characters
ed_tty_flush_output(el
, c
)
* Tty disallow output characters
ed_tty_stop_output(el
, c
)
/* ed_tty_start_output():
* Tty allow output characters
ed_tty_start_output(el
, c
)
*el
->el_line
.lastchar
++ = '\n';
*el
->el_line
.lastchar
= '\0';
if (el
->el_map
.type
== MAP_VI
)
el
->el_chared
.c_vcmd
.ins
= el
->el_line
.buffer
;
/* ed_delete_prev_char():
* Delete the character to the left of the cursor
ed_delete_prev_char(el
, c
)
if (el
->el_line
.cursor
<= el
->el_line
.buffer
)
c_delbefore(el
, el
->el_state
.argument
);
el
->el_line
.cursor
-= el
->el_state
.argument
;
if (el
->el_line
.cursor
< el
->el_line
.buffer
)
el
->el_line
.cursor
= el
->el_line
.buffer
;
* Clear screen leaving current line at the top
term_clear_screen(el
); /* clear the whole real screen */
re_clear_display(el
); /* reset everything */
* Erase current line and start from scratch
/* ed_sequence_lead_in():
* First character in a bound sequence
* Placeholder for external keys
ed_sequence_lead_in(el
, c
)
* Move to the previous history line
el
->el_chared
.c_undo
.action
= NOP
;
*el
->el_line
.lastchar
= '\0'; /* just in case */
if (el
->el_history
.eventno
== 0) { /* save the current buffer away */
(void) strncpy(el
->el_history
.buf
, el
->el_line
.buffer
, EL_BUFSIZ
);
el
->el_history
.last
= el
->el_history
.buf
+
(el
->el_line
.lastchar
- el
->el_line
.buffer
);
el
->el_history
.eventno
+= el
->el_state
.argument
;
if (hist_get(el
) == CC_ERROR
) {
/* el->el_history.eventno was fixed by first call */
return CC_NORM
; /* was CC_UP_HIST */
* Move to the next history line
el
->el_chared
.c_undo
.action
= NOP
;
*el
->el_line
.lastchar
= '\0'; /* just in case */
el
->el_history
.eventno
-= el
->el_state
.argument
;
if (el
->el_history
.eventno
< 0) {
el
->el_history
.eventno
= 0;
return CC_ERROR
; /* make it beep */
/* ed_search_prev_history():
* Search previous in history for a line matching the current
* next search history [M-P] [K]
ed_search_prev_history(el
, c
)
el
->el_chared
.c_vcmd
.action
= NOP
;
el
->el_chared
.c_undo
.action
= NOP
;
*el
->el_line
.lastchar
= '\0'; /* just in case */
if (el
->el_history
.eventno
< 0) {
(void) fprintf(el
->el_errfile
, "e_prev_search_hist(): eventno < 0;\n");
el
->el_history
.eventno
= 0;
if (el
->el_history
.eventno
== 0) {
(void) strncpy(el
->el_history
.buf
, el
->el_line
.buffer
, EL_BUFSIZ
);
el
->el_history
.last
= el
->el_history
.buf
+
(el
->el_line
.lastchar
- el
->el_line
.buffer
);
if (el
->el_history
.ref
== NULL
)
c_setpat(el
); /* Set search pattern !! */
for (h
= 1; h
<= el
->el_history
.eventno
; h
++)
(void) fprintf(el
->el_errfile
, "Comparing with \"%s\"\n", hp
);
if ((strncmp(hp
, el
->el_line
.buffer
,
el
->el_line
.lastchar
- el
->el_line
.buffer
) ||
hp
[el
->el_line
.lastchar
-el
->el_line
.buffer
]) &&
(void) fprintf(el
->el_errfile
, "not found\n");
el
->el_history
.eventno
= h
;
/* ed_search_next_history():
* Search next in history for a line matching the current
ed_search_next_history(el
, c
)
el
->el_chared
.c_vcmd
.action
= NOP
;
el
->el_chared
.c_undo
.action
= NOP
;
*el
->el_line
.lastchar
= '\0'; /* just in case */
if (el
->el_history
.eventno
== 0)
if (el
->el_history
.ref
== NULL
)
c_setpat(el
); /* Set search pattern !! */
for (h
= 1; h
< el
->el_history
.eventno
&& hp
; h
++) {
(void) fprintf(el
->el_errfile
, "Comparing with \"%s\"\n", hp
);
if ((strncmp(hp
, el
->el_line
.buffer
,
el
->el_line
.lastchar
- el
->el_line
.buffer
) ||
hp
[el
->el_line
.lastchar
-el
->el_line
.buffer
]) &&
if (!found
) { /* is it the current history number? */
if (!c_hmatch(el
, el
->el_history
.buf
)) {
(void) fprintf(el
->el_errfile
, "not found\n");
el
->el_history
.eventno
= found
;
* Move to the line requested
if (*(ptr
= el
->el_line
.cursor
) == '\n')
for (; ptr
>= el
->el_line
.buffer
; ptr
--)
if (*ptr
== '\n' && --el
->el_state
.argument
<= 0)
if (el
->el_state
.argument
> 0)
* Move to the beginning of the line
for (ptr
--; ptr
>= el
->el_line
.buffer
&& *ptr
!= '\n'; ptr
--)
* Move to the character requested
nchars
-- > 0 && ptr
< el
->el_line
.lastchar
&& *ptr
!= '\n';
el
->el_line
.cursor
= ptr
;
* Move to the line requested
for (ptr
= el
->el_line
.cursor
; ptr
< el
->el_line
.lastchar
; ptr
++)
if (*ptr
== '\n' && --el
->el_state
.argument
<= 0)
if (el
->el_state
.argument
> 0)
* Move to the character requested
nchars
-- > 0 && ptr
< el
->el_line
.lastchar
&& *ptr
!= '\n';
el
->el_line
.cursor
= ptr
;
* Editline extended command
el
->el_line
.buffer
[0] = '\0';
el
->el_line
.lastchar
= el
->el_line
.buffer
;
el
->el_line
.cursor
= el
->el_line
.buffer
;
c_insert(el
, 3); /* prompt + ": " */
*el
->el_line
.cursor
++ = '\n';
*el
->el_line
.cursor
++ = ':';
*el
->el_line
.cursor
++ = ' ';
tmplen
= c_gets(el
, tmpbuf
);
el
->el_line
.buffer
[0] = '\0';
el
->el_line
.lastchar
= el
->el_line
.buffer
;
el
->el_line
.cursor
= el
->el_line
.buffer
;
if (parse_line(el
, tmpbuf
) == -1)