Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!cbatt!ucbvax!ULKYVX.BITNET!RDROYA01 From: RDROYA01@ULKYVX.BITNET.UUCP Newsgroups: comp.sys.atari.st Subject: Uemail source (3 of 12) Message-ID: <8702041623.AA16202@ucbvax.Berkeley.EDU> Date: Wed, 4-Feb-87 10:06:00 EST Article-I.D.: ucbvax.8702041623.AA16202 Posted: Wed Feb 4 10:06:00 1987 Date-Received: Sat, 7-Feb-87 05:06:18 EST Sender: daemon@ucbvax.BERKELEY.EDU Organization: University of Louisville Lines: 980 # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # basic.c # buffer.c # region.c # This archive created: Tue Feb 3 17:41:14 1987 cat << \SHAR_EOF > basic.c /* * The routines in this file * move the cursor around on the screen. * They compute a new value for the cursor, then * adjust ".". The display code always updates the * cursor location, so only moves between lines, * or functions that adjust the top line in the window * and invalidate the framing, are hard. */ #include #include "ed.h" /* * Move the cursor to the * beginning of the current line * or the beginning of the last * line if already at beginning. * Trivial. */ gotobol(f, n) register int f, n; { if(curwp->w_doto == 0) backline(f, n); curwp->w_doto = 0; return (TRUE); } /* * Move the cursor backwards by * "n" characters. If "n" is less than * zero call "forwchar" to actually do the * move. Otherwise compute the new cursor * location. Error if you try and move * out of the buffer. Set the flag if the * line pointer for dot changes. */ backchar(f, n) register int f, n; { register LINE *lp; if (n < 0) return (forwchar(f, -n)); while (n--) { if (curwp->w_doto == 0) { if ((lp=lback(curwp->w_dotp)) == curbp->b_linep) return (FALSE); curwp->w_dotp = lp; curwp->w_doto = llength(lp); curwp->w_flag |= WFMOVE; } else curwp->w_doto--; } return (TRUE); } /* * Move the cursor to the end * of the current line or the * end of the next line if * dot is already at the end. * Trivial. No errors. */ gotoeol(f, n) register int f, n; { if (curwp->w_doto == llength(curwp->w_dotp)) forwline(f, n); curwp->w_doto = llength(curwp->w_dotp); return (TRUE); } /* * Move the cursor forwwards by * "n" characters. If "n" is less than * zero call "backchar" to actually do the * move. Otherwise compute the new cursor * location, and move ".". Error if you * try and move off the end of the * buffer. Set the flag if the line pointer * for dot changes. */ forwchar(f, n) register int f, n; { if (n < 0) return (backchar(f, -n)); while (n--) { if (curwp->w_doto == llength(curwp->w_dotp)) { if (curwp->w_dotp == curbp->b_linep) return (FALSE); curwp->w_dotp = lforw(curwp->w_dotp); curwp->w_doto = 0; curwp->w_flag |= WFMOVE; } else curwp->w_doto++; } return (TRUE); } /* * Goto the beginning of the buffer. * Massive adjustment of dot. This is considered * to be hard motion; it really isn't if the original * value of dot is the same as the new value of dot. * Normally bound to "M-<". */ gotobob(f, n) register int f, n; { curwp->w_dotp = lforw(curbp->b_linep); curwp->w_doto = 0; curwp->w_flag |= WFHARD; return (TRUE); } /* * Move to the end of the buffer. * Dot is always put at the end of the * file (ZJ). The standard screen code does * most of the hard parts of update. Bound to * "M->". */ gotoeob(f, n) register int f, n; { curwp->w_dotp = curbp->b_linep; curwp->w_doto = 0; curwp->w_flag |= WFHARD; return (TRUE); } /* * Move forward by full lines. * If the number of lines to move is less * than zero, call the backward line function to * actually do it. The last command controls how * the goal column is set. Bound to "C-N". No * errors are possible. */ forwline(f, n) register int f, n; { register LINE *dlp; if (n < 0) return (backline(f, -n)); if ((lastflag&CFCPCN) == 0) /* Reset goal if last */ curgoal = curcol; /* not C-P or C-N */ thisflag |= CFCPCN; dlp = curwp->w_dotp; while (n-- && dlp!=curbp->b_linep) dlp = lforw(dlp); curwp->w_dotp = dlp; curwp->w_doto = getgoal(dlp); curwp->w_flag |= WFMOVE; return (TRUE); } /* * This function is like "forwline", but * goes backwards. The scheme is exactly the same. * Check for arguments that are less than zero and * call your alternate. Figure out the new line and * call "movedot" to perform the motion. No errors * are possible. Bound to "C-P". */ backline(f, n) register int f, n; { register LINE *dlp; if (n < 0) return (forwline(f, -n)); if ((lastflag&CFCPCN) == 0) /* Reset goal if the */ curgoal = curcol; /* last isn't C-P, C-N */ thisflag |= CFCPCN; dlp = curwp->w_dotp; while (n-- && lback(dlp)!=curbp->b_linep) dlp = lback(dlp); curwp->w_dotp = dlp; curwp->w_doto = getgoal(dlp); curwp->w_flag |= WFMOVE; return (TRUE); } /* * This routine, given a pointer to * a LINE, and the current cursor goal * column, return the best choice for the * offset. The offset is returned. * Used by "C-N" and "C-P". */ getgoal(dlp) register LINE *dlp; { register int c; register int col; register int newcol; register int dbo; col = 0; dbo = 0; while (dbo != llength(dlp)) { c = lgetc(dlp, dbo); newcol = col; if (c == '\t') newcol |= 0x07; else if (c<0x20 || c==0x7F) ++newcol; ++newcol; if (newcol > curgoal) break; col = newcol; ++dbo; } return (dbo); } /* * Scroll forward by a specified number * of lines, or by a full page if no argument. * Bound to "C-V". The "2" in the arithmetic on * the window size is the overlap; this value is * the default overlap value in ITS EMACS. * Because this zaps the top line in the display * window, we have to do a hard update. */ forwpage(f, n) register int f, n; { register LINE *lp; if (f == FALSE) { n = curwp->w_ntrows - 2; /* Default scroll. */ if (n <= 0) /* Forget the overlap */ n = 1; /* if tiny window. */ } else if (n < 0) return (backpage(f, -n)); #if CVMVAS else /* Convert from pages */ n *= curwp->w_ntrows; /* to lines. */ #endif lp = curwp->w_linep; while (n-- && lp!=curbp->b_linep) lp = lforw(lp); curwp->w_linep = lp; curwp->w_dotp = lp; curwp->w_doto = 0; curwp->w_flag |= WFHARD; return (TRUE); } /* * This command is like "forwpage", * but it goes backwards. The "2", like above, * is the overlap between the two windows. The * value is from the ITS EMACS manual. Bound * to "M-V". We do a hard update for exactly * the same reason. */ backpage(f, n) register int f, n; { register LINE *lp; if (f == FALSE) { n = curwp->w_ntrows - 2; /* Default scroll. */ if (n <= 0) /* Don't blow up if the */ n = 1; /* window is tiny. */ } else if (n < 0) return (forwpage(f, -n)); #if CVMVAS else /* Convert from pages */ n *= curwp->w_ntrows; /* to lines. */ #endif lp = curwp->w_linep; while (n-- && lback(lp)!=curbp->b_linep) lp = lback(lp); curwp->w_linep = lp; curwp->w_dotp = lp; curwp->w_doto = 0; curwp->w_flag |= WFHARD; return (TRUE); } /* * Set the mark in the current window * to the value of "." in the window. No errors * are possible. Bound to "M-.". */ setmark(f, n) register int f, n; { curwp->w_markp = curwp->w_dotp; curwp->w_marko = curwp->w_doto; mlwrite("[Mark set]"); return (TRUE); } /* * Swap the values of "." and "mark" in * the current window. This is pretty easy, bacause * all of the hard work gets done by the standard routine * that moves the mark about. The only possible error is * "no mark". Bound to "C-X C-X". */ swapmark(f, n) register int f, n; { register LINE *odotp; register int odoto; if (curwp->w_markp == NULL) { mlwrite("No mark in this window"); return (FALSE); } odotp = curwp->w_dotp; odoto = curwp->w_doto; curwp->w_dotp = curwp->w_markp; curwp->w_doto = curwp->w_marko; curwp->w_markp = odotp; curwp->w_marko = odoto; curwp->w_flag |= WFMOVE; return (TRUE); } SHAR_EOF cat << \SHAR_EOF > buffer.c /* * Buffer management. * Some of the functions are internal, * and some are actually attached to user * keys. Like everyone else, they set hints * for the display system. */ #include #include "ed.h" /* USEBUFFER eXtended command. Prompt for buffer name. Store it in * external pattern lastbuf. Call selbuf() to make the change. Bound * to CTLX-B. */ usebuffer(f, n) register int f, n; { register int s; if ((s=readpattern("Use buffer [DEFAULT] ", &lastbuf)) != TRUE) return (s); return(selbuf(lastbuf)); } /* * Attach a buffer to a window. The * values of dot and mark come from the buffer * if the use count is 0. Otherwise, they come * from some other window. */ selbuf(bufname) register char *bufname; { register BUFFER *bp; register WINDOW *wp; /* Find a buffer. If the buffer does not exist, then ask the user * whether a new buffer should be created. */ if ((bp=bfind(bufname, MAYBE, 0)) == NULL) return (FALSE); strcpy(lastbuf, curbp->b_bname); /* set up for return */ if (--curbp->b_nwnd == 0) { /* Last use. */ curbp->b_dotp = curwp->w_dotp; curbp->b_doto = curwp->w_doto; curbp->b_markp = curwp->w_markp; curbp->b_marko = curwp->w_marko; } curbp = bp; /* Switch. */ curwp->w_bufp = bp; curwp->w_linep = bp->b_linep; /* For macros, ignored. */ curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty. */ if (bp->b_nwnd++ == 0) { /* First use. */ curwp->w_dotp = bp->b_dotp; curwp->w_doto = bp->b_doto; curwp->w_markp = bp->b_markp; curwp->w_marko = bp->b_marko; return (TRUE); } wp = wheadp; /* Look for old. */ while (wp != NULL) { if (wp!=curwp && wp->w_bufp==bp) { curwp->w_dotp = wp->w_dotp; curwp->w_doto = wp->w_doto; curwp->w_markp = wp->w_markp; curwp->w_marko = wp->w_marko; break; } wp = wp->w_wndp; } return (TRUE); } /* KILLBUFFER eXtended command. Prompt for buffer name. Call delbuf() * to do the actual kill. Bound to CTLX-K. */ killbuffer(f, n) register int f, n; { register int s; if ((s=readpattern("Kill buffer [DEFAULT] ", &lastbuf)) != TRUE) return (s); return(delbuf(lastbuf)); } /* * Dispose of a buffer, by name. * Look up bufname (don't get too * upset if it isn't there at all!). Get quite upset * if the buffer is being displayed. Clear the buffer (ask * if the buffer has been changed). Then free the header * line and the buffer header. */ delbuf(bufname) register char *bufname; { register BUFFER *bp; register BUFFER *bp1; register BUFFER *bp2; register int s; if ((bp=bfind(bufname, FALSE, 0)) == NULL) /* Easy if unknown.*/ return (TRUE); strcpy(lastbuf, curbp->b_bname); if (bp->b_nwnd != 0) { /* Error if on screen. */ mlwrite("Buffer is being displayed"); return (FALSE); } if ((s=bclear(bp)) != TRUE) /* Blow text away. */ return (s); free((char *) bp->b_linep); /* Release header line. */ bp1 = NULL; /* Find the header. */ bp2 = bheadp; while (bp2 != bp) { bp1 = bp2; bp2 = bp2->b_bufp; } bp2 = bp2->b_bufp; /* Next one in chain. */ if (bp1 == NULL) /* Unlink it. */ bheadp = bp2; else bp1->b_bufp = bp2; free((char *) bp); /* Release buffer block */ return (TRUE); } /* * List all of the active * buffers. First update the special * buffer that holds the list. Next make * sure at least 1 window is displaying the * buffer list, splitting the screen if this * is what it takes. Lastly, repaint all of * the windows that are displaying the * list. Bound to "C-X C-B". */ listbuffers(f, n) register int f, n; { register WINDOW *wp; register BUFFER *bp; register int s; if (blistp == NULL) { blistp = bfind("[List]", TRUE, BFTEMP); /* Buffer list buffer*/ if (blistp == NULL) return(ABORT); } if ((s=makelist()) != TRUE) return (s); if (blistp->b_nwnd == 0) { /* Not on screen yet. */ if ((wp=wpopup()) == NULL) return (FALSE); bp = wp->w_bufp; if (--bp->b_nwnd == 0) { bp->b_dotp = wp->w_dotp; bp->b_doto = wp->w_doto; bp->b_markp = wp->w_markp; bp->b_marko = wp->w_marko; } wp->w_bufp = blistp; ++blistp->b_nwnd; } wp = wheadp; while (wp != NULL) { if (wp->w_bufp == blistp) { wp->w_linep = lforw(blistp->b_linep); wp->w_dotp = lforw(blistp->b_linep); wp->w_doto = 0; wp->w_markp = NULL; wp->w_marko = 0; wp->w_flag |= WFMODE|WFHARD; } wp = wp->w_wndp; } return (TRUE); } /* * This routine rebuilds the * text in the special secret buffer * that holds the buffer list. It is called * by the list buffers command. Return TRUE * if everything works. Return FALSE if there * is an error (if there is no memory). */ makelist() { register char *cp1; register char *cp2; register int c; register BUFFER *bp; register LINE *lp; register long nbytes; register int s; register int type; char b[6+1]; char line[128]; blistp->b_flag &= ~BFCHG; /* Don't complain! */ blistp->b_bmode |= BMNWRAP; if ((s=bclear(blistp)) != TRUE) /* Blow old text away */ return (s); strcpy(blistp->b_fname, ""); if (addline(blistp,"C Size Buffer File") == FALSE || addline(blistp,"- ---- ------ ----") == FALSE) return (FALSE); bp = bheadp; /* For all buffers */ while (bp != NULL) { if ((bp->b_flag&BFTEMP) != 0) { /* Skip magic ones. */ bp = bp->b_bufp; continue; } cp1 = &line[0]; /* Start at left edge */ if ((bp->b_flag&BFCHG) != 0) /* "*" if changed */ *cp1++ = '*'; else *cp1++ = ' '; *cp1++ = ' '; /* Gap. */ nbytes = 0L; /* Count bytes in buf. */ lp = lforw(bp->b_linep); while (lp != bp->b_linep) { nbytes += llength(lp)+1; lp = lforw(lp); } ltoa(b, 6, nbytes); /* 6 digit buffer size. */ cp2 = &b[0]; while ((c = *cp2++) != 0) *cp1++ = c; *cp1++ = ' '; /* Gap. */ cp2 = &bp->b_bname[0]; /* Buffer name */ while ((c = *cp2++) != 0) *cp1++ = c; cp2 = &bp->b_fname[0]; /* File name */ if (*cp2 != 0) { while (cp1 < &line[1+1+6+1+NBUFN+1]) *cp1++ = ' '; while ((c = *cp2++) != 0) { if (cp1 < &line[128-1]) *cp1++ = c; } } *cp1 = 0; /* Add to the buffer. */ if (addline(blistp, line) == FALSE) return (FALSE); bp = bp->b_bufp; } return (TRUE); /* All done */ } ltoa(buf, width, num) register char buf[]; register int width; register long num; { buf[width] = 0; /* End of string. */ while (num >= 10L) { /* Conditional digits. */ buf[--width] = (int)(num%10L) + '0'; num /= 10L; } buf[--width] = num + '0'; /* Always 1 digit. */ while (width != 0) /* Pad with blanks. */ buf[--width] = ' '; } /* * The argument "text" points to * a string. Append this line to the * buffer "bp" (one with BFTEMP set). Handcraft the EOL * on the end. Return TRUE if it worked and * FALSE if you ran out of room. */ addline(bp, text) register BUFFER *bp; register char *text; { register LINE *lp; register int i; register int ntext; ntext = strlen(text); if ((lp=lalloc(ntext)) == NULL) return (FALSE); for (i=0; ib_linep->l_bp->l_fp = lp; /* Hook onto the end */ lp->l_bp = bp->b_linep->l_bp; bp->b_linep->l_bp = lp; lp->l_fp = bp->b_linep; if (bp->b_dotp == bp->b_linep) /* If "." is at the end */ bp->b_dotp = lp; /* move it to new line */ return (TRUE); } /* * Look through the list of * buffers. Return TRUE if there * are any changed buffers. Buffers * that hold magic internal stuff are * not considered; who cares if the * list of buffer names is hacked. * Return FALSE if no buffers * have been changed. */ anycb() { register BUFFER *bp; bp = bheadp; while (bp != NULL) { if ((bp->b_flag&BFTEMP)==0 && (bp->b_flag&BFCHG)!=0) return (TRUE); bp = bp->b_bufp; } return (FALSE); } /* * Find a buffer, by name. Return a pointer * to the BUFFER structure associated with it. If * the named buffer is found, but is a TEMP buffer (like * the buffer list) conplain. If the buffer is not found * and the "cflag" is TRUE, create it. The "bflag" is * the settings for the flags in in buffer. */ BUFFER * bfind(bname, cflag, bflag) register char *bname; register int cflag, bflag; { register BUFFER *bp; register LINE *lp; char *index(),*ptr; bp = bheadp; while (bp != NULL) { if (strcmp(bname, bp->b_bname) == 0) { if ((bp->b_flag&BFTEMP) != 0) if (cflag == FALSE) { mlwrite("Cannot select builtin buffer"); return (FALSE); } return (bp); } bp = bp->b_bufp; } /* Buffer does not exist. Prompt the user to see if a new * buffer should be created. */ if (cflag == MAYBE) { if (mlyesno("Create new buffer") != TRUE) return(FALSE); cflag = TRUE; /* yes, create it */ } if (cflag == TRUE) { if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL) return (NULL); if ((lp=lalloc(0)) == NULL) { free((char *) bp); return (NULL); } /* clear all mode flags */ bp->b_bmode &=~BMWRAP; bp->b_bmode &=~BMNWRAP; bp->b_bmode &=~BMCMODE; if (ptr=index(bname,'.')) { if (strncmp(ptr, ".mss",4)==0) bp->b_bmode |= BMWRAP; else if (strcmp(ptr,".c")==0) bp->b_bmode |= BMCMODE; else if (strcmp(ptr,".h")==0) bp->b_bmode |= BMCMODE; else bp->b_bmode |= glmode; } else bp->b_bmode |= glmode; bp->b_bufp = bheadp; bheadp = bp; bp->b_dotp = lp; bp->b_doto = 0; bp->b_markp = lp; /* All new buffers begin with mark */ bp->b_marko = 0; bp->b_flag = bflag; bp->b_nwnd = 0; bp->b_linep = lp; strcpy(bp->b_fname, ""); strcpy(bp->b_bname, bname); lp->l_fp = lp; lp->l_bp = lp; } return (bp); } /* * This routine blows away all of the text * in a buffer. If the buffer is marked as changed * then we ask if it is ok to blow it away; this is * to save the user the grief of losing text. The * window chain is nearly always wrong if this gets * called; the caller must arrange for the updates * that are required. Return TRUE if everything * looks good. */ bclear(bp) register BUFFER *bp; { register LINE *lp; register int s; if ((bp->b_flag&BFTEMP) == 0 /* Not scratch buffer. */ && (bp->b_flag&BFCHG) != 0 /* Something changed */ && (s=mlyesno("Discard changes")) != TRUE) return (s); bp->b_flag &= ~BFCHG; /* Not changed */ while ((lp=lforw(bp->b_linep)) != bp->b_linep) lfree(lp); bp->b_dotp = bp->b_linep; /* Fix "." */ bp->b_doto = 0; bp->b_markp = NULL; /* Invalidate "mark" */ bp->b_marko = 0; return (TRUE); } SHAR_EOF cat << \SHAR_EOF > region.c /* * 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 #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 f, n; { register int s; REGION region; if ((s=getregion(®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; 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 kill region followed * by a yank. Bound to "M-W". */ copyregion(f, n) register int f, n; { register LINE *linep; register int loffs; register int s; REGION region; if ((s=getregion(®ion)) != TRUE) return (s); 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 ((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); } /* * 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 int f, n; { register LINE *linep; register int loffs; register int c; register int s; REGION region; 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); if (c>='A' && c<='Z') lputc(linep, loffs, c+'a'-'A'); ++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 int f, n; { register LINE *linep; register int loffs; register int c; register int s; REGION region; 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); if (c>='a' && c<='z') lputc(linep, loffs, c-'a'+'A'); ++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) { mlwrite("No mark set in this window"); 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); } SHAR_EOF # End of shell archive exit 0 %NONAME-W-NOMSG, Message number 00000000