cut.c 8.65 KB
Newer Older
Chris Allegretta's avatar
Chris Allegretta committed
1
/* $Id$ */
Chris Allegretta's avatar
Chris Allegretta committed
2
3
4
/**************************************************************************
 *   cut.c                                                                *
 *                                                                        *
5
 *   Copyright (C) 1999-2004 Chris Allegretta                             *
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
6
 *   Copyright (C) 2005-2006 David Lawrence Ramsey                        *
Chris Allegretta's avatar
Chris Allegretta committed
7
8
 *   This program is free software; you can redistribute it and/or modify *
 *   it under the terms of the GNU General Public License as published by *
9
 *   the Free Software Foundation; either version 2, or (at your option)  *
Chris Allegretta's avatar
Chris Allegretta committed
10
11
 *   any later version.                                                   *
 *                                                                        *
12
13
14
15
 *   This program is distributed in the hope that it will be useful, but  *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of           *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    *
 *   General Public License for more details.                             *
Chris Allegretta's avatar
Chris Allegretta committed
16
17
18
 *                                                                        *
 *   You should have received a copy of the GNU General Public License    *
 *   along with this program; if not, write to the Free Software          *
19
20
 *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA            *
 *   02110-1301, USA.                                                     *
Chris Allegretta's avatar
Chris Allegretta committed
21
22
23
 *                                                                        *
 **************************************************************************/

24
#include "proto.h"
25

Chris Allegretta's avatar
Chris Allegretta committed
26
27
28
#include <string.h>
#include <stdio.h>

29
static bool keep_cutbuffer = FALSE;
30
	/* Should we keep the contents of the cutbuffer? */
31
static filestruct *cutbottom = NULL;
32
	/* Pointer to the end of the cutbuffer. */
33

34
35
/* Indicate that we should no longer keep the contents of the
 * cutbuffer. */
36
37
38
39
void cutbuffer_reset(void)
{
    keep_cutbuffer = FALSE;
}
Chris Allegretta's avatar
Chris Allegretta committed
40

David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
41
/* If we aren't on the last line of the file, move all the text of the
42
43
 * current line, plus the newline at the end, into the cutbuffer.  If we
 * are, move all of the text of the current line into the cutbuffer.  In
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
44
45
 * both cases, set the current place we want to the beginning of the
 * current line. */
46
void cut_line(void)
Chris Allegretta's avatar
Chris Allegretta committed
47
{
48
    if (openfile->current != openfile->filebot)
49
50
	move_to_filestruct(&cutbuffer, &cutbottom, openfile->current, 0,
		openfile->current->next, 0);
51
    else
52
	move_to_filestruct(&cutbuffer, &cutbottom, openfile->current, 0,
53
		openfile->current, strlen(openfile->current->data));
54
    openfile->placewewant = 0;
Chris Allegretta's avatar
Chris Allegretta committed
55
56
}

57
#ifndef NANO_TINY
58
59
/* Move all currently marked text into the cutbuffer, and set the
 * current place we want to where the text used to start. */
60
void cut_marked(void)
Chris Allegretta's avatar
Chris Allegretta committed
61
{
62
63
    filestruct *top, *bot;
    size_t top_x, bot_x;
64

65
    mark_order((const filestruct **)&top, &top_x,
66
	(const filestruct **)&bot, &bot_x, NULL);
Chris Allegretta's avatar
Chris Allegretta committed
67

68
    move_to_filestruct(&cutbuffer, &cutbottom, top, top_x, bot, bot_x);
69
    openfile->placewewant = xplustabs();
70
}
71

David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
72
73
/* If we aren't at the end of the current line, move all the text from
 * the current cursor position to the end of the current line, not
74
 * counting the newline at the end, into the cutbuffer.  If we are, and
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
75
 * we're not on the last line of the file, move the newline at the end
76
 * into the cutbuffer, and set the current place we want to where the
77
 * newline used to be. */
78
79
void cut_to_eol(void)
{
80
    size_t data_len = strlen(openfile->current->data);
81

82
    assert(openfile->current_x <= data_len);
83

84
    if (openfile->current_x < data_len)
85
86
	/* If we're not at the end of the line, move all the text from
	 * the current position up to it, not counting the newline at
87
	 * the end, into the cutbuffer. */
88
89
	move_to_filestruct(&cutbuffer, &cutbottom, openfile->current,
		openfile->current_x, openfile->current, data_len);
90
91
92
93
    else if (openfile->current != openfile->filebot) {
	/* If we're at the end of the line, and it isn't the last line
	 * of the file, move all the text from the current position up
	 * to the beginning of the next line, i.e, the newline at the
94
	 * end, into the cutbuffer. */
95
96
97
	move_to_filestruct(&cutbuffer, &cutbottom, openfile->current,
		openfile->current_x, openfile->current->next, 0);
	openfile->placewewant = xplustabs();
Chris Allegretta's avatar
Chris Allegretta committed
98
99
    }
}
100
101
102
103
104
105
106
107
108

/* Move all the text from the current cursor position to the end of the
 * file into the cutbuffer. */
void cut_to_eof(void)
{
    move_to_filestruct(&cutbuffer, &cutbottom, openfile->current,
	openfile->current_x, openfile->filebot,
	strlen(openfile->filebot->data));
}
109
#endif /* !NANO_TINY */
Chris Allegretta's avatar
Chris Allegretta committed
110

111
/* Move text from the current filestruct into the cutbuffer.  If
112
113
114
 * copy_text is TRUE, copy the text back into the filestruct afterward.
 * If cut_till_end is TRUE, move all text from the current cursor
 * position to the end of the file into the cutbuffer. */
115
116
void do_cut_text(
#ifndef NANO_TINY
117
	bool copy_text, bool cut_till_end
118
119
120
121
#else
	void
#endif
	)
Chris Allegretta's avatar
Chris Allegretta committed
122
{
123
124
125
126
#ifndef NANO_TINY
    filestruct *cb_save = NULL;
	/* The current end of the cutbuffer, before we add text to
	 * it. */
127
128
129
    size_t cb_save_len = 0;
	/* The length of the string at the current end of the cutbuffer,
	 * before we add text to it.  */
130
    bool old_no_newlines = ISSET(NO_NEWLINES);
131
132
#endif

133
    assert(openfile->current != NULL && openfile->current->data != NULL);
134

135
136
137
    /* If keep_cutbuffer is FALSE and the cutbuffer isn't empty, blow
     * away the text in the cutbuffer. */
    if (!keep_cutbuffer && cutbuffer != NULL) {
Chris Allegretta's avatar
Chris Allegretta committed
138
139
140
	free_filestruct(cutbuffer);
	cutbuffer = NULL;
#ifdef DEBUG
141
	fprintf(stderr, "Blew away cutbuffer =)\n");
Chris Allegretta's avatar
Chris Allegretta committed
142
143
#endif
    }
144

145
#ifndef NANO_TINY
146
147
148
149
150
    if (copy_text) {
	if (cutbuffer != NULL) {
	    /* If the cutbuffer isn't empty, save where it currently
	     * ends.  This is where the new text will be added. */
	    cb_save = cutbottom;
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
151
	    cb_save_len = strlen(cutbottom->data);
152
153
154
155
156
	}

	/* Set NO_NEWLINES to TRUE, so that we don't disturb the last
	 * line of the file when moving text to the cutbuffer. */
	SET(NO_NEWLINES);
157
158
159
    }
#endif

160
161
162
    /* Set keep_cutbuffer to TRUE, so that the text we're going to move
     * into the cutbuffer will be added to the text already in the
     * cutbuffer instead of replacing it. */
163
    keep_cutbuffer = TRUE;
Chris Allegretta's avatar
Chris Allegretta committed
164

165
#ifndef NANO_TINY
166
167
168
169
170
    if (cut_till_end) {
	/* If cut_till_end is TRUE, move all text up to the end of the
	 * file into the cutbuffer. */
	cut_to_eof();
    } else if (openfile->mark_set) {
171
	/* If the mark is on, move the marked text to the cutbuffer, and
172
173
	 * turn the mark off. */
	cut_marked();
174
	openfile->mark_set = FALSE;
175
    } else if (ISSET(CUT_TO_END))
176
177
178
	/* Otherwise, if the CUT_TO_END flag is set, move all text up to
	 * the end of the line into the cutbuffer. */
	cut_to_eol();
Chris Allegretta's avatar
Chris Allegretta committed
179
    else
180
#endif
181
182
	/* Otherwise, move the entire line into the cutbuffer. */
	cut_line();
Chris Allegretta's avatar
Chris Allegretta committed
183

184
#ifndef NANO_TINY
185
    if (copy_text) {
186
187
188
189
	/* Copy the text in the cutbuffer, starting at its saved end if
	 * there is one, back into the filestruct.  This effectively
	 * uncuts the text we just cut without marking the file as
	 * modified. */
190
191
192
193
194
195
196
197
	if (cutbuffer != NULL) {
	    if (cb_save != NULL) {
		cb_save->data += cb_save_len;
		copy_from_filestruct(cb_save, cutbottom);
		cb_save->data -= cb_save_len;
	    } else
		copy_from_filestruct(cutbuffer, cutbottom);
	}
198
199
200
201
202

	/* Set NO_NEWLINES back to what it was before, since we're done
	 * disturbing the text. */
	if (!old_no_newlines)
	    UNSET(NO_NEWLINES);
203
    } else
204
205
206
207
208
209
#endif
	/* Leave the text in the cutbuffer, and mark the file as
	 * modified. */
	set_modified();

    /* Update the screen. */
210
    edit_refresh();
211
212

#ifdef DEBUG
213
    dump_filestruct(cutbuffer);
Chris Allegretta's avatar
Chris Allegretta committed
214
#endif
Chris Allegretta's avatar
Chris Allegretta committed
215
216
}

217
218
219
/* Move text from the current filestruct into the cutbuffer. */
void do_cut_text_void(void)
{
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
220
221
    do_cut_text(
#ifndef NANO_TINY
222
	FALSE, FALSE
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
223
224
#endif
	);
225
226
}

227
#ifndef NANO_TINY
228
229
230
231
/* Move text from the current filestruct into the cutbuffer, and copy it
 * back into the filestruct afterward. */
void do_copy_text(void)
{
232
    do_cut_text(TRUE, FALSE);
233
234
}

235
236
237
/* Cut from the current cursor position to the end of the file. */
void do_cut_till_end(void)
{
238
    do_cut_text(FALSE, TRUE);
239
}
240
#endif /* !NANO_TINY */
241

242
/* Copy text from the cutbuffer into the current filestruct. */
243
void do_uncut_text(void)
Chris Allegretta's avatar
Chris Allegretta committed
244
{
245
    assert(openfile->current != NULL && openfile->current->data != NULL);
Chris Allegretta's avatar
Chris Allegretta committed
246

247
248
    /* If the cutbuffer is empty, get out. */
    if (cutbuffer == NULL)
249
	return;
250

251
    /* Add a copy of the text in the cutbuffer to the current filestruct
252
     * at the current cursor position. */
253
    copy_from_filestruct(cutbuffer, cutbottom);
Chris Allegretta's avatar
Chris Allegretta committed
254

255
256
    /* Set the current place we want to where the text from the
     * cutbuffer ends. */
257
    openfile->placewewant = xplustabs();
Chris Allegretta's avatar
Chris Allegretta committed
258

David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
259
    /* Mark the file as modified. */
260
    set_modified();
Chris Allegretta's avatar
Chris Allegretta committed
261

David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
262
263
264
    /* Update the screen. */
    edit_refresh();

Chris Allegretta's avatar
Chris Allegretta committed
265
#ifdef DEBUG
266
    dump_filestruct_reverse();
Chris Allegretta's avatar
Chris Allegretta committed
267
#endif
Chris Allegretta's avatar
Chris Allegretta committed
268
}