static char rcsid[] = "$Id: region.c,v 1.2 1992/12/29 00:15:46 mike Exp $"; /* $Log: region.c,v $ * Revision 1.2 1992/12/29 00:15:46 mike * - Drop a note to the user if `copyregion' succeeded. * * Revision 1.1 1992/09/05 01:13:32 mike * Initial revision * */ /* * * REGION.C MODULE * * The routines in this file deal with the region, that magic space * between two marks (usually dot and mark 0). * Some functions are commands, some functions are just for internal use. */ /* Copyright 1990, 1991, 1992 Craig Durland * Distributed under the terms of the GNU General Public License. * Distributed "as is", without warranties of any kind, but comments, * suggestions and bug reports are welcome. */ #include #include #include "me2.h" static int tankregion(); getregion(rp) Region *rp; { return get_region(id_to_mark(THE_DOT), id_to_mark(THE_MARK), rp); } /* * Cut the region and save it in the cut buffer. * Bound to "C-w". */ cutregion(f,n) { return tankregion(TRUE); } /* * Delete the region and don't save it. * Same as cutregion except the region is not saved. * It would save code to make this part of cutregion() (^U^W => don't save) * but that would make typos a real pain. */ delregion(f,n) { return tankregion(FALSE); } /* * Delete the region. Ask getregion() to figure out the bounds of the region. * Move dot to the start, and delete the characters. * If save == TRUE, do a cut: save region then delete it * If last command was a cut command add region to cut buffer * else clear cut_buffer then add region. */ static int tankregion(save) { Region region; if (getregion(®ion) == 0) return FALSE; if (save) { if ((lastflag & CFCUT) == 0) clear_bag(cut_buffer); thisflag |= CFCUT; /* this is a cut command. */ } *the_dot = region.mark; return ldelete(region.r_size,save); } /* * Copy all of the characters in the region to the cut buffer. Don't move * dot at all. This is a bit like a cut region followed by a yank. * Bound to "M-w". */ copyregion(f,n) { extern int MMask_pgm; Region region; int status; if (getregion(®ion) == 0) return FALSE; if ((lastflag & CFCUT) == 0) clear_bag(cut_buffer); thisflag |= CFCUT; status = copy_region_to_bag(®ion.mark, region.r_size, cut_buffer); if (status == TRUE && !MMask_pgm) mlwrite("[Region copied]"); return status; } /* ******************************************************************** */ /* ******************************************************************** */ /* ******************************************************************** */ /* Append text from the current buffer to a bag. * Input: * mark: pointer to a mark in the current buffer. It marks the start * of the text to be copied. * size: number of characters to copy. * bag: where to put the text. * Returns: * TRUE: Region copied to bag or hit EoB before copied all text. * FALSE: Bag overflowed, copy not completed. */ copy_region_to_bag(mark,size, bag) Mark *mark; int32 size; Bag *bag; { register Line *lp; register int chunk, offset; int s; lp = mark->line; offset = mark->offset; chunk = llength(lp) -offset; s = TRUE; while (size > 0 && s) { if (lp == BUFFER_LAST_LINE(curbp)) break; /* Hit end of buffer */ if (chunk == 0) /* end of the line == newline */ { s = bag_append(bag,"\n",1); size--; offset = 0; lp = lforw(lp); chunk = llength(lp); } else { if (chunk > size) chunk = size; s = bag_append(bag,&lp->l_text[offset],chunk); size -= chunk; chunk = 0; } } return s; } /* * Get the stats about the region between mark1 and mark2 and put the * results in rp. * Because the marks are usually very close together, we scan outward from * mark1 looking for mark2. This should save time. * Input: * mark1, mark2: Pointers to live marks in the current buffer. They * don't have to be valid (see mark.c for terms). * rp: Pointer to a region to be filled in with the stats about the region * between mark1 and mark2. * Returns: * 0 (No mark), 1 (mark1 and mark2 on same line), 2 (mark1 above * mark2), 3 (mark1 below mark2) * WARNING: * If mark1 or mark2 live in a different buffer, this routine will loop * forever. */ get_region(mark1,mark2,rp) Mark *mark1, *mark2; Region *rp; { register Line *flp, *blp, *first_line = BUFFER_FIRST_LINE(curbp), *last_line = BUFFER_LAST_LINE(curbp); register int32 fsize, bsize; int hf, hb; if (!mark1->line || !mark2->line) { mlwrite("No mark."); return 0; } if (mark1->line == mark2->line) { rp->mark.line = mark1->line; rp->mark.offset = imin(mark1->offset, mark2->offset); rp->r_size = iabs(mark1->offset -mark2->offset); rp->height = 1; return 1; } blp = flp = mark1->line; hf = hb = 1; bsize = mark1->offset; fsize = llength(flp) -bsize +1; while (TRUE) { if (flp != last_line) { flp = lforw(flp); hf++; if (flp == mark2->line) { rp->mark = *mark1; rp->r_size = fsize +mark2->offset; rp->height = hf; return 2; } fsize += llength(flp) +1; } if (blp != first_line) { blp = lback(blp); bsize += llength(blp) +1; hb++; if (blp == mark2->line) { rp->mark = *mark2; rp->r_size = bsize -mark2->offset; rp->height = hb; return 3; } } } /* never gets here */ } /* Get rectangle info about the region between mark1 and mark2. These 2 * marks locate the upper left and lower right of the rectangle. * WARNING! mark1 and mark2 MUST be live marks in the current buffer. * Returns: same as get_region(). */ get_rectangle(mark1,mark2, rp) Mark *mark1, *mark2; register Region *rp; { register int x, y, s; if ((s = get_region(mark1,mark2, rp)) == 0) return 0; x = getcol(mark1->line,mark1->offset); y = getcol(mark2->line,mark2->offset); rp->ulcol = imin(x,y); rp->width = iabs(x-y); return s; } #if 0 /* Convert a region to upper or 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. */ caseregion(lower) int lower; /* TRUE if convert region to lowercase, else uppercase */ { register Line *linep; register int loffs; register unsigned char c; Region region; if (getregion(®ion) == 0) return FALSE; lchange(WFHARD); linep = region.mark.line; loffs = region.mark.offset; while (region.r_size--) { if (loffs == llength(linep)) { linep = lforw(linep); loffs = 0; } else { c = lgetc(linep,loffs); c = lower ? tolower(c) : toupper(c); lputc(linep,loffs, c); ++loffs; } } return TRUE; } /* * Lower case region. Zap all of the upper case characters in the region to * lower case. * Bound to "C-x C-l". */ lowerregion(f,n) { return caseregion(TRUE); } /* * Upper case region. Zap all of the lower case characters in the region to * upper case. * Bound to "C-x C-u". */ upperregion(f,n) { return caseregion(FALSE); } #endif