2 * The functions in this file are a general set of line management utilities.
3 * They are the only routines that touch the text. They also touch the buffer
4 * and window structures, to make sure that the necessary updating gets done.
5 * There are routines in this file that handle the kill buffer too. It isn't
6 * here for any good reason.
8 * Note that this code only updates the dot and mark values in the window list.
9 * Since all the code acts on the current window, the buffer that we are
10 * editing must be being displayed, which means that "b_nwnd" is non zero,
11 * which means that the dot and mark values in the buffer headers are nonsense.
18 #define NBLOCK 16 /* Line block chunk size */
19 #define KBLOCK 256 /* Kill buffer block size */
21 char *kbufp
= NULL
; /* Kill buffer data */
22 int kused
= 0; /* # of bytes used in KB */
23 int ksize
= 0; /* # of bytes allocated in KB */
26 * This routine allocates a block of memory large enough to hold a LINE
27 * containing "used" characters. The block is always rounded up a bit. Return
28 * a pointer to the new block, or NULL if there isn't any memory left. Print a
29 * message in the message line if no space.
38 size
= (used
+NBLOCK
-1) & ~(NBLOCK
-1);
39 if (size
== 0) /* Assume that an empty */
40 size
= NBLOCK
; /* line is for type-in. */
41 if ((lp
= (LINE
*) malloc(sizeof(LINE
)+size
)) == NULL
) {
42 mlwrite("Cannot allocate %d bytes", size
);
51 * Delete line "lp". Fix all of the links that might point at it (they are
52 * moved to offset 0 of the next line. Unlink the line from whatever buffer it
53 * might be in. Release the memory. The buffers are updated too; the magic
54 * conditions described in the above comments don't hold here.
64 if (wp
->w_linep
== lp
)
65 wp
->w_linep
= lp
->l_fp
;
66 if (wp
->w_dotp
== lp
) {
67 wp
->w_dotp
= lp
->l_fp
;
70 if (wp
->w_markp
== lp
) {
71 wp
->w_markp
= lp
->l_fp
;
78 if (bp
->b_nwnd
== 0) {
79 if (bp
->b_dotp
== lp
) {
80 bp
->b_dotp
= lp
->l_fp
;
83 if (bp
->b_markp
== lp
) {
84 bp
->b_markp
= lp
->l_fp
;
90 lp
->l_bp
->l_fp
= lp
->l_fp
;
91 lp
->l_fp
->l_bp
= lp
->l_bp
;
96 * This routine gets called when a character is changed in place in the current
97 * buffer. It updates all of the required flags in the buffer and window
98 * system. The flag used is passed as an argument; if the buffer is being
99 * displayed in more than 1 window we change EDIT t HARD. Set MODE if the
100 * mode line needs to be updated (the "*" has to be set).
107 if (curbp
->b_nwnd
!= 1) /* Ensure hard. */
109 if ((curbp
->b_flag
&BFCHG
) == 0) { /* First change, so */
110 flag
|= WFMODE
; /* update mode lines. */
111 curbp
->b_flag
|= BFCHG
;
115 if (wp
->w_bufp
== curbp
)
122 * Insert "n" copies of the character "c" at the current location of dot. In
123 * the easy case all that happens is the text is stored in the line. In the
124 * hard case, the line has to be reallocated. When the window list is updated,
125 * take special care; I screwed it up once. You always update dot in the
126 * current window. You update mark, and a dot in another window, if it is
127 * greater than the place where you did the insert. Return TRUE if all is
128 * well, and FALSE on errors.
144 lp1
= curwp
->w_dotp
; /* Current line */
145 if (lp1
== curbp
->b_linep
) { /* At the end: special */
146 if (curwp
->w_doto
!= 0) {
147 mlwrite("bug: linsert");
150 if ((lp2
=lalloc(n
)) == NULL
) /* Allocate new line */
152 lp3
= lp1
->l_bp
; /* Previous line */
153 lp3
->l_fp
= lp2
; /* Link in */
163 doto
= curwp
->w_doto
; /* Save for later. */
164 if (lp1
->l_used
+n
> lp1
->l_size
) { /* Hard: reallocate */
165 if ((lp2
=lalloc(lp1
->l_used
+n
)) == NULL
)
167 cp1
= &lp1
->l_text
[0];
168 cp2
= &lp2
->l_text
[0];
169 while (cp1
!= &lp1
->l_text
[doto
])
172 while (cp1
!= &lp1
->l_text
[lp1
->l_used
])
174 lp1
->l_bp
->l_fp
= lp2
;
175 lp2
->l_fp
= lp1
->l_fp
;
176 lp1
->l_fp
->l_bp
= lp2
;
177 lp2
->l_bp
= lp1
->l_bp
;
179 } else { /* Easy: in place */
180 lp2
= lp1
; /* Pretend new line */
182 cp2
= &lp1
->l_text
[lp1
->l_used
];
184 while (cp1
!= &lp1
->l_text
[doto
])
187 for (i
=0; i
<n
; ++i
) /* Add the characters */
188 lp2
->l_text
[doto
+i
] = c
;
189 wp
= wheadp
; /* Update windows */
191 if (wp
->w_linep
== lp1
)
193 if (wp
->w_dotp
== lp1
) {
195 if (wp
==curwp
|| wp
->w_doto
>doto
)
198 if (wp
->w_markp
== lp1
) {
200 if (wp
->w_marko
> doto
)
209 * Insert a newline into the buffer at the current location of dot in the
210 * current window. The funny ass-backwards way it does things is not a botch;
211 * it just makes the last line in the file not a special case. Return TRUE if
212 * everything works out and FALSE on error (memory allocation failure). The
213 * update of dot and mark is a bit easier then in the above case, because the
214 * split forces more updating.
226 lp1
= curwp
->w_dotp
; /* Get the address and */
227 doto
= curwp
->w_doto
; /* offset of "." */
228 if ((lp2
=lalloc(doto
)) == NULL
) /* New first half line */
230 cp1
= &lp1
->l_text
[0]; /* Shuffle text around */
231 cp2
= &lp2
->l_text
[0];
232 while (cp1
!= &lp1
->l_text
[doto
])
234 cp2
= &lp1
->l_text
[0];
235 while (cp1
!= &lp1
->l_text
[lp1
->l_used
])
238 lp2
->l_bp
= lp1
->l_bp
;
240 lp2
->l_bp
->l_fp
= lp2
;
242 wp
= wheadp
; /* Windows */
244 if (wp
->w_linep
== lp1
)
246 if (wp
->w_dotp
== lp1
) {
247 if (wp
->w_doto
< doto
)
252 if (wp
->w_markp
== lp1
) {
253 if (wp
->w_marko
< doto
)
264 * This function deletes "n" bytes, starting at dot. It understands how do deal
265 * with end of lines, etc. It returns TRUE if all of the characters were
266 * deleted, and FALSE if they were not (because dot ran into the end of the
267 * buffer. The "kflag" is TRUE if the text should be put in the kill buffer.
281 dotp
= curwp
->w_dotp
;
282 doto
= curwp
->w_doto
;
283 if (dotp
== curbp
->b_linep
) /* Hit end of buffer. */
285 chunk
= dotp
->l_used
-doto
; /* Size of chunk. */
288 if (chunk
== 0) { /* End of line, merge. */
290 if (ldelnewline() == FALSE
291 || (kflag
!=FALSE
&& kinsert('\n')==FALSE
))
297 cp1
= &dotp
->l_text
[doto
]; /* Scrunch text. */
299 if (kflag
!= FALSE
) { /* Kill? */
301 if (kinsert(*cp1
) == FALSE
)
305 cp1
= &dotp
->l_text
[doto
];
307 while (cp2
!= &dotp
->l_text
[dotp
->l_used
])
309 dotp
->l_used
-= chunk
;
310 wp
= wheadp
; /* Fix windows */
312 if (wp
->w_dotp
==dotp
&& wp
->w_doto
>=doto
) {
314 if (wp
->w_doto
< doto
)
317 if (wp
->w_markp
==dotp
&& wp
->w_marko
>=doto
) {
318 wp
->w_marko
-= chunk
;
319 if (wp
->w_marko
< doto
)
330 * Delete a newline. Join the current line with the next line. If the next line
331 * is the magic header line always return TRUE; merging the last line with the
332 * header line can be thought of as always being a successful operation, even
333 * if nothing is done, and this makes the kill buffer work "right". Easy cases
334 * can be done by shuffling data around. Hard cases require that lines be moved
335 * about in memory. Return FALSE on error and TRUE if all looks ok. Called by
349 if (lp2
== curbp
->b_linep
) { /* At the buffer end. */
350 if (lp1
->l_used
== 0) /* Blank line. */
354 if (lp2
->l_used
<= lp1
->l_size
-lp1
->l_used
) {
355 cp1
= &lp1
->l_text
[lp1
->l_used
];
356 cp2
= &lp2
->l_text
[0];
357 while (cp2
!= &lp2
->l_text
[lp2
->l_used
])
361 if (wp
->w_linep
== lp2
)
363 if (wp
->w_dotp
== lp2
) {
365 wp
->w_doto
+= lp1
->l_used
;
367 if (wp
->w_markp
== lp2
) {
369 wp
->w_marko
+= lp1
->l_used
;
373 lp1
->l_used
+= lp2
->l_used
;
374 lp1
->l_fp
= lp2
->l_fp
;
375 lp2
->l_fp
->l_bp
= lp1
;
379 if ((lp3
=lalloc(lp1
->l_used
+lp2
->l_used
)) == NULL
)
381 cp1
= &lp1
->l_text
[0];
382 cp2
= &lp3
->l_text
[0];
383 while (cp1
!= &lp1
->l_text
[lp1
->l_used
])
385 cp1
= &lp2
->l_text
[0];
386 while (cp1
!= &lp2
->l_text
[lp2
->l_used
])
388 lp1
->l_bp
->l_fp
= lp3
;
389 lp3
->l_fp
= lp2
->l_fp
;
390 lp2
->l_fp
->l_bp
= lp3
;
391 lp3
->l_bp
= lp1
->l_bp
;
394 if (wp
->w_linep
==lp1
|| wp
->w_linep
==lp2
)
396 if (wp
->w_dotp
== lp1
)
398 else if (wp
->w_dotp
== lp2
) {
400 wp
->w_doto
+= lp1
->l_used
;
402 if (wp
->w_markp
== lp1
)
404 else if (wp
->w_markp
== lp2
) {
406 wp
->w_marko
+= lp1
->l_used
;
416 * Delete all of the text saved in the kill buffer. Called by commands when a
417 * new kill context is being created. The kill buffer array is released, just
418 * in case the buffer has grown to immense size. No errors.
423 free((char *) kbufp
);
431 * Insert a character to the kill buffer, enlarging the buffer if there isn't
432 * any room. Always grow the buffer in chunks, on the assumption that if you
433 * put something in the kill buffer you are going to put more stuff there too
434 * later. Return TRUE if all is well, and FALSE on errors.
439 register char *nbufp
;
442 if (kused
== ksize
) {
443 if ((nbufp
=(char *)malloc(ksize
+KBLOCK
)) == NULL
)
445 for (i
=0; i
<ksize
; ++i
)
448 free((char *) kbufp
);
457 * This function gets characters from the kill buffer. If the character index
458 * "n" is off the end, it returns "-1". This lets the caller just scan along
459 * until it gets a "-1" back.
467 return (kbufp
[n
] & 0xFF);