home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
programs
/
text
/
jed
/
src
/
jed.lha
/
edit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-08
|
25KB
|
1,092 lines
/*
* EDIT.C
* (c) 1992 J.Harper
*/
#include "jed.h"
#include "jed_protos.h"
Prototype BOOL clearlinelist (TX *);
Prototype VOID killlinelist (TX *);
Prototype VOID killsomelines (TX *, LONG, LONG);
Prototype LINE * resizelinelist (TX *, LONG, LONG);
Prototype BOOL stuffline (STRPTR, LONG);
Prototype BOOL insertstr (STRPTR);
Prototype BOOL insertstrn (STRPTR, WORD);
Prototype BOOL insertstring (STRPTR, LONG);
Prototype BOOL insertsection (STRPTR);
Prototype BOOL deletechars (WORD);
Prototype BOOL deletelines (LONG);
Prototype BOOL deletesection (POS *);
Prototype BOOL splitline (VOID);
Prototype BOOL joinlines (VOID);
Prototype BOOL wrapline (VOID);
Prototype BOOL padcursor (VOID);
Prototype VOID orderpos (POS *, POS *);
Prototype BOOL getsection (STRPTR, POS *);
Prototype LONG sectionlength (POS *, POS *);
Prototype VOID copysection (POS *, POS *, STRPTR);
Prototype BOOL posinblock (WORD, LONG);
Prototype BOOL cursinblock (VOID);
Prototype BOOL pageinblock (VOID);
Prototype WORD lineinblock (LONG);
Prototype VOID orderblock (VOID);
Prototype VOID setblockrefresh (VOID);
Prototype LONG offset (VOID);
Prototype LONG size (VOID);
#define allocll(n) AllocVec(sizeof(LINE) * (n), 0L)
#define freell(l) FreeVec(l)
/*
* This macro copies a line list (or part of one).
* d = destination
* s = source
* n = number of LINE's to copy.
*/
#define movll(d,s,n) CopyMemQuick((ULONG *)(s), (ULONG *)(d), (n) << 3)
/*
* Makes file empty (null string in first line)
*/
BOOL
clearlinelist(TX *tx)
{
if(tx->tx_Lines)
killlinelist(tx);
if(tx->tx_Lines = allocll(1));
{
if(tx->tx_Lines[0].ln_Line = savestring(""))
tx->tx_Lines[0].ln_Strlen = 1;
else
tx->tx_Lines[0].ln_Strlen = 0;
tx->tx_NumLines = 1;
return(TRUE);
}
return(FALSE);
}
/*
* deallocates all lines and their list
*/
VOID
killlinelist(TX *tx)
{
if(tx->tx_Lines)
{
LINE *line;
LONG i;
for(i = 0, line = tx->tx_Lines; i < tx->tx_NumLines; i++, line++)
{
if(line->ln_Strlen)
FreeVec(line->ln_Line);
}
freell(tx->tx_Lines);
tx->tx_Lines = NULL;
tx->tx_NumLines = 0;
}
killmarklist(tx);
}
/*
* deallocates some lines (but not the list)
*/
VOID
killsomelines(TX *tx, LONG start, LONG number)
{
LINE *line = tx->tx_Lines + start;
LONG i;
for(i = 0; i < number; i++, line++)
{
if(line->ln_Strlen)
{
FreeVec(line->ln_Line);
line->ln_Strlen = 0;
line->ln_Line = NULL;
}
}
}
/*
* Creates blank entries or removes existing lines starting from line 'where'
* 'change' is the number of lines to insert, negative numbers mean delete
* that number of lines starting at the cursor line.
* If lines are deleted the actual text is also deleted.
*/
LINE *
resizelinelist(TX *tx, LONG change, LONG where)
{
LINE *newlines;
LONG newsize = tx->tx_NumLines + change;
if((newsize >= 0) && (newlines = allocll(newsize)))
{
if(tx->tx_Lines)
{
if(change > 0)
{
movll(newlines, tx->tx_Lines, where);
movll(newlines + where + change, tx->tx_Lines + where, tx->tx_NumLines - where);
}
else
{
movll(newlines, tx->tx_Lines, where);
movll(newlines + where, tx->tx_Lines + where - change, tx->tx_NumLines - where + change);
killsomelines(tx, where, -change);
}
freell(tx->tx_Lines);
}
if(change > 0)
bzero(newlines + where, change * sizeof(LINE));
tx->tx_Lines = newlines;
tx->tx_NumLines = newsize;
return(newlines);
}
return(FALSE);
}
/*
* Pastes a line into the current view at line num.
* a LINE should have been made if it is wanted.
* text is not copied, it should have been AllocVec()'ed (or savestring()'ed)
*/
BOOL
stuffline(STRPTR text, LONG lineNum)
{
LINE *line = CurrVW->vw_Tx->tx_Lines + lineNum;
if(line->ln_Strlen)
FreeVec(line->ln_Line);
line->ln_Strlen = strlen(text) + 1;
line->ln_Line = text;
return(TRUE);
}
/*
* Inserts a string into the current line at the cursor pos
*/
BOOL
insertstr(STRPTR text)
{
return(insertstrn(text, strlen(text)));
}
BOOL
insertstrn(STRPTR text, WORD textLen)
{
VW *vw = CurrVW;
TX *tx = vw->vw_Tx;
LINE *line = tx->tx_Lines + vw->vw_CursorPos.pos_Line;
STRPTR newline;
if(newline = AllocVec(textLen + line->ln_Strlen, 0L))
{
if(line->ln_Strlen)
{
memcpy(newline, line->ln_Line, vw->vw_CursorPos.pos_Col);
memcpy(newline + vw->vw_CursorPos.pos_Col, text, textLen);
strcpy(newline + vw->vw_CursorPos.pos_Col + textLen, line->ln_Line + vw->vw_CursorPos.pos_Col);
}
else
{
memcpy(newline, text, textLen);
newline[textLen] = 0;
}
stuffline(newline, vw->vw_CursorPos.pos_Line);
keepposaddx(textLen);
return(TRUE);
}
return(FALSE);
}
/*
* Inserts a null teminated string, this routine acts on any '\n' or '\t'
* characters that it finds.
* I expect that this routine will be incredibly slow.
*/
BOOL
insertstring(STRPTR text, LONG tabSize)
{
STRPTR buff = AllocVec(1024, 0L);
if(buff)
{
VW *vw = CurrVW;
STRPTR str = text;
setrefresh(RFF_LINEFROM, vw->vw_CursorPos.pos_Col, vw->vw_CursorPos.pos_Line);
while(*str)
{
UBYTE c;
LONG i = 0;
WORD startx = vw->vw_CursorPos.pos_Col;
while((c = *str++) && (c != '\n') && (i < 1024))
{
if(c == '\t')
{
WORD numspc = tabSize - ((i + startx) % tabSize);
memcpy(buff + i, Spaces, numspc);
i += numspc;
}
else
buff[i++] = c;
}
buff[i] = 0;
if(c == '\n')
{
vw->vw_RefreshType |= RFF_ALLFROM;
if(vw->vw_CursorPos.pos_Col)
{
if(!insertstrn(buff, i))
goto abort;
if(!splitline())
goto abort;
}
else
{
STRPTR copy;
if(!resizelinelist(vw->vw_Tx, +1, vw->vw_CursorPos.pos_Line))
goto abort;
if(!(copy = savestring(buff)))
goto abort;
stuffline(copy, vw->vw_CursorPos.pos_Line);
keepposaddy(+1);
}
startx = 0;
}
else
{
str--;
if(!insertstrn(buff, i))
{
abort:
settitle(NoMemMsg);
FreeVec(buff);
return(FALSE);
}
}
}
FreeVec(buff);
return(TRUE);
}
settitle(NoMemMsg);
return(FALSE);
}
/*
* Inserts a section from the text file into the current cursor position.
* You can't insert into the text that is to be inserted.
* Works out if the copied text is to be inserted before the cursor (if so
* all line numbers have to recalculated after each line is inserted).
*/
BOOL
insertsection(STRPTR sectType)
{
VW *vw = CurrVW;
TX *tx = vw->vw_Tx;
POS endpos, temp;
POS startpos = vw->vw_CursorPos;
if(getsection(sectType, &endpos))
{
BOOL copyback = FALSE;
/* If some of the next code seems totally weird it's because the
* startpos and vw_CursorPos are actually swapped with each other
* for this part :-)
*/
if(!(
((startpos.pos_Line < vw->vw_CursorPos.pos_Line) || (startpos.pos_Line > endpos.pos_Line)) ||
((startpos.pos_Line == vw->vw_CursorPos.pos_Line) && (startpos.pos_Col < vw->vw_CursorPos.pos_Col)) ||
((startpos.pos_Line == endpos.pos_Line) && (startpos.pos_Col >= endpos.pos_Col))
)){
settitle("error: can't insert into self");
vw->vw_CursorPos = startpos;
return(FALSE);
}
/* They're switched back here.
*/
temp = vw->vw_CursorPos;
vw->vw_CursorPos = startpos;
startpos = temp;
/* Test if we're copying to a line behind where we're copying from,
* this would really screw up the copy if not accounted for!
*/
if(vw->vw_CursorPos.pos_Line < startpos.pos_Line)
copyback = TRUE;
if(startpos.pos_Line == endpos.pos_Line)
{
setrefresh(RFF_LINEFROM, vw->vw_CursorPos.pos_Col, vw->vw_CursorPos.pos_Line);
return(insertstrn(tx->tx_Lines[startpos.pos_Line].ln_Line + startpos.pos_Col, endpos.pos_Col - startpos.pos_Col));
}
else
{
LONG middle;
setrefresh(RFF_ALLFROM, vw->vw_CursorPos.pos_Col, vw->vw_CursorPos.pos_Line);
if(startpos.pos_Col || vw->vw_CursorPos.pos_Col)
{
LINE *sline = tx->tx_Lines + startpos.pos_Line;
if(!insertstrn(sline->ln_Line + startpos.pos_Col, sline->ln_Strlen - startpos.pos_Col - 1))
goto abort;
if(!splitline())
goto abort;
if(copyback)
{
endpos.pos_Line++;
startpos.pos_Line += 2;
}
else
startpos.pos_Line++;
}
middle = endpos.pos_Line - startpos.pos_Line;
if(!resizelinelist(vw->vw_Tx, middle, vw->vw_CursorPos.pos_Line))
goto abort;
if(copyback)
{
endpos.pos_Line += middle;
startpos.pos_Line += middle;
}
while(startpos.pos_Line < endpos.pos_Line)
{
LINE *sline = tx->tx_Lines + startpos.pos_Line;
LINE *dline = tx->tx_Lines + vw->vw_CursorPos.pos_Line;
STRPTR copy = savestring(sline->ln_Line);
if(!copy)
goto abort;
dline->ln_Line = copy;
dline->ln_Strlen = sline->ln_Strlen;
keepposaddy(+1);
startpos.pos_Line++;
}
if(endpos.pos_Col)
{
if(!insertstrn(tx->tx_Lines[endpos.pos_Line].ln_Line, endpos.pos_Col))
{
abort:
settitle(NoMemMsg);
return(FALSE);
}
}
}
return(TRUE);
}
return(FALSE);
}
/*
* Deletes some text from the cursor pos (this line only)
*/
BOOL
deletechars(WORD size)
{
VW *vw = CurrVW;
TX *tx = vw->vw_Tx;
LINE *line = tx->tx_Lines + vw->vw_CursorPos.pos_Line;
if(line->ln_Strlen)
{
STRPTR newline;
if(size >= line->ln_Strlen)
size = line->ln_Strlen - 1;
if(newline = AllocVec(line->ln_Strlen - size, 0L))
{
strncpy(newline, line->ln_Line, vw->vw_CursorPos.pos_Col);
strcpy(newline + vw->vw_CursorPos.pos_Col, line->ln_Line + vw->vw_CursorPos.pos_Col + size);
FreeVec(line->ln_Line);
line->ln_Strlen -= size;
line->ln_Line = newline;
keeppossubx(size);
return(TRUE);
}
return(FALSE);
}
return(TRUE);
}
/*
* deletes some lines from the cursor pos
*/
BOOL
deletelines(LONG size)
{
VW *vw = CurrVW;
BOOL rc;
rc = (BOOL)resizelinelist(vw->vw_Tx, -size, vw->vw_CursorPos.pos_Line);
keeppossuby(size);
return(rc);
}
/*
* Deletes from the cursor to endPos
* sets refresh flags and resync*()'s text but doesn't call refresh().
*/
BOOL
deletesection(POS *endPos)
{
VW *vw = CurrVW;
TX *tx = vw->vw_Tx;
POS oldcurs = vw->vw_CursorPos;
if(endPos->pos_Line == vw->vw_CursorPos.pos_Line)
{
deletechars(endPos->pos_Col - vw->vw_CursorPos.pos_Col);
setrefresh(RFF_LINEFROM, oldcurs.pos_Col, oldcurs.pos_Line);
resyncx();
}
else
{
LONG middle;
BOOL joinflag = FALSE;
if(vw->vw_CursorPos.pos_Col)
{
WORD start = tx->tx_Lines[vw->vw_CursorPos.pos_Line].ln_Strlen - vw->vw_CursorPos.pos_Col - 1;
if(start)
deletechars(start);
vw->vw_CursorPos.pos_Col = 0;
vw->vw_CursorPos.pos_Line++;
joinflag = TRUE;
}
if(middle = endPos->pos_Line - vw->vw_CursorPos.pos_Line)
{
deletelines(middle);
endPos->pos_Line -= middle;
}
if(endPos->pos_Col)
deletechars(endPos->pos_Col);
if(joinflag && vw->vw_CursorPos.pos_Line)
{
vw->vw_CursorPos.pos_Line--;
vw->vw_CursorPos.pos_Col = tx->tx_Lines[vw->vw_CursorPos.pos_Line].ln_Strlen - 1;
joinlines();
}
setrefresh(RFF_ALLFROM, oldcurs.pos_Col, oldcurs.pos_Line);
resyncxy();
}
return(TRUE);
}
/*
* splits the line into two at the cursor pos
*/
BOOL
splitline(VOID)
{
VW *vw = CurrVW;
TX *tx = vw->vw_Tx;
if(resizelinelist(tx, +1, vw->vw_CursorPos.pos_Line + 1))
{
LINE *line = tx->tx_Lines + vw->vw_CursorPos.pos_Line;
STRPTR newline1;
if(newline1 = savestringn(line->ln_Line, vw->vw_CursorPos.pos_Col))
{
STRPTR newline2;
if(newline2 = savestring(line->ln_Line + vw->vw_CursorPos.pos_Col))
{
stuffline(newline1, vw->vw_CursorPos.pos_Line);
stuffline(newline2, vw->vw_CursorPos.pos_Line + 1);
keeppossplity();
return(TRUE);
}
freestring(newline1);
}
}
settitle(NoMemMsg);
return(FALSE);
}
/*
* joins the current line to the line below it.
*/
BOOL
joinlines(VOID)
{
VW *vw = CurrVW;
TX *tx = vw->vw_Tx;
if((vw->vw_CursorPos.pos_Line + 1) < tx->tx_NumLines)
{
LINE *line1 = tx->tx_Lines + vw->vw_CursorPos.pos_Line;
LINE *line2 = line1 + 1;
STRPTR newstr;
if(newstr = AllocVec(line1->ln_Strlen + line2->ln_Strlen - 1, 0L))
{
stpcpy(stpcpy(newstr, line1->ln_Line), line2->ln_Line);
resizelinelist(tx, -1, vw->vw_CursorPos.pos_Line);
stuffline(newstr, vw->vw_CursorPos.pos_Line);
keepposjoiny();
return(TRUE);
}
settitle(NoMemMsg);
}
return(FALSE);
}
/*
* Does a 'wordwrap'
*/
BOOL
wrapline(VOID)
{
VW *vw = CurrVW;
TX *tx = vw->vw_Tx;
LINE *line = tx->tx_Lines + vw->vw_CursorPos.pos_Line;
STRPTR txt = line->ln_Line + vw->vw_CursorPos.pos_Col;
while(!isspace(*txt--))
{
if(txt == line->ln_Line - 1)
return(FALSE);
}
txt++;
vw->vw_CursorPos.pos_Col = txt - line->ln_Line;
setrefresh(RFF_ALLFROM, vw->vw_CursorPos.pos_Col, vw->vw_CursorPos.pos_Line);
if(resizelinelist(tx, +1, vw->vw_CursorPos.pos_Line + 1))
{
LINE *line = tx->tx_Lines + vw->vw_CursorPos.pos_Line;
STRPTR newline1;
if(newline1 = savestringn(line->ln_Line, vw->vw_CursorPos.pos_Col))
{
STRPTR newline2;
LONG newlen = line->ln_Strlen - vw->vw_CursorPos.pos_Col - 1;
LONG indlen = 0;
LONG movlen = vw->vw_Prefs.prf_RightMargin - vw->vw_CursorPos.pos_Col - 1;
if(vw->vw_Prefs.prf_AutoIndent)
{
STRPTR spc = line->ln_Line;
while(isspace(*spc++))
indlen++;
}
else
indlen = vw->vw_Prefs.prf_LeftMargin;
movlen += indlen;
if(newline2 = AllocVec(newlen + indlen + 1, 0L))
{
STRPTR spc = newline2;
while(indlen--)
*spc++ = ' ';
memcpy(spc, line->ln_Line + vw->vw_CursorPos.pos_Col + 1, newlen);
stuffline(newline1, vw->vw_CursorPos.pos_Line);
stuffline(newline2, vw->vw_CursorPos.pos_Line + 1);
/* This next bit isn't too satisfactory.
*/
keeppossubx(line->ln_Strlen - vw->vw_CursorPos.pos_Col - 1);
keeppossplity();
if(movlen > 0)
keepposaddx(movlen);
else
keeppossubx(-movlen);
return(TRUE);
}
freestring(newline1);
}
}
settitle(NoMemMsg);
return(FALSE);
}
/*
* Inserts spaces from end of line to cursor position (for free-form editing)
*/
BOOL
padcursor(VOID)
{
VW *vw = CurrVW;
TX *tx = vw->vw_Tx;
LINE *line = tx->tx_Lines + vw->vw_CursorPos.pos_Line;
if(vw->vw_LineUndo.line != vw->vw_CursorPos.pos_Line)
{
freestring(vw->vw_LineUndo.text);
vw->vw_LineUndo.text = savestring(line->ln_Line);
vw->vw_LineUndo.line = vw->vw_CursorPos.pos_Line;
vw->vw_LineUndo.changes = tx->tx_Changes;
}
if(line->ln_Strlen < (vw->vw_CursorPos.pos_Col + 1))
{
STRPTR newline;
if(newline = AllocVec(vw->vw_CursorPos.pos_Col + 1, 0L))
{
WORD i;
strcpy(newline, line->ln_Line);
for(i = line->ln_Strlen - 1; i < vw->vw_CursorPos.pos_Col; i++)
newline[i] = ' ';
newline[i] = 0;
stuffline(newline, vw->vw_CursorPos.pos_Line);
return(TRUE);
}
settitle(NoMemMsg);
vw->vw_CursorPos.pos_Col = line->ln_Strlen - 1;
return(FALSE);
}
return(TRUE);
}
/*
* if end is before start then swap the two
*/
VOID
orderpos(POS *start, POS *end)
{
if
(
((start->pos_Line == end->pos_Line) && (start->pos_Col > end->pos_Col)) ||
(start->pos_Line > end->pos_Line)
)
{
POS temp;
temp = *start;
*start = *end;
*end = temp;
}
}
/*
* cursor is set to start of section, end to end (end is exclusive)
* types,
* b - marked Block
* c - char under Cursor
* f - whole File
* l - Line
* p - Previous character
* n - Next character
* w - word
* el - to EoL
* sl - to SoL
* ef - to EoF
* sf - to SoF
* mX - to mark X
*/
BOOL
getsection(STRPTR type, POS *end)
{
VW *vw = CurrVW;
TX *tx = vw->vw_Tx;
BOOL rc = TRUE;
switch(tolower(*type++))
{
case 'b':
if(!vw->vw_BlockStatus)
{
vw->vw_CursorPos = vw->vw_Block[0];
*end = vw->vw_Block[1];
vw->vw_BlockStatus = -1;
setblockrefresh();
}
else
rc = FALSE;
break;
case 'c':
end->pos_Col = vw->vw_CursorPos.pos_Col + 1;
end->pos_Line = vw->vw_CursorPos.pos_Line;
if(end->pos_Col >= tx->tx_Lines[end->pos_Line].ln_Strlen)
{
end->pos_Col = 0;
if(++end->pos_Line >= tx->tx_NumLines)
rc = FALSE;
}
break;
case 'f':
vw->vw_CursorPos.pos_Col = vw->vw_CursorPos.pos_Line = 0;
end->pos_Col = tx->tx_Lines[tx->tx_NumLines - 1].ln_Strlen - 1;
end->pos_Line = tx->tx_NumLines - 1;
break;
case 'l':
vw->vw_CursorPos.pos_Col = 0;
end->pos_Col = 0;
end->pos_Line = vw->vw_CursorPos.pos_Line + 1;
if(end->pos_Line >= tx->tx_NumLines)
{
end->pos_Line--;
end->pos_Col = tx->tx_Lines[end->pos_Line].ln_Strlen - 1;
}
break;
case 'p':
end->pos_Col = vw->vw_CursorPos.pos_Col--;
end->pos_Line = vw->vw_CursorPos.pos_Line;
if(vw->vw_CursorPos.pos_Col < 0)
{
if(--vw->vw_CursorPos.pos_Line < 0)
{
vw->vw_CursorPos.pos_Col++;
vw->vw_CursorPos.pos_Line++;
return(FALSE);
}
vw->vw_CursorPos.pos_Col = tx->tx_Lines[vw->vw_CursorPos.pos_Line].ln_Strlen - 1;
}
break;
case 'n':
if(++vw->vw_CursorPos.pos_Col > tx->tx_Lines[vw->vw_CursorPos.pos_Line].ln_Strlen - 1)
{
if(++vw->vw_CursorPos.pos_Line >= tx->tx_NumLines)
{
vw->vw_CursorPos.pos_Col--;
vw->vw_CursorPos.pos_Line--;
return(FALSE);
}
vw->vw_CursorPos.pos_Col = 0;
}
end->pos_Col = vw->vw_CursorPos.pos_Col + 1;
end->pos_Line = vw->vw_CursorPos.pos_Line;
if(end->pos_Col > tx->tx_Lines[end->pos_Line].ln_Strlen - 1)
{
if(++end->pos_Line >= tx->tx_NumLines)
return(FALSE);
end->pos_Col = 0;
}
break;
case 'w':
if(vw->vw_CursorPos.pos_Col < tx->tx_Lines[vw->vw_CursorPos.pos_Line].ln_Strlen)
{
STRPTR line = tx->tx_Lines[vw->vw_CursorPos.pos_Line].ln_Line;
STRPTR word = line + vw->vw_CursorPos.pos_Col;
while(isalnum(*word--))
;
word += 2;
vw->vw_CursorPos.pos_Col = word - line;
end->pos_Col = stpalnum(word) - line;
end->pos_Line = vw->vw_CursorPos.pos_Line;
rc = TRUE;
}
else
rc = FALSE;
break;
case 'e':
switch(tolower(*type++))
{
case 'f':
end->pos_Col = tx->tx_Lines[tx->tx_NumLines - 1].ln_Strlen - 1;
end->pos_Line = tx->tx_NumLines - 1;
break;
case 'l':
end->pos_Col = tx->tx_Lines[vw->vw_CursorPos.pos_Line].ln_Strlen - 1;
end->pos_Line = vw->vw_CursorPos.pos_Line;
break;
default:
rc = FALSE;
}
break;
case 's':
switch(tolower(*type++))
{
case 'f':
*end = vw->vw_CursorPos;
vw->vw_CursorPos.pos_Col = vw->vw_CursorPos.pos_Line = 0;
break;
case 'l':
*end = vw->vw_CursorPos;
vw->vw_CursorPos.pos_Col = 0;
break;
default:
rc = FALSE;
}
break;
case 'm':
APTR dummy;
MARK *mk;
WORD mknum = strtol(type, &dummy, 0);
for(mk = (MARK *)tx->tx_Marks.mlh_Head; mk->mk_Node.mln_Succ; mk = (MARK *)mk->mk_Node.mln_Succ)
{
if(mk->mk_Index == mknum)
break;
}
if(mk->mk_Node.mln_Succ)
{
*end = mk->mk_Pos;
if(end->pos_Line >= tx->tx_NumLines)
end->pos_Line = tx->tx_NumLines - 1;
if(end->pos_Col >= tx->tx_Lines[end->pos_Line].ln_Strlen)
end->pos_Col = tx->tx_Lines[end->pos_Line].ln_Strlen - 1;
orderpos(&vw->vw_CursorPos, end);
}
else
{
settitlefmt("error: mark %ld is not set", mknum);
rc = FALSE;
}
break;
default:
settitle("error: invalid section specification");
rc = FALSE;
break;
}
return(rc);
}
/*
* Returns the number of bytes needed to store a section, doesn't include
* a zero terminator but does include all newline chars.
*/
LONG
sectionlength(POS *startPos, POS *endPos)
{
LONG linenum = startPos->pos_Line;
LINE *line = CurrVW->vw_Tx->tx_Lines + linenum;
LONG length;
if(startPos->pos_Line == endPos->pos_Line)
length = endPos->pos_Col - startPos->pos_Col;
else
{
length = line->ln_Strlen - startPos->pos_Col;
linenum++;
line++;
while(linenum < endPos->pos_Line)
{
length += line->ln_Strlen;
linenum++;
line++;
}
length += endPos->pos_Col;
}
return(length);
}
/*
* Copies a section to a buffer.
* end of copy does NOT have a zero appended to it.
*/
VOID
copysection(POS *startPos, POS *endPos, STRPTR buff)
{
LONG linenum = startPos->pos_Line;
LINE *line = CurrVW->vw_Tx->tx_Lines + linenum;
LONG copylen;
if(startPos->pos_Line == endPos->pos_Line)
{
copylen = endPos->pos_Col - startPos->pos_Col;
memcpy(buff, line->ln_Line + startPos->pos_Col, copylen);
buff[copylen] = 0;
}
else
{
copylen = line->ln_Strlen - startPos->pos_Col - 1;
memcpy(buff, line->ln_Line + startPos->pos_Col, copylen);
buff[copylen] = '\n';
buff += copylen + 1;
linenum++;
line++;
while(linenum < endPos->pos_Line)
{
copylen = line->ln_Strlen - 1;
memcpy(buff, line->ln_Line, copylen);
buff[copylen] = '\n';
buff += copylen + 1;
linenum++;
line++;
}
memcpy(buff, line->ln_Line, endPos->pos_Col);
}
}
/*
* returns TRUE if the specified position is inside a block
*/
BOOL
posinblock(WORD col, LONG line)
{
VW *vw = CurrVW;
if
(
(vw->vw_BlockStatus) ||
(line < vw->vw_Block[0].pos_Line) ||
((line == vw->vw_Block[0].pos_Line) && (col < vw->vw_Block[0].pos_Col))
)
return(FALSE);
if
(
(line < vw->vw_Block[1].pos_Line) ||
((line == vw->vw_Block[1].pos_Line) && (col < vw->vw_Block[1].pos_Col))
)
return(TRUE);
return(FALSE);
}
BOOL
cursinblock(VOID)
{
VW *vw = CurrVW;
return(posinblock(vw->vw_CursorPos.pos_Col, vw->vw_CursorPos.pos_Line));
}
BOOL
pageinblock(VOID)
{
VW *vw = CurrVW;
if
(
(vw->vw_BlockStatus) ||
(vw->vw_Block[1].pos_Line < vw->vw_StartLine) ||
(vw->vw_Block[0].pos_Line >= vw->vw_StartLine + vw->vw_MaxY)
)
return(FALSE);
return(TRUE);
}
/*
* these returns,
*
* 0 line not in block
* 1 whole line in block
* 2 start of line in block
* 3 end of line in block
* 4 middle of line in block
*
* note:
* this isn't very intelligent (but it works :-).
*/
WORD
lineinblock(LONG line)
{
VW *vw = CurrVW;
BOOL startin = FALSE;
BOOL endin = FALSE;
if
(
(vw->vw_BlockStatus) ||
(line < vw->vw_Block[0].pos_Line) ||
(line > vw->vw_Block[1].pos_Line)
)
return(0);
if(line == vw->vw_Block[1].pos_Line)
startin = TRUE;
if(line == vw->vw_Block[0].pos_Line)
endin = TRUE;
if(startin)
{
if(endin)
return(4);
return(2);
}
if(endin)
return(3);
return(1);
}
/*
* makes sure that the marked block is valid
*/
VOID
orderblock(VOID)
{
VW *vw = CurrVW;
LINE *fline = vw->vw_Tx->tx_Lines;
if(!vw->vw_BlockStatus)
{
if(vw->vw_Block[0].pos_Col >= fline[vw->vw_Block[0].pos_Line].ln_Strlen)
vw->vw_Block[0].pos_Col = fline[vw->vw_Block[0].pos_Line].ln_Strlen - 1;
if(vw->vw_Block[1].pos_Col >= fline[vw->vw_Block[1].pos_Line].ln_Strlen)
vw->vw_Block[1].pos_Col = fline[vw->vw_Block[1].pos_Line].ln_Strlen - 1;
if(vw->vw_Block[0].pos_Line > vw->vw_Block[1].pos_Line)
{
POS temp = vw->vw_Block[1];
vw->vw_Block[1] = vw->vw_Block[0];
vw->vw_Block[0] = temp;
}
else if(vw->vw_Block[0].pos_Line == vw->vw_Block[1].pos_Line)
{
if(vw->vw_Block[0].pos_Col > vw->vw_Block[1].pos_Col)
{
POS temp = vw->vw_Block[1];
vw->vw_Block[1] = vw->vw_Block[0];
vw->vw_Block[0] = temp;
}
}
}
}
/*
* Set up the refresh flags to refresh the block in the most efficient manner.
* To make it better I'll have to add a refresh type which allows you to say
* where to stop drawing.
*/
VOID
setblockrefresh(VOID)
{
VW *vw = CurrVW;
LONG endline = vw->vw_StartLine + vw->vw_MaxY;
WORD refx;
LONG refy;
if((vw->vw_Block[0].pos_Line > endline) || (vw->vw_Block[1].pos_Line < vw->vw_StartLine))
return;
if(vw->vw_Block[0].pos_Line < vw->vw_StartLine)
{
refy= vw->vw_StartLine;
refx = 0;
}
else
{
refy = vw->vw_Block[0].pos_Line;
refx = vw->vw_Block[0].pos_Col;
}
if(vw->vw_Block[0].pos_Line == vw->vw_Block[1].pos_Line)
setrefresh(RFF_LINEFROM, refx, refy);
else
setrefresh(RFF_ALLFROM, refx, refy);
}
/*
* Returns the number of bytes from the start of the file that the cursor
* is.
*/
LONG
offset(VOID)
{
VW *vw = CurrVW;
LINE *line = vw->vw_Tx->tx_Lines;
LONG linenum = 0;
LONG off = 0;
while(linenum < vw->vw_CursorPos.pos_Line)
{
off += line->ln_Strlen;
line++;
linenum++;
}
off += vw->vw_CursorPos.pos_Col;
return(off);
}
/*
* Returns the number of bytes in the file
*/
LONG
size(VOID)
{
TX *tx = CurrVW->vw_Tx;
LINE *line = tx->tx_Lines;
LONG linenum = 0;
LONG size = 0;
while(linenum < tx->tx_NumLines)
{
size += line->ln_Strlen;
line++;
linenum++;
}
return(size);
}