home *** CD-ROM | disk | FTP | other *** search
- /*
- * The routines in this file
- * deal with the region, that magic space
- * between "." and mark. Some functions are
- * commands. Some functions are just for
- * internal use.
- */
- #include <stdio.h>
- #include "estruct.h"
- #include "etype.h"
- #include "edef.h"
- #include "elang.h"
-
- /* regundent: undent a region.
- */
-
- PASCAL NEAR regundent(n)
- int n; /* number of spaces to undent */
-
- {
- REGION region;
- LINE *olddotp, *oldmarkp;
- int olddoto, oldmarko, infolds;
-
- /* check for a valid region first */
- if (getregion(®ion) != TRUE)
- return(FALSE);
-
- olddotp = curwp->w_dotp;
- olddoto = curwp->w_doto;
- oldmarkp = curwp->w_markp[0];
- oldmarko = curwp->w_marko[0];
-
- /* start at the top of the region.... */
- curwp->w_dotp = region.r_linep;
- curwp->w_doto = region.r_offset;
-
- region.r_size += region.r_offset;
-
- infolds = 0;
-
- /* scan the region... undenting */
- while (region.r_size > 0L) {
- region.r_size -= llength(curwp->w_dotp) + 1;
- if ((curwp->w_doto == 0) && (infolds == 0)) {
- ldelete((long)n, FALSE, FALSE, FALSE);
- curwp->w_dotp->l_lmargin -= n;
- }
- if (infolds > 0) /* line too short for calculation */
- region.r_size -=n;
- if (curwp->w_dotp->l_type == LSOEFOLD)
- infolds++;
- else if (curwp->w_dotp->l_type == LEOEFOLD)
- infolds--;
- curwp->w_dotp = lforw(curwp->w_dotp);
- curwp->w_doto = 0;
- }
-
- /* place us at the start position */
- curwp->w_dotp = olddotp;
- curwp->w_markp[0] = oldmarkp;
- if (olddotp == region.r_linep) {
- curwp->w_doto = olddoto;
- curwp->w_marko[0] = (oldmarko < n) ? 0 : oldmarko - n;
- }
- else {
- curwp->w_marko[0] = oldmarko;
- curwp->w_doto = (olddoto < n) ? 0 : olddoto - n;
- }
-
- return(TRUE);
- }
-
-
- /* reglines: how many lines in the current region
- used by the trim/entab/detab-region commands
- */
-
- int PASCAL NEAR reglines()
-
- {
- register LINE *linep; /* position while scanning */
- register int n; /* number of lines in this current region */
- REGION region;
-
- /* check for a valid region first */
- if (getrawregion(®ion) != TRUE)
- return(0);
-
- /* 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 "." to the start, and kill the characters.
- * Bound to "C-W".
- * If necessary remove any fold indentation.
- */
- PASCAL NEAR killregion(f, n)
-
- {
- register int s;
- REGION region;
- int indent;
- int setfoldbound;
-
- if (curbp->b_mode&MDVIEW) /* don't allow this command if */
- return(rdonly()); /* we are in read only mode */
-
- killedcr = TRUE;
- setfoldbound = FALSE;
-
- if (curwp->w_markp[0] == (LINE *)NULL) {
- mlwrite(TEXT76);
- /* "No mark set in this window" */
- return(FALSE);
- }
-
- /* Start & finish at left margin if at < the left margin */
- if (curwp->w_doto < curwp->w_dotp->l_lmargin)
- curwp->w_doto = curwp->w_dotp->l_lmargin;
-
- if ((curwp->w_markp[0] != (LINE *)NULL) &&
- (curwp->w_marko[0] < curwp->w_markp[0]->l_lmargin))
- curwp->w_marko[0] = curwp->w_markp[0]->l_lmargin;
-
- /* check if limits are fold lines, if so set offset to 0 */
- if (curwp->w_dotp->l_type != LNORMAL) {
- curwp->w_doto = 0;
- setfoldbound = TRUE;
- }
- if ((curwp->w_markp[0] != (LINE*)NULL) &&
- (curwp->w_markp[0]->l_type != LNORMAL)) {
- curwp->w_marko[0] = 0;
- setfoldbound = TRUE;
- }
-
- /* Don't allow the mark or dot to be on a fold marker if
- * we aren't killing whole lines.
- */
- if (curwp->w_dotp->l_type != LNORMAL) {
- if (curwp->w_marko[0] > curwp->w_markp[0]->l_lmargin)
- return(beep());
- else
- curwp->w_marko[0] = 0;
- }
-
- if (curwp->w_markp[0]->l_type != LNORMAL) {
- if (curwp->w_doto > curwp->w_dotp->l_lmargin)
- return(beep());
- else
- curwp->w_doto = 0;
- }
-
- /* call getrawregion first, cos this will check if we cross crease */
- if ((s = getrawregion(®ion)) != TRUE)
- return(s);
-
- /* Check if prefix removal required */
- indent = ((curwp->w_dotp == curwp->w_markp[0]) &&
- (curwp->w_doto >= curwp->w_dotp->l_lmargin) &&
- (curwp->w_marko[0] >= curwp->w_markp[0]->l_lmargin)) ?
- 0 : minleftmarg(curwp->w_dotp);
-
- if (indent > 0) {
- regundent(indent);
- /* recalculate the region */
- if ((s = getrawregion(®ion)) != TRUE)
- return(s);
- }
-
- if ((lastflag&CFKILL) == 0) /* This is a kill type */
- kdelete(); /* command, so do magic */
- thisflag |= CFKILL; /* kill buffer stuff. */
- curwp->w_dotp = region.r_linep;
- curwp->w_doto = region.r_offset;
- s = ldelete(region.r_size, TRUE, TRUE, FALSE);
- curwp->w_dotp->l_lmargin = minleftmarg(curwp->w_dotp);
- if (curwp->w_dotp->l_type == LNORMAL)
- marginchk(curwp->w_dotp, curwp->w_doto); /* may have killed indent */
- if (curwp->w_doto < curwp->w_dotp->l_lmargin)
- curwp->w_doto = curwp->w_dotp->l_lmargin;
- killfoldbound = setfoldbound; /* kdelete changes flag */
-
- return(s);
- }
-
- /*
- * Copy all of the characters in the
- * region to the kill buffer. Don't move dot
- * at all. This is a bit like a kill region followed
- * by a yank. Bound to "M-W".
- * We have to remove any indentation due to folds, copy and
- * then put indentation back.
- */
- PASCAL NEAR copyregion(f, n)
- {
- register LINE *linep;
- register int loffs;
- register int s;
- REGION region;
- int indent;
- int setfoldbound;
-
- setfoldbound = FALSE;
- killedcr = TRUE;
-
- /* check if limits are fold lines, if so set offset to 0 */
-
- if (curwp->w_dotp->l_type != LNORMAL) {
- curwp->w_doto = 0;
- setfoldbound = TRUE;
- }
- if ((curwp->w_markp[0] != (LINE*)NULL) &&
- (curwp->w_markp[0]->l_type != LNORMAL)) {
- curwp->w_marko[0] = 0;
- setfoldbound = TRUE;
- }
- if ((s=getrawregion(®ion)) != TRUE)
- return(s);
- if ((lastflag&CFKILL) == 0) /* Kill type command. */
- kdelete();
- thisflag |= CFKILL;
- linep = region.r_linep; /* Current line. */
- if (region.r_offset < linep->l_lmargin) { /* move to margin */
- loffs = linep->l_lmargin;
- region.r_size -= (linep->l_lmargin - region.r_offset);
- }
- else
- loffs = region.r_offset; /* Current offset. */
-
- while (region.r_size-- > 0) {
- if (loffs == llength(linep)) { /* End of line. */
- if ((s=kinsert('\r')) != TRUE)
- return(s);
- linep = linep->l_fp;
- loffs = region.r_linep->l_lmargin;
- region.r_size -= loffs;
- } else { /* Middle of line. */
- if ((s=kinsert(lgetc(linep, loffs))) != TRUE)
- return(s);
- ++loffs;
- }
- }
- killfoldbound = setfoldbound; /* kdelete changes flag */
- mlwrite(TEXT70);
- /* "[region copied]" */
- return(TRUE);
- }
-
- /*
- * 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. Bound to
- * "C-X C-L".
- */
- PASCAL NEAR lowerregion(f, n)
- {
- register LINE *linep;
- register int loffs;
- register int s;
- int c;
- REGION region;
-
- if (curbp->b_mode&MDVIEW) /* don't allow this command if */
- return(rdonly()); /* we are in read only mode */
- if ((s=getregion(®ion)) != TRUE)
- return(s);
- 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);
- c = lowerc(c);
- lputc(linep, loffs, c);
- ++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. Bound to
- * "C-X C-L".
- */
- PASCAL NEAR upperregion(f, n)
- {
- register LINE *linep;
- register int loffs;
- register int s;
- int c;
- REGION region;
-
- if (curbp->b_mode&MDVIEW) /* don't allow this command if */
- return(rdonly()); /* we are in read only mode */
- if ((s=getregion(®ion)) != TRUE)
- return(s);
- 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);
- c = upperc(c);
- lputc(linep, loffs, c);
- ++loffs;
- }
- }
- return(TRUE);
- }
-
- /* Narrow-to-region (^X-<) makes all but the current region in
- the current buffer invisable and unchangable
- */
-
- PASCAL NEAR narrow(f, n)
-
- {
- register int status; /* return status */
- BUFFER *bp; /* buffer being narrowed */
- WINDOW *wp; /* windows to fix up pointers in as well */
- REGION creg; /* region boundry structure */
- int cmark; /* current mark */
-
- /* 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(TEXT71);
- /* "%%This buffer is already narrowed" */
- return(FALSE);
- }
-
- /* find the boundries of the current region */
- if ((status=getregion(&creg)) != TRUE)
- return(status);
- curwp->w_dotp = creg.r_linep; /* only by full lines please! */
- curwp->w_doto = 0;
- creg.r_size += (long)creg.r_offset;
- if (creg.r_size <= (long)curwp->w_dotp->l_used) {
- mlwrite(TEXT72);
- /* "%%Must narrow at least 1 full line" */
- return(FALSE);
- }
-
- /* archive the top fragment */
- if (bp->b_linep->l_fp != creg.r_linep) {
- bp->b_topline = bp->b_linep->l_fp;
- creg.r_linep->l_bp->l_fp = (LINE *)NULL;
- bp->b_linep->l_fp = creg.r_linep;
- creg.r_linep->l_bp = bp->b_linep;
- }
-
- /* move forward to the end of this region
- (a long number of bytes perhaps) */
- while (creg.r_size > (long)32000) {
- forwchar(TRUE, 32000);
- creg.r_size -= (long)32000;
- }
- forwchar(TRUE, (int)creg.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 = (LINE *)NULL;
- 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 = creg.r_linep;
- wp->w_dotp = creg.r_linep;
- wp->w_doto = 0;
- for (cmark = 0; cmark < NMARKS; cmark++) {
- wp->w_markp[cmark] = creg.r_linep;
- wp->w_marko[cmark] = 0;
- }
- wp->w_flag |= (WFHARD|WFMODE);
- }
- wp = wp->w_wndp;
- }
-
- /* and now remember we are narrowed */
- bp->b_flag |= BFNAROW;
- mlwrite(TEXT73);
- /* "[Buffer is narrowed]" */
- return(TRUE);
- }
-
- /* widen-from-region (^X->) restores a narrowed region */
-
- PASCAL NEAR widen(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(TEXT74);
- /* "%%This buffer is not narrowed" */
- return(FALSE);
- }
-
- /* recover the top fragment */
- if (bp->b_topline != (LINE *)NULL) {
- lp = bp->b_topline;
- while (lp->l_fp != (LINE *)NULL)
- 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 = (LINE *)NULL;
- }
-
- /* recover the bottom fragment */
- if (bp->b_botline != (LINE *)NULL) {
- lp = bp->b_botline;
- while (lp->l_fp != (LINE *)NULL)
- 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 = (LINE *)NULL;
- }
-
- /* 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(TEXT75);
- /* "[Buffer is widened]" */
- 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 confirm thing later.
- */
-
- PASCAL NEAR getregion(rp)
-
- register REGION *rp;
-
- {
- register LINE *flp;
- register LINE *blp;
- long fsize;
- long bsize;
-
- if (curwp->w_markp[0] == (LINE *)NULL) {
- mlwrite(TEXT76);
- /* "No mark set in this window" */
- return(FALSE);
- }
- if (curwp->w_dotp == curwp->w_markp[0]) {
- rp->r_linep = curwp->w_dotp;
- if (curwp->w_doto < curwp->w_marko[0]) {
- rp->r_offset = curwp->w_doto;
- rp->r_size = (long)(curwp->w_marko[0]-curwp->w_doto);
- } else {
- rp->r_offset = curwp->w_marko[0];
- rp->r_size = (long)(curwp->w_doto-curwp->w_marko[0]);
- }
- 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[0]) {
- rp->r_linep = curwp->w_dotp;
- rp->r_offset = curwp->w_doto;
- rp->r_size = fsize+curwp->w_marko[0];
- return(TRUE);
- }
- fsize += llength(flp)+1;
- }
- if (lback(blp) != curbp->b_linep) {
- blp = lback(blp);
- bsize += llength(blp)+1;
- if (blp == curwp->w_markp[0]) {
- rp->r_linep = blp;
- rp->r_offset = curwp->w_marko[0];
- rp->r_size = bsize - curwp->w_marko[0];
- return(TRUE);
- }
- }
- }
- mlwrite(TEXT77);
- /* "Bug: lost mark" */
- return(FALSE);
- }
-
-
- /*
- * This routine figures out the bounds of the region in the current
- * window, IT DESCENDS INTO FOLDS, 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 confirm thing later.
- * This routine will return an error if an incomplete open fold is
- * within the region.
- */
-
- PASCAL NEAR getrawregion(rp)
-
- register REGION *rp;
-
- {
- register LINE *flp;
- register LINE *blp;
- long fsize;
- long bsize;
- int ffcnt, fferr, bfcnt, bferr;
-
- if (curwp->w_markp[0] == (LINE *)NULL) {
- mlwrite(TEXT76);
- /* "No mark set in this window" */
- return(FALSE);
- }
- if (curwp->w_dotp == curwp->w_markp[0]) {
- if (curwp->w_dotp->l_type != LNORMAL)
- return(beep());
- rp->r_linep = curwp->w_dotp;
- if (curwp->w_doto < curwp->w_marko[0]) {
- rp->r_offset = curwp->w_doto;
- rp->r_size = (long)(curwp->w_marko[0]-curwp->w_doto);
- } else {
- rp->r_offset = curwp->w_marko[0];
- rp->r_size = (long)(curwp->w_doto-curwp->w_marko[0]);
- }
- return(TRUE);
- }
-
- /* initialise fold error counts and markers */
- /* since search is bi-directional, errors may be virtual */
- if ((curwp->w_dotp->l_type == LSOEFOLD) ||
- (curwp->w_dotp->l_type == LSOFOLD)) {
- if (curwp->w_doto > curwp->w_dotp->l_lmargin)
- curwp->w_doto = loffset(curwp->w_dotp);
- bfcnt = 0;
- ffcnt = 1;
- bferr = fferr = FALSE;
- }
- else if (curwp->w_dotp->l_type == LEOEFOLD) {
- if (curwp->w_doto > curwp->w_dotp->l_lmargin)
- curwp->w_doto = curwp->w_dotp->l_used;
- bfcnt = 0;
- ffcnt = -1;
- bferr = FALSE;
- fferr = TRUE;
- }
- else {
- bfcnt = ffcnt = 0;
- bferr = fferr = FALSE;
- }
-
- 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 || blp->l_bp !=curbp->b_linep) {
- if (flp != curbp->b_linep) {
- flp = flp->l_fp;
- if (flp == curwp->w_markp[0]) {
- rp->r_linep = curwp->w_dotp;
- rp->r_offset = curwp->w_doto;
- rp->r_size = fsize+curwp->w_marko[0];
- if (ffcnt || fferr)
- mlwrite(TEXT232);
- /* "%%Region contains folds" */
- return(!ffcnt && !fferr);
- }
- /* going forward we don't want to check last line */
- else if ((flp->l_type == LSOEFOLD) ||
- (flp->l_type == LSOFOLD))
- ffcnt++;
- else if ((flp->l_type == LEOEFOLD) ||
- (flp->l_type == LEOFOLD))
- fferr = fferr | (--ffcnt < 0);
- fsize += llength(flp)+1;
- }
- if (blp->l_bp != curbp->b_linep) {
- blp = blp->l_bp;
- if ((blp->l_type == LSOEFOLD) ||
- (blp->l_type == LSOFOLD))
- bferr = bferr | (--bfcnt < 0);
- else if ((blp->l_type == LEOEFOLD) ||
- (blp->l_type == LEOFOLD))
- bfcnt++;
- bsize += llength(blp)+1;
- if (blp == curwp->w_markp[0]) {
- rp->r_linep = blp;
- rp->r_offset = curwp->w_marko[0];
- rp->r_size = bsize - curwp->w_marko[0];
- if (bfcnt || bferr)
- mlwrite(TEXT232);
- /* "%%Region contains folds" */
- return(!bfcnt && !bferr);
- }
- }
- }
- mlwrite(TEXT77);
- /* "Bug: lost mark" */
- return(FALSE);
- }
-
- char *PASCAL NEAR getreg() /* return some of the contents of the current region */
-
- {
- register char * sp; /* ptr into temporary buffer */
- register LINE *linep;
- register int loffs;
- register int s;
- REGION region;
- char value[NSTRING]; /* temp buffer for value */
-
- /* get the region limits */
- if ((s=getregion(®ion)) != TRUE)
- return(errorm);
- linep = region.r_linep; /* Current line. */
- loffs = region.r_offset; /* Current offset. */
-
- /* don't let the region be larger than a string can hold */
- if (region.r_size >= NSTRING)
- region.r_size = NSTRING - 1;
-
- /* scan the region, record the characters */
- sp = value;
- while (region.r_size--) {
- if (loffs == llength(linep)) { /* End of line. */
- *sp++ = '\r';
- linep = lforw(linep);
- loffs = 0;
- } else { /* Middle of line. */
- *sp++ = lgetc(linep, loffs);
- ++loffs;
- }
- }
-
- /* and return the constructed value */
- *sp = 0;
- return(value);
- }
-
-