1/* $Id: cut.c,v 1.61 2007/01/01 05:15:32 dolorous Exp $ */ 2/************************************************************************** 3 * cut.c * 4 * * 5 * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Chris Allegretta * 6 * Copyright (C) 2005, 2006, 2007 David Lawrence Ramsey * 7 * This program is free software; you can redistribute it and/or modify * 8 * 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) * 10 * any later version. * 11 * * 12 * This program is distributed in the hope that it will be useful, but * 13 * WITHOUT ANY WARRANTY; without even the implied warranty of * 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 15 * General Public License for more details. * 16 * * 17 * You should have received a copy of the GNU General Public License * 18 * along with this program; if not, write to the Free Software * 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 20 * 02110-1301, USA. * 21 * * 22 **************************************************************************/ 23 24#include "proto.h" 25 26#include <string.h> 27#include <stdio.h> 28 29static bool keep_cutbuffer = FALSE; 30 /* Should we keep the contents of the cutbuffer? */ 31static filestruct *cutbottom = NULL; 32 /* Pointer to the end of the cutbuffer. */ 33 34/* Indicate that we should no longer keep the contents of the 35 * cutbuffer. */ 36void cutbuffer_reset(void) 37{ 38 keep_cutbuffer = FALSE; 39} 40 41/* If we aren't on the last line of the file, move all the text of the 42 * current line, plus the newline at the end, into the cutbuffer. If we 43 * are, move all of the text of the current line into the cutbuffer. In 44 * both cases, set the current place we want to the beginning of the 45 * current line. */ 46void cut_line(void) 47{ 48 if (openfile->current != openfile->filebot) 49 move_to_filestruct(&cutbuffer, &cutbottom, openfile->current, 0, 50 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; 55} 56 57#ifndef NANO_TINY 58/* Move all currently marked text into the cutbuffer, and set the 59 * current place we want to where the text used to start. */ 60void cut_marked(void) 61{ 62 filestruct *top, *bot; 63 size_t top_x, bot_x; 64 65 mark_order((const filestruct **)&top, &top_x, 66 (const filestruct **)&bot, &bot_x, NULL); 67 68 move_to_filestruct(&cutbuffer, &cutbottom, top, top_x, bot, bot_x); 69 openfile->placewewant = xplustabs(); 70} 71 72/* If we aren't at the end of the current line, move all the text from 73 * 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 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. */ 78void cut_to_eol(void) 79{ 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 /* If we're not at the end of the line, move all the text from 86 * the current position up to it, not counting the newline at 87 * the end, into the cutbuffer. */ 88 move_to_filestruct(&cutbuffer, &cutbottom, openfile->current, 89 openfile->current_x, openfile->current, data_len); 90 else if (openfile->current != openfile->filebot) { 91 /* If we're at the end of the line, and it isn't the last line 92 * of the file, move all the text from the current position up 93 * to the beginning of the next line, i.e. the newline at the 94 * end, into the cutbuffer. */ 95 move_to_filestruct(&cutbuffer, &cutbottom, openfile->current, 96 openfile->current_x, openfile->current->next, 0); 97 openfile->placewewant = xplustabs(); 98 } 99} 100 101/* Move all the text from the current cursor position to the end of the 102 * file into the cutbuffer. */ 103void cut_to_eof(void) 104{ 105 move_to_filestruct(&cutbuffer, &cutbottom, openfile->current, 106 openfile->current_x, openfile->filebot, 107 strlen(openfile->filebot->data)); 108} 109#endif /* !NANO_TINY */ 110 111/* Move text from the current filestruct into the cutbuffer. If 112 * copy_text is TRUE, copy the text back into the filestruct afterward. 113 * If cut_till_end is TRUE, move all text from the current cursor 114 * position to the end of the file into the cutbuffer. */ 115void do_cut_text( 116#ifndef NANO_TINY 117 bool copy_text, bool cut_till_end 118#else 119 void 120#endif 121 ) 122{ 123#ifndef NANO_TINY 124 filestruct *cb_save = NULL; 125 /* The current end of the cutbuffer, before we add text to 126 * it. */ 127 size_t cb_save_len = 0; 128 /* The length of the string at the current end of the cutbuffer, 129 * before we add text to it. */ 130 bool old_no_newlines = ISSET(NO_NEWLINES); 131#endif 132 133 assert(openfile->current != NULL && openfile->current->data != NULL); 134 135 /* If keep_cutbuffer is FALSE and the cutbuffer isn't empty, blow 136 * away the text in the cutbuffer. */ 137 if (!keep_cutbuffer && cutbuffer != NULL) { 138 free_filestruct(cutbuffer); 139 cutbuffer = NULL; 140#ifdef DEBUG 141 fprintf(stderr, "Blew away cutbuffer =)\n"); 142#endif 143 } 144 145#ifndef NANO_TINY 146 if (copy_text) { 147 if (cutbuffer != NULL) { 148 /* If the cutbuffer isn't empty, save where it currently 149 * ends. This is where we'll add the new text. */ 150 cb_save = cutbottom; 151 cb_save_len = strlen(cutbottom->data); 152 } 153 154 /* Set NO_NEWLINES to TRUE, so that we don't disturb the last 155 * line of the file when moving text to the cutbuffer. */ 156 SET(NO_NEWLINES); 157 } 158#endif 159 160 /* Set keep_cutbuffer to TRUE, so that the text we're going to move 161 * into the cutbuffer will be added to the text already in the 162 * cutbuffer instead of replacing it. */ 163 keep_cutbuffer = TRUE; 164 165#ifndef NANO_TINY 166 if (cut_till_end) { 167 /* If cut_till_end is TRUE, move all text up to the end of the 168 * file into the cutbuffer. */ 169 cut_to_eof(); 170 } else if (openfile->mark_set) { 171 /* If the mark is on, move the marked text to the cutbuffer, and 172 * turn the mark off. */ 173 cut_marked(); 174 openfile->mark_set = FALSE; 175 } else if (ISSET(CUT_TO_END)) 176 /* If the CUT_TO_END flag is set, move all text up to the end of 177 * the line into the cutbuffer. */ 178 cut_to_eol(); 179 else 180#endif 181 /* Move the entire line into the cutbuffer. */ 182 cut_line(); 183 184#ifndef NANO_TINY 185 if (copy_text) { 186 /* Copy the text in the cutbuffer, starting at its saved end if 187 * there is one, back into the filestruct. This effectively 188 * uncuts the text we just cut without marking the file as 189 * modified. */ 190 if (cutbuffer != NULL) { 191 if (cb_save != NULL) { 192 cb_save->data += cb_save_len; 193 copy_from_filestruct(cb_save, cutbottom); 194 cb_save->data -= cb_save_len; 195 } else 196 copy_from_filestruct(cutbuffer, cutbottom); 197 198 /* Set the current place we want to where the text from the 199 * cutbuffer ends. */ 200 openfile->placewewant = xplustabs(); 201 } 202 203 /* Set NO_NEWLINES back to what it was before, since we're done 204 * disturbing the text. */ 205 if (!old_no_newlines) 206 UNSET(NO_NEWLINES); 207 } else 208#endif 209 /* Leave the text in the cutbuffer, and mark the file as 210 * modified. */ 211 set_modified(); 212 213 /* Update the screen. */ 214 edit_refresh(); 215 216#ifdef DEBUG 217 dump_filestruct(cutbuffer); 218#endif 219} 220 221/* Move text from the current filestruct into the cutbuffer. */ 222void do_cut_text_void(void) 223{ 224 do_cut_text( 225#ifndef NANO_TINY 226 FALSE, FALSE 227#endif 228 ); 229} 230 231#ifndef NANO_TINY 232/* Move text from the current filestruct into the cutbuffer, and copy it 233 * back into the filestruct afterward. */ 234void do_copy_text(void) 235{ 236 do_cut_text(TRUE, FALSE); 237} 238 239/* Cut from the current cursor position to the end of the file. */ 240void do_cut_till_end(void) 241{ 242 do_cut_text(FALSE, TRUE); 243} 244#endif /* !NANO_TINY */ 245 246/* Copy text from the cutbuffer into the current filestruct. */ 247void do_uncut_text(void) 248{ 249 assert(openfile->current != NULL && openfile->current->data != NULL); 250 251 /* If the cutbuffer is empty, get out. */ 252 if (cutbuffer == NULL) 253 return; 254 255 /* Add a copy of the text in the cutbuffer to the current filestruct 256 * at the current cursor position. */ 257 copy_from_filestruct(cutbuffer, cutbottom); 258 259 /* Set the current place we want to where the text from the 260 * cutbuffer ends. */ 261 openfile->placewewant = xplustabs(); 262 263 /* Mark the file as modified. */ 264 set_modified(); 265 266 /* Update the screen. */ 267 edit_refresh(); 268 269#ifdef DEBUG 270 dump_filestruct_reverse(); 271#endif 272} 273