1 /* $OpenBSD: yank.c,v 1.10 2011/07/15 16:50:52 deraadt Exp $ */
3 /* This file is in the public domain. */
14 #define KBLOCK 256 /* Kill buffer block size. */
17 static char *kbufp = NULL; /* Kill buffer data. */
18 static RSIZE kused = 0; /* # of bytes used in KB. */
19 static RSIZE ksize = 0; /* # of bytes allocated in KB. */
20 static RSIZE kstart = 0; /* # of first used byte in KB. */
22 static int kgrow(int);
25 * Delete all of the text saved in the kill buffer. Called by commands when
26 * a new kill context is created. The kill buffer array is released, just in
27 * case the buffer has grown to an immense size. No errors.
35 kstart = kused = ksize = 0;
40 * Insert a character to the kill buffer, enlarging the buffer if there
41 * isn't any room. Always grow the buffer in chunks, on the assumption
42 * that if you put something in the kill buffer you are going to put more
43 * stuff there too later. Return TRUE if all is well, and FALSE on errors.
44 * Print a message on errors. Dir says whether to put it at back or front.
45 * This call is ignored if KNONE is set.
48 kinsert(int c, int dir)
52 if (kused == ksize && dir == KFORW && kgrow(dir) == FALSE)
54 if (kstart == 0 && dir == KBACK && kgrow(dir) == FALSE)
58 else if (dir == KBACK)
61 panic("broken kinsert call"); /* Oh shit! */
66 * kgrow - just get more kill buffer for the callee. If dir = KBACK
67 * we are trying to get space at the beginning of the kill buffer.
75 if ((unsigned)(ksize + KBLOCK) <= (unsigned)ksize) {
76 /* probably 16 bit unsigned */
77 ewprintf("Kill buffer size at maximum");
80 if ((nbufp = malloc((unsigned)(ksize + KBLOCK))) == NULL) {
81 ewprintf("Can't get %ld bytes", (long)(ksize + KBLOCK));
84 nstart = (dir == KBACK) ? (kstart + KBLOCK) : (KBLOCK / 4);
85 bcopy(&(kbufp[kstart]), &(nbufp[nstart]), (int)(kused - kstart));
90 kused = kused - kstart + nstart;
96 * This function gets characters from the kill buffer. If the character
97 * index "n" is off the end, it returns "-1". This lets the caller just
98 * scan along until it gets a "-1" back.
103 if (n < 0 || n + kstart >= kused)
105 return (CHARMASK(kbufp[n + kstart]));
109 * Copy a string into the kill buffer. kflag gives direction.
110 * if KNONE, do nothing.
113 kchunk(char *cp1, RSIZE chunk, int kflag)
116 * HACK - doesn't matter, and fixes back-over-nl bug for empty
123 while (ksize - kused < chunk)
124 if (kgrow(kflag) == FALSE)
126 bcopy(cp1, &(kbufp[kused]), (int)chunk);
128 } else if (kflag & KBACK) {
129 while (kstart < chunk)
130 if (kgrow(kflag) == FALSE)
132 bcopy(cp1, &(kbufp[kstart - chunk]), (int)chunk);
140 * Kill line. If called without an argument, it kills from dot to the end
141 * of the line, unless it is at the end of the line, when it kills the
142 * newline. If called with an argument of 0, it kills from the start of the
143 * line to dot. If called with a positive argument, it kills from dot
144 * forward over that number of newlines. If called with a negative argument
145 * it kills any text before dot on the current line, then it kills back
150 killline(int f, int n)
156 /* clear kill buffer if last wasn't a kill */
157 if ((lastflag & CFKILL) == 0)
161 for (i = curwp->w_doto; i < llength(curwp->w_dotp); ++i)
162 if ((c = lgetc(curwp->w_dotp, i)) != ' ' && c != '\t')
164 if (i == llength(curwp->w_dotp))
165 chunk = llength(curwp->w_dotp) - curwp->w_doto + 1;
167 chunk = llength(curwp->w_dotp) - curwp->w_doto;
172 chunk = llength(curwp->w_dotp) - curwp->w_doto;
173 nextp = lforw(curwp->w_dotp);
174 if (nextp != curbp->b_headp)
175 chunk++; /* newline */
176 if (nextp == curbp->b_headp)
180 chunk += llength(nextp);
181 nextp = lforw(nextp);
182 if (nextp != curbp->b_headp)
183 chunk++; /* newline */
184 if (nextp == curbp->b_headp)
189 chunk = curwp->w_doto;
193 if (lforw(curwp->w_dotp))
195 curwp->w_dotp = lback(curwp->w_dotp);
196 curwp->w_rflag |= WFMOVE;
197 chunk += llength(curwp->w_dotp);
201 * KFORW here is a bug. Should be KBACK/KFORW, but we need to
202 * rewrite the ldelete code (later)?
206 return (ldelete(chunk, KFORW));
211 * Yank text back from the kill buffer. This is really easy. All of the work
212 * is done by the standard insert routines. All you do is run the loop, and
213 * check for errors. The blank lines are inserted with a call to "newline"
214 * instead of a call to "lnewline" so that the magic stuff that happens when
215 * you type a carriage return also happens when a carriage return is yanked
216 * back from the kill buffer. An attempt has been made to fix the cosmetic
217 * bug associated with a yank when dot is on the top line of the window
218 * (nothing moves, because all of the new text landed off screen).
230 /* newline counting */
233 undo_boundary_enable(FFRAND, 0);
235 /* mark around last yank */
238 while ((c = kremove(i)) >= 0) {
240 if (newline(FFRAND, 1) == FALSE)
244 if (linsert(1, c) == FALSE)
250 /* cosmetic adjustment */
253 /* if offscreen insert */
254 if (curwp->w_dotp == lp) {
255 while (nline-- && lback(lp) != curbp->b_headp)
259 curwp->w_rflag |= WFFULL;
261 undo_boundary_enable(FFRAND, 1);