home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Der Mediaplex Sampler - Die 6 von Plex
/
6_v_plex.zip
/
6_v_plex
/
DISK5
/
DOS_50
/
PVIC.ZIP
/
EDIT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-21
|
8KB
|
354 lines
/*
*
* The main edit loop as well as some other simple cursor movement routines.
*/
#include <stdio.h>
#include "pvic.h"
#include "locdefs.h"
/*
* This flag is used to make auto-indent work right on lines where only
* a <RETURN> or <ESC> is typed. It is set when an auto-indent is done,
* and reset when any other editting is done on the line. If an <ESC>
* or <RETURN> is received, and did_ai is (1), the line is truncated.
*/
int did_ai = (0);
void edit()
{
extern int need_redraw;
int c;
register char *p, *q;
prenum = 0;
/* position the display and the cursor at the top of the file. */
*top_char = *file_memory;
*cursor_char = *file_memory;
cursor_row = cursor_column = 0;
update_screen(0);
for ( ;; ) {
/* Figure out where the cursor is based on cursor_char. */
update_cursor(0);
if(!is_input_pending())
{
if(need_redraw)update_screen(0);
goto_screen_pos(cursor_row,cursor_column);
}
c = get_char_from_input_buffer();
if (current_status == STATUS_NORMAL) {
/* We're in the normal (non-insert) mode. */
/* Pick up any leading digits and compute 'prenum' */
if ( (prenum>0 && is_digit(c)) || (is_digit(c) && c!='0') ){
prenum = prenum*10 + (c-'0');
continue;
}
/* execute the command */
normal(c);
prenum = 0;
} else {
/*
* Insert or Replace mode.
*/
changed=1;
switch (c) {
case ESC: /* an escape ends input mode */
/*
* If we just did an auto-indent, truncate the
* line, and put the cursor back.
*/
if (did_ai) {
cursor_char->linep->s[0] = '\0';
cursor_char->index = 0;
did_ai = (0);
}
set_wanted_cursor_column = (1);
/* Don't end up on a '\n' if you can help it. */
if (gchar(cursor_char) == '\0' && cursor_char->index != 0)
dec(cursor_char);
/*
* The cursor should end up on the last inserted
* character. This is an attempt to match the real
* 'vi', but it may not be quite right yet.
*/
if (cursor_char->index != 0 && !end_of_line(cursor_char))
dec(cursor_char);
current_status = STATUS_NORMAL;
msg("");
/* construct the Redo buffer */
p=redo_buffer;
q=insert_buffer;
while ( q < insert_pointer )
*p++ = *q++;
*p++ = ESC;
*p = '\0';
update_screen(0);
break;
case CTRL_D:
/*
* Control-D is treated as a backspace in insert
* mode to make auto-indent easier. This isn't
* completely compatible with vi, but it's a lot
* easier than doing it exactly right, and the
* difference isn't very noticeable.
*/
case CTRL_H:
/* can't backup past starting point */
if (cursor_char->linep == start_insert->linep &&
cursor_char->index <= start_insert->index) {
beep();
break;
}
/* can't backup to a previous line */
if (cursor_char->linep != start_insert->linep &&
cursor_char->index <= 0) {
beep();
break;
}
did_ai = (0);
dec(cursor_char);
if (current_status == STATUS_INSERT)
delete_char((1));
/*
* It's a little strange to put backspaces into
* the redo buffer, but it makes auto-indent a
* lot easier to deal with.
*/
*insert_pointer++ = CTRL_H;
insert_n++;
update_cursor(0);
update_line(0);
break;
case CTRL_J:
case CTRL_M:
if (current_status == STATUS_REPLACE)
{
current_status = STATUS_NORMAL;
msg("");
/* construct the Redo buffer */
p=redo_buffer;
q=insert_buffer;
while ( q < insert_pointer )
*p++ = *q++;
*p++ = ESC;
*p = '\0';
if (!line_empty())
inc(cursor_char);
u_save_line();
do_start_insert(mkstr(c), (0));
}
*insert_pointer++ = '\n';
insert_n++;
open_command(SEARCH_FORWARD, (1)); /* open a new line */
break;
default:
did_ai = (0);
insert_char(c);
break;
}
}
}
}
void insert_char(c)
int c;
{
inschar(c);
*insert_pointer++ = c;
insert_n++;
/*
* The following kludge avoids overflowing the statically
* allocated insert buffer. Just dump the user back into
* command mode, and print a message.
*/
if (insert_pointer+10 >= &insert_buffer[1024]) {
put_string_into_input_buffer(mkstr(ESC));
error_message("No buffer space, returning to command mode");
loop_n_seconds(3);
}
update_line();
}
void get_out()
{
goto_screen_pos(current_lines-1,0);
putc('\n',stdout);
pvic_exit(0);
}
void scroll_down(nlines)
int nlines;
{
register LPTR *p;
register int done = 0; /* total # of physical lines done */
/* Scroll up 'nlines' lines. */
while (nlines--) {
if ((p = previous_line(top_char)) == NULL)
break;
done += plines(p);
*top_char = *p;
/*
* If the cursor is on the bottom line, we need to
* make sure it gets moved up the appropriate number
* of lines so it stays on the screen.
*/
if (cursor_char->linep == bottom_char->linep->prev) {
int i = 0;
while (i < done) {
i += plines(cursor_char);
*cursor_char = *previous_line(cursor_char);
}
}
}
}
void scroll_up(nlines)
int nlines;
{
register LPTR *p;
register int done = 0; /* total # of physical lines done */
register int pl; /* # of plines for the current line */
/* Scroll down 'nlines' lines. */
while (nlines--) {
pl = plines(top_char);
if ((p = next_line(top_char)) == NULL)
break;
done += pl;
if (cursor_char->linep == top_char->linep)
*cursor_char = *p;
*top_char = *p;
}
}
/*
* one_right
* one_left
* one_down
* one_up
*
* Move one char {right,left,down,up}. Return (1) when
* successful, (0) when we hit a boundary (of a line, or the file).
*/
int one_right()
{
set_wanted_cursor_column = (1);
switch (inc(cursor_char)) {
case 0:
return (1);
case 1:
dec(cursor_char); /* crossed a line, so back up */
/* fall through */
}
/*NOTREACHED*/
return (0); /* v1.1 cut out Turbo C complaints */
}
int one_left()
{
set_wanted_cursor_column = (1);
switch (dec(cursor_char)) {
case 0:
return (1);
case 1:
inc(cursor_char); /* crossed a line, so back up */
/* fall through */
}
/*NOTREACHED*/
return (0); /* v1.1 cut out Turbo C complaints */
}
void begin_line(flag)
int flag;
{
while ( one_left() )
;
if (flag) {
while (is_space(gchar(cursor_char)) && one_right())
;
}
set_wanted_cursor_column = (1);
}
int one_up(n)
int n;
{
LPTR p, *np;
register int k;
p = *cursor_char;
for ( k=0; k<n; k++ ) {
/* Look for the previous line */
if ( (np=previous_line(&p)) == NULL ) {
/* If we've at least backed up a little .. */
if ( k > 0 )
break; /* to update the cursor, etc. */
else
return (0);
}
p = *np;
}
*cursor_char = p;
/* This makes sure top_char gets updated so the complete line */
/* is one the screen. */
update_cursor(0);
/* try to advance to the column we want to be at */
*cursor_char = *advance_column(&p, wanted_cursor_column);
return (1);
}
int one_down(n)
int n;
{
LPTR p, *np;
register int k;
p = *cursor_char;
for ( k=0; k<n; k++ ) {
/* Look for the next line */
if ( (np=next_line(&p)) == NULL ) {
if ( k > 0 )
break;
else
return (0);
}
p = *np;
}
/* try to advance to the column we want to be at */
*cursor_char = *advance_column(&p, wanted_cursor_column);
return (1);
}