aboutsummaryrefslogblamecommitdiff
path: root/tap/readline/text.c
blob: 2cb7adf433237dd100190e70c6e9f5df2ae29a04 (plain) (tree)

































































































































































































































































































































































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