home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
CMDS
/
pvic_10a.lzh
/
SRCE
/
misccmds.c
< prev
next >
Wrap
Text File
|
1998-04-23
|
10KB
|
432 lines
/*
* Various routines to perform specific editing operations or return
* useful information about the file.
*/
#include <stdio.h>
#include "pvic.h"
#include "locdefs.h"
static void openfwd(), openbwd();
extern int did_ai;
/*
* open_command
*
* Add a blank line above or below the current line.
*/
void
open_command(dir, can_ai)
int dir;
int can_ai; /* if true, consider auto-indent */
{
if (dir == SEARCH_FORWARD)
openfwd(can_ai);
else
openbwd(can_ai);
}
static void
openfwd(can_ai)
int can_ai;
{
register LINE *l;
LPTR *next;
register char *s; /* string to be moved to new line, if any */
int newindex = 0; /* index of the cursor on the new line */
/*
* If we're in insert mode, we need to move the remainder of the
* current line onto the new line. Otherwise the new line is left
* blank.
*/
if (current_status == STATUS_INSERT || current_status == STATUS_REPLACE)
s = &cursor_char->linep->s[cursor_char->index];
else
s = "";
if ((next = next_line(cursor_char)) == NULL) /* open on last line */
next = end_of_file;
/*
* By asking for as much space as the prior line had we make sure
* that we'll have enough space for any auto-indenting.
*/
if ((l = newline(strlen(cursor_char->linep->s) + SLOP)) == NULL)
return;
if (*s != '\0')
strcpy(l->s, s); /* copy string to new line */
else if (can_ai && PARAMETER_VALUE(PARAMETER_AUTOINDENT) && !is_input_pending()) {
char *p;
/*
* Copy prior line, and truncate after white space
*/
strcpy(l->s, cursor_char->linep->s);
for (p = l->s; *p == ' ' || *p == CTRL_I ;p++)
;
*p = '\0';
newindex = p - l->s;
/*
* If we just did an auto-indent, then we didn't type
* anything on the prior line, and it should be truncated.
*/
if (did_ai)
cursor_char->linep->s[0] = '\0';
did_ai = (1);
}
/* truncate current line at cursor */
if (current_status == STATUS_INSERT || current_status == STATUS_REPLACE)
*s = '\0';
cursor_char->linep->next = l; /* link neighbors to new line */
next->linep->prev = l;
l->prev = cursor_char->linep; /* link new line to neighbors */
l->next = next->linep;
if (next == end_of_file) /* new line at end */
l->num = cursor_char->linep->num + LINEINC;
else if ((l->prev->num) + 1 == l->next->num) /* no gap, renumber */
renum();
else { /* stick it in the middle */
unsigned long lnum;
lnum = ((long)l->prev->num + (long)l->next->num) / 2;
l->num = lnum;
}
/*
* Get the cursor to the start of the line, so that 'cursor_row'
* gets set to the right physical line number for the stuff
* that follows...
*/
cursor_char->index = 0;
update_cursor(0);
/*
* If we're doing an open on the last logical line, then
* go ahead and scroll the screen up. Otherwise, just insert
* a blank line at the right place. We use calls to plines()
* in case the cursor is resting on a long line.
*/
if (cursor_row + plines(cursor_char) == (current_lines - 1))
scroll_up(1);
*cursor_char = *next_line(cursor_char); /* cursor moves down */
cursor_char->index = newindex;
update_screen(0); /* because bottom_char is now invalid... */
update_cursor(0); /* update cursor_row before insert */
}
static void
openbwd(can_ai)
int can_ai;
{
register LINE *l;
LINE *prev;
int newindex = 0;
prev = cursor_char->linep->prev;
if ((l = newline(strlen(cursor_char->linep->s) + SLOP)) == NULL)
return;
cursor_char->linep->prev = l; /* link neighbors to new line */
prev->next = l;
l->next = cursor_char->linep; /* link new line to neighbors */
l->prev = prev;
if (can_ai && PARAMETER_VALUE(PARAMETER_AUTOINDENT) && !is_input_pending()) {
char *p;
/*
* Copy current line, and truncate after white space
*/
strcpy(l->s, cursor_char->linep->s);
for (p = l->s; *p == ' ' || *p == CTRL_I ;p++)
;
*p = '\0';
newindex = p - l->s;
did_ai = (1);
}
cursor_char->linep = cursor_char->linep->prev;
cursor_char->index = newindex;
if (prev == top_of_file->linep) /* new start of file */
file_memory->linep = l;
renum(); /* keep it simple - we don't do this often */
update_cursor(0); /* update cursor_row before insert */
update_screen(0);
}
int
cntllines(pbegin,pend)
register LPTR *pbegin, *pend;
{
register LINE *lp;
int lnum = 1;
for (lp = pbegin->linep; lp != pend->linep ;lp = lp->next)
lnum++;
return(lnum);
}
/*
* plines(p) - return the number of physical screen lines taken by line 'p'
*/
int
plines(p)
LPTR *p;
{
register int col = 0;
register char *s;
s = p->linep->s;
if (*s == '\0') /* empty line */
return 1;
for (; *s != '\0' ;s++) {
if ( *s == CTRL_I && !PARAMETER_VALUE(PARAMETER_LIST))
col += PARAMETER_VALUE(PARAMETER_TABSTOP) - (col % PARAMETER_VALUE(PARAMETER_TABSTOP));
else
col += chars[(unsigned)(*s & 0xff)].ch_size;
}
/*
* If list mode is on, then the '$' at the end of
* the line takes up one extra column.
*/
if (PARAMETER_VALUE(PARAMETER_LIST))
col += 1;
/*
* If 'number' mode is on, add another 8.
*/
if (PARAMETER_VALUE(PARAMETER_NUMBER))
col += 8;
return ((col + (current_columns-1)) / current_columns);
}
void
file_info()
{
extern int number_of_files, current_file;
register long l1, l2;
if (buffer_empty()) {
l1 = 0;
l2 = 1; /* don't div by zero */
} else {
l1 = cntllines(file_memory, cursor_char);
l2 = cntllines(file_memory, end_of_file) - 1;
}
if (number_of_files > 1)
show_message("\"%s\"%s line %ld of %ld -- %ld %% -- (file %d of %d)",
(file_name != NULL) ? file_name : "No File",
changed ? " [Modified]" : "",
l1, l2, (l1 * 100)/l2,
current_file+1, number_of_files);
else
show_message("\"%s\"%s line %ld of %ld -- %ld %% --",
(file_name != NULL) ? file_name : "No File",
changed ? " [Modified]" : "",
l1, l2, (l1 * 100)/l2);
}
/*
* goto_line(n) - return a pointer to line 'n'
*
* Returns a pointer to the last line of the file if n is zero, or
* beyond the end of the file.
*/
LPTR *
goto_line(n)
register int n;
{
static LPTR l;
l.index = 0;
if ( n == 0 )
l = *previous_line(end_of_file);
else {
LPTR *p;
for (l = *file_memory; --n > 0 ;l = *p)
if ((p = next_line(&l)) == NULL)
break;
}
return &l;
}
void
inschar(c)
int c;
{
register char *p, *pend;
/* make room for the new char. */
if ( ! can_increase(1) )
return;
if (current_status != STATUS_REPLACE) {
p = &cursor_char->linep->s[strlen(cursor_char->linep->s) + 1];
pend = &cursor_char->linep->s[cursor_char->index];
for (; p > pend ;p--)
*p = *(p-1);
*p = c;
} else { /* replace mode */
/*
* Once we reach the end of the line, we are effectively
* inserting new text, so make sure the string terminator
* stays out there.
*/
if (gchar(cursor_char) == '\0')
cursor_char->linep->s[cursor_char->index+1] = '\0';
pchar(cursor_char, c);
}
/*
* If we're in insert mode and show_match mode is set, then
* check for right parens and braces. If there isn't a match,
* then beep. If there is a match AND it's on the screen, then
* flash to it briefly. If it isn't on the screen, don't do anything.
*/
if (PARAMETER_VALUE(PARAMETER_SHOWMATCH) && current_status == STATUS_INSERT && (c == ')' || c == '}' || c == ']')) {
LPTR *lpos, csave;
if ((lpos = show_match()) == NULL) /* no match, so beep */
beep();
else if (LINEOF(lpos) >= LINEOF(top_char)) {
update_screen(0); /* show the new char first */
csave = *cursor_char;
*cursor_char = *lpos; /* move to matching char */
update_cursor(1);
goto_screen_pos(cursor_row, cursor_column);
loop_n_seconds(1); /* brief pause */
*cursor_char = csave; /* restore cursor position */
update_cursor(0);
}
}
inc(cursor_char);
CHANGED;
}
int
delete_char(fixpos)
int fixpos; /* if (1), fix the cursor position when done */
{
register int i;
/* Check for degenerate case; there's nothing in the file. */
if (buffer_empty())
return (0);
if (line_empty()) /* can't do anything */
return (0);
/* Delete the char. at cursor_char by shifting everything */
/* in the line down. */
for ( i=cursor_char->index+1; i < cursor_char->linep->size ;i++)
cursor_char->linep->s[i-1] = cursor_char->linep->s[i];
/* If we just took off the last character of a non-blank line, */
/* we don't want to end up positioned at the newline. */
if (fixpos) {
if (gchar(cursor_char)=='\0' && cursor_char->index>0 && current_status!=STATUS_INSERT)
cursor_char->index--;
}
CHANGED;
return (1);
}
void
delete_line(nlines, can_update)
int nlines;
int can_update;
{
register LINE *p, *q;
int doscreen; /* if true, update the screen */
doscreen = can_update;
/*
* There's no point in keeping the screen updated if we're
* deleting more than a screen's worth of lines.
*/
if (nlines > (current_lines - 1) && can_update) {
doscreen = (0);
}
while ( nlines-- > 0 ) {
if (buffer_empty()) /* nothing to delete */
break;
if (buf1line()) { /* just clear the line */
cursor_char->linep->s[0] = '\0';
cursor_char->index = 0;
break;
}
p = cursor_char->linep->prev;
q = cursor_char->linep->next;
if (p == top_of_file->linep) { /* first line of file so... */
file_memory->linep = q; /* adjust start of file */
top_char->linep = q; /* and screen */
}
p->next = q;
q->prev = p;
clear_mark(cursor_char->linep); /* clear marks for the line */
/*
* If deleting the top line on the screen, adjust top_char
*/
if (top_char->linep == cursor_char->linep)
top_char->linep = q;
free(cursor_char->linep->s);
free((char *) cursor_char->linep);
cursor_char->linep = q;
cursor_char->index = 0; /* is this right? */
CHANGED;
/* If we delete the last line in the file, back up */
if ( cursor_char->linep == end_of_file->linep) {
cursor_char->linep = cursor_char->linep->prev;
/* and don't try to delete any more lines */
break;
}
}
}