home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
misc
/
volume24
/
mced
/
part01
/
vi_edit.c
< prev
Wrap
C/C++ Source or Header
|
1991-10-26
|
15KB
|
741 lines
/*
* This software is Copyright (c) 1991 by Andy Knight
*
* Permission is hereby granted to copy, distribute or otherwise
* use any part of this package as long as you do not try to make
* money from it or pretend that you wrote it. This copyright
* notice must be maintained in any copy made.
*
* Use of this software constitutes acceptance for use in an AS IS
* condition. There are NO warranties with regard to this software.
* In no event shall the author be liable for any damages whatsoever
* arising out of or in connection with the use or performance of this
* software. Any use of this software is at the user's own risk.
*
* If you make modifications to this software that you feel
* increases it usefulness for the rest of the community, please
* email the changes, enhancements, bug fixes as well as any and
* all ideas to me. This software is going to be maintained and
* enhanced as deemed necessary by the community.
*
* " ... Freely you have recieved, freely give" <Matthew 10:8>
*
* Andy Knight
* aknight@ourgang.prime.com
*/
#include "config.h"
extern char *hist[], cstr[];
extern int xbeg, cur_cmd, last_hline, pwolfe_getch();
extern int edit_mode, x_pos, savex_pos, xend;
extern void my_wmove(), add_hline(), cmd_to_win(), win_to_cmd();
extern void my_winsch(), my_waddstr(), case_upper();
extern void my_wdelch(), case_lower(), eat_white();
extern SIGTYPE die_curses(), die_normal();
extern WINDOW *win;
#ifdef SYSVcurses
extern struct termio tio, tin;
#else
extern struct tchars tco, tcn;
#endif
edit_cmd()
{
int stop_it, p_init, xins_strt, edch, i, j, tmp_cmd;
int dot_mode, dot_iterations, n_iterations, n_times, indx;
char tch, dot_cmd;
char save_ins[MAX_W_SAVED + 1], save_del[MAX_W_SAVED + 1];
fprintf(stdout, "\n");
if (initscr() == ERR)
{
fprintf(stderr, "Curses won't initialize - help!\n");
die_normal();
}
signal(SIGINT, die_curses); /* die cleanly */
CBREAKF();
noecho();
#ifdef SYSVcurses
win = newwin(2, COLS, 0, 0);
#else
clearok(curscr, FALSE); /* SYSV curses clears it anyway ;-( */
win = newwin(2, COLS, LINES - 2, 0);
#endif
cmd_to_win();
my_wmove(--x_pos);
wrefresh(win);
savex_pos = x_pos;
#ifdef SYSVcurses /* disable STOP/START (CTRL-S) */
if (ioctl(0, TCGETA, &tio) != 0)
perror("ioctl");
tin = tio;
tin.c_iflag &= ~IXON;
if (ioctl(0, TCSETA, &tin) != 0)
perror("ioctl");
#else
if (ioctl(0, TIOCGETC, &tco) != 0)
perror("ioctl");
tcn = tco;
tcn.t_stopc = -1;
if (ioctl(0, TIOCSETC, &tcn) != 0)
perror("ioctl");
#endif
edit_mode = VI_NINS_MODE;
dot_iterations = 1;
dot_cmd = NO;
n_times = indx = 0;
p_init = NO;
for (; (edch = pwolfe_getch(win)) != '\n';)
{
if ((edch == 'u' || edch == 'U') && edit_mode == VI_NINS_MODE)
{
cmd_to_win();
x_pos = savex_pos;
my_wmove(x_pos);
wrefresh(win);
continue;
}
if (edit_mode == VI_NINS_MODE && (edch == 'a' || edch == 'A'
|| edch == 'i' || edch == 'I' || edch == 'p' || edch == 'P'
|| edch == '.' || edch == 'x' || edch == 'd' || edch == 'D'
|| edch == 'c' || edch == 'C' || edch == 'r' || edch == 'R'
|| edch == '\~' || edch == 'X' || edch == ControlW
|| edch == Sun_R1))
{
savex_pos = x_pos;
win_to_cmd(); /* for undo function */
my_wmove(x_pos);
}
if (edit_mode == VI_NINS_MODE)
{
if (edch == 'c')
{
indx = 0;
xins_strt = x_pos;
edit_mode = VI_c_MODE;
continue;
}
else if (edch == 'd')
{
edit_mode = VI_d_MODE;
continue;
}
else if (edch == 'r')
{
edit_mode = VI_r_MODE;
continue;
}
else if (edch == 'R')
{
indx = 0;
xins_strt = x_pos;
dot_mode = VI_NINS_MODE;
dot_cmd = 'R';
edit_mode = VI_R_MODE;
continue;
}
}
if (isdigit(edch) && edit_mode == VI_NINS_MODE)
{
if (n_times != 0)
n_times *= 10;
n_times += edch - '0';
continue;
}
if (n_times != 0)
{
n_iterations = n_times;
n_times = 0;
}
else
n_iterations = 1;
if (edch == '\.' && edit_mode == VI_NINS_MODE)
{
if (dot_cmd != NO)
{
edch = dot_cmd;
edit_mode = dot_mode;
n_iterations = dot_iterations;
if (edch == 'i' || edch == 'a')
{
if (edch == 'a')
my_wmove(++x_pos);
my_waddstr(save_ins);
my_wmove(--x_pos);
n_iterations = 0;
}
else if (edch == 'R')
{
for (i = 0; i < indx && x_pos >= xbeg && x_pos < xend; i++)
my_wdelch();
my_waddstr(save_ins);
my_wmove(--x_pos);
n_iterations = 0;
}
else if (edit_mode == VI_c_MODE)
{
my_waddstr(save_ins);
n_iterations = 1;
edit_mode = VI_c_MODE;
dot_mode = NO_BEG_INS;
}
}
else
beep();
}
if (edit_mode == VI_INS_MODE)
{
if (edch == ControlU)
{
wclear(win);
wrefresh(win);
die_curses();
}
else if (edch == Escape)
{
edit_mode = VI_NINS_MODE;
if (x_pos > xbeg)
my_wmove(--x_pos);
}
else if (edch == ControlW || edch == Sun_R1)
{
if (x_pos > xbeg)
{
my_wmove(--x_pos);
eat_white(-1, YES);
for (; !(isspace(winch(win))) && (x_pos >= xins_strt);)
{
my_wdelch();
if (x_pos == xbeg)
break;
else
my_wmove(--x_pos);
}
if (x_pos > xbeg && x_pos < xend - 1)
my_wmove(++x_pos);
}
else
beep();
}
else if (edch == Delete)
{
if (x_pos > xbeg && x_pos > xins_strt)
{
my_wmove(--x_pos);
my_wdelch();
}
else
beep();
}
else if (isprint(edch))
{
my_winsch(edch);
if (indx < MAX_W_SAVED)
{
save_ins[indx] = edch;
save_ins[++indx] = '\0';
}
}
else
beep();
}
else if (edit_mode == VI_R_MODE)
{
if (edch == Escape)
{
if (x_pos > xbeg)
my_wmove(--x_pos);
if (x_pos > xend - 1)
xend = x_pos + 1;
edit_mode = VI_NINS_MODE;
}
else if (edch == ControlU)
{
wclear(win);
wrefresh(win);
die_curses();
}
else if (edch == Delete)
{
if (x_pos > xbeg && x_pos > xins_strt)
{
my_winsch(' ');
x_pos -= 2;
my_wmove(x_pos);
my_wdelch();
save_ins[--indx] = ' ';
}
else
beep();
}
else if (isprint(edch))
{
my_wdelch();
my_winsch(edch);
if (indx < MAX_W_SAVED)
{
save_ins[indx] = edch;
save_ins[++indx] = '\0';
}
}
else
beep();
}
else
{
stop_it = NO;
for (j = 0; j < n_iterations && edch != Escape; j++)
{
if (edit_mode == VI_d_MODE || edit_mode == VI_c_MODE)
{
if (edch == 'w' || edch == 'W') /* delete or change word */
{
if (x_pos < xend)
{
if (!(isalnum(winch(win))) && winch(win) != '_'
&& edch == 'w')
{
if (x_pos < xend)
{
p_init = YES;
if (MAX_W_SAVED > 1)
{
save_del[0] = winch(win);
save_del[1] = '\0';
}
my_wdelch();
i = 1;
}
}
else
{
for (i = 0; (( edch == 'w' && (isalnum(winch(win)))
|| edch == 'W')
&& !(isspace(winch(win)))
|| winch(win) == '_')
&& (x_pos < xend);)
{
if (i < MAX_W_SAVED)
save_del[i] = winch(win);
my_wdelch();
++i;
}
save_del[MIN(i, MAX_W_SAVED)] = '\0';
p_init = YES;
}
if (winch(win) == ' ' && x_pos <= xend - 1
&& edit_mode != VI_c_MODE)
{
my_wdelch();
if (i < MAX_W_SAVED)
{
save_del[i] = ' ';
save_del[MIN((i + 1), MAX_W_SAVED)] = '\0';
}
}
}
else
beep();
if (x_pos == xend && edit_mode != VI_c_MODE)
my_wmove(--x_pos);
if (edit_mode == VI_d_MODE)
{
dot_cmd = edch;
dot_iterations = n_iterations;
dot_mode = VI_d_MODE;
}
if (edit_mode == VI_c_MODE)
{
if (dot_mode != NO_BEG_INS)
edit_mode = VI_INS_MODE;
else
{
edit_mode = VI_NINS_MODE;
my_wmove(--x_pos);
}
dot_cmd = edch;
dot_iterations = 1;
dot_mode = VI_c_MODE;
}
else if (j >= n_iterations - 1)
edit_mode = VI_NINS_MODE;
}
else if (edch == 'd' && edit_mode != VI_c_MODE)
{
wclear(win);
wrefresh(win);
die_curses();
break;
}
else
{
edit_mode = VI_NINS_MODE;
beep();
}
}
else if (edit_mode == VI_r_MODE)
{
if (isprint(edch))
{
dot_mode = VI_r_MODE;
dot_cmd = edch;
my_wdelch();
my_winsch(edch);
my_wmove(--x_pos);
}
else
beep();
edit_mode = VI_NINS_MODE;
}
else
{
switch (edch)
{
case 'I':
dot_cmd = NO;
x_pos = xbeg;
xins_strt = x_pos;
my_wmove(x_pos);
edit_mode = VI_INS_MODE;
break;
case 'i':
indx = 0;
dot_cmd = 'i';
dot_iterations = 1;
dot_mode = VI_NINS_MODE;
xins_strt = x_pos;
edit_mode = VI_INS_MODE;
break;
case 'A':
dot_cmd = NO;
if (x_pos < xend)
{
x_pos = xend;
xins_strt = x_pos;
my_wmove(x_pos);
}
edit_mode = VI_INS_MODE;
break;
case 'a':
indx = 0;
dot_cmd = 'a';
dot_iterations = 1;
dot_mode = VI_NINS_MODE;
if (x_pos < xend)
my_wmove(++x_pos);
xins_strt = x_pos;
edit_mode = VI_INS_MODE;
break;
case ControlU:
case Sun_R3:
wclear(win);
wrefresh(win);
die_curses();
break;
case ControlW: /* Delete backwards to next space */
case Sun_R1:
dot_cmd = ControlW;
dot_iterations = n_iterations;
dot_mode = VI_NINS_MODE;
if (x_pos > xbeg)
{
if (x_pos != xend - 1)
my_wmove(--x_pos);
eat_white(-1, YES);
for (; !(isspace(winch(win))) && (x_pos >= xbeg);)
{
my_wdelch();
if (x_pos == xbeg)
break;
else
my_wmove(--x_pos);
}
if (x_pos > xbeg && x_pos < xend - 1)
my_wmove(++x_pos);
}
else
beep();
break;
case 'b': /* move back to beginning of previous word */
case 'B':
case Sun_R4:
if (x_pos > xbeg)
{
my_wmove(--x_pos);
eat_white(-1, NO);
for (; !(isspace(winch(win))) && (x_pos > xbeg);)
{
my_wmove(--x_pos);
}
if (x_pos > xbeg)
my_wmove(++x_pos);
}
else
beep();
break;
case 'w': /* move forward to beginning of next word */
case 'W':
case Sun_R6:
if (x_pos < xend - 1)
{
eat_white(1, NO);
for (; !(isspace(winch(win))) && (x_pos < xend - 1);)
{
my_wmove(++x_pos);
}
if (x_pos < xend - 1)
my_wmove(++x_pos);
}
else
beep();
break;
case ControlL: /* redraw win */
savex_pos = x_pos;
win_to_cmd();
wclear(win);
wrefresh(win);
cmd_to_win();
x_pos = savex_pos;
my_wmove(x_pos);
break;
case BackSpace:
case KEY_LEFT:
case KEY_BACKSPACE:
case 'h':
case Sun_R10:
if (x_pos > xbeg)
my_wmove(--x_pos);
else
beep();
break;
case EscapeM: /* move cursor to middle */
case Sun_R11:
x_pos = xbeg + (xend - xbeg) / 2;
my_wmove(x_pos);
break;
case KEY_RIGHT:
case 'l':
case ' ':
case Sun_R12:
if (x_pos < xend - 1)
my_wmove(++x_pos);
else
beep();
break;
case KEY_UP: /* move upward in history list */
case 'k':
case Sun_R8:
if (cur_cmd > 0)
{
--cur_cmd;
strcpy(cstr, hist[cur_cmd]);
wclear(win);
cmd_to_win();
my_wmove(--x_pos);
}
else
beep();
break;
case KEY_DOWN: /* move downward in history list */
case 'j':
case Sun_R14:
if (cur_cmd < last_hline)
{
++cur_cmd;
strcpy(cstr, hist[cur_cmd]);
wclear(win);
cmd_to_win();
my_wmove(--x_pos);
}
else
beep();
break;
case 'n': /* search history list backwards */
if ((tmp_cmd = index_cmd(cur_cmd - 1, -1)) != cur_cmd)
{
cur_cmd = tmp_cmd;
strcpy(cstr, hist[cur_cmd]);
wclear(win);
cmd_to_win();
my_wmove(--x_pos);
}
else
beep();
break;
case '\^':
case Sun_R7:
my_wmove(xbeg);
x_pos = xbeg;
break;
case '\$':
case Sun_R13:
case Sun_R9:
x_pos = xend - 1;
my_wmove(x_pos);
break;
case 'D': /* delete to end of line */
if (x_pos < xend)
{
p_init = YES;
dot_cmd = NO;
for (i = 0; (xend - x_pos) > 0; i++)
{
if (i < MAX_W_SAVED)
{
save_del[i] = winch(win);
save_del[MIN((i + 1), MAX_W_SAVED)] = '\0';
}
my_wdelch();
}
if (x_pos == xend)
my_wmove(--x_pos);
}
else
beep();
break;
case 'C': /* delete to end of line and insert */
if (x_pos < xend)
{
dot_cmd = NO;
xins_strt = x_pos;
for (i = xend; i > x_pos; i--)
{
my_wdelch();
}
edit_mode = VI_INS_MODE;
}
else
beep();
break;
case 'J':
x_pos = xend;
my_wmove(x_pos);
my_winsch(' ');
add_hline();
break;
case 'p':
case 'P':
if (p_init == YES)
{
if (edch == 'p')
my_wmove(++x_pos);
my_waddstr(save_del);
my_wmove(--x_pos);
}
else
beep();
break;
case 'x': /* delete current character */
dot_cmd = 'x';
dot_iterations = n_iterations;
dot_mode = VI_NINS_MODE;
p_init = YES;
if (j < MAX_W_SAVED)
{
save_del[j] = winch(win);
save_del[MIN((j + 1), MAX_W_SAVED)] = '\0';
}
if (x_pos == xend - 1 && stop_it == NO)
{
if (j <= n_iterations - 1)
stop_it = YES;
my_wdelch();
my_wmove(--x_pos);
}
else if (x_pos != xend - 1)
{
if (x_pos >= xbeg)
{
my_wdelch();
}
else
beep();
}
break;
case 'X': /* delete character before cursor */
dot_cmd = 'X';
dot_iterations = n_iterations;
dot_mode = VI_NINS_MODE;
if (x_pos > xbeg)
{
my_wmove(--x_pos);
p_init = YES;
if ((n_iterations - j - 1) < MAX_W_SAVED)
{
save_del[n_iterations - j - 1] = winch(win);
save_del[MIN(n_iterations, MAX_W_SAVED)] = '\0';
}
my_wdelch();
}
else
beep();
break;
case EscapeL: /* lower case whole command */
case Sun_R2:
savex_pos = x_pos;
win_to_cmd();
case_lower();
cmd_to_win();
x_pos = savex_pos;
my_wmove(x_pos);
break;
case EscapeU: /* upper case whole command */
savex_pos = x_pos;
win_to_cmd();
case_upper();
cmd_to_win();
x_pos = savex_pos;
my_wmove(x_pos);
break;
case '\~': /* toggle case of current character */
case Sun_R5:
tch = winch(win);
if (isupper(tch))
{
wdelch(win);
winsch(win, tolower(tch));
}
else if (islower(tch))
{
wdelch(win);
winsch(win, toupper(tch));
}
if (x_pos < xend - 1)
my_wmove(++x_pos);
break;
default:
beep();
break;
}
}
}
}
wrefresh(win);
if (xend <= xbeg)
die_curses();
}
win_to_cmd();
#ifdef SYSVcurses /* reset tty */
if (ioctl(0, TCSETA, &tio) != 0)
perror("ioctl");
#else
if (ioctl(0, TIOCSETC, &tco) != 0)
perror("ioctl");
#endif
NOCBREAKF();
echo();
endwin();
return; /* finished, execute command */
}