Annotation of embedaddon/readline/text.c, revision 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>