blob: 36517984a5d374c3408e2243a28eef9d7c24e19e [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);
200 totlines--;
201 fileptr->prev = NULL;
202 edit_update(fileage);
203 current = fileptr;
204 } else {
205 add_to_cutbuffer(fileptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000206 fileage = make_new_node(NULL);
207 fileage->data = nmalloc(1);
Robert Siemborskiea19c732000-06-09 00:52:26 +0000208 fileage->data[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000209 current = fileage;
210 }
211 } else {
212 if (fileptr->prev != NULL)
213 fileptr->prev->next = fileptr->next;
214
215 if (fileptr->next != NULL) {
216 (fileptr->next)->prev = fileptr->prev;
217 current = fileptr->next;
218 totlines--;
219 } else {
220 /* we're deleteing the last line
221 and replacing it with a dummy line,
222 so totlines is the same */
223 tmp = fileptr->prev;
224 tmp->next = make_new_node(tmp);
225 tmp = tmp->next;
226 tmp->data = nmalloc(1);
227 strcpy(tmp->data, "");
228 current = tmp;
229 filebot = tmp;
230 }
231
232 add_to_cutbuffer(fileptr);
233 }
234
235 if (fileptr == edittop)
236 edittop = current;
237
238 edit_refresh();
239
240 dump_buffer(cutbuffer);
241 reset_cursor();
242
243 set_modified();
244 marked_cut = 0;
245 current_x = 0;
246 placewewant = 0;
247 update_cursor();
248 renumber(tmp);
249 SET(KEEP_CUTBUFFER);
250 return 1;
251}
252
253int do_uncut_text(void)
254{
255 filestruct *tmp = current, *fileptr = current, *newbuf, *newend;
256#ifndef NANO_SMALL
257 char *tmpstr, *tmpstr2;
258#endif
259 int i;
260
261 wrap_reset();
262 if (cutbuffer == NULL || fileptr == NULL)
263 return 0; /* AIEEEEEEEEEEEE */
264
265 newbuf = copy_filestruct(cutbuffer);
266 for (newend = newbuf; newend->next != NULL && newend != NULL;
267 newend = newend->next) {
268 totlines++;
269 }
270
271 /* Hook newbuf into fileptr */
272#ifndef NANO_SMALL
273 if (marked_cut == 1) {
274 /* If there's only one line in the cutbuffer */
275 if (cutbuffer->next == NULL) {
276 tmpstr =
277 nmalloc(strlen(current->data) + strlen(cutbuffer->data) +
278 1);
279 strncpy(tmpstr, current->data, current_x);
280 strcpy(&tmpstr[current_x], cutbuffer->data);
281 strcat(tmpstr, &current->data[current_x]);
282 free(current->data);
283 current->data = tmpstr;
284 current_x += strlen(cutbuffer->data);
285 totsize += strlen(cutbuffer->data);
286
287 placewewant = xplustabs();
288 update_cursor();
289 renumber(current);
290 } else { /* yuck -- no kidding! */
291 tmp = current->next;
292 /* New beginning */
293 tmpstr = nmalloc(current_x + strlen(newbuf->data) + 1);
294 strncpy(tmpstr, current->data, current_x);
295 strcpy(&tmpstr[current_x], newbuf->data);
296 totsize += strlen(newbuf->data) + strlen(newend->data) + 1;
297
298 /* New end */
299 tmpstr2 = nmalloc(strlen(newend->data) +
300 strlen(&current->data[current_x]) + 1);
301 strcpy(tmpstr2, newend->data);
302 strcat(tmpstr2, &current->data[current_x]);
303
304 free(current->data);
305 current->data = tmpstr;
306 current->next = newbuf->next;
307 newbuf->next->prev = current;
308 delete_node(newbuf);
309
310 current_x = strlen(newend->data);
311 placewewant = xplustabs();
312 free(newend->data);
313 newend->data = tmpstr2;
314
315 newend->next = tmp;
316
317 /* If tmp isn't null, we're in the middle: update the
318 * prev pointer. If it IS null, we're at the end, update
319 * the filebot pointer */
320
321 if (tmp != NULL)
322 tmp->prev = newend;
323 else
324 filebot = newend;
325
326 /* Now why don't we update the totsize also */
327 for (tmp = current->next; tmp != newend; tmp = tmp->next)
328 totsize += strlen(tmp->data) + 1;
329
330 i = editbot->lineno;
331
332 renumber(current);
333
334 current = newend;
335 if (i <= newend->lineno)
336 edit_update(current);
337 }
338
339 dump_buffer(fileage);
340 dump_buffer(cutbuffer);
341 set_modified();
342 edit_refresh();
343 return 0;
344#else
345 if (0) {
346#endif
347 } else if (fileptr != fileage) {
348 tmp = fileptr->prev;
349 tmp->next = newbuf;
350 newbuf->prev = tmp;
351 totlines++; /* Unmarked uncuts don't split lines */
352 } else {
353 fileage = newbuf;
354 totlines++; /* Unmarked uncuts don't split lines */
355 }
356
357 /* This is so uncutting at the top of the buffer will work => */
358 if (current_y == 0)
359 edittop = newbuf;
360
361 /* Connect the end of the buffer to the filestruct */
362 newend->next = fileptr;
363 fileptr->prev = newend;
364
365 /* recalculate size *sigh* */
366 for (tmp = newbuf; tmp != fileptr; tmp = tmp->next)
367 totsize += strlen(tmp->data) + 1;
368
369 i = editbot->lineno;
370 renumber(newbuf);
371 if (i < newend->lineno)
372 edit_update(fileptr);
373
374 dump_buffer_reverse(fileptr);
375
376 set_modified();
377 UNSET(KEEP_CUTBUFFER);
378 edit_refresh();
379 return 1;
380}