File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / readline / misc.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jul 30 08:16:45 2014 UTC (9 years, 10 months ago) by misho
Branches: readline, MAIN
CVS tags: v6_3, p6, HEAD
readline 6.3

    1: /* misc.c -- miscellaneous bindable readline functions. */
    2: 
    3: /* Copyright (C) 1987-2012 Free Software Foundation, Inc.
    4: 
    5:    This file is part of the GNU Readline Library (Readline), a library
    6:    for reading lines of text with interactive input and history editing.      
    7: 
    8:    Readline is free software: you can redistribute it and/or modify
    9:    it under the terms of the GNU General Public License as published by
   10:    the Free Software Foundation, either version 3 of the License, or
   11:    (at your option) any later version.
   12: 
   13:    Readline is distributed in the hope that it will be useful,
   14:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16:    GNU General Public License for more details.
   17: 
   18:    You should have received a copy of the GNU General Public License
   19:    along with Readline.  If not, see <http://www.gnu.org/licenses/>.
   20: */
   21: 
   22: #define READLINE_LIBRARY
   23: 
   24: #if defined (HAVE_CONFIG_H)
   25: #  include <config.h>
   26: #endif
   27: 
   28: #if defined (HAVE_UNISTD_H)
   29: #  include <unistd.h>
   30: #endif /* HAVE_UNISTD_H */
   31: 
   32: #if defined (HAVE_STDLIB_H)
   33: #  include <stdlib.h>
   34: #else
   35: #  include "ansi_stdlib.h"
   36: #endif /* HAVE_STDLIB_H */
   37: 
   38: #if defined (HAVE_LOCALE_H)
   39: #  include <locale.h>
   40: #endif
   41: 
   42: #include <stdio.h>
   43: 
   44: /* System-specific feature definitions and include files. */
   45: #include "rldefs.h"
   46: #include "rlmbutil.h"
   47: 
   48: /* Some standard library routines. */
   49: #include "readline.h"
   50: #include "history.h"
   51: 
   52: #include "rlprivate.h"
   53: #include "rlshell.h"
   54: #include "xmalloc.h"
   55: 
   56: static int rl_digit_loop PARAMS((void));
   57: static void _rl_history_set_point PARAMS((void));
   58: 
   59: extern int history_offset;
   60: 
   61: /* Forward declarations used in this file */
   62: void _rl_free_history_entry PARAMS((HIST_ENTRY *));
   63: 
   64: /* If non-zero, rl_get_previous_history and rl_get_next_history attempt
   65:    to preserve the value of rl_point from line to line. */
   66: int _rl_history_preserve_point = 0;
   67: 
   68: _rl_arg_cxt _rl_argcxt;
   69: 
   70: /* Saved target point for when _rl_history_preserve_point is set.  Special
   71:    value of -1 means that point is at the end of the line. */
   72: int _rl_history_saved_point = -1;
   73: 
   74: /* **************************************************************** */
   75: /*								    */
   76: /*			Numeric Arguments			    */
   77: /*								    */
   78: /* **************************************************************** */
   79: 
   80: int
   81: _rl_arg_overflow ()
   82: {
   83:   if (rl_numeric_arg > 1000000)
   84:     {
   85:       _rl_argcxt = 0;
   86:       rl_explicit_arg = rl_numeric_arg = 0;
   87:       rl_ding ();
   88:       rl_restore_prompt ();
   89:       rl_clear_message ();
   90:       RL_UNSETSTATE(RL_STATE_NUMERICARG);
   91:       return 1;
   92:     }
   93:   return 0;
   94: }
   95: 
   96: void
   97: _rl_arg_init ()
   98: {
   99:   rl_save_prompt ();
  100:   _rl_argcxt = 0;
  101:   RL_SETSTATE(RL_STATE_NUMERICARG);
  102: }
  103: 
  104: int
  105: _rl_arg_getchar ()
  106: {
  107:   int c;
  108: 
  109:   rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
  110:   RL_SETSTATE(RL_STATE_MOREINPUT);
  111:   c = rl_read_key ();
  112:   RL_UNSETSTATE(RL_STATE_MOREINPUT);
  113: 
  114:   return c;
  115: }
  116: 
  117: /* Process C as part of the current numeric argument.  Return -1 if the
  118:    argument should be aborted, 0 if we should not read any more chars, and
  119:    1 if we should continue to read chars. */
  120: int
  121: _rl_arg_dispatch (cxt, c)
  122:      _rl_arg_cxt cxt;
  123:      int c;
  124: {
  125:   int key, r;
  126: 
  127:   key = c;
  128: 
  129:   /* If we see a key bound to `universal-argument' after seeing digits,
  130:       it ends the argument but is otherwise ignored. */
  131:   if (_rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
  132:     {
  133:       if ((cxt & NUM_SAWDIGITS) == 0)
  134: 	{
  135: 	  rl_numeric_arg *= 4;
  136: 	  return 1;
  137: 	}
  138:       else if (RL_ISSTATE (RL_STATE_CALLBACK))
  139:         {
  140:           _rl_argcxt |= NUM_READONE;
  141:           return 0;	/* XXX */
  142:         }
  143:       else
  144: 	{
  145: 	  RL_SETSTATE(RL_STATE_MOREINPUT);
  146: 	  key = rl_read_key ();
  147: 	  RL_UNSETSTATE(RL_STATE_MOREINPUT);
  148: 	  rl_restore_prompt ();
  149: 	  rl_clear_message ();
  150: 	  RL_UNSETSTATE(RL_STATE_NUMERICARG);
  151: 	  if (key < 0)
  152: 	    return -1;
  153: 	  return (_rl_dispatch (key, _rl_keymap));
  154: 	}
  155:     }
  156: 
  157:   c = UNMETA (c);
  158: 
  159:   if (_rl_digit_p (c))
  160:     {
  161:       r = _rl_digit_value (c);    	
  162:       rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) +  r : r;
  163:       rl_explicit_arg = 1;
  164:       _rl_argcxt |= NUM_SAWDIGITS;
  165:     }
  166:   else if (c == '-' && rl_explicit_arg == 0)
  167:     {
  168:       rl_numeric_arg = 1;
  169:       _rl_argcxt |= NUM_SAWMINUS;
  170:       rl_arg_sign = -1;
  171:     }
  172:   else
  173:     {
  174:       /* Make M-- command equivalent to M--1 command. */
  175:       if ((_rl_argcxt & NUM_SAWMINUS) && rl_numeric_arg == 1 && rl_explicit_arg == 0)
  176: 	rl_explicit_arg = 1;
  177:       rl_restore_prompt ();
  178:       rl_clear_message ();
  179:       RL_UNSETSTATE(RL_STATE_NUMERICARG);
  180: 
  181:       r = _rl_dispatch (key, _rl_keymap);
  182:       if (RL_ISSTATE (RL_STATE_CALLBACK))
  183: 	{
  184: 	  /* At worst, this will cause an extra redisplay.  Otherwise,
  185: 	     we have to wait until the next character comes in. */
  186: 	  if (rl_done == 0)
  187: 	    (*rl_redisplay_function) ();
  188: 	  r = 0;
  189: 	}
  190:       return r;
  191:     }
  192: 
  193:   return 1;
  194: }
  195: 
  196: /* Handle C-u style numeric args, as well as M--, and M-digits. */
  197: static int
  198: rl_digit_loop ()
  199: {
  200:   int c, r;
  201: 
  202:   while (1)
  203:     {
  204:       if (_rl_arg_overflow ())
  205: 	return 1;
  206: 
  207:       c = _rl_arg_getchar ();
  208: 
  209:       if (c < 0)
  210: 	{
  211: 	  _rl_abort_internal ();
  212: 	  return -1;
  213: 	}
  214: 
  215:       r = _rl_arg_dispatch (_rl_argcxt, c);
  216:       if (r <= 0 || (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
  217:         break;
  218:     }
  219: 
  220:   return r;
  221: }
  222: 
  223: /* Create a default argument. */
  224: void
  225: _rl_reset_argument ()
  226: {
  227:   rl_numeric_arg = rl_arg_sign = 1;
  228:   rl_explicit_arg = 0;
  229:   _rl_argcxt = 0;
  230: }
  231: 
  232: /* Start a numeric argument with initial value KEY */
  233: int
  234: rl_digit_argument (ignore, key)
  235:      int ignore, key;
  236: {
  237:   _rl_arg_init ();
  238:   if (RL_ISSTATE (RL_STATE_CALLBACK))
  239:     {
  240:       _rl_arg_dispatch (_rl_argcxt, key);
  241:       rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
  242:       return 0;
  243:     }
  244:   else
  245:     {
  246:       rl_execute_next (key);
  247:       return (rl_digit_loop ());
  248:     }
  249: }
  250: 
  251: /* C-u, universal argument.  Multiply the current argument by 4.
  252:    Read a key.  If the key has nothing to do with arguments, then
  253:    dispatch on it.  If the key is the abort character then abort. */
  254: int
  255: rl_universal_argument (count, key)
  256:      int count, key;
  257: {
  258:   _rl_arg_init ();
  259:   rl_numeric_arg *= 4;
  260: 
  261:   return (RL_ISSTATE (RL_STATE_CALLBACK) ? 0 : rl_digit_loop ());
  262: }
  263: 
  264: int
  265: _rl_arg_callback (cxt)
  266:      _rl_arg_cxt cxt;
  267: {
  268:   int c, r;
  269: 
  270:   c = _rl_arg_getchar ();
  271: 
  272:   if (_rl_argcxt & NUM_READONE)
  273:     {
  274:       _rl_argcxt &= ~NUM_READONE;
  275:       rl_restore_prompt ();
  276:       rl_clear_message ();
  277:       RL_UNSETSTATE(RL_STATE_NUMERICARG);
  278:       rl_execute_next (c);
  279:       return 0;
  280:     }
  281: 
  282:   r = _rl_arg_dispatch (cxt, c);
  283:   return (r != 1);
  284: }
  285: 
  286: /* What to do when you abort reading an argument. */
  287: int
  288: rl_discard_argument ()
  289: {
  290:   rl_ding ();
  291:   rl_clear_message ();
  292:   _rl_reset_argument ();
  293: 
  294:   return 0;
  295: }
  296: 
  297: /* **************************************************************** */
  298: /*								    */
  299: /*			History Utilities			    */
  300: /*								    */
  301: /* **************************************************************** */
  302: 
  303: /* We already have a history library, and that is what we use to control
  304:    the history features of readline.  This is our local interface to
  305:    the history mechanism. */
  306: 
  307: /* While we are editing the history, this is the saved
  308:    version of the original line. */
  309: HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
  310: 
  311: /* Set the history pointer back to the last entry in the history. */
  312: void
  313: _rl_start_using_history ()
  314: {
  315:   using_history ();
  316:   if (_rl_saved_line_for_history)
  317:     _rl_free_history_entry (_rl_saved_line_for_history);
  318: 
  319:   _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
  320: }
  321: 
  322: /* Free the contents (and containing structure) of a HIST_ENTRY. */
  323: void
  324: _rl_free_history_entry (entry)
  325:      HIST_ENTRY *entry;
  326: {
  327:   if (entry == 0)
  328:     return;
  329: 
  330:   FREE (entry->line);
  331:   FREE (entry->timestamp);
  332: 
  333:   xfree (entry);
  334: }
  335: 
  336: /* Perhaps put back the current line if it has changed. */
  337: int
  338: rl_maybe_replace_line ()
  339: {
  340:   HIST_ENTRY *temp;
  341: 
  342:   temp = current_history ();
  343:   /* If the current line has changed, save the changes. */
  344:   if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
  345:     {
  346:       temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
  347:       xfree (temp->line);
  348:       FREE (temp->timestamp);
  349:       xfree (temp);
  350:     }
  351:   return 0;
  352: }
  353: 
  354: /* Restore the _rl_saved_line_for_history if there is one. */
  355: int
  356: rl_maybe_unsave_line ()
  357: {
  358:   if (_rl_saved_line_for_history)
  359:     {
  360:       /* Can't call with `1' because rl_undo_list might point to an undo
  361: 	 list from a history entry, as in rl_replace_from_history() below. */
  362:       rl_replace_line (_rl_saved_line_for_history->line, 0);
  363:       rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
  364:       _rl_free_history_entry (_rl_saved_line_for_history);
  365:       _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
  366:       rl_point = rl_end;	/* rl_replace_line sets rl_end */
  367:     }
  368:   else
  369:     rl_ding ();
  370:   return 0;
  371: }
  372: 
  373: /* Save the current line in _rl_saved_line_for_history. */
  374: int
  375: rl_maybe_save_line ()
  376: {
  377:   if (_rl_saved_line_for_history == 0)
  378:     {
  379:       _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
  380:       _rl_saved_line_for_history->line = savestring (rl_line_buffer);
  381:       _rl_saved_line_for_history->timestamp = (char *)NULL;
  382:       _rl_saved_line_for_history->data = (char *)rl_undo_list;
  383:     }
  384: 
  385:   return 0;
  386: }
  387: 
  388: int
  389: _rl_free_saved_history_line ()
  390: {
  391:   if (_rl_saved_line_for_history)
  392:     {
  393:       _rl_free_history_entry (_rl_saved_line_for_history);
  394:       _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
  395:     }
  396:   return 0;
  397: }
  398: 
  399: static void
  400: _rl_history_set_point ()
  401: {
  402:   rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1)
  403: 		? _rl_history_saved_point
  404: 		: rl_end;
  405:   if (rl_point > rl_end)
  406:     rl_point = rl_end;
  407: 
  408: #if defined (VI_MODE)
  409:   if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap)
  410:     rl_point = 0;
  411: #endif /* VI_MODE */
  412: 
  413:   if (rl_editing_mode == emacs_mode)
  414:     rl_mark = (rl_point == rl_end ? 0 : rl_end);
  415: }
  416: 
  417: void
  418: rl_replace_from_history (entry, flags)
  419:      HIST_ENTRY *entry;
  420:      int flags;			/* currently unused */
  421: {
  422:   /* Can't call with `1' because rl_undo_list might point to an undo list
  423:      from a history entry, just like we're setting up here. */
  424:   rl_replace_line (entry->line, 0);
  425:   rl_undo_list = (UNDO_LIST *)entry->data;
  426:   rl_point = rl_end;
  427:   rl_mark = 0;
  428: 
  429: #if defined (VI_MODE)
  430:   if (rl_editing_mode == vi_mode)
  431:     {
  432:       rl_point = 0;
  433:       rl_mark = rl_end;
  434:     }
  435: #endif
  436: }
  437: 
  438: /* Process and free undo lists attached to each history entry prior to the
  439:    current entry, inclusive, reverting each line to its saved state.  This 
  440:    is destructive, and state about the current line is lost.  This is not
  441:    intended to be called while actively editing, and the current line is
  442:    not assumed to have been added to the history list. */
  443: void
  444: _rl_revert_all_lines ()
  445: {
  446:   int hpos;
  447:   HIST_ENTRY *entry;
  448:   UNDO_LIST *ul, *saved_undo_list;
  449:   char *lbuf;
  450: 
  451:   lbuf = savestring (rl_line_buffer);
  452:   saved_undo_list = rl_undo_list;
  453:   hpos = where_history ();
  454: 
  455:   entry = (hpos == history_length) ? previous_history () : current_history ();
  456:   while (entry)
  457:     {
  458:       if (ul = (UNDO_LIST *)entry->data)
  459: 	{
  460: 	  if (ul == saved_undo_list)
  461: 	    saved_undo_list = 0;
  462: 	  /* Set up rl_line_buffer and other variables from history entry */
  463: 	  rl_replace_from_history (entry, 0);	/* entry->line is now current */
  464: 	  /* Undo all changes to this history entry */
  465: 	  while (rl_undo_list)
  466: 	    rl_do_undo ();
  467: 	  /* And copy the reverted line back to the history entry, preserving
  468: 	     the timestamp. */
  469: 	  FREE (entry->line);
  470: 	  entry->line = savestring (rl_line_buffer);
  471: 	  entry->data = 0;
  472: 	}
  473:       entry = previous_history ();
  474:     }
  475: 
  476:   /* Restore history state */
  477:   rl_undo_list = saved_undo_list;	/* may have been set to null */
  478:   history_set_pos (hpos);
  479:   
  480:   /* reset the line buffer */
  481:   rl_replace_line (lbuf, 0);
  482:   _rl_set_the_line ();
  483: 
  484:   /* and clean up */
  485:   xfree (lbuf);
  486: }  
  487: 
  488: /* Free the history list, including private readline data and take care
  489:    of pointer aliases to history data.  Resets rl_undo_list if it points
  490:    to an UNDO_LIST * saved as some history entry's data member.  This
  491:    should not be called while editing is active. */
  492: void
  493: rl_clear_history ()
  494: {
  495:   HIST_ENTRY **hlist, *hent;
  496:   register int i;
  497:   UNDO_LIST *ul, *saved_undo_list;
  498: 
  499:   saved_undo_list = rl_undo_list;
  500:   hlist = history_list ();		/* direct pointer, not copy */
  501: 
  502:   for (i = 0; i < history_length; i++)
  503:     {
  504:       hent = hlist[i];
  505:       if (ul = (UNDO_LIST *)hent->data)
  506: 	{
  507: 	  if (ul == saved_undo_list)
  508: 	    saved_undo_list = 0;
  509: 	  _rl_free_undo_list (ul);
  510: 	  hent->data = 0;
  511: 	}
  512:       _rl_free_history_entry (hent);
  513:     }
  514: 
  515:   history_offset = history_length = 0;
  516:   rl_undo_list = saved_undo_list;	/* should be NULL */
  517: }
  518: 
  519: /* **************************************************************** */
  520: /*								    */
  521: /*			History Commands			    */
  522: /*								    */
  523: /* **************************************************************** */
  524: 
  525: /* Meta-< goes to the start of the history. */
  526: int
  527: rl_beginning_of_history (count, key)
  528:      int count, key;
  529: {
  530:   return (rl_get_previous_history (1 + where_history (), key));
  531: }
  532: 
  533: /* Meta-> goes to the end of the history.  (The current line). */
  534: int
  535: rl_end_of_history (count, key)
  536:      int count, key;
  537: {
  538:   rl_maybe_replace_line ();
  539:   using_history ();
  540:   rl_maybe_unsave_line ();
  541:   return 0;
  542: }
  543: 
  544: /* Move down to the next history line. */
  545: int
  546: rl_get_next_history (count, key)
  547:      int count, key;
  548: {
  549:   HIST_ENTRY *temp;
  550: 
  551:   if (count < 0)
  552:     return (rl_get_previous_history (-count, key));
  553: 
  554:   if (count == 0)
  555:     return 0;
  556: 
  557:   rl_maybe_replace_line ();
  558: 
  559:   /* either not saved by rl_newline or at end of line, so set appropriately. */
  560:   if (_rl_history_saved_point == -1 && (rl_point || rl_end))
  561:     _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
  562: 
  563:   temp = (HIST_ENTRY *)NULL;
  564:   while (count)
  565:     {
  566:       temp = next_history ();
  567:       if (!temp)
  568: 	break;
  569:       --count;
  570:     }
  571: 
  572:   if (temp == 0)
  573:     rl_maybe_unsave_line ();
  574:   else
  575:     {
  576:       rl_replace_from_history (temp, 0);
  577:       _rl_history_set_point ();
  578:     }
  579:   return 0;
  580: }
  581: 
  582: /* Get the previous item out of our interactive history, making it the current
  583:    line.  If there is no previous history, just ding. */
  584: int
  585: rl_get_previous_history (count, key)
  586:      int count, key;
  587: {
  588:   HIST_ENTRY *old_temp, *temp;
  589: 
  590:   if (count < 0)
  591:     return (rl_get_next_history (-count, key));
  592: 
  593:   if (count == 0)
  594:     return 0;
  595: 
  596:   /* either not saved by rl_newline or at end of line, so set appropriately. */
  597:   if (_rl_history_saved_point == -1 && (rl_point || rl_end))
  598:     _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
  599: 
  600:   /* If we don't have a line saved, then save this one. */
  601:   rl_maybe_save_line ();
  602: 
  603:   /* If the current line has changed, save the changes. */
  604:   rl_maybe_replace_line ();
  605: 
  606:   temp = old_temp = (HIST_ENTRY *)NULL;
  607:   while (count)
  608:     {
  609:       temp = previous_history ();
  610:       if (temp == 0)
  611: 	break;
  612: 
  613:       old_temp = temp;
  614:       --count;
  615:     }
  616: 
  617:   /* If there was a large argument, and we moved back to the start of the
  618:      history, that is not an error.  So use the last value found. */
  619:   if (!temp && old_temp)
  620:     temp = old_temp;
  621: 
  622:   if (temp == 0)
  623:     rl_ding ();
  624:   else
  625:     {
  626:       rl_replace_from_history (temp, 0);
  627:       _rl_history_set_point ();
  628:     }
  629: 
  630:   return 0;
  631: }
  632: 
  633: /* **************************************************************** */
  634: /*								    */
  635: /*			    Editing Modes			    */
  636: /*								    */
  637: /* **************************************************************** */
  638: /* How to toggle back and forth between editing modes. */
  639: int
  640: rl_vi_editing_mode (count, key)
  641:      int count, key;
  642: {
  643: #if defined (VI_MODE)
  644:   _rl_set_insert_mode (RL_IM_INSERT, 1);	/* vi mode ignores insert mode */
  645:   rl_editing_mode = vi_mode;
  646:   rl_vi_insert_mode (1, key);
  647: #endif /* VI_MODE */
  648: 
  649:   return 0;
  650: }
  651: 
  652: int
  653: rl_emacs_editing_mode (count, key)
  654:      int count, key;
  655: {
  656:   rl_editing_mode = emacs_mode;
  657:   _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
  658:   _rl_keymap = emacs_standard_keymap;
  659: 
  660:   if (_rl_show_mode_in_prompt)
  661:     _rl_reset_prompt ();
  662: 
  663:   return 0;
  664: }
  665: 
  666: /* Function for the rest of the library to use to set insert/overwrite mode. */
  667: void
  668: _rl_set_insert_mode (im, force)
  669:      int im, force;
  670: {
  671: #ifdef CURSOR_MODE
  672:   _rl_set_cursor (im, force);
  673: #endif
  674: 
  675:   rl_insert_mode = im;
  676: }
  677: 
  678: /* Toggle overwrite mode.  A positive explicit argument selects overwrite
  679:    mode.  A negative or zero explicit argument selects insert mode. */
  680: int
  681: rl_overwrite_mode (count, key)
  682:      int count, key;
  683: {
  684:   if (rl_explicit_arg == 0)
  685:     _rl_set_insert_mode (rl_insert_mode ^ 1, 0);
  686:   else if (count > 0)
  687:     _rl_set_insert_mode (RL_IM_OVERWRITE, 0);
  688:   else
  689:     _rl_set_insert_mode (RL_IM_INSERT, 0);
  690: 
  691:   return 0;
  692: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>