File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / readline / text.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 01:01:01 2021 UTC (3 years, 3 months ago) by misho
Branches: readline, MAIN
CVS tags: v8_2p0, v8_1p0, HEAD
readline 8.1

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

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