File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / readline / text.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, 11 months ago) by misho
Branches: readline, MAIN
CVS tags: v6_3p10_cross, v6_3p10, v6_3, p6, HEAD
readline 6.3

    1: /* text.c -- text handling commands for readline. */
    2: 
    3: /* Copyright (C) 1987-2010 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: #if defined (__EMX__)
   49: #  define INCL_DOSPROCESS
   50: #  include <os2.h>
   51: #endif /* __EMX__ */
   52: 
   53: /* Some standard library routines. */
   54: #include "readline.h"
   55: #include "history.h"
   56: 
   57: #include "rlprivate.h"
   58: #include "rlshell.h"
   59: #include "xmalloc.h"
   60: 
   61: /* Forward declarations. */
   62: static int rl_change_case PARAMS((int, int));
   63: static int _rl_char_search PARAMS((int, int, int));
   64: 
   65: #if defined (READLINE_CALLBACKS)
   66: static int _rl_insert_next_callback PARAMS((_rl_callback_generic_arg *));
   67: static int _rl_char_search_callback PARAMS((_rl_callback_generic_arg *));
   68: #endif
   69: 
   70: /* The largest chunk of text that can be inserted in one call to
   71:    rl_insert_text.  Text blocks larger than this are divided. */
   72: #define TEXT_COUNT_MAX	1024
   73: 
   74: /* **************************************************************** */
   75: /*								    */
   76: /*			Insert and Delete			    */
   77: /*								    */
   78: /* **************************************************************** */
   79: 
   80: /* Insert a string of text into the line at point.  This is the only
   81:    way that you should do insertion.  _rl_insert_char () calls this
   82:    function.  Returns the number of characters inserted. */
   83: int
   84: rl_insert_text (string)
   85:      const char *string;
   86: {
   87:   register int i, l;
   88: 
   89:   l = (string && *string) ? strlen (string) : 0;
   90:   if (l == 0)
   91:     return 0;
   92: 
   93:   if (rl_end + l >= rl_line_buffer_len)
   94:     rl_extend_line_buffer (rl_end + l);
   95: 
   96:   for (i = rl_end; i >= rl_point; i--)
   97:     rl_line_buffer[i + l] = rl_line_buffer[i];
   98:   strncpy (rl_line_buffer + rl_point, string, l);
   99: 
  100:   /* Remember how to undo this if we aren't undoing something. */
  101:   if (_rl_doing_an_undo == 0)
  102:     {
  103:       /* If possible and desirable, concatenate the undos. */
  104:       if ((l == 1) &&
  105: 	  rl_undo_list &&
  106: 	  (rl_undo_list->what == UNDO_INSERT) &&
  107: 	  (rl_undo_list->end == rl_point) &&
  108: 	  (rl_undo_list->end - rl_undo_list->start < 20))
  109: 	rl_undo_list->end++;
  110:       else
  111: 	rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
  112:     }
  113:   rl_point += l;
  114:   rl_end += l;
  115:   rl_line_buffer[rl_end] = '\0';
  116:   return l;
  117: }
  118: 
  119: /* Delete the string between FROM and TO.  FROM is inclusive, TO is not.
  120:    Returns the number of characters deleted. */
  121: int
  122: rl_delete_text (from, to)
  123:      int from, to;
  124: {
  125:   register char *text;
  126:   register int diff, i;
  127: 
  128:   /* Fix it if the caller is confused. */
  129:   if (from > to)
  130:     SWAP (from, to);
  131: 
  132:   /* fix boundaries */
  133:   if (to > rl_end)
  134:     {
  135:       to = rl_end;
  136:       if (from > to)
  137: 	from = to;
  138:     }
  139:   if (from < 0)
  140:     from = 0;
  141: 
  142:   text = rl_copy_text (from, to);
  143: 
  144:   /* Some versions of strncpy() can't handle overlapping arguments. */
  145:   diff = to - from;
  146:   for (i = from; i < rl_end - diff; i++)
  147:     rl_line_buffer[i] = rl_line_buffer[i + diff];
  148: 
  149:   /* Remember how to undo this delete. */
  150:   if (_rl_doing_an_undo == 0)
  151:     rl_add_undo (UNDO_DELETE, from, to, text);
  152:   else
  153:     xfree (text);
  154: 
  155:   rl_end -= diff;
  156:   rl_line_buffer[rl_end] = '\0';
  157:   return (diff);
  158: }
  159: 
  160: /* Fix up point so that it is within the line boundaries after killing
  161:    text.  If FIX_MARK_TOO is non-zero, the mark is forced within line
  162:    boundaries also. */
  163: 
  164: #define _RL_FIX_POINT(x) \
  165: 	do { \
  166: 	if (x > rl_end) \
  167: 	  x = rl_end; \
  168: 	else if (x < 0) \
  169: 	  x = 0; \
  170: 	} while (0)
  171: 
  172: void
  173: _rl_fix_point (fix_mark_too)
  174:      int fix_mark_too;
  175: {
  176:   _RL_FIX_POINT (rl_point);
  177:   if (fix_mark_too)
  178:     _RL_FIX_POINT (rl_mark);
  179: }
  180: #undef _RL_FIX_POINT
  181: 
  182: /* Replace the contents of the line buffer between START and END with
  183:    TEXT.  The operation is undoable.  To replace the entire line in an
  184:    undoable mode, use _rl_replace_text(text, 0, rl_end); */
  185: int
  186: _rl_replace_text (text, start, end)
  187:      const char *text;
  188:      int start, end;
  189: {
  190:   int n;
  191: 
  192:   n = 0;
  193:   rl_begin_undo_group ();
  194:   if (start <= end)
  195:     rl_delete_text (start, end + 1);
  196:   rl_point = start;
  197:   if (*text)
  198:     n = rl_insert_text (text);
  199:   rl_end_undo_group ();
  200: 
  201:   return n;
  202: }
  203: 
  204: /* Replace the current line buffer contents with TEXT.  If CLEAR_UNDO is
  205:    non-zero, we free the current undo list. */
  206: void
  207: rl_replace_line (text, clear_undo)
  208:      const char *text;
  209:      int clear_undo;
  210: {
  211:   int len;
  212: 
  213:   len = strlen (text);
  214:   if (len >= rl_line_buffer_len)
  215:     rl_extend_line_buffer (len);
  216:   strcpy (rl_line_buffer, text);
  217:   rl_end = len;
  218: 
  219:   if (clear_undo)
  220:     rl_free_undo_list ();
  221: 
  222:   _rl_fix_point (1);
  223: }
  224: 
  225: /* **************************************************************** */
  226: /*								    */
  227: /*			Readline character functions		    */
  228: /*								    */
  229: /* **************************************************************** */
  230: 
  231: /* This is not a gap editor, just a stupid line input routine.  No hair
  232:    is involved in writing any of the functions, and none should be. */
  233: 
  234: /* Note that:
  235: 
  236:    rl_end is the place in the string that we would place '\0';
  237:    i.e., it is always safe to place '\0' there.
  238: 
  239:    rl_point is the place in the string where the cursor is.  Sometimes
  240:    this is the same as rl_end.
  241: 
  242:    Any command that is called interactively receives two arguments.
  243:    The first is a count: the numeric arg passed to this command.
  244:    The second is the key which invoked this command.
  245: */
  246: 
  247: /* **************************************************************** */
  248: /*								    */
  249: /*			Movement Commands			    */
  250: /*								    */
  251: /* **************************************************************** */
  252: 
  253: /* Note that if you `optimize' the display for these functions, you cannot
  254:    use said functions in other functions which do not do optimizing display.
  255:    I.e., you will have to update the data base for rl_redisplay, and you
  256:    might as well let rl_redisplay do that job. */
  257: 
  258: /* Move forward COUNT bytes. */
  259: int
  260: rl_forward_byte (count, key)
  261:      int count, key;
  262: {
  263:   if (count < 0)
  264:     return (rl_backward_byte (-count, key));
  265: 
  266:   if (count > 0)
  267:     {
  268:       int end, lend;
  269: 
  270:       end = rl_point + count;
  271: #if defined (VI_MODE)
  272:       lend = rl_end > 0 ? rl_end - (VI_COMMAND_MODE()) : rl_end;
  273: #else
  274:       lend = rl_end;
  275: #endif
  276: 
  277:       if (end > lend)
  278: 	{
  279: 	  rl_point = lend;
  280: 	  rl_ding ();
  281: 	}
  282:       else
  283: 	rl_point = end;
  284:     }
  285: 
  286:   if (rl_end < 0)
  287:     rl_end = 0;
  288: 
  289:   return 0;
  290: }
  291: 
  292: int
  293: _rl_forward_char_internal (count)
  294:      int count;
  295: {
  296:   int point;
  297: 
  298: #if defined (HANDLE_MULTIBYTE)
  299:   point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
  300: 
  301: #if defined (VI_MODE)
  302:   if (point >= rl_end && VI_COMMAND_MODE())
  303:     point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO);
  304: #endif
  305: 
  306:     if (rl_end < 0)
  307: 	rl_end = 0;
  308: #else
  309:   point = rl_point + count;
  310:   if (point > rl_end)
  311:     point = rl_end;
  312: #endif
  313: 
  314:   return (point);
  315: }
  316: 
  317: #if defined (HANDLE_MULTIBYTE)
  318: /* Move forward COUNT characters. */
  319: int
  320: rl_forward_char (count, key)
  321:      int count, key;
  322: {
  323:   int point;
  324: 
  325:   if (MB_CUR_MAX == 1 || rl_byte_oriented)
  326:     return (rl_forward_byte (count, key));
  327: 
  328:   if (count < 0)
  329:     return (rl_backward_char (-count, key));
  330: 
  331:   if (count > 0)
  332:     {
  333:       if (rl_point == rl_end && EMACS_MODE())
  334: 	{
  335: 	  rl_ding ();
  336: 	  return 0;
  337: 	}
  338: 
  339:       point = _rl_forward_char_internal (count);
  340: 
  341:       if (rl_point == point)
  342: 	rl_ding ();
  343: 
  344:       rl_point = point;
  345:     }
  346: 
  347:   return 0;
  348: }
  349: #else /* !HANDLE_MULTIBYTE */
  350: int
  351: rl_forward_char (count, key)
  352:      int count, key;
  353: {
  354:   return (rl_forward_byte (count, key));
  355: }
  356: #endif /* !HANDLE_MULTIBYTE */
  357:   
  358: /* Backwards compatibility. */
  359: int
  360: rl_forward (count, key)
  361:      int count, key;
  362: {
  363:   return (rl_forward_char (count, key));
  364: }
  365: 
  366: /* Move backward COUNT bytes. */
  367: int
  368: rl_backward_byte (count, key)
  369:      int count, key;
  370: {
  371:   if (count < 0)
  372:     return (rl_forward_byte (-count, key));
  373: 
  374:   if (count > 0)
  375:     {
  376:       if (rl_point < count)
  377: 	{
  378: 	  rl_point = 0;
  379: 	  rl_ding ();
  380: 	}
  381:       else
  382: 	rl_point -= count;
  383:     }
  384: 
  385:   if (rl_point < 0)
  386:     rl_point = 0;
  387: 
  388:   return 0;
  389: }
  390: 
  391: #if defined (HANDLE_MULTIBYTE)
  392: /* Move backward COUNT characters. */
  393: int
  394: rl_backward_char (count, key)
  395:      int count, key;
  396: {
  397:   int point;
  398: 
  399:   if (MB_CUR_MAX == 1 || rl_byte_oriented)
  400:     return (rl_backward_byte (count, key));
  401: 
  402:   if (count < 0)
  403:     return (rl_forward_char (-count, key));
  404: 
  405:   if (count > 0)
  406:     {
  407:       point = rl_point;
  408: 
  409:       while (count > 0 && point > 0)
  410: 	{
  411: 	  point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO);
  412: 	  count--;
  413: 	}
  414:       if (count > 0)
  415: 	{
  416: 	  rl_point = 0;
  417: 	  rl_ding ();
  418: 	}
  419:       else
  420:         rl_point = point;
  421:     }
  422: 
  423:   return 0;
  424: }
  425: #else
  426: int
  427: rl_backward_char (count, key)
  428:      int count, key;
  429: {
  430:   return (rl_backward_byte (count, key));
  431: }
  432: #endif
  433: 
  434: /* Backwards compatibility. */
  435: int
  436: rl_backward (count, key)
  437:      int count, key;
  438: {
  439:   return (rl_backward_char (count, key));
  440: }
  441: 
  442: /* Move to the beginning of the line. */
  443: int
  444: rl_beg_of_line (count, key)
  445:      int count, key;
  446: {
  447:   rl_point = 0;
  448:   return 0;
  449: }
  450: 
  451: /* Move to the end of the line. */
  452: int
  453: rl_end_of_line (count, key)
  454:      int count, key;
  455: {
  456:   rl_point = rl_end;
  457:   return 0;
  458: }
  459: 
  460: /* Move forward a word.  We do what Emacs does.  Handles multibyte chars. */
  461: int
  462: rl_forward_word (count, key)
  463:      int count, key;
  464: {
  465:   int c;
  466: 
  467:   if (count < 0)
  468:     return (rl_backward_word (-count, key));
  469: 
  470:   while (count)
  471:     {
  472:       if (rl_point == rl_end)
  473: 	return 0;
  474: 
  475:       /* If we are not in a word, move forward until we are in one.
  476: 	 Then, move forward until we hit a non-alphabetic character. */
  477:       c = _rl_char_value (rl_line_buffer, rl_point);
  478: 
  479:       if (_rl_walphabetic (c) == 0)
  480: 	{
  481: 	  rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
  482: 	  while (rl_point < rl_end)
  483: 	    {
  484: 	      c = _rl_char_value (rl_line_buffer, rl_point);
  485: 	      if (_rl_walphabetic (c))
  486: 		break;
  487: 	      rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
  488: 	    }
  489: 	}
  490: 
  491:       if (rl_point == rl_end)
  492: 	return 0;
  493: 
  494:       rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
  495:       while (rl_point < rl_end)
  496: 	{
  497: 	  c = _rl_char_value (rl_line_buffer, rl_point);
  498: 	  if (_rl_walphabetic (c) == 0)
  499: 	    break;
  500: 	  rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
  501: 	}
  502: 
  503:       --count;
  504:     }
  505: 
  506:   return 0;
  507: }
  508: 
  509: /* Move backward a word.  We do what Emacs does.  Handles multibyte chars. */
  510: int
  511: rl_backward_word (count, key)
  512:      int count, key;
  513: {
  514:   int c, p;
  515: 
  516:   if (count < 0)
  517:     return (rl_forward_word (-count, key));
  518: 
  519:   while (count)
  520:     {
  521:       if (rl_point == 0)
  522: 	return 0;
  523: 
  524:       /* Like rl_forward_word (), except that we look at the characters
  525: 	 just before point. */
  526: 
  527:       p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
  528:       c = _rl_char_value (rl_line_buffer, p);
  529: 
  530:       if (_rl_walphabetic (c) == 0)
  531: 	{
  532: 	  rl_point = p;
  533: 	  while (rl_point > 0)
  534: 	    {
  535: 	      p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
  536: 	      c = _rl_char_value (rl_line_buffer, p);
  537: 	      if (_rl_walphabetic (c))
  538: 		break;
  539: 	      rl_point = p;
  540: 	    }
  541: 	}
  542: 
  543:       while (rl_point)
  544: 	{
  545: 	  p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
  546: 	  c = _rl_char_value (rl_line_buffer, p);	  
  547: 	  if (_rl_walphabetic (c) == 0)
  548: 	    break;
  549: 	  else
  550: 	    rl_point = p;
  551: 	}
  552: 
  553:       --count;
  554:     }
  555: 
  556:   return 0;
  557: }
  558: 
  559: /* Clear the current line.  Numeric argument to C-l does this. */
  560: int
  561: rl_refresh_line (ignore1, ignore2)
  562:      int ignore1, ignore2;
  563: {
  564:   int curr_line;
  565: 
  566:   curr_line = _rl_current_display_line ();
  567: 
  568:   _rl_move_vert (curr_line);
  569:   _rl_move_cursor_relative (0, rl_line_buffer);   /* XXX is this right */
  570: 
  571:   _rl_clear_to_eol (0);		/* arg of 0 means to not use spaces */
  572: 
  573:   rl_forced_update_display ();
  574:   rl_display_fixed = 1;
  575: 
  576:   return 0;
  577: }
  578: 
  579: /* C-l typed to a line without quoting clears the screen, and then reprints
  580:    the prompt and the current input line.  Given a numeric arg, redraw only
  581:    the current line. */
  582: int
  583: rl_clear_screen (count, key)
  584:      int count, key;
  585: {
  586:   if (rl_explicit_arg)
  587:     {
  588:       rl_refresh_line (count, key);
  589:       return 0;
  590:     }
  591: 
  592:   _rl_clear_screen ();		/* calls termcap function to clear screen */
  593:   rl_forced_update_display ();
  594:   rl_display_fixed = 1;
  595: 
  596:   return 0;
  597: }
  598: 
  599: int
  600: rl_skip_csi_sequence (count, key)
  601:      int count, key;
  602: {
  603:   int ch;
  604: 
  605:   RL_SETSTATE (RL_STATE_MOREINPUT);
  606:   do
  607:     ch = rl_read_key ();
  608:   while (ch >= 0x20 && ch < 0x40);
  609:   RL_UNSETSTATE (RL_STATE_MOREINPUT);
  610: 
  611:   return 0;
  612: }
  613: 
  614: int
  615: rl_arrow_keys (count, c)
  616:      int count, c;
  617: {
  618:   int ch;
  619: 
  620:   RL_SETSTATE(RL_STATE_MOREINPUT);
  621:   ch = rl_read_key ();
  622:   RL_UNSETSTATE(RL_STATE_MOREINPUT);
  623: 
  624:   switch (_rl_to_upper (ch))
  625:     {
  626:     case 'A':
  627:       rl_get_previous_history (count, ch);
  628:       break;
  629: 
  630:     case 'B':
  631:       rl_get_next_history (count, ch);
  632:       break;
  633: 
  634:     case 'C':
  635:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
  636: 	rl_forward_char (count, ch);
  637:       else
  638: 	rl_forward_byte (count, ch);
  639:       break;
  640: 
  641:     case 'D':
  642:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
  643: 	rl_backward_char (count, ch);
  644:       else
  645: 	rl_backward_byte (count, ch);
  646:       break;
  647: 
  648:     default:
  649:       rl_ding ();
  650:     }
  651: 
  652:   return 0;
  653: }
  654: 
  655: /* **************************************************************** */
  656: /*								    */
  657: /*			Text commands				    */
  658: /*								    */
  659: /* **************************************************************** */
  660: 
  661: #ifdef HANDLE_MULTIBYTE
  662: static char pending_bytes[MB_LEN_MAX];
  663: static int pending_bytes_length = 0;
  664: static mbstate_t ps = {0};
  665: #endif
  666: 
  667: /* Insert the character C at the current location, moving point forward.
  668:    If C introduces a multibyte sequence, we read the whole sequence and
  669:    then insert the multibyte char into the line buffer. */
  670: int
  671: _rl_insert_char (count, c)
  672:      int count, c;
  673: {
  674:   register int i;
  675:   char *string;
  676: #ifdef HANDLE_MULTIBYTE
  677:   int string_size;
  678:   char incoming[MB_LEN_MAX + 1];
  679:   int incoming_length = 0;
  680:   mbstate_t ps_back;
  681:   static int stored_count = 0;
  682: #endif
  683: 
  684:   if (count <= 0)
  685:     return 0;
  686: 
  687: #if defined (HANDLE_MULTIBYTE)
  688:   if (MB_CUR_MAX == 1 || rl_byte_oriented)
  689:     {
  690:       incoming[0] = c;
  691:       incoming[1] = '\0';
  692:       incoming_length = 1;
  693:     }
  694:   else
  695:     {
  696:       wchar_t wc;
  697:       size_t ret;
  698: 
  699:       if (stored_count <= 0)
  700: 	stored_count = count;
  701:       else
  702: 	count = stored_count;
  703: 
  704:       ps_back = ps;
  705:       pending_bytes[pending_bytes_length++] = c;
  706:       ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps);
  707: 
  708:       if (ret == (size_t)-2)
  709: 	{
  710: 	  /* Bytes too short to compose character, try to wait for next byte.
  711: 	     Restore the state of the byte sequence, because in this case the
  712: 	     effect of mbstate is undefined. */
  713: 	  ps = ps_back;
  714: 	  return 1;
  715: 	}
  716:       else if (ret == (size_t)-1)
  717: 	{
  718: 	  /* Invalid byte sequence for the current locale.  Treat first byte
  719: 	     as a single character. */
  720: 	  incoming[0] = pending_bytes[0];
  721: 	  incoming[1] = '\0';
  722: 	  incoming_length = 1;
  723: 	  pending_bytes_length--;
  724: 	  memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
  725: 	  /* Clear the state of the byte sequence, because in this case the
  726: 	     effect of mbstate is undefined. */
  727: 	  memset (&ps, 0, sizeof (mbstate_t));
  728: 	}
  729:       else if (ret == (size_t)0)
  730: 	{
  731: 	  incoming[0] = '\0';
  732: 	  incoming_length = 0;
  733: 	  pending_bytes_length--;
  734: 	  /* Clear the state of the byte sequence, because in this case the
  735: 	     effect of mbstate is undefined. */
  736: 	  memset (&ps, 0, sizeof (mbstate_t));
  737: 	}
  738:       else
  739: 	{
  740: 	  /* We successfully read a single multibyte character. */
  741: 	  memcpy (incoming, pending_bytes, pending_bytes_length);
  742: 	  incoming[pending_bytes_length] = '\0';
  743: 	  incoming_length = pending_bytes_length;
  744: 	  pending_bytes_length = 0;
  745: 	}
  746:     }
  747: #endif /* HANDLE_MULTIBYTE */
  748: 	  
  749:   /* If we can optimize, then do it.  But don't let people crash
  750:      readline because of extra large arguments. */
  751:   if (count > 1 && count <= TEXT_COUNT_MAX)
  752:     {
  753: #if defined (HANDLE_MULTIBYTE)
  754:       string_size = count * incoming_length;
  755:       string = (char *)xmalloc (1 + string_size);
  756: 
  757:       i = 0;
  758:       while (i < string_size)
  759: 	{
  760: 	  strncpy (string + i, incoming, incoming_length);
  761: 	  i += incoming_length;
  762: 	}
  763:       incoming_length = 0;
  764:       stored_count = 0;
  765: #else /* !HANDLE_MULTIBYTE */
  766:       string = (char *)xmalloc (1 + count);
  767: 
  768:       for (i = 0; i < count; i++)
  769: 	string[i] = c;
  770: #endif /* !HANDLE_MULTIBYTE */
  771: 
  772:       string[i] = '\0';
  773:       rl_insert_text (string);
  774:       xfree (string);
  775: 
  776:       return 0;
  777:     }
  778: 
  779:   if (count > TEXT_COUNT_MAX)
  780:     {
  781:       int decreaser;
  782: #if defined (HANDLE_MULTIBYTE)
  783:       string_size = incoming_length * TEXT_COUNT_MAX;
  784:       string = (char *)xmalloc (1 + string_size);
  785: 
  786:       i = 0;
  787:       while (i < string_size)
  788: 	{
  789: 	  strncpy (string + i, incoming, incoming_length);
  790: 	  i += incoming_length;
  791: 	}
  792: 
  793:       while (count)
  794: 	{
  795: 	  decreaser = (count > TEXT_COUNT_MAX) ? TEXT_COUNT_MAX : count;
  796: 	  string[decreaser*incoming_length] = '\0';
  797: 	  rl_insert_text (string);
  798: 	  count -= decreaser;
  799: 	}
  800: 
  801:       xfree (string);
  802:       incoming_length = 0;
  803:       stored_count = 0;
  804: #else /* !HANDLE_MULTIBYTE */
  805:       char str[TEXT_COUNT_MAX+1];
  806: 
  807:       for (i = 0; i < TEXT_COUNT_MAX; i++)
  808: 	str[i] = c;
  809: 
  810:       while (count)
  811: 	{
  812: 	  decreaser = (count > TEXT_COUNT_MAX ? TEXT_COUNT_MAX : count);
  813: 	  str[decreaser] = '\0';
  814: 	  rl_insert_text (str);
  815: 	  count -= decreaser;
  816: 	}
  817: #endif /* !HANDLE_MULTIBYTE */
  818: 
  819:       return 0;
  820:     }
  821: 
  822:   if (MB_CUR_MAX == 1 || rl_byte_oriented)
  823:     {
  824:       /* We are inserting a single character.
  825: 	 If there is pending input, then make a string of all of the
  826: 	 pending characters that are bound to rl_insert, and insert
  827: 	 them all.  Don't do this if we're current reading input from
  828: 	 a macro. */
  829:       if ((RL_ISSTATE (RL_STATE_MACROINPUT) == 0) && _rl_pushed_input_available ())
  830: 	_rl_insert_typein (c);
  831:       else
  832: 	{
  833: 	  /* Inserting a single character. */
  834: 	  char str[2];
  835: 
  836: 	  str[1] = '\0';
  837: 	  str[0] = c;
  838: 	  rl_insert_text (str);
  839: 	}
  840:     }
  841: #if defined (HANDLE_MULTIBYTE)
  842:   else
  843:     {
  844:       rl_insert_text (incoming);
  845:       stored_count = 0;
  846:     }
  847: #endif
  848: 
  849:   return 0;
  850: }
  851: 
  852: /* Overwrite the character at point (or next COUNT characters) with C.
  853:    If C introduces a multibyte character sequence, read the entire sequence
  854:    before starting the overwrite loop. */
  855: int
  856: _rl_overwrite_char (count, c)
  857:      int count, c;
  858: {
  859:   int i;
  860: #if defined (HANDLE_MULTIBYTE)
  861:   char mbkey[MB_LEN_MAX];
  862:   int k;
  863: 
  864:   /* Read an entire multibyte character sequence to insert COUNT times. */
  865:   if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
  866:     k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX);
  867: #endif
  868: 
  869:   rl_begin_undo_group ();
  870: 
  871:   for (i = 0; i < count; i++)
  872:     {
  873: #if defined (HANDLE_MULTIBYTE)
  874:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
  875: 	rl_insert_text (mbkey);
  876:       else
  877: #endif
  878: 	_rl_insert_char (1, c);
  879: 
  880:       if (rl_point < rl_end)
  881: 	rl_delete (1, c);
  882:     }
  883: 
  884:   rl_end_undo_group ();
  885: 
  886:   return 0;
  887: }
  888: 
  889: int
  890: rl_insert (count, c)
  891:      int count, c;
  892: {
  893:   return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c)
  894:   					 : _rl_overwrite_char (count, c));
  895: }
  896: 
  897: /* Insert the next typed character verbatim. */
  898: static int
  899: _rl_insert_next (count)
  900:      int count;
  901: {
  902:   int c;
  903: 
  904:   RL_SETSTATE(RL_STATE_MOREINPUT);
  905:   c = rl_read_key ();
  906:   RL_UNSETSTATE(RL_STATE_MOREINPUT);
  907: 
  908:   if (c < 0)
  909:     return -1;
  910: 
  911:   if (RL_ISSTATE (RL_STATE_MACRODEF))
  912:     _rl_add_macro_char (c);
  913: 
  914: #if defined (HANDLE_SIGNALS)
  915:   if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
  916:     _rl_restore_tty_signals ();
  917: #endif
  918: 
  919:   return (_rl_insert_char (count, c));  
  920: }
  921: 
  922: #if defined (READLINE_CALLBACKS)
  923: static int
  924: _rl_insert_next_callback (data)
  925:      _rl_callback_generic_arg *data;
  926: {
  927:   int count;
  928: 
  929:   count = data->count;
  930: 
  931:   /* Deregister function, let rl_callback_read_char deallocate data */
  932:   _rl_callback_func = 0;
  933:   _rl_want_redisplay = 1;
  934:  
  935:   return _rl_insert_next (count);
  936: }
  937: #endif
  938:   
  939: int
  940: rl_quoted_insert (count, key)
  941:      int count, key;
  942: {
  943:   /* Let's see...should the callback interface futz with signal handling? */
  944: #if defined (HANDLE_SIGNALS)
  945:   if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
  946:     _rl_disable_tty_signals ();
  947: #endif
  948: 
  949: #if defined (READLINE_CALLBACKS)
  950:   if (RL_ISSTATE (RL_STATE_CALLBACK))
  951:     {
  952:       _rl_callback_data = _rl_callback_data_alloc (count);
  953:       _rl_callback_func = _rl_insert_next_callback;
  954:       return (0);
  955:     }
  956: #endif
  957:       
  958:   return _rl_insert_next (count);
  959: }
  960: 
  961: /* Insert a tab character. */
  962: int
  963: rl_tab_insert (count, key)
  964:      int count, key;
  965: {
  966:   return (_rl_insert_char (count, '\t'));
  967: }
  968: 
  969: /* What to do when a NEWLINE is pressed.  We accept the whole line.
  970:    KEY is the key that invoked this command.  I guess it could have
  971:    meaning in the future. */
  972: int
  973: rl_newline (count, key)
  974:      int count, key;
  975: {
  976:   rl_done = 1;
  977: 
  978:   if (_rl_history_preserve_point)
  979:     _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
  980: 
  981:   RL_SETSTATE(RL_STATE_DONE);
  982: 
  983: #if defined (VI_MODE)
  984:   if (rl_editing_mode == vi_mode)
  985:     {
  986:       _rl_vi_done_inserting ();
  987:       if (_rl_vi_textmod_command (_rl_vi_last_command) == 0)	/* XXX */
  988: 	_rl_vi_reset_last ();
  989:     }
  990: #endif /* VI_MODE */
  991: 
  992:   /* If we've been asked to erase empty lines, suppress the final update,
  993:      since _rl_update_final calls rl_crlf(). */
  994:   if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
  995:     return 0;
  996: 
  997:   if (_rl_echoing_p)
  998:     _rl_update_final ();
  999:   return 0;
 1000: }
 1001: 
 1002: /* What to do for some uppercase characters, like meta characters,
 1003:    and some characters appearing in emacs_ctlx_keymap.  This function
 1004:    is just a stub, you bind keys to it and the code in _rl_dispatch ()
 1005:    is special cased. */
 1006: int
 1007: rl_do_lowercase_version (ignore1, ignore2)
 1008:      int ignore1, ignore2;
 1009: {
 1010:   return 0;
 1011: }
 1012: 
 1013: /* This is different from what vi does, so the code's not shared.  Emacs
 1014:    rubout in overwrite mode has one oddity:  it replaces a control
 1015:    character that's displayed as two characters (^X) with two spaces. */
 1016: int
 1017: _rl_overwrite_rubout (count, key)
 1018:      int count, key;
 1019: {
 1020:   int opoint;
 1021:   int i, l;
 1022: 
 1023:   if (rl_point == 0)
 1024:     {
 1025:       rl_ding ();
 1026:       return 1;
 1027:     }
 1028: 
 1029:   opoint = rl_point;
 1030: 
 1031:   /* L == number of spaces to insert */
 1032:   for (i = l = 0; i < count; i++)
 1033:     {
 1034:       rl_backward_char (1, key);
 1035:       l += rl_character_len (rl_line_buffer[rl_point], rl_point);	/* not exactly right */
 1036:     }
 1037: 
 1038:   rl_begin_undo_group ();
 1039: 
 1040:   if (count > 1 || rl_explicit_arg)
 1041:     rl_kill_text (opoint, rl_point);
 1042:   else
 1043:     rl_delete_text (opoint, rl_point);
 1044: 
 1045:   /* Emacs puts point at the beginning of the sequence of spaces. */
 1046:   if (rl_point < rl_end)
 1047:     {
 1048:       opoint = rl_point;
 1049:       _rl_insert_char (l, ' ');
 1050:       rl_point = opoint;
 1051:     }
 1052: 
 1053:   rl_end_undo_group ();
 1054: 
 1055:   return 0;
 1056: }
 1057:   
 1058: /* Rubout the character behind point. */
 1059: int
 1060: rl_rubout (count, key)
 1061:      int count, key;
 1062: {
 1063:   if (count < 0)
 1064:     return (rl_delete (-count, key));
 1065: 
 1066:   if (!rl_point)
 1067:     {
 1068:       rl_ding ();
 1069:       return -1;
 1070:     }
 1071: 
 1072:   if (rl_insert_mode == RL_IM_OVERWRITE)
 1073:     return (_rl_overwrite_rubout (count, key));
 1074: 
 1075:   return (_rl_rubout_char (count, key));
 1076: }
 1077: 
 1078: int
 1079: _rl_rubout_char (count, key)
 1080:      int count, key;
 1081: {
 1082:   int orig_point;
 1083:   unsigned char c;
 1084: 
 1085:   /* Duplicated code because this is called from other parts of the library. */
 1086:   if (count < 0)
 1087:     return (rl_delete (-count, key));
 1088: 
 1089:   if (rl_point == 0)
 1090:     {
 1091:       rl_ding ();
 1092:       return -1;
 1093:     }
 1094: 
 1095:   orig_point = rl_point;
 1096:   if (count > 1 || rl_explicit_arg)
 1097:     {
 1098:       rl_backward_char (count, key);
 1099:       rl_kill_text (orig_point, rl_point);
 1100:     }
 1101:   else if (MB_CUR_MAX == 1 || rl_byte_oriented)
 1102:     {
 1103:       c = rl_line_buffer[--rl_point];
 1104:       rl_delete_text (rl_point, orig_point);
 1105:       /* The erase-at-end-of-line hack is of questionable merit now. */
 1106:       if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
 1107: 	{
 1108: 	  int l;
 1109: 	  l = rl_character_len (c, rl_point);
 1110: 	  _rl_erase_at_end_of_line (l);
 1111: 	}
 1112:     }
 1113:   else
 1114:     {
 1115:       rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
 1116:       rl_delete_text (rl_point, orig_point);
 1117:     }
 1118: 
 1119:   return 0;
 1120: }
 1121: 
 1122: /* Delete the character under the cursor.  Given a numeric argument,
 1123:    kill that many characters instead. */
 1124: int
 1125: rl_delete (count, key)
 1126:      int count, key;
 1127: {
 1128:   int xpoint;
 1129: 
 1130:   if (count < 0)
 1131:     return (_rl_rubout_char (-count, key));
 1132: 
 1133:   if (rl_point == rl_end)
 1134:     {
 1135:       rl_ding ();
 1136:       return -1;
 1137:     }
 1138: 
 1139:   if (count > 1 || rl_explicit_arg)
 1140:     {
 1141:       xpoint = rl_point;
 1142:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
 1143: 	rl_forward_char (count, key);
 1144:       else
 1145: 	rl_forward_byte (count, key);
 1146: 
 1147:       rl_kill_text (xpoint, rl_point);
 1148:       rl_point = xpoint;
 1149:     }
 1150:   else
 1151:     {
 1152:       xpoint = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
 1153:       rl_delete_text (rl_point, xpoint);
 1154:     }
 1155:   return 0;
 1156: }
 1157: 
 1158: /* Delete the character under the cursor, unless the insertion
 1159:    point is at the end of the line, in which case the character
 1160:    behind the cursor is deleted.  COUNT is obeyed and may be used
 1161:    to delete forward or backward that many characters. */      
 1162: int
 1163: rl_rubout_or_delete (count, key)
 1164:      int count, key;
 1165: {
 1166:   if (rl_end != 0 && rl_point == rl_end)
 1167:     return (_rl_rubout_char (count, key));
 1168:   else
 1169:     return (rl_delete (count, key));
 1170: }  
 1171: 
 1172: /* Delete all spaces and tabs around point. */
 1173: int
 1174: rl_delete_horizontal_space (count, ignore)
 1175:      int count, ignore;
 1176: {
 1177:   int start;
 1178: 
 1179:   while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
 1180:     rl_point--;
 1181: 
 1182:   start = rl_point;
 1183: 
 1184:   while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
 1185:     rl_point++;
 1186: 
 1187:   if (start != rl_point)
 1188:     {
 1189:       rl_delete_text (start, rl_point);
 1190:       rl_point = start;
 1191:     }
 1192: 
 1193:   if (rl_point < 0)
 1194:     rl_point = 0;
 1195: 
 1196:   return 0;
 1197: }
 1198: 
 1199: /* Like the tcsh editing function delete-char-or-list.  The eof character
 1200:    is caught before this is invoked, so this really does the same thing as
 1201:    delete-char-or-list-or-eof, as long as it's bound to the eof character. */
 1202: int
 1203: rl_delete_or_show_completions (count, key)
 1204:      int count, key;
 1205: {
 1206:   if (rl_end != 0 && rl_point == rl_end)
 1207:     return (rl_possible_completions (count, key));
 1208:   else
 1209:     return (rl_delete (count, key));
 1210: }
 1211: 
 1212: #ifndef RL_COMMENT_BEGIN_DEFAULT
 1213: #define RL_COMMENT_BEGIN_DEFAULT "#"
 1214: #endif
 1215: 
 1216: /* Turn the current line into a comment in shell history.
 1217:    A K*rn shell style function. */
 1218: int
 1219: rl_insert_comment (count, key)
 1220:      int count, key;
 1221: {
 1222:   char *rl_comment_text;
 1223:   int rl_comment_len;
 1224: 
 1225:   rl_beg_of_line (1, key);
 1226:   rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT;
 1227: 
 1228:   if (rl_explicit_arg == 0)
 1229:     rl_insert_text (rl_comment_text);
 1230:   else
 1231:     {
 1232:       rl_comment_len = strlen (rl_comment_text);
 1233:       if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len))
 1234: 	rl_delete_text (rl_point, rl_point + rl_comment_len);
 1235:       else
 1236: 	rl_insert_text (rl_comment_text);
 1237:     }
 1238: 
 1239:   (*rl_redisplay_function) ();
 1240:   rl_newline (1, '\n');
 1241: 
 1242:   return (0);
 1243: }
 1244: 
 1245: /* **************************************************************** */
 1246: /*								    */
 1247: /*			Changing Case				    */
 1248: /*								    */
 1249: /* **************************************************************** */
 1250: 
 1251: /* The three kinds of things that we know how to do. */
 1252: #define UpCase 1
 1253: #define DownCase 2
 1254: #define CapCase 3
 1255: 
 1256: /* Uppercase the word at point. */
 1257: int
 1258: rl_upcase_word (count, key)
 1259:      int count, key;
 1260: {
 1261:   return (rl_change_case (count, UpCase));
 1262: }
 1263: 
 1264: /* Lowercase the word at point. */
 1265: int
 1266: rl_downcase_word (count, key)
 1267:      int count, key;
 1268: {
 1269:   return (rl_change_case (count, DownCase));
 1270: }
 1271: 
 1272: /* Upcase the first letter, downcase the rest. */
 1273: int
 1274: rl_capitalize_word (count, key)
 1275:      int count, key;
 1276: {
 1277:  return (rl_change_case (count, CapCase));
 1278: }
 1279: 
 1280: /* The meaty function.
 1281:    Change the case of COUNT words, performing OP on them.
 1282:    OP is one of UpCase, DownCase, or CapCase.
 1283:    If a negative argument is given, leave point where it started,
 1284:    otherwise, leave it where it moves to. */
 1285: static int
 1286: rl_change_case (count, op)
 1287:      int count, op;
 1288: {
 1289:   int start, next, end;
 1290:   int inword, c, nc, nop;
 1291: #if defined (HANDLE_MULTIBYTE)
 1292:   wchar_t wc, nwc;
 1293:   char mb[MB_LEN_MAX+1];
 1294:   int mlen;
 1295:   size_t m;
 1296:   mbstate_t mps;
 1297: #endif
 1298: 
 1299:   start = rl_point;
 1300:   rl_forward_word (count, 0);
 1301:   end = rl_point;
 1302: 
 1303:   if (op != UpCase && op != DownCase && op != CapCase)
 1304:     {
 1305:       rl_ding ();
 1306:       return -1;
 1307:     }
 1308: 
 1309:   if (count < 0)
 1310:     SWAP (start, end);
 1311: 
 1312: #if defined (HANDLE_MULTIBYTE)
 1313:   memset (&mps, 0, sizeof (mbstate_t));
 1314: #endif
 1315: 
 1316:   /* We are going to modify some text, so let's prepare to undo it. */
 1317:   rl_modifying (start, end);
 1318: 
 1319:   inword = 0;
 1320:   while (start < end)
 1321:     {
 1322:       c = _rl_char_value (rl_line_buffer, start);
 1323:       /*  This assumes that the upper and lower case versions are the same width. */
 1324:       next = MB_NEXTCHAR (rl_line_buffer, start, 1, MB_FIND_NONZERO);
 1325: 
 1326:       if (_rl_walphabetic (c) == 0)
 1327: 	{
 1328: 	  inword = 0;
 1329: 	  start = next;
 1330: 	  continue;
 1331: 	}
 1332: 
 1333:       if (op == CapCase)
 1334: 	{
 1335: 	  nop = inword ? DownCase : UpCase;
 1336: 	  inword = 1;
 1337: 	}
 1338:       else
 1339: 	nop = op;
 1340:       if (MB_CUR_MAX == 1 || rl_byte_oriented || isascii (c))
 1341: 	{
 1342: 	  nc = (nop == UpCase) ? _rl_to_upper (c) : _rl_to_lower (c);
 1343: 	  rl_line_buffer[start] = nc;
 1344: 	}
 1345: #if defined (HANDLE_MULTIBYTE)
 1346:       else
 1347: 	{
 1348: 	  m = mbrtowc (&wc, rl_line_buffer + start, end - start, &mps);
 1349: 	  if (MB_INVALIDCH (m))
 1350: 	    wc = (wchar_t)rl_line_buffer[start];
 1351: 	  else if (MB_NULLWCH (m))
 1352: 	    wc = L'\0';
 1353: 	  nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc);
 1354: 	  if  (nwc != wc)	/*  just skip unchanged characters */
 1355: 	    {
 1356: 	      mlen = wcrtomb (mb, nwc, &mps);
 1357: 	      if (mlen > 0)
 1358: 		mb[mlen] = '\0';
 1359: 	      /* Assume the same width */
 1360: 	      strncpy (rl_line_buffer + start, mb, mlen);
 1361: 	    }
 1362: 	}
 1363: #endif
 1364: 
 1365:       start = next;
 1366:     }
 1367: 
 1368:   rl_point = end;
 1369:   return 0;
 1370: }
 1371: 
 1372: /* **************************************************************** */
 1373: /*								    */
 1374: /*			Transposition				    */
 1375: /*								    */
 1376: /* **************************************************************** */
 1377: 
 1378: /* Transpose the words at point.  If point is at the end of the line,
 1379:    transpose the two words before point. */
 1380: int
 1381: rl_transpose_words (count, key)
 1382:      int count, key;
 1383: {
 1384:   char *word1, *word2;
 1385:   int w1_beg, w1_end, w2_beg, w2_end;
 1386:   int orig_point = rl_point;
 1387: 
 1388:   if (!count)
 1389:     return 0;
 1390: 
 1391:   /* Find the two words. */
 1392:   rl_forward_word (count, key);
 1393:   w2_end = rl_point;
 1394:   rl_backward_word (1, key);
 1395:   w2_beg = rl_point;
 1396:   rl_backward_word (count, key);
 1397:   w1_beg = rl_point;
 1398:   rl_forward_word (1, key);
 1399:   w1_end = rl_point;
 1400: 
 1401:   /* Do some check to make sure that there really are two words. */
 1402:   if ((w1_beg == w2_beg) || (w2_beg < w1_end))
 1403:     {
 1404:       rl_ding ();
 1405:       rl_point = orig_point;
 1406:       return -1;
 1407:     }
 1408: 
 1409:   /* Get the text of the words. */
 1410:   word1 = rl_copy_text (w1_beg, w1_end);
 1411:   word2 = rl_copy_text (w2_beg, w2_end);
 1412: 
 1413:   /* We are about to do many insertions and deletions.  Remember them
 1414:      as one operation. */
 1415:   rl_begin_undo_group ();
 1416: 
 1417:   /* Do the stuff at word2 first, so that we don't have to worry
 1418:      about word1 moving. */
 1419:   rl_point = w2_beg;
 1420:   rl_delete_text (w2_beg, w2_end);
 1421:   rl_insert_text (word1);
 1422: 
 1423:   rl_point = w1_beg;
 1424:   rl_delete_text (w1_beg, w1_end);
 1425:   rl_insert_text (word2);
 1426: 
 1427:   /* This is exactly correct since the text before this point has not
 1428:      changed in length. */
 1429:   rl_point = w2_end;
 1430: 
 1431:   /* I think that does it. */
 1432:   rl_end_undo_group ();
 1433:   xfree (word1);
 1434:   xfree (word2);
 1435: 
 1436:   return 0;
 1437: }
 1438: 
 1439: /* Transpose the characters at point.  If point is at the end of the line,
 1440:    then transpose the characters before point. */
 1441: int
 1442: rl_transpose_chars (count, key)
 1443:      int count, key;
 1444: {
 1445: #if defined (HANDLE_MULTIBYTE)
 1446:   char *dummy;
 1447:   int i;
 1448: #else
 1449:   char dummy[2];
 1450: #endif
 1451:   int char_length, prev_point;
 1452: 
 1453:   if (count == 0)
 1454:     return 0;
 1455: 
 1456:   if (!rl_point || rl_end < 2)
 1457:     {
 1458:       rl_ding ();
 1459:       return -1;
 1460:     }
 1461: 
 1462:   rl_begin_undo_group ();
 1463: 
 1464:   if (rl_point == rl_end)
 1465:     {
 1466:       rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
 1467:       count = 1;
 1468:     }
 1469: 
 1470:   prev_point = rl_point;
 1471:   rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
 1472: 
 1473: #if defined (HANDLE_MULTIBYTE)
 1474:   char_length = prev_point - rl_point;
 1475:   dummy = (char *)xmalloc (char_length + 1);
 1476:   for (i = 0; i < char_length; i++)
 1477:     dummy[i] = rl_line_buffer[rl_point + i];
 1478:   dummy[i] = '\0';
 1479: #else
 1480:   dummy[0] = rl_line_buffer[rl_point];
 1481:   dummy[char_length = 1] = '\0';
 1482: #endif
 1483: 
 1484:   rl_delete_text (rl_point, rl_point + char_length);
 1485: 
 1486:   rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
 1487: 
 1488:   _rl_fix_point (0);
 1489:   rl_insert_text (dummy);
 1490:   rl_end_undo_group ();
 1491: 
 1492: #if defined (HANDLE_MULTIBYTE)
 1493:   xfree (dummy);
 1494: #endif
 1495: 
 1496:   return 0;
 1497: }
 1498: 
 1499: /* **************************************************************** */
 1500: /*								    */
 1501: /*			Character Searching			    */
 1502: /*								    */
 1503: /* **************************************************************** */
 1504: 
 1505: int
 1506: #if defined (HANDLE_MULTIBYTE)
 1507: _rl_char_search_internal (count, dir, smbchar, len)
 1508:      int count, dir;
 1509:      char *smbchar;
 1510:      int len;
 1511: #else
 1512: _rl_char_search_internal (count, dir, schar)
 1513:      int count, dir, schar;
 1514: #endif
 1515: {
 1516:   int pos, inc;
 1517: #if defined (HANDLE_MULTIBYTE)
 1518:   int prepos;
 1519: #endif
 1520: 
 1521:   if (dir == 0)
 1522:     return -1;
 1523: 
 1524:   pos = rl_point;
 1525:   inc = (dir < 0) ? -1 : 1;
 1526:   while (count)
 1527:     {
 1528:       if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
 1529: 	{
 1530: 	  rl_ding ();
 1531: 	  return -1;
 1532: 	}
 1533: 
 1534: #if defined (HANDLE_MULTIBYTE)
 1535:       pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
 1536: 		      : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
 1537: #else
 1538:       pos += inc;
 1539: #endif
 1540:       do
 1541: 	{
 1542: #if defined (HANDLE_MULTIBYTE)
 1543: 	  if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len))
 1544: #else
 1545: 	  if (rl_line_buffer[pos] == schar)
 1546: #endif
 1547: 	    {
 1548: 	      count--;
 1549: 	      if (dir < 0)
 1550: 	        rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
 1551: 					: pos;
 1552: 	      else
 1553: 		rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)
 1554: 					: pos;
 1555: 	      break;
 1556: 	    }
 1557: #if defined (HANDLE_MULTIBYTE)
 1558: 	  prepos = pos;
 1559: #endif
 1560: 	}
 1561: #if defined (HANDLE_MULTIBYTE)
 1562:       while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos
 1563: 		       : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos);
 1564: #else
 1565:       while ((dir < 0) ? pos-- : ++pos < rl_end);
 1566: #endif
 1567:     }
 1568:   return (0);
 1569: }
 1570: 
 1571: /* Search COUNT times for a character read from the current input stream.
 1572:    FDIR is the direction to search if COUNT is non-negative; otherwise
 1573:    the search goes in BDIR.  So much is dependent on HANDLE_MULTIBYTE
 1574:    that there are two separate versions of this function. */
 1575: #if defined (HANDLE_MULTIBYTE)
 1576: static int
 1577: _rl_char_search (count, fdir, bdir)
 1578:      int count, fdir, bdir;
 1579: {
 1580:   char mbchar[MB_LEN_MAX];
 1581:   int mb_len;
 1582: 
 1583:   mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
 1584: 
 1585:   if (mb_len <= 0)
 1586:     return -1;
 1587: 
 1588:   if (count < 0)
 1589:     return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
 1590:   else
 1591:     return (_rl_char_search_internal (count, fdir, mbchar, mb_len));
 1592: }
 1593: #else /* !HANDLE_MULTIBYTE */
 1594: static int
 1595: _rl_char_search (count, fdir, bdir)
 1596:      int count, fdir, bdir;
 1597: {
 1598:   int c;
 1599: 
 1600:   RL_SETSTATE(RL_STATE_MOREINPUT);
 1601:   c = rl_read_key ();
 1602:   RL_UNSETSTATE(RL_STATE_MOREINPUT);
 1603: 
 1604:   if (c < 0)
 1605:     return -1;
 1606: 
 1607:   if (count < 0)
 1608:     return (_rl_char_search_internal (-count, bdir, c));
 1609:   else
 1610:     return (_rl_char_search_internal (count, fdir, c));
 1611: }
 1612: #endif /* !HANDLE_MULTIBYTE */
 1613: 
 1614: #if defined (READLINE_CALLBACKS)
 1615: static int
 1616: _rl_char_search_callback (data)
 1617:      _rl_callback_generic_arg *data;
 1618: {
 1619:   _rl_callback_func = 0;
 1620:   _rl_want_redisplay = 1;
 1621: 
 1622:   return (_rl_char_search (data->count, data->i1, data->i2));
 1623: }
 1624: #endif
 1625: 
 1626: int
 1627: rl_char_search (count, key)
 1628:      int count, key;
 1629: {
 1630: #if defined (READLINE_CALLBACKS)
 1631:   if (RL_ISSTATE (RL_STATE_CALLBACK))
 1632:     {
 1633:       _rl_callback_data = _rl_callback_data_alloc (count);
 1634:       _rl_callback_data->i1 = FFIND;
 1635:       _rl_callback_data->i2 = BFIND;
 1636:       _rl_callback_func = _rl_char_search_callback;
 1637:       return (0);
 1638:     }
 1639: #endif
 1640:   
 1641:   return (_rl_char_search (count, FFIND, BFIND));
 1642: }
 1643: 
 1644: int
 1645: rl_backward_char_search (count, key)
 1646:      int count, key;
 1647: {
 1648: #if defined (READLINE_CALLBACKS)
 1649:   if (RL_ISSTATE (RL_STATE_CALLBACK))
 1650:     {
 1651:       _rl_callback_data = _rl_callback_data_alloc (count);
 1652:       _rl_callback_data->i1 = BFIND;
 1653:       _rl_callback_data->i2 = FFIND;
 1654:       _rl_callback_func = _rl_char_search_callback;
 1655:       return (0);
 1656:     }
 1657: #endif
 1658: 
 1659:   return (_rl_char_search (count, BFIND, FFIND));
 1660: }
 1661: 
 1662: /* **************************************************************** */
 1663: /*								    */
 1664: /*		   The Mark and the Region.			    */
 1665: /*								    */
 1666: /* **************************************************************** */
 1667: 
 1668: /* Set the mark at POSITION. */
 1669: int
 1670: _rl_set_mark_at_pos (position)
 1671:      int position;
 1672: {
 1673:   if (position > rl_end)
 1674:     return -1;
 1675: 
 1676:   rl_mark = position;
 1677:   return 0;
 1678: }
 1679: 
 1680: /* A bindable command to set the mark. */
 1681: int
 1682: rl_set_mark (count, key)
 1683:      int count, key;
 1684: {
 1685:   return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
 1686: }
 1687: 
 1688: /* Exchange the position of mark and point. */
 1689: int
 1690: rl_exchange_point_and_mark (count, key)
 1691:      int count, key;
 1692: {
 1693:   if (rl_mark > rl_end)
 1694:     rl_mark = -1;
 1695: 
 1696:   if (rl_mark == -1)
 1697:     {
 1698:       rl_ding ();
 1699:       return -1;
 1700:     }
 1701:   else
 1702:     SWAP (rl_point, rl_mark);
 1703: 
 1704:   return 0;
 1705: }

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