home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 4
/
FreshFish_May-June1994.bin
/
bbs
/
may94
/
util
/
edit
/
jade.lha
/
Jade
/
src
/
edit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-19
|
22KB
|
981 lines
/* edit.c -- Editing buffers
Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
This file is part of Jade.
Jade is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Jade is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jade; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "jade.h"
#include "jade_protos.h"
#include <string.h>
#include <ctype.h>
_PR bool clearlinelist(TX *);
_PR void killlinelist(TX *);
_PR LINE *resizelinelist(TX *, long, long);
_PR bool insertgap(TX *, long, const POS *);
_PR bool insertstr(TX *, const u_char *, POS *);
_PR bool insertstrn(TX *, const u_char *, long, POS *);
_PR bool insertstring(TX *, const u_char *, long, POS *);
_PR bool rectinsertstring(TX *, const u_char *, POS *);
_PR bool deletechars(TX *, const POS *, long);
_PR bool deletelines(TX *, long, long);
_PR bool deletesection(TX *, POS *, POS *);
_PR bool rectdeletesection(TX *, POS *, POS *);
_PR bool splitline(TX *, POS *);
static bool joinlines(TX *, POS *);
_PR bool padpos(TX *, POS *);
_PR bool padcursor(VW *);
_PR void orderpos(POS *, POS *);
_PR void orderrect(POS *, POS *, POS *, POS *);
_PR bool checksect(TX *, POS *, POS *);
_PR void checkpos(TX *, POS *);
_PR bool checkline(TX *, POS *);
_PR long sectionlength(TX *, POS *, POS *);
_PR void copysection(TX *, POS *, POS *, u_char *);
_PR long rectsectionlength(TX *, POS *, POS *);
_PR void rectcopysection(TX *, POS *, POS *, u_char *);
_PR bool colcopysect(TX *, long *, u_char *, long);
_PR bool posinblock(VW *, long, long);
_PR bool cursinblock(VW *);
_PR bool pageinblock(VW *);
_PR short lineinblock(VW *, long);
_PR void orderblock(VW *);
_PR void setblockrefresh(VW *);
_PR bool readonly(TX *);
#define ALLOCLL(n) mymalloc(sizeof(LINE) * (n))
#define FREELL(l) myfree(l)
/*
* This copies a line list (or part of one).
* d = destination
* s = source
* n = number of LINE's to copy.
*/
#define MOVLL(d,s,n) memcpy((d), (s), (n) * sizeof(LINE))
/*
* void
* MOVLL(LINE *dst, LINE *src, long number)
* {
* memcpy(dst, src, number * sizeof(LINE));
* }
*/
/*
* Makes file empty (null string in first line)
*/
bool
clearlinelist(TX *tx)
{
if(tx->tx_Lines)
killlinelist(tx);
tx->tx_Lines = ALLOCLL(1);
if(tx->tx_Lines)
{
tx->tx_Lines[0].ln_Line = mystrdupn("", 0);
if(tx->tx_Lines[0].ln_Line)
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)
mystrfree(line->ln_Line);
}
FREELL(tx->tx_Lines);
tx->tx_Lines = NULL;
tx->tx_NumLines = 0;
}
}
/*
* deallocates some lines (but not the list)
*/
static 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)
{
mystrfree(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.
* NOTE: You can't have a line list of zero lines.
*/
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);
}
#if 0
/*
* 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 mymalloc()'ed (or savestring()'ed)
*/
bool
stuffline(TX *tx, u_char *text, long lineNum)
{
LINE *line = tx->tx_Lines + lineNum;
if(line->ln_Strlen)
mystrfree(line->ln_Line);
line->ln_Strlen = strlen(text) + 1;
line->ln_Line = text;
return(TRUE);
}
#endif
/*
* Inserts some `space' at pos. The gap will be filled with random garbage.
* pos is *not* altered.
*/
bool
insertgap(TX *tx, long len, const POS *pos)
{
LINE *line = tx->tx_Lines + pos->pos_Line;
u_char *newline = mystralloc(len + line->ln_Strlen);
if(newline)
{
if(line->ln_Strlen)
{
memcpy(newline, line->ln_Line, pos->pos_Col);
strcpy(newline + pos->pos_Col + len, line->ln_Line + pos->pos_Col);
mystrfree(line->ln_Line);
}
else
newline[len] = 0;
line->ln_Line = newline;
line->ln_Strlen += len;
keepposaddx(tx, len, pos->pos_Col, pos->pos_Line);
return(TRUE);
}
return(FALSE);
}
/*
* Inserts a string into the current line at the cursor pos
*
* IMPORTANT: For any of the next functions which insert text the pos
* argument must not be one which will be fiddled with by the keeppos*()
* functions (specifically a direct pointer to vw_CursorPos).
*/
bool
insertstr(TX *tx, const u_char *text, POS *pos)
{
return(insertstrn(tx, text, strlen(text), pos));
}
bool
insertstrn(TX *tx, const u_char *text, long textLen, POS *pos)
{
LINE *line = tx->tx_Lines + pos->pos_Line;
if(insertgap(tx, textLen, pos))
{
memcpy(line->ln_Line + pos->pos_Col, text, textLen);
pos->pos_Col += 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(TX *tx, const u_char *text, long tabSize, POS *pos)
{
#define INSERT_BUF_LEN 128
u_char *buff = mystralloc(INSERT_BUF_LEN);
if(buff)
{
const u_char *str = text;
POS orig = *pos;
while(*str)
{
u_char c;
long i = 0;
long startx = pos->pos_Col;
while((c = *str++) && (c != '\n') && (i < INSERT_BUF_LEN))
{
if(c == '\t')
{
int numspc = tabSize - ((i + startx) % tabSize);
memset(buff + i, ' ', numspc);
i += numspc;
}
else
buff[i++] = c;
}
buff[i] = 0;
if(c == '\n')
{
if(pos->pos_Col)
{
if(!insertstrn(tx, buff, i, pos))
goto abort;
if(!splitline(tx, pos))
goto abort;
pos->pos_Col = 0;
}
else
{
u_char *copy;
if(!resizelinelist(tx, +1, pos->pos_Line))
goto abort;
if(!(copy = mystrdupn(buff, i)))
goto abort;
tx->tx_Lines[pos->pos_Line].ln_Strlen = i + 1;
tx->tx_Lines[pos->pos_Line].ln_Line = copy;
keepposaddy(tx, +1, pos->pos_Line);
}
pos->pos_Line++;
startx = 0;
}
else
{
str--;
if(!insertstrn(tx, buff, i, pos))
{
abort:
settitle(NoMemMsg);
mystrfree(buff);
return(FALSE);
}
}
}
flaginsertion(tx, &orig, pos);
mystrfree(buff);
return(TRUE);
}
settitle(NoMemMsg);
return(FALSE);
}
/*
*/
bool
rectinsertstring(TX *tx, const u_char *text, POS *pos)
{
long col = pos->pos_Col;
LINE *line = tx->tx_Lines + pos->pos_Line;
long llen = 0;
POS orig;
while(*text && (pos->pos_Line < tx->tx_NumLines))
{
const u_char *tmp = text;
while(*tmp