/* 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;
}