home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Black Box 4
/
BlackBox.cdr
/
progc
/
ce331src.arj
/
REGION.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-03-10
|
14KB
|
590 lines
/*
* R E G I O N . C
*
* purpose:
* The routines in this file deal with the region, that magic space
* between dot and mark. Some functions are commands. Some functions
* are just for internal use.
*/
#include <stdio.h> /* Turbo C++ verison 1.0 */
#include <dos.h>
#include <pdefs.h> /* PforCe version 1.05 (includes jwg.h) */
#include <pf_ansi.h>
#include "struct.h"
#include "def.h"
#include "protos.h"
/*
* local function prototypes
*/
static int near getregion(struct region *, int);
/**
* Get the number of lines in the current region
* (used by the Detab/Entab/Trim commands)
*
* Note the difference here from emacs 3.10 functionality. I return n = 1
* if there is no defined region, so Detab, Entab and Trim work just like
* they did in the past, i.e., they work on the current line if given no
* numeric argument.
*/
int RegionLines()
{
LINE *linep; /* position while scanning */
int n; /* number of lines in this current region */
REGION region;
/* check for a valid region first */
if (getregion(®ion, FALSE) != TRUE)
return(1); /* just do the current line */
/* start at the top of the region */
linep = region.r_linep;
region.r_size += region.r_offset;
n = 0;
/* scan the region, counting lines */
while (region.r_size > 0L)
{
region.r_size -= llength(linep) + 1;
linep = lforw(linep);
n++;
}
/* place us at the beginning of the region */
curwp->w_dotp = region.r_linep;
curwp->w_doto = region.r_offset;
return(n);
}
/**
* Kill the region. Ask "getregion" to figure out the bounds of the region.
* Move dot to the start, and kill the characters.
*/
int KillRegion(f, n)
int f, n;
{
REGION region;
if (curbp->b_mode & MDVIEW) /* don't allow this command if */
return(ReadOnly()); /* we are in read only mode */
if (!getregion(®ion, TRUE))
return(FALSE);
if ((lastflag & CFKILL) == 0) /* this is a kill type command, so do */
KDelete(); /* magic kill buffer stuff */
thisflag |= CFKILL;
curwp->w_dotp = region.r_linep;
curwp->w_doto = region.r_offset;
return(LDelete(region.r_size, TRUE));
}
/**
* Copy all of the characters in the region to the kill buffer. Don't move
* dot at all. This is a bit like a KillRegion followed by a Yank.
*/
int CopyRegion(f, n)
int f, n;
{
LINE *linep;
int loffs;
REGION region;
if (!getregion(®ion, TRUE))
return(FALSE);
if ((lastflag & CFKILL) == 0) /* kill type command */
KDelete();
thisflag |= CFKILL;
linep = region.r_linep; /* current line */
loffs = region.r_offset; /* current offset */
while (region.r_size--)
{
if (loffs == llength(linep)) /* end of line */
{
if (!KInsert('\n'))
return(FALSE);
linep = lforw(linep);
loffs = 0;
}
else /* middle of line */
{
if (!KInsert(lgetc(linep, loffs)))
return(FALSE);
++loffs;
}
}
MlWrite("Region copied");
return(TRUE);
}
/**
* Move region. Insert the characters between mark and anchor at dot.
*/
int MoveRegion(f, n)
int f, n;
{
LINE *odotp;
short odoto;
int status;
if (curwp->w_anchorp == NULLLPTR)
{
MlWrite("No anchor set in this window");
return(FALSE);
}
/*
* if you can't fix it, call it a feature
*/
if (curwp->w_dotp == curwp->w_anchorp)
{
MlWrite("Can't move within same line");
PcPutC(BELL);
return(FALSE);
}
odotp = curwp->w_dotp;
odoto = curwp->w_doto;
curwp->w_dotp = curwp->w_anchorp;
curwp->w_doto = curwp->w_anchoro;
status = KillRegion(TRUE, 1);
curwp->w_dotp = odotp;
curwp->w_doto = odoto;
if (status)
status = Yank(TRUE, 1);
return(status);
}
/**
* Lower case region. Zap all of the upper case characters in the region to
* lower case. Use the region code to set the limits. Scan the buffer, doing
* the changes. Call "LChange" to ensure that redisplay is done in all buffers.
*/
int LowerRegion(f, n)
int f, n;
{
LINE *linep;
int loffs;
int c;
REGION region;
if (curbp->b_mode & MDVIEW) /* don't allow this command if */
return(ReadOnly()); /* we are in read only mode */
if (!getregion(®ion, TRUE))
return(FALSE);
LChange(WFHARD);
linep = region.r_linep;
loffs = region.r_offset;
while (region.r_size--)
{
if (loffs == llength(linep))
{
linep = lforw(linep);
loffs = 0;
}
else
{
c = lgetc(linep, loffs);
if (c >= 'A' && c <= 'Z')
lputc(linep, loffs, (char)c ^ 0x20);
++loffs;
}
}
return(TRUE);
}
/**
* Upper case region. Zap all of the lower case characters in the region to
* upper case. Use the region code to set the limits. Scan the buffer, doing
* the changes. Call "LChange" to ensure that redisplay is done in all buffers.
*/
int UpperRegion(f, n)
int f, n;
{
LINE *linep;
int loffs;
int c;
REGION region;
if (curbp->b_mode & MDVIEW) /* don't allow this command if */
return(ReadOnly()); /* we are in read only mode */
if (!getregion(®ion, TRUE))
return(FALSE);
LChange(WFHARD);
linep = region.r_linep;
loffs = region.r_offset;
while (region.r_size--)
{
if (loffs == llength(linep))
{
linep = lforw(linep);
loffs = 0;
}
else
{
c = lgetc(linep, loffs);
if (c >= 'a' && c <= 'z')
lputc(linep, loffs, (char)c ^ 0x20);
++loffs;
}
}
return(TRUE);
}
/**
* Make all but the current region in the current buffer invisible
* and unchangable
*/
int Narrow(f, n)
int f, n;
{
int status; /* return status */
BUFFER *bp; /* buffer being narrowed */
WINDOW *wp; /* windows to fix up pointers in as well */
REGION region; /* region Boundry structure */
#if BMARKS
int bmark;
#endif
/* find the proper buffer and make sure we aren't already Narrow */
bp = curwp->w_bufp; /* find the right buffer */
if (bp->b_flag & BFNAROW)
{
MlWrite("This buffer is already narrowed");
return(FALSE);
}
/* find the boundries of the current region */
if ((status = getregion(®ion, TRUE)) != TRUE)
return(status);
curwp->w_dotp = region.r_linep; /* only by full lines please! */
curwp->w_doto = 0;
region.r_size += (long)region.r_offset;
if (region.r_size <= (long)curwp->w_dotp->l_used)
{
MlWrite("Must Narrow at least 1 full line");
return(FALSE);
}
/* archive the top fragment */
if (bp->b_linep->l_fp != region.r_linep)
{
bp->b_topline = bp->b_linep->l_fp;
region.r_linep->l_bp->l_fp = NULLLPTR;
bp->b_linep->l_fp = region.r_linep;
region.r_linep->l_bp = bp->b_linep;
}
/* move forward to the end of this region (a long number of bytes perhaps)*/
while (region.r_size > (long)32000)
{
ForwChar(TRUE, 32000);
region.r_size -= (long)32000;
}
ForwChar(TRUE, (int)region.r_size);
curwp->w_doto = 0; /* only full lines! */
/* archive the bottom fragment */
if (bp->b_linep != curwp->w_dotp)
{
bp->b_botline = curwp->w_dotp;
bp->b_botline->l_bp->l_fp = bp->b_linep;
bp->b_linep->l_bp->l_fp = NULLLPTR;
bp->b_linep->l_bp = bp->b_botline->l_bp;
}
/* let all the proper windows be updated */
wp = wheadp;
while (wp)
{
if (wp->w_bufp == bp)
{
wp->w_linep = region.r_linep;
wp->w_dotp = region.r_linep;
wp->w_doto = 0;
wp->w_markp = region.r_linep;
wp->w_marko = 0;
wp->w_anchorp = region.r_linep;
wp->w_anchoro = 0;
wp->w_fcol = 0;
#if BMARKS
for (bmark = 0; bmark < NBMARKS; bmark++)
{
wp->w_bmarkp[bmark] = region.r_linep;
wp->w_bmarko[bmark] = 0;
}
#endif
wp->w_flag |= WFHARD | WFMODE;
}
wp = wp->w_wndp;
}
/* and now remember we are narrowed */
bp->b_flag |= BFNAROW;
MlWrite("Buffer is narrowed");
return(TRUE);
}
/**
* Restore a narrowed region
*/
int Widen(f, n)
int f, n;
{
LINE *lp; /* temp line pointer */
BUFFER *bp; /* buffer being narrowed */
WINDOW *wp; /* windows to fix up pointers in as well */
/* find the proper buffer and make sure we are Narrow */
bp = curwp->w_bufp; /* find the right buffer */
if ((bp->b_flag & BFNAROW) == 0)
{
MlWrite("This buffer is not narrowed");
return(FALSE);
}
/* recover the top fragment */
if (bp->b_topline != NULLLPTR)
{
lp = bp->b_topline;
while (lp->l_fp != NULLLPTR)
lp = lp->l_fp;
lp->l_fp = bp->b_linep->l_fp;
lp->l_fp->l_bp = lp;
bp->b_linep->l_fp = bp->b_topline;
bp->b_topline->l_bp = bp->b_linep;
bp->b_topline = NULLLPTR;
}
/* recover the bottom fragment */
if (bp->b_botline != NULLLPTR)
{
lp = bp->b_botline;
while (lp->l_fp != NULLLPTR)
lp = lp->l_fp;
lp->l_fp = bp->b_linep;
bp->b_linep->l_bp->l_fp = bp->b_botline;
bp->b_botline->l_bp = bp->b_linep->l_bp;
bp->b_linep->l_bp = lp;
bp->b_botline = NULLLPTR;
}
/* let all the proper windows be updated */
wp = wheadp;
while (wp)
{
if (wp->w_bufp == bp)
wp->w_flag |= WFHARD | WFMODE;
wp = wp->w_wndp;
}
/* and now remember we are not narrowed */
bp->b_flag &= (~BFNAROW);
MlWrite("Buffer is widened");
return(TRUE);
}
/**
* Indent region one level
*/
int IndentRegion(f, n)
int f, n;
{
int curline;
short odoto;
int nlines;
int dirf = 1; /* direction flag (1=forw, -1=back) */
if (curbp->b_mode & MDVIEW) /* don't allow this command if */
return(ReadOnly()); /* we are in read only mode */
curline = GetCurLine();
odoto = curwp->w_doto;
/* swap dot and mark, plus make sure we've got a defined region */
if (!SwapMark(TRUE, 1))
return(FALSE);
/* adjust line count and direction if dot was before mark */
nlines = curline - GetCurLine();
if (nlines < 0)
{
nlines = -nlines;
dirf = -1;
}
/* make sure we leave the region defined when we're done */
discmd = FALSE;
SetMark(FALSE, 1);
discmd = TRUE;
/* insert a Tab's worth at the beginning of each line in the region */
while (nlines--)
{
GotoBOL(TRUE, 1);
if (llength(curwp->w_dotp) > 0)
{
if (!stabsize)
LInsert(1, '\t');
else
LInsert(stabsize - (GetCurCol(FALSE) % stabsize), ' ');
}
ForwLine(TRUE, dirf);
}
curwp->w_doto = odoto;
if (n > 1)
IndentRegion(TRUE, --n);
return(TRUE);
}
/**
* Undent region one level
*/
int UndentRegion(f, n)
int f, n;
{
int curline;
short odoto;
int nlines;
int dirf = 1; /* direction flag (1=forw, -1=back) */
int c;
int tsiz; /* num. spaces to del if not hard Tab */
LINE *linep;
if (curbp->b_mode & MDVIEW) /* don't allow this command if */
return(ReadOnly()); /* we are in read only mode */
curline = GetCurLine();
odoto = curwp->w_doto;
/* swap dot and mark, plus make sure we've got a defined region */
if (!SwapMark(TRUE, 1))
return(FALSE);
/* adjust line count and direction if dot was before mark */
nlines = curline - GetCurLine();
if (nlines < 0)
{
nlines = -nlines;
dirf = -1;
}
/* make sure we leave the region defined when we're done */
discmd = FALSE;
SetMark(FALSE, 1);
discmd = TRUE;
/* delete the first char (tabs or spaces only) on each line in the region */
while (nlines--)
{
GotoBOL(TRUE, 1);
linep = curwp->w_dotp;
c = lgetc(linep, 0);
if (llength(linep) > 0 && (c == '\t' || c == ' '))
{
if (c == '\t') /* if a hard Tab */
LDelete(1L, FALSE); /* delete the sucker */
else /* else we have at least one space */
{
if (!stabsize) /* using hard tabs */
tsiz = tabsize; /* max. number of spaces to delete */
else
tsiz = stabsize; /* using soft tabs (spaces) */
do
{
LDelete(1L, FALSE);
--tsiz;
} while (((c = lgetc(linep, 0)) == ' ') && tsiz);
}
}
ForwLine(TRUE, dirf);
}
curwp->w_doto = odoto;
if (n > 1)
UndentRegion(TRUE, --n);
return(TRUE);
}
/**
* This routine figures out the bounds of the region in the current window, and
* fills in the fields of the "REGION" structure pointed to by "rp". Because
* the dot and mark are usually very close together, we scan outward from dot
* looking for mark. This should save time. Return a standard code. Callers of
* this routine should be prepared to get an "ABORT" status; we might make this
* have the conform thing later.
*/
static int near getregion(rp, regcmd)
REGION *rp;
int regcmd;
{
LINE *flp;
LINE *blp;
long fsize;
long bsize;
if (curwp->w_markp == NULLLPTR)
{
if (regcmd)
MlWrite("No mark set in this window");
return(FALSE);
}
/* if dot and mark are on the same line */
if (curwp->w_dotp == curwp->w_markp)
{
rp->r_linep = curwp->w_dotp;
if (curwp->w_doto < curwp->w_marko)
{
rp->r_offset = curwp->w_doto;
rp->r_size = (long)(curwp->w_marko - curwp->w_doto);
}
else
{
rp->r_offset = curwp->w_marko;
rp->r_size = (long)(curwp->w_doto - curwp->w_marko);
}
return(TRUE);
}
blp = curwp->w_dotp;
bsize = (long)curwp->w_doto;
flp = curwp->w_dotp;
fsize = (long)(llength(flp) - curwp->w_doto + 1);
while (flp != curbp->b_linep || lback(blp) != curbp->b_linep)
{
if (flp != curbp->b_linep)
{
flp = lforw(flp);
if (flp == curwp->w_markp)
{
rp->r_linep = curwp->w_dotp;
rp->r_offset = curwp->w_doto;
rp->r_size = fsize + (long)curwp->w_marko;
return(TRUE);
}
fsize += (long)(llength(flp) + 1);
}
if (lback(blp) != curbp->b_linep)
{
blp = lback(blp);
bsize += (long)(llength(blp) + 1);
if (blp == curwp->w_markp)
{
rp->r_linep = blp;
rp->r_offset = curwp->w_marko;
rp->r_size = bsize - (long)curwp->w_marko;
return(TRUE);
}
}
}
return(FALSE);
}