/* text.c * Part of the Readline module for Tap. These are functions which * manipulate the text in some way. */ /* Copyright (C) 1999 Jonathan duSaint * * This file is part of Tap, an interactive program for reading and * writing data to the serial port to facilitate the reverse * engineering of communication protocols. * * Tap is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * Tap 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. * * The GNU General Public License is generally kept in a file called * COPYING or LICENSE. If you do not have a copy of the license, write * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "readline.h" /* Move the cursor one space to the left, * don't perform range check and don't update * position in line */ void cursor_left (void) { if (input_window->_curx == 0) { input_window->_cury--; input_window->_curx = window_width - 1; } else input_window->_curx--; } /* Move the cursor one space to the right, * don't perform range check and don't update * position in line */ void cursor_right (void) { if (input_window->_curx + 1 == window_width) { input_window->_cury++; input_window->_curx = 0; } else input_window->_curx++; } /* Kill the region from the mark to the point; * bound to C-w */ void kill_region (void) { long kstart, kend; /* find the region to be killed */ if (mark_start == -1) { warning_beep (); return; } else if (mark_start == current_position) { mark_start = -1; return; } else if (mark_start < current_position) { int k; kstart = mark_start; kend = current_position; for (k = 0; k < kend - kstart; k++) cursor_left (); } else { kstart = current_position; kend = mark_start; } kill_to_ring (kstart, kend); memmove (current_line + kstart, current_line + kend, chars_in_line - kend + 1); chars_in_line -= kend - kstart; mark_start = -1; current_position = kstart; } /* Kill from the point to the end of the line; * bound to C-k */ void kill_to_eol (void) { kill_to_ring (current_position, chars_in_line); current_line[current_position] = 0; chars_in_line = current_position; } /* Move the cursor left, doing range check and * updating position in line; * bound to C-b and the left arrow key */ void move_cursor_left (void) { if (current_position == 0) { warning_beep (); return; } current_position--; cursor_left (); } /* Move the cursor right, doing range check and * updating position in line; * bound to C-f and the right arrow key */ void move_cursor_right (void) { if (current_position == chars_in_line) { warning_beep (); return; } current_position++; cursor_right (); } /* Move the cursor to the start of the line; * bound to C-a */ void move_cursor_to_start (void) { int k; for (k = 0; k < current_position; k++) cursor_left (); current_position = 0; } /* Move the cursor to the end of the line; * bound to C-e */ void move_cursor_to_end (void) { int k; for (k = 0; k < chars_in_line - current_position; k++) cursor_right (); current_position = chars_in_line; } /* Transpose the character under the point with the one * to the left performing range checking; * bound to C-t */ void transpose_chars (void) { char ch; if (current_position == 0 || current_position == chars_in_line) { warning_beep (); return; } ch = current_line[current_position]; current_line[current_position] = current_line[current_position - 1]; current_line[current_position - 1] = ch; move_cursor_right (); } /* Insert CH into the line at CURRENT_POSITION */ void insert_char (char ch) { if (chars_in_line + 1 == line_size) { current_line = xrealloc (current_line, line_size + GROW_SIZE); line_size += GROW_SIZE; } memmove (current_line + current_position + 1, current_line + current_position, chars_in_line - current_position + 1); current_line[current_position] = ch; cursor_right (); current_position++; chars_in_line++; } /* Delete the character either under the point * or to the left depending on the direction; * bound to C-d and DEL as RIGHT and C-h and * BACKSPACE as LEFT */ void delete_char (enum direction which) { /* check if there is a char to delete */ if ((which == LEFT && current_position == 0) || (which == RIGHT && current_position == chars_in_line)) { warning_beep (); return; } if (which == LEFT) { current_position--; cursor_left (); } memmove (current_line + current_position, current_line + current_position + 1, chars_in_line - current_position); chars_in_line--; } /* Yank text out of the kill ring and insert into the line; * bound to C-y */ void yank_text (void) { int k; char *insert_text; insert_text = get_ring_entry (repeat_value); for (k = 0; k < strlen (insert_text); k++) { insert_char (insert_text[k]); } } /* Read in a number and repeat the following command that * many times, or if the next command is yank, uses the * count as an index into the kill ring; * bound to C-u */ void do_count (void) { int k, y_save, ok, ch = 0, x0, y0, line_pos; /* save the sojourn */ x0 = input_window->_curx; y0 = input_window->_cury; line_pos = current_position; move_cursor_to_end (); waddstr (input_window, "\nC-u> "); wrefresh (input_window); y_save = input_window->_cury; repeat_value = 0; /* read in a number */ while (1) { ch = wgetch (input_window); if (ch >= '0' && ch <= '9') { repeat_value *= 10; repeat_value += ch - '0'; waddch (input_window, ch); wrefresh (input_window); } else { /* if ok == 1 , the number has been read */ ok = (ch == '\n') ? 1 : 0; break; } } if (ok) /* got a \n */ { waddch (input_window, ' '); wrefresh (input_window); ch = readchar (); } /* restore the old positions */ input_window->_cury = y_save; input_window->_curx = 0; waddnstr (input_window, " ", window_width); wrefresh (input_window); input_window->_curx = x0; input_window->_cury = y0; current_position = line_pos; if (!ok) /* if a valid number wasn't read, just return */ { repeat_value = 1; warning_beep (); return; } if (ch == ECYANK) yank_text (); else if (ch == ECQUIT) ungetch ('\n'); else if (ch == ECCOUNT) warning_beep (); else { for (k = 0; k < repeat_value; k++) { if (ch > 0xFF) dispatch_special (ch); else insert_char (ch); } } repeat_value = 1; }