cut.c 8.39 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
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
42
 * current line, plus the newline at the end, to the cutbuffer.  If we
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
43
44
45
 * are, move all of the text of the current line to the cutbuffer.  In
 * 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
60
/* Move all currently marked text to the cutbuffer, and set the current
 * place we want to where the text used to start. */
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
74
75
76
/* 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
 * counting the newline at the end, to the cutbuffer.  If we are, and
 * we're not on the last line of the file, move the newline at the end
 * to 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
87
	/* 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
	 * the end, to the cutbuffer. */
88
89
	move_to_filestruct(&cutbuffer, &cutbottom, openfile->current,
		openfile->current_x, openfile->current, data_len);
90
91
92
93
94
    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
	 * end, to 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
#endif /* !NANO_TINY */
Chris Allegretta's avatar
Chris Allegretta committed
101

102
103
104
105
106
107
108
109
110
111
/* Move text from the current filestruct into the cutbuffer.  If
 * copy_text is TRUE, copy the text back into the filestruct
 * afterward. */
void do_cut_text(
#ifndef NANO_TINY
	bool copy_text
#else
	void
#endif
	)
Chris Allegretta's avatar
Chris Allegretta committed
112
{
113
114
115
116
117
#ifndef NANO_TINY
    filestruct *cb_save = NULL;
	/* The current end of the cutbuffer, before we add text to
	 * it. */
    bool old_mark_set = openfile->mark_set;
118
    bool old_no_newlines = ISSET(NO_NEWLINES);
119
120
#endif

121
    assert(openfile->current != NULL && openfile->current->data != NULL);
122

123
    check_statusblank();
Chris Allegretta's avatar
Chris Allegretta committed
124

125
126
127
    /* 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
128
129
130
	free_filestruct(cutbuffer);
	cutbuffer = NULL;
#ifdef DEBUG
131
	fprintf(stderr, "Blew away cutbuffer =)\n");
Chris Allegretta's avatar
Chris Allegretta committed
132
133
#endif
    }
134

135
#ifndef NANO_TINY
136
137
138
139
140
141
142
143
144
145
146
    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;
	    cb_save->data += strlen(cb_save->data);
	}

	/* 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);
147
148
149
    }
#endif

150
151
152
    /* 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. */
153
    keep_cutbuffer = TRUE;
Chris Allegretta's avatar
Chris Allegretta committed
154

155
#ifndef NANO_TINY
156
    if (openfile->mark_set) {
157
	/* If the mark is on, move the marked text to the cutbuffer, and
158
159
	 * turn the mark off. */
	cut_marked();
160
	openfile->mark_set = FALSE;
161
    } else if (ISSET(CUT_TO_END))
162
163
164
	/* 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
165
    else
166
#endif
167
168
	/* Otherwise, move the entire line into the cutbuffer. */
	cut_line();
Chris Allegretta's avatar
Chris Allegretta committed
169

170
#ifndef NANO_TINY
171
    if (copy_text) {
172
173
174
175
	/* 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. */
176
177
178
	if (cutbuffer != NULL)
	    copy_from_filestruct((cb_save != NULL) ? cb_save :
		cutbuffer, cutbottom);
179
180
181
182
183

	/* Set NO_NEWLINES back to what it was before, since we're done
	 * disturbing the text. */
	if (!old_no_newlines)
	    UNSET(NO_NEWLINES);
184
    } else
185
186
187
188
189
190
191
192
193
194
#endif
	/* Leave the text in the cutbuffer, and mark the file as
	 * modified. */
	set_modified();

    /* Update the screen. */
#ifndef NANO_TINY
    if (!copy_text || old_mark_set)
#endif
	edit_refresh();
195
196

#ifdef DEBUG
197
    dump_filestruct(cutbuffer);
Chris Allegretta's avatar
Chris Allegretta committed
198
#endif
Chris Allegretta's avatar
Chris Allegretta committed
199
200
}

201
202
203
/* Move text from the current filestruct into the cutbuffer. */
void do_cut_text_void(void)
{
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
204
205
206
207
208
    do_cut_text(
#ifndef NANO_TINY
	FALSE
#endif
	);
209
210
}

211
#ifndef NANO_TINY
212
213
214
215
216
217
218
/* Move text from the current filestruct into the cutbuffer, and copy it
 * back into the filestruct afterward. */
void do_copy_text(void)
{
    do_cut_text(TRUE);
}

219
220
221
/* Cut from the current cursor position to the end of the file. */
void do_cut_till_end(void)
{
222
    assert(openfile->current != NULL && openfile->current->data != NULL);
223
224
225

    check_statusblank();

226
    move_to_filestruct(&cutbuffer, &cutbottom, openfile->current,
227
228
	openfile->current_x, openfile->filebot,
	strlen(openfile->filebot->data));
229

230
231
    /* Leave the text in the cutbuffer, and mark the file as
     * modified. */
232
233
    set_modified();

234
235
236
    /* Update the screen. */
    edit_refresh();

237
#ifdef DEBUG
238
    dump_filestruct(cutbuffer);
239
240
#endif
}
241
#endif /* !NANO_TINY */
242

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

248
#ifndef DISABLE_WRAPPING
Chris Allegretta's avatar
Chris Allegretta committed
249
    wrap_reset();
250
#endif
Chris Allegretta's avatar
Chris Allegretta committed
251

252
    check_statusblank();
Chris Allegretta's avatar
Chris Allegretta committed
253

254
255
    /* If the cutbuffer is empty, get out. */
    if (cutbuffer == NULL)
256
	return;
257

258
    /* Add a copy of the text in the cutbuffer to the current filestruct
259
     * at the current cursor position. */
260
    copy_from_filestruct(cutbuffer, cutbottom);
Chris Allegretta's avatar
Chris Allegretta committed
261

262
263
    /* Set the current place we want to where the text from the
     * cutbuffer ends. */
264
    openfile->placewewant = xplustabs();
Chris Allegretta's avatar
Chris Allegretta committed
265

266
    edit_refresh();
267
    set_modified();
Chris Allegretta's avatar
Chris Allegretta committed
268

Chris Allegretta's avatar
Chris Allegretta committed
269
#ifdef DEBUG
270
    dump_filestruct_reverse();
Chris Allegretta's avatar
Chris Allegretta committed
271
#endif
Chris Allegretta's avatar
Chris Allegretta committed
272
}