/*
 * 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 "ed.h"

/*
 * 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".
 */
killregion(f, n)
{
 register int s;
 REGION  region;

 if ((s=getregion(&region)) == FALSE)
  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;
#ifdef DEUTSCH
 mlwrite( "[Bereich gelöscht]" );
#else
 mlwrite( "[Region Cut]" );
#endif
 return (ldelete(region.r_size, TRUE));
}

/*
 * Kill the region. Ask "getregion"
 * to figure out the bounds of the region.
 * Move "." to the start, and kill the characters.
 */
eraseregion(f, n)
{
 register int s;
 REGION  region;

 if ((s=getregion(&region)) == FALSE)
  return (s);
 curwp->w_dotp = region.r_linep;
 curwp->w_doto = region.r_offset;
#ifdef DEUTSCH
 mlwrite( "[Bereich gelöscht]" );
#else
 mlwrite( "[Region Cut]" );
#endif
 return (ldelete(region.r_size, FALSE));
}

/*
 * 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".
 */
copyregion(f, n)
{
 register LINE *linep;
 register int loffs;
 register int s;
 REGION  region;

 if ((s=getregion(&region)) == FALSE)
  return (s);
 if ((lastflag&CFKILL) == 0)  /* Kill type command. */
  kdelete();
 thisflag |= CFKILL;
 linep = region.r_linep;   /* Current line. */
 loffs = region.r_offset;  /* Current offset. */
#ifdef DEUTSCH
 mlwrite( "[Bereich kopiert]" );
#else
 mlwrite( "[Region Copied]" );
#endif
 while (region.r_size--) {
  if (loffs == llength(linep)) { /* End of line.  */
   if ((s=kinsert('\n')) != TRUE)
    return (s);
   linep = lforw(linep);
   loffs = 0;
  } else {   /* Middle of line. */
   if ((s=kinsert(lgetc(linep, loffs))) != TRUE)
    return (s);
   ++loffs;
  }
 }
 return (TRUE);
}

extern char cap(),ceil();

/*
 * 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".
 */
lowerregion(f, n)
{
 register LINE *linep;
 register int loffs;
 register int s;
 REGION  region;

 if ((s=getregion(&region)) == FALSE)
  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 {
   lputc(linep,loffs,ceil(lgetc(linep,loffs)));
   ++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".
 */
upperregion(f, n)
{
 register LINE *linep;
 register int loffs;
 register int s;
 REGION  region;

 if ((s=getregion(&region)) == FALSE)
  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 {
   lputc(linep,loffs,cap(lgetc(linep,loffs)));
   ++loffs;
  }
 }
 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.
 */
getregion(rp)
register REGION *rp;
{
 register LINE *flp;
 register LINE *blp;
 register int fsize;
 register int bsize;

 if (curwp->w_markp == NULL) {
#ifdef DEUTSCH
  mlwrite("Keine Marke in diesem Fenster");
#else
  mlwrite("No mark set in this window");
#endif
  return (FALSE);
 }
 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 = curwp->w_marko-curwp->w_doto;
  } else {
   rp->r_offset = curwp->w_marko;
   rp->r_size = curwp->w_doto-curwp->w_marko;
  }
  return (TRUE);
 }
 blp = curwp->w_dotp;
 bsize = curwp->w_doto;
 flp = curwp->w_dotp;
 fsize = 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+curwp->w_marko;
    return (TRUE);
   }
   fsize += llength(flp)+1;
  }
  if (lback(blp) != curbp->b_linep) {
   blp = lback(blp);
   bsize += llength(blp)+1;
   if (blp == curwp->w_markp) {
    rp->r_linep = blp;
    rp->r_offset = curwp->w_marko;
    rp->r_size = bsize - curwp->w_marko;
    return (TRUE);
   }
  }
 }
 mlwrite("Bug: lost mark");
 return (FALSE);
}

