blob: a746a74401e6fe011905d32c05e589a82b74d29f [file] [log] [blame]
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001/**************************************************************************
2 * cut.c *
3 * *
4 * Copyright (C) 1999 Chris Allegretta *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 1, or (at your option) *
8 * any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software *
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
18 * *
19 **************************************************************************/
20
21#include <stdlib.h>
22#include <string.h>
23#include <stdio.h>
24#include "config.h"
25#include "proto.h"
26#include "nano.h"
27
28#ifndef NANO_SMALL
29#include <libintl.h>
30#define _(string) gettext(string)
31#else
32#define _(string) (string)
33#endif
34
35static int marked_cut; /* Is the cutbuffer from a mark */
36static filestruct *cutbottom = NULL; /* Pointer to end of cutbuffer */
37
38void add_to_cutbuffer(filestruct * inptr)
39{
40 filestruct *tmp;
41
42#ifdef DEBUG
43 fprintf(stderr, _("add_to_cutbuffer called with inptr->data = %s\n"),
44 inptr->data);
45#endif
46
Robert Siemborskiea19c732000-06-09 00:52:26 +000047 totsize -= strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000048 tmp = cutbuffer;
49 if (cutbuffer == NULL) {
50 cutbuffer = inptr;
51 inptr->prev = NULL;
52 } else {
53 cutbottom->next = inptr;
54 inptr->prev = cutbottom;
55 }
56
57 inptr->next = NULL;
58 cutbottom = inptr;
59}
60
61#ifndef NANO_SMALL
62void cut_marked_segment(filestruct * top, int top_x, filestruct * bot,
63 int bot_x)
64{
65 filestruct *tmp, *next;
66 char *tmpstr;
67
68 /* Set up the beginning of the cutbuffer */
69 tmp = copy_node(top);
70 tmpstr = nmalloc(strlen(&top->data[top_x]) + 1);
71 strcpy(tmpstr, &top->data[top_x]);
72 free(tmp->data);
73 tmp->data = tmpstr;
74
75 /* Chop off the end of the first line */
76 tmpstr = nmalloc(top_x + 1);
77 strncpy(tmpstr, top->data, top_x);
78 free(top->data);
79 top->data = tmpstr;
80
81 do {
82 next = tmp->next;
83 add_to_cutbuffer(tmp);
84 totlines--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +000085 totsize--; /* newline (add_to_cutbuffer doesn't count newlines) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000086 tmp = next;
87 }
88 while (next != bot && next != NULL);
89
90 dump_buffer(cutbuffer);
91 if (next == NULL)
92 return;
93 /* Now, paste bot[bot_x] into top[top_x] */
94 tmpstr = nmalloc(strlen(top->data) + strlen(&bot->data[bot_x]));
95 strncpy(tmpstr, top->data, top_x);
96 strcpy(&tmpstr[top_x], &bot->data[bot_x]);
97 free(top->data);
98 top->data = tmpstr;
99
100 bot->data[bot_x] = 0;
101 align(&bot->data);
102 next = bot->next;
103
104 /* We explicitly don't decrement totlines here because we don't snarf
Robert Siemborskiea19c732000-06-09 00:52:26 +0000105 * up a newline when we're grabbing the last line of the mark. For
106 * the same reason we don't do an extra totsize decrement */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000107
108 add_to_cutbuffer(bot);
109 top->next = next;
110 if (next != NULL)
111 next->prev = top;
112
113 dump_buffer(cutbuffer);
114 renumber(top);
115 current = top;
116 current_x = top_x;
117
118 /* If we're hitting the end of the buffer we should clean that up. */
119 if (bot == filebot) {
120 if (next != NULL) {
121 filebot = next;
122 } else {
123 filebot = top;
124 }
125 }
126 if (top->lineno < edittop->lineno)
127 edit_update(top);
128}
129#endif
130
131int do_cut_text(void)
132{
133 filestruct *tmp, *fileptr = current;
134#ifndef NANO_SMALL
135 char *tmpstr;
136 int newsize;
137#endif
138
139 if (fileptr == NULL || fileptr->data == NULL)
140 return 0;
141
142 tmp = fileptr->next;
143
144 if (!ISSET(KEEP_CUTBUFFER) || ISSET(MARK_ISSET)) {
145 free_filestruct(cutbuffer);
146 cutbuffer = NULL;
147#ifdef DEBUG
148 fprintf(stderr, _("Blew away cutbuffer =)\n"));
149#endif
150 }
151#ifndef NANO_SMALL
152 if (ISSET(MARK_ISSET)) {
153 if (current->lineno == mark_beginbuf->lineno) {
154 tmp = copy_node(current);
155 newsize = abs(strlen(&current->data[mark_beginx]) -
156 strlen(&current->data[current_x]));
157
158 tmpstr = nmalloc(newsize);
159 if (current_x < mark_beginx) {
160 strncpy(tmpstr, &current->data[current_x], newsize);
161 memmove(&current->data[current_x],
162 &current->data[mark_beginx],
163 strlen(&current->data[mark_beginx] - newsize));
164 } else {
165 strncpy(tmpstr, &current->data[mark_beginx], newsize);
166 memmove(&current->data[mark_beginx],
167 &current->data[current_x],
168 strlen(&current->data[current_x] - newsize));
169 current_x = mark_beginx;
170 update_cursor();
171 }
172 tmpstr[newsize] = 0;
173 tmp->data = tmpstr;
174 add_to_cutbuffer(tmp);
175 dump_buffer(cutbuffer);
176 align(&current->data);
177 } else if (current->lineno < mark_beginbuf->lineno)
178 cut_marked_segment(current, current_x, mark_beginbuf,
179 mark_beginx);
180 else
181 cut_marked_segment(mark_beginbuf, mark_beginx, current,
182 current_x);
183
184 placewewant = xplustabs();
185 UNSET(MARK_ISSET);
186 marked_cut = 1;
187 set_modified();
Robert Siemborskiea19c732000-06-09 00:52:26 +0000188 edit_update(current);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000189 return 1;
190#else
191 if (0) {
192#endif
193 } else if (fileptr == fileage) {
194 /* we're cutting the first line */
195 if (fileptr->next != NULL) {
196 fileptr = fileptr->next;
197 tmp = fileptr;
198 fileage = fileptr;
199 add_to_cutbuffer(fileptr->prev);
Robert Siemborski66b0fc52000-07-04 21:29:24 +0000200 totsize--; /* get the newline */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000201 totlines--;
202 fileptr->prev = NULL;
203 edit_update(fileage);
204 current = fileptr;
205 } else {
206 add_to_cutbuffer(fileptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000207 fileage = make_new_node(NULL);
208 fileage->data = nmalloc(1);
Robert Siemborskiea19c732000-06-09 00:52:26 +0000209 fileage->data[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000210 current = fileage;
211 }
212 } else {
213 if (fileptr->prev != NULL)
214 fileptr->prev->next = fileptr->next;
215
216 if (fileptr->next != NULL) {
217 (fileptr->next)->prev = fileptr->prev;
218 current = fileptr->next;
219 totlines--;
Robert Siemborski66b0fc52000-07-04 21:29:24 +0000220 totsize--; /* get the newline */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000221 } else {
222 /* we're deleteing the last line
223 and replacing it with a dummy line,
224 so totlines is the same */
225 tmp = fileptr->prev;
226 tmp->next = make_new_node(tmp);
227 tmp = tmp->next;
228 tmp->data = nmalloc(1);
229 strcpy(tmp->data, "");
230 current = tmp;
231 filebot = tmp;
232 }
233
234 add_to_cutbuffer(fileptr);
235 }
236
237 if (fileptr == edittop)
238 edittop = current;
239
240 edit_refresh();
241
242 dump_buffer(cutbuffer);
243 reset_cursor();
244
245 set_modified();
246 marked_cut = 0;
247 current_x = 0;
248 placewewant = 0;
249 update_cursor();
250 renumber(tmp);
251 SET(KEEP_CUTBUFFER);
252 return 1;
253}
254
255int do_uncut_text(void)
256{
257 filestruct *tmp = current, *fileptr = current, *newbuf, *newend;
258#ifndef NANO_SMALL
259 char *tmpstr, *tmpstr2;
260#endif
261 int i;
262
263 wrap_reset();
264 if (cutbuffer == NULL || fileptr == NULL)
265 return 0; /* AIEEEEEEEEEEEE */
266
267 newbuf = copy_filestruct(cutbuffer);
268 for (newend = newbuf; newend->next != NULL && newend != NULL;
269 newend = newend->next) {
270 totlines++;
271 }
272
273 /* Hook newbuf into fileptr */
274#ifndef NANO_SMALL
275 if (marked_cut == 1) {
276 /* If there's only one line in the cutbuffer */
277 if (cutbuffer->next == NULL) {
278 tmpstr =
279 nmalloc(strlen(current->data) + strlen(cutbuffer->data) +
280 1);
281 strncpy(tmpstr, current->data, current_x);
282 strcpy(&tmpstr[current_x], cutbuffer->data);
283 strcat(tmpstr, &current->data[current_x]);
284 free(current->data);
285 current->data = tmpstr;
286 current_x += strlen(cutbuffer->data);
287 totsize += strlen(cutbuffer->data);
288
289 placewewant = xplustabs();
290 update_cursor();
291 renumber(current);
292 } else { /* yuck -- no kidding! */
293 tmp = current->next;
294 /* New beginning */
295 tmpstr = nmalloc(current_x + strlen(newbuf->data) + 1);
296 strncpy(tmpstr, current->data, current_x);
297 strcpy(&tmpstr[current_x], newbuf->data);
298 totsize += strlen(newbuf->data) + strlen(newend->data) + 1;
299
300 /* New end */
301 tmpstr2 = nmalloc(strlen(newend->data) +
302 strlen(&current->data[current_x]) + 1);
303 strcpy(tmpstr2, newend->data);
304 strcat(tmpstr2, &current->data[current_x]);
305
306 free(current->data);
307 current->data = tmpstr;
308 current->next = newbuf->next;
309 newbuf->next->prev = current;
310 delete_node(newbuf);
311
312 current_x = strlen(newend->data);
313 placewewant = xplustabs();
314 free(newend->data);
315 newend->data = tmpstr2;
316
317 newend->next = tmp;
318
319 /* If tmp isn't null, we're in the middle: update the
320 * prev pointer. If it IS null, we're at the end, update
321 * the filebot pointer */
322
323 if (tmp != NULL)
324 tmp->prev = newend;
325 else
326 filebot = newend;
327
328 /* Now why don't we update the totsize also */
329 for (tmp = current->next; tmp != newend; tmp = tmp->next)
330 totsize += strlen(tmp->data) + 1;
331
332 i = editbot->lineno;
333
334 renumber(current);
335
336 current = newend;
337 if (i <= newend->lineno)
338 edit_update(current);
339 }
340
341 dump_buffer(fileage);
342 dump_buffer(cutbuffer);
343 set_modified();
344 edit_refresh();
345 return 0;
346#else
347 if (0) {
348#endif
349 } else if (fileptr != fileage) {
350 tmp = fileptr->prev;
351 tmp->next = newbuf;
352 newbuf->prev = tmp;
353 totlines++; /* Unmarked uncuts don't split lines */
354 } else {
355 fileage = newbuf;
356 totlines++; /* Unmarked uncuts don't split lines */
357 }
358
359 /* This is so uncutting at the top of the buffer will work => */
360 if (current_y == 0)
361 edittop = newbuf;
362
363 /* Connect the end of the buffer to the filestruct */
364 newend->next = fileptr;
365 fileptr->prev = newend;
366
367 /* recalculate size *sigh* */
368 for (tmp = newbuf; tmp != fileptr; tmp = tmp->next)
369 totsize += strlen(tmp->data) + 1;
370
371 i = editbot->lineno;
372 renumber(newbuf);
373 if (i < newend->lineno)
374 edit_update(fileptr);
375
376 dump_buffer_reverse(fileptr);
377
378 set_modified();
379 UNSET(KEEP_CUTBUFFER);
380 edit_refresh();
381 return 1;
382}