995
|
1 /*
|
|
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.
|
|
7 *
|
|
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.
|
|
12 */
|
|
13
|
|
14 #include <stdio.h>
|
|
15 #include "ueed.h"
|
|
16
|
|
17 #define NBLOCK 16 /* Line block chunk size */
|
|
18 #define KBLOCK 256 /* Kill buffer block size */
|
|
19
|
|
20 char *kbufp = NULL; /* Kill buffer data */
|
|
21 int kused = 0; /* # of bytes used in KB */
|
|
22 int ksize = 0; /* # of bytes allocated in KB */
|
|
23
|
|
24 /*
|
|
25 * This routine allocates a block of memory large enough to hold a LINE
|
|
26 * containing "used" characters. The block is always rounded up a bit. Return
|
|
27 * a pointer to the new block, or NULL if there isn't any memory left. Print a
|
|
28 * message in the message line if no space.
|
|
29 */
|
|
30 LINE *lalloc(used)
|
|
31 register int used;
|
|
32 {
|
|
33 register LINE *lp;
|
|
34 register int size;
|
|
35
|
|
36 size = (used+NBLOCK-1) & ~(NBLOCK-1);
|
|
37 if (size == 0) /* Assume that an empty */
|
|
38 size = NBLOCK; /* line is for type-in. */
|
|
39 if ((lp = (LINE *) malloc(sizeof(LINE)+size)) == NULL) {
|
|
40 mlwrite("Cannot allocate %d bytes", size);
|
|
41 return (NULL);
|
|
42 }
|
|
43 lp->l_size = size;
|
|
44 lp->l_used = used;
|
|
45 return (lp);
|
|
46 }
|
|
47
|
|
48 /*
|
|
49 * Delete line "lp". Fix all of the links that might point at it (they are
|
|
50 * moved to offset 0 of the next line. Unlink the line from whatever buffer it
|
|
51 * might be in. Release the memory. The buffers are updated too; the magic
|
|
52 * conditions described in the above comments don't hold here.
|
|
53 */
|
|
54 lfree(lp)
|
|
55 register LINE *lp;
|
|
56 {
|
|
57 register BUFFER *bp;
|
|
58 register WINDOW *wp;
|
|
59
|
|
60 wp = wheadp;
|
|
61 while (wp != NULL) {
|
|
62 if (wp->w_linep == lp)
|
|
63 wp->w_linep = lp->l_fp;
|
|
64 if (wp->w_dotp == lp) {
|
|
65 wp->w_dotp = lp->l_fp;
|
|
66 wp->w_doto = 0;
|
|
67 }
|
|
68 if (wp->w_markp == lp) {
|
|
69 wp->w_markp = lp->l_fp;
|
|
70 wp->w_marko = 0;
|
|
71 }
|
|
72 wp = wp->w_wndp;
|
|
73 }
|
|
74 bp = bheadp;
|
|
75 while (bp != NULL) {
|
|
76 if (bp->b_nwnd == 0) {
|
|
77 if (bp->b_dotp == lp) {
|
|
78 bp->b_dotp = lp->l_fp;
|
|
79 bp->b_doto = 0;
|
|
80 }
|
|
81 if (bp->b_markp == lp) {
|
|
82 bp->b_markp = lp->l_fp;
|
|
83 bp->b_marko = 0;
|
|
84 }
|
|
85 }
|
|
86 bp = bp->b_bufp;
|
|
87 }
|
|
88 lp->l_bp->l_fp = lp->l_fp;
|
|
89 lp->l_fp->l_bp = lp->l_bp;
|
|
90 free((char *) lp);
|
|
91 }
|
|
92
|
|
93 /*
|
|
94 * This routine gets called when a character is changed in place in the current
|
|
95 * buffer. It updates all of the required flags in the buffer and window
|
|
96 * system. The flag used is passed as an argument; if the buffer is being
|
|
97 * displayed in more than 1 window we change EDIT t HARD. Set MODE if the
|
|
98 * mode line needs to be updated (the "*" has to be set).
|
|
99 */
|
|
100 lchange(flag)
|
|
101 register int flag;
|
|
102 {
|
|
103 register WINDOW *wp;
|
|
104 if (curbp->b_nwnd != 1) /* Ensure hard. */
|
|
105 flag = WFHARD;
|
|
106 if ((curbp->b_flag&BFCHG) == 0) { /* First change, so */
|
|
107 flag |= WFMODE; /* update mode lines. */
|
|
108 curbp->b_flag |= BFCHG;
|
|
109 }
|
|
110 wp = wheadp;
|
|
111 while (wp != NULL) {
|
|
112 if (wp->w_bufp == curbp)
|
|
113 wp->w_flag |= flag;
|
|
114 wp = wp->w_wndp;
|
|
115 }
|
|
116 }
|
|
117
|
|
118 /*
|
|
119 * Insert "n" copies of the character "c" at the current location of dot. In
|
|
120 * the easy case all that happens is the text is stored in the line. In the
|
|
121 * hard case, the line has to be reallocated. When the window list is updated,
|
|
122 * take special care; I screwed it up once. You always update dot in the
|
|
123 * current window. You update mark, and a dot in another window, if it is
|
|
124 * greater than the place where you did the insert. Return TRUE if all is
|
|
125 * well, and FALSE on errors.
|
|
126 */
|
|
127 linsert(n, c)
|
|
128 {
|
|
129 register char *cp1;
|
|
130 register char *cp2;
|
|
131 register LINE *lp1;
|
|
132 register LINE *lp2;
|
|
133 register LINE *lp3;
|
|
134 register int doto;
|
|
135 register int i;
|
|
136 register WINDOW *wp;
|
|
137
|
|
138 lchange(WFEDIT);
|
|
139 lp1 = curwp->w_dotp; /* Current line */
|
|
140 if (lp1 == curbp->b_linep) { /* At the end: special */
|
|
141 if (curwp->w_doto != 0) {
|
|
142 mlwrite("bug: linsert");
|
|
143 return (FALSE);
|
|
144 }
|
|
145 if ((lp2=lalloc(n)) == NULL) /* Allocate new line */
|
|
146 return (FALSE);
|
|
147 lp3 = lp1->l_bp; /* Previous line */
|
|
148 lp3->l_fp = lp2; /* Link in */
|
|
149 lp2->l_fp = lp1;
|
|
150 lp1->l_bp = lp2;
|
|
151 lp2->l_bp = lp3;
|
|
152 for (i=0; i<n; ++i)
|
|
153 lp2->l_text[i] = c;
|
|
154 curwp->w_dotp = lp2;
|
|
155 curwp->w_doto = n;
|
|
156 return (TRUE);
|
|
157 }
|
|
158 doto = curwp->w_doto; /* Save for later. */
|
|
159 if (lp1->l_used+n > lp1->l_size) { /* Hard: reallocate */
|
|
160 if ((lp2=lalloc(lp1->l_used+n)) == NULL)
|
|
161 return (FALSE);
|
|
162 cp1 = &lp1->l_text[0];
|
|
163 cp2 = &lp2->l_text[0];
|
|
164 while (cp1 != &lp1->l_text[doto])
|
|
165 *cp2++ = *cp1++;
|
|
166 cp2 += n;
|
|
167 while (cp1 != &lp1->l_text[lp1->l_used])
|
|
168 *cp2++ = *cp1++;
|
|
169 lp1->l_bp->l_fp = lp2;
|
|
170 lp2->l_fp = lp1->l_fp;
|
|
171 lp1->l_fp->l_bp = lp2;
|
|
172 lp2->l_bp = lp1->l_bp;
|
|
173 free((char *) lp1);
|
|
174 } else { /* Easy: in place */
|
|
175 lp2 = lp1; /* Pretend new line */
|
|
176 lp2->l_used += n;
|
|
177 cp2 = &lp1->l_text[lp1->l_used];
|
|
178 cp1 = cp2-n;
|
|
179 while (cp1 != &lp1->l_text[doto])
|
|
180 *--cp2 = *--cp1;
|
|
181 }
|
|
182 for (i=0; i<n; ++i) /* Add the characters */
|
|
183 lp2->l_text[doto+i] = c;
|
|
184 wp = wheadp; /* Update windows */
|
|
185 while (wp != NULL) {
|
|
186 if (wp->w_linep == lp1)
|
|
187 wp->w_linep = lp2;
|
|
188 if (wp->w_dotp == lp1) {
|
|
189 wp->w_dotp = lp2;
|
|
190 if (wp==curwp || wp->w_doto>doto)
|
|
191 wp->w_doto += n;
|
|
192 }
|
|
193 if (wp->w_markp == lp1) {
|
|
194 wp->w_markp = lp2;
|
|
195 if (wp->w_marko > doto)
|
|
196 wp->w_marko += n;
|
|
197 }
|
|
198 wp = wp->w_wndp;
|
|
199 }
|
|
200 return (TRUE);
|
|
201 }
|