source: trunk/third/readline/kill.c @ 15410

Revision 15410, 13.8 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15409, which included commits to RCS files with non-trunk default branches.
Line 
1/* kill.c -- kill ring management. */
2
3/* Copyright (C) 1994 Free Software Foundation, Inc.
4
5   This file is part of the GNU Readline Library, a library for
6   reading lines of text with interactive input and history editing.
7
8   The GNU Readline Library is free software; you can redistribute it
9   and/or modify it under the terms of the GNU General Public License
10   as published by the Free Software Foundation; either version 2, or
11   (at your option) any later version.
12
13   The GNU Readline Library is distributed in the hope that it will be
14   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   The GNU General Public License is often shipped with GNU software, and
19   is generally kept in a file called COPYING or LICENSE.  If you do not
20   have a copy of the license, write to the Free Software Foundation,
21   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
22#define READLINE_LIBRARY
23
24#if defined (HAVE_CONFIG_H)
25#  include <config.h>
26#endif
27
28#include <sys/types.h>
29
30#if defined (HAVE_UNISTD_H)
31#  include <unistd.h>           /* for _POSIX_VERSION */
32#endif /* HAVE_UNISTD_H */
33
34#if defined (HAVE_STDLIB_H)
35#  include <stdlib.h>
36#else
37#  include "ansi_stdlib.h"
38#endif /* HAVE_STDLIB_H */
39
40#include <stdio.h>
41
42/* System-specific feature definitions and include files. */
43#include "rldefs.h"
44
45/* Some standard library routines. */
46#include "readline.h"
47#include "history.h"
48
49#include "rlprivate.h"
50#include "xmalloc.h"
51
52/* **************************************************************** */
53/*                                                                  */
54/*                      Killing Mechanism                           */
55/*                                                                  */
56/* **************************************************************** */
57
58/* What we assume for a max number of kills. */
59#define DEFAULT_MAX_KILLS 10
60
61/* The real variable to look at to find out when to flush kills. */
62static int rl_max_kills =  DEFAULT_MAX_KILLS;
63
64/* Where to store killed text. */
65static char **rl_kill_ring = (char **)NULL;
66
67/* Where we are in the kill ring. */
68static int rl_kill_index;
69
70/* How many slots we have in the kill ring. */
71static int rl_kill_ring_length;
72
73/* How to say that you only want to save a certain amount
74   of kill material. */
75int
76rl_set_retained_kills (num)
77     int num;
78{
79  return 0;
80}
81
82/* Add TEXT to the kill ring, allocating a new kill ring slot as necessary.
83   This uses TEXT directly, so the caller must not free it.  If APPEND is
84   non-zero, and the last command was a kill, the text is appended to the
85   current kill ring slot, otherwise prepended. */
86static int
87_rl_copy_to_kill_ring (text, append)
88     char *text;
89     int append;
90{
91  char *old, *new;
92  int slot;
93
94  /* First, find the slot to work with. */
95  if (_rl_last_command_was_kill == 0)
96    {
97      /* Get a new slot.  */
98      if (rl_kill_ring == 0)
99        {
100          /* If we don't have any defined, then make one. */
101          rl_kill_ring = (char **)
102            xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *));
103          rl_kill_ring[slot = 0] = (char *)NULL;
104        }
105      else
106        {
107          /* We have to add a new slot on the end, unless we have
108             exceeded the max limit for remembering kills. */
109          slot = rl_kill_ring_length;
110          if (slot == rl_max_kills)
111            {
112              register int i;
113              free (rl_kill_ring[0]);
114              for (i = 0; i < slot; i++)
115                rl_kill_ring[i] = rl_kill_ring[i + 1];
116            }
117          else
118            {
119              slot = rl_kill_ring_length += 1;
120              rl_kill_ring = (char **)xrealloc (rl_kill_ring, slot * sizeof (char *));
121            }
122          rl_kill_ring[--slot] = (char *)NULL;
123        }
124    }
125  else
126    slot = rl_kill_ring_length - 1;
127
128  /* If the last command was a kill, prepend or append. */
129  if (_rl_last_command_was_kill && rl_editing_mode != vi_mode)
130    {
131      old = rl_kill_ring[slot];
132      new = xmalloc (1 + strlen (old) + strlen (text));
133
134      if (append)
135        {
136          strcpy (new, old);
137          strcat (new, text);
138        }
139      else
140        {
141          strcpy (new, text);
142          strcat (new, old);
143        }
144      free (old);
145      free (text);
146      rl_kill_ring[slot] = new;
147    }
148  else
149    rl_kill_ring[slot] = text;
150
151  rl_kill_index = slot;
152  return 0;
153}
154
155/* The way to kill something.  This appends or prepends to the last
156   kill, if the last command was a kill command.  if FROM is less
157   than TO, then the text is appended, otherwise prepended.  If the
158   last command was not a kill command, then a new slot is made for
159   this kill. */
160int
161rl_kill_text (from, to)
162     int from, to;
163{
164  char *text;
165
166  /* Is there anything to kill? */
167  if (from == to)
168    {
169      _rl_last_command_was_kill++;
170      return 0;
171    }
172
173  text = rl_copy_text (from, to);
174
175  /* Delete the copied text from the line. */
176  rl_delete_text (from, to);
177
178  _rl_copy_to_kill_ring (text, from < to);
179
180  _rl_last_command_was_kill++;
181  return 0;
182}
183
184/* Now REMEMBER!  In order to do prepending or appending correctly, kill
185   commands always make rl_point's original position be the FROM argument,
186   and rl_point's extent be the TO argument. */
187
188/* **************************************************************** */
189/*                                                                  */
190/*                      Killing Commands                            */
191/*                                                                  */
192/* **************************************************************** */
193
194/* Delete the word at point, saving the text in the kill ring. */
195int
196rl_kill_word (count, key)
197     int count, key;
198{
199  int orig_point = rl_point;
200
201  if (count < 0)
202    return (rl_backward_kill_word (-count, key));
203  else
204    {
205      rl_forward_word (count, key);
206
207      if (rl_point != orig_point)
208        rl_kill_text (orig_point, rl_point);
209
210      rl_point = orig_point;
211    }
212  return 0;
213}
214
215/* Rubout the word before point, placing it on the kill ring. */
216int
217rl_backward_kill_word (count, ignore)
218     int count, ignore;
219{
220  int orig_point = rl_point;
221
222  if (count < 0)
223    return (rl_kill_word (-count, ignore));
224  else
225    {
226      rl_backward_word (count, ignore);
227
228      if (rl_point != orig_point)
229        rl_kill_text (orig_point, rl_point);
230    }
231  return 0;
232}
233
234/* Kill from here to the end of the line.  If DIRECTION is negative, kill
235   back to the line start instead. */
236int
237rl_kill_line (direction, ignore)
238     int direction, ignore;
239{
240  int orig_point = rl_point;
241
242  if (direction < 0)
243    return (rl_backward_kill_line (1, ignore));
244  else
245    {
246      rl_end_of_line (1, ignore);
247      if (orig_point != rl_point)
248        rl_kill_text (orig_point, rl_point);
249      rl_point = orig_point;
250    }
251  return 0;
252}
253
254/* Kill backwards to the start of the line.  If DIRECTION is negative, kill
255   forwards to the line end instead. */
256int
257rl_backward_kill_line (direction, ignore)
258     int direction, ignore;
259{
260  int orig_point = rl_point;
261
262  if (direction < 0)
263    return (rl_kill_line (1, ignore));
264  else
265    {
266      if (!rl_point)
267        ding ();
268      else
269        {
270          rl_beg_of_line (1, ignore);
271          rl_kill_text (orig_point, rl_point);
272        }
273    }
274  return 0;
275}
276
277/* Kill the whole line, no matter where point is. */
278int
279rl_kill_full_line (count, ignore)
280     int count, ignore;
281{
282  rl_begin_undo_group ();
283  rl_point = 0;
284  rl_kill_text (rl_point, rl_end);
285  rl_end_undo_group ();
286  return 0;
287}
288
289/* The next two functions mimic unix line editing behaviour, except they
290   save the deleted text on the kill ring.  This is safer than not saving
291   it, and since we have a ring, nobody should get screwed. */
292
293/* This does what C-w does in Unix.  We can't prevent people from
294   using behaviour that they expect. */
295int
296rl_unix_word_rubout (count, key)
297     int count, key;
298{
299  int orig_point;
300
301  if (rl_point == 0)
302    ding ();
303  else
304    {
305      orig_point = rl_point;
306      if (count <= 0)
307        count = 1;
308
309      while (count--)
310        {
311          while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
312            rl_point--;
313
314          while (rl_point && (whitespace (rl_line_buffer[rl_point - 1]) == 0))
315            rl_point--;
316        }
317
318      rl_kill_text (orig_point, rl_point);
319    }
320  return 0;
321}
322
323/* Here is C-u doing what Unix does.  You don't *have* to use these
324   key-bindings.  We have a choice of killing the entire line, or
325   killing from where we are to the start of the line.  We choose the
326   latter, because if you are a Unix weenie, then you haven't backspaced
327   into the line at all, and if you aren't, then you know what you are
328   doing. */
329int
330rl_unix_line_discard (count, key)
331     int count, key;
332{
333  if (rl_point == 0)
334    ding ();
335  else
336    {
337      rl_kill_text (rl_point, 0);
338      rl_point = 0;
339    }
340  return 0;
341}
342
343/* Copy the text in the `region' to the kill ring.  If DELETE is non-zero,
344   delete the text from the line as well. */
345static int
346region_kill_internal (delete)
347     int delete;
348{
349  char *text;
350
351  if (rl_mark == rl_point)
352    {
353      _rl_last_command_was_kill++;
354      return 0;
355    }
356
357  text = rl_copy_text (rl_point, rl_mark);
358  if (delete)
359    rl_delete_text (rl_point, rl_mark);
360  _rl_copy_to_kill_ring (text, rl_point < rl_mark);
361
362  _rl_last_command_was_kill++;
363  return 0;
364}
365
366/* Copy the text in the region to the kill ring. */
367int
368rl_copy_region_to_kill (count, ignore)
369     int count, ignore;
370{
371  return (region_kill_internal (0));
372}
373
374/* Kill the text between the point and mark. */
375int
376rl_kill_region (count, ignore)
377     int count, ignore;
378{
379  int r, npoint;
380
381  npoint = (rl_point < rl_mark) ? rl_point : rl_mark;
382  r = region_kill_internal (1);
383  _rl_fix_point (1);
384  rl_point = npoint;
385  return r;
386}
387
388/* Copy COUNT words to the kill ring.  DIR says which direction we look
389   to find the words. */
390static int
391_rl_copy_word_as_kill (count, dir)
392     int count, dir;
393{
394  int om, op, r;
395
396  om = rl_mark;
397  op = rl_point;
398
399  if (dir > 0)
400    rl_forward_word (count, 0);
401  else
402    rl_backward_word (count, 0);
403
404  rl_mark = rl_point;
405
406  if (dir > 0)
407    rl_backward_word (count, 0);
408  else
409    rl_forward_word (count, 0);
410
411  r = region_kill_internal (0);
412
413  rl_mark = om;
414  rl_point = op;
415
416  return r;
417}
418
419int
420rl_copy_forward_word (count, key)
421     int count, key;
422{
423  if (count < 0)
424    return (rl_copy_backward_word (-count, key));
425
426  return (_rl_copy_word_as_kill (count, 1));
427}
428
429int
430rl_copy_backward_word (count, key)
431     int count, key;
432{
433  if (count < 0)
434    return (rl_copy_forward_word (-count, key));
435
436  return (_rl_copy_word_as_kill (count, -1));
437}
438 
439/* Yank back the last killed text.  This ignores arguments. */
440int
441rl_yank (count, ignore)
442     int count, ignore;
443{
444  if (rl_kill_ring == 0)
445    {
446      _rl_abort_internal ();
447      return -1;
448    }
449
450  _rl_set_mark_at_pos (rl_point);
451  rl_insert_text (rl_kill_ring[rl_kill_index]);
452  return 0;
453}
454
455/* If the last command was yank, or yank_pop, and the text just
456   before point is identical to the current kill item, then
457   delete that text from the line, rotate the index down, and
458   yank back some other text. */
459int
460rl_yank_pop (count, key)
461     int count, key;
462{
463  int l, n;
464
465  if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) ||
466      !rl_kill_ring)
467    {
468      _rl_abort_internal ();
469      return -1;
470    }
471
472  l = strlen (rl_kill_ring[rl_kill_index]);
473  n = rl_point - l;
474  if (n >= 0 && STREQN (rl_line_buffer + n, rl_kill_ring[rl_kill_index], l))
475    {
476      rl_delete_text (n, rl_point);
477      rl_point = n;
478      rl_kill_index--;
479      if (rl_kill_index < 0)
480        rl_kill_index = rl_kill_ring_length - 1;
481      rl_yank (1, 0);
482      return 0;
483    }
484  else
485    {
486      _rl_abort_internal ();
487      return -1;
488    }
489}
490
491/* Yank the COUNTh argument from the previous history line, skipping
492   HISTORY_SKIP lines before looking for the `previous line'. */
493static int
494rl_yank_nth_arg_internal (count, ignore, history_skip)
495     int count, ignore, history_skip;
496{
497  register HIST_ENTRY *entry;
498  char *arg;
499  int i, pos;
500
501  pos = where_history ();
502
503  if (history_skip)
504    {
505      for (i = 0; i < history_skip; i++)
506        entry = previous_history ();
507    }
508
509  entry = previous_history ();
510
511  history_set_pos (pos);
512
513  if (entry == 0)
514    {
515      ding ();
516      return -1;
517    }
518
519  arg = history_arg_extract (count, count, entry->line);
520  if (!arg || !*arg)
521    {
522      ding ();
523      return -1;
524    }
525
526  rl_begin_undo_group ();
527
528#if defined (VI_MODE)
529  /* Vi mode always inserts a space before yanking the argument, and it
530     inserts it right *after* rl_point. */
531  if (rl_editing_mode == vi_mode)
532    {
533      rl_vi_append_mode (1, ignore);
534      rl_insert_text (" ");
535    }
536#endif /* VI_MODE */
537
538  rl_insert_text (arg);
539  free (arg);
540
541  rl_end_undo_group ();
542  return 0;
543}
544
545/* Yank the COUNTth argument from the previous history line. */
546int
547rl_yank_nth_arg (count, ignore)
548     int count, ignore;
549{
550  return (rl_yank_nth_arg_internal (count, ignore, 0));
551}
552
553/* Yank the last argument from the previous history line.  This `knows'
554   how rl_yank_nth_arg treats a count of `$'.  With an argument, this
555   behaves the same as rl_yank_nth_arg. */
556int
557rl_yank_last_arg (count, key)
558     int count, key;
559{
560  static int history_skip = 0;
561  static int explicit_arg_p = 0;
562  static int count_passed = 1;
563  static int direction = 1;
564  static int undo_needed = 0;
565  int retval;
566
567  if (rl_last_func != rl_yank_last_arg)
568    {
569      history_skip = 0;
570      explicit_arg_p = rl_explicit_arg;
571      count_passed = count;
572      direction = 1;
573    }
574  else
575    {
576      if (undo_needed)
577        rl_do_undo ();
578      if (count < 1)
579        direction = -direction;
580      history_skip += direction;
581      if (history_skip < 0)
582        history_skip = 0;
583    }
584 
585  if (explicit_arg_p)
586    retval = rl_yank_nth_arg_internal (count_passed, key, history_skip);
587  else
588    retval = rl_yank_nth_arg_internal ('$', key, history_skip);
589
590  undo_needed = retval == 0;
591  return retval;
592}
593
594/* A special paste command for users of Cygnus's cygwin32. */
595#if defined (__CYGWIN32__)
596#include <windows.h>
597
598int
599rl_paste_from_clipboard (count, key)
600     int count, key;
601{
602  char *data, *ptr;
603  int len;
604
605  if (OpenClipboard (NULL) == 0)
606    return (0);
607
608  data = (char *)GetClipboardData (CF_TEXT);
609  if (data)
610    {
611      ptr = strchr (data, '\r');
612      if (ptr)
613        {
614          len = ptr - data;
615          ptr = xmalloc (len + 1);
616          ptr[len] = '\0';
617          strncpy (ptr, data, len);
618        }
619      else
620        ptr = data;
621      rl_insert_text (ptr);
622      if (ptr != data)
623        free (ptr);
624      CloseClipboard ();
625    }
626  return (0);
627}
628#endif /* __CYGWIN32__ */
Note: See TracBrowser for help on using the repository browser.