Annotation of embedaddon/readline/text.c, revision 1.1.1.1

1.1       misho       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>