text.c revision 165670
1119610Sache/* text.c -- text handling commands for readline. */ 2119610Sache 3157184Sache/* Copyright (C) 1987-2005 Free Software Foundation, Inc. 4119610Sache 5119610Sache This file is part of the GNU Readline Library, a library for 6119610Sache reading lines of text with interactive input and history editing. 7119610Sache 8119610Sache The GNU Readline Library is free software; you can redistribute it 9119610Sache and/or modify it under the terms of the GNU General Public License 10119610Sache as published by the Free Software Foundation; either version 2, or 11119610Sache (at your option) any later version. 12119610Sache 13119610Sache The GNU Readline Library is distributed in the hope that it will be 14119610Sache useful, but WITHOUT ANY WARRANTY; without even the implied warranty 15119610Sache of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16119610Sache GNU General Public License for more details. 17119610Sache 18119610Sache The GNU General Public License is often shipped with GNU software, and 19119610Sache is generally kept in a file called COPYING or LICENSE. If you do not 20119610Sache have a copy of the license, write to the Free Software Foundation, 21119610Sache 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 22119610Sache#define READLINE_LIBRARY 23119610Sache 24119610Sache#if defined (HAVE_CONFIG_H) 25119610Sache# include <config.h> 26119610Sache#endif 27119610Sache 28119610Sache#if defined (HAVE_UNISTD_H) 29119610Sache# include <unistd.h> 30119610Sache#endif /* HAVE_UNISTD_H */ 31119610Sache 32119610Sache#if defined (HAVE_STDLIB_H) 33119610Sache# include <stdlib.h> 34119610Sache#else 35119610Sache# include "ansi_stdlib.h" 36119610Sache#endif /* HAVE_STDLIB_H */ 37119610Sache 38119610Sache#if defined (HAVE_LOCALE_H) 39119610Sache# include <locale.h> 40119610Sache#endif 41119610Sache 42119610Sache#include <stdio.h> 43119610Sache 44119610Sache/* System-specific feature definitions and include files. */ 45119610Sache#include "rldefs.h" 46119610Sache#include "rlmbutil.h" 47119610Sache 48119610Sache#if defined (__EMX__) 49119610Sache# define INCL_DOSPROCESS 50119610Sache# include <os2.h> 51119610Sache#endif /* __EMX__ */ 52119610Sache 53119610Sache/* Some standard library routines. */ 54119610Sache#include "readline.h" 55119610Sache#include "history.h" 56119610Sache 57119610Sache#include "rlprivate.h" 58119610Sache#include "rlshell.h" 59119610Sache#include "xmalloc.h" 60119610Sache 61119610Sache/* Forward declarations. */ 62119610Sachestatic int rl_change_case PARAMS((int, int)); 63119610Sachestatic int _rl_char_search PARAMS((int, int, int)); 64119610Sache 65157184Sache#if defined (READLINE_CALLBACKS) 66157184Sachestatic int _rl_insert_next_callback PARAMS((_rl_callback_generic_arg *)); 67157184Sachestatic int _rl_char_search_callback PARAMS((_rl_callback_generic_arg *)); 68157184Sache#endif 69157184Sache 70119610Sache/* **************************************************************** */ 71119610Sache/* */ 72119610Sache/* Insert and Delete */ 73119610Sache/* */ 74119610Sache/* **************************************************************** */ 75119610Sache 76119610Sache/* Insert a string of text into the line at point. This is the only 77119610Sache way that you should do insertion. _rl_insert_char () calls this 78119610Sache function. Returns the number of characters inserted. */ 79119610Sacheint 80119610Sacherl_insert_text (string) 81119610Sache const char *string; 82119610Sache{ 83119610Sache register int i, l; 84119610Sache 85119610Sache l = (string && *string) ? strlen (string) : 0; 86119610Sache if (l == 0) 87119610Sache return 0; 88119610Sache 89119610Sache if (rl_end + l >= rl_line_buffer_len) 90119610Sache rl_extend_line_buffer (rl_end + l); 91119610Sache 92119610Sache for (i = rl_end; i >= rl_point; i--) 93119610Sache rl_line_buffer[i + l] = rl_line_buffer[i]; 94119610Sache strncpy (rl_line_buffer + rl_point, string, l); 95119610Sache 96119610Sache /* Remember how to undo this if we aren't undoing something. */ 97119610Sache if (_rl_doing_an_undo == 0) 98119610Sache { 99119610Sache /* If possible and desirable, concatenate the undos. */ 100119610Sache if ((l == 1) && 101119610Sache rl_undo_list && 102119610Sache (rl_undo_list->what == UNDO_INSERT) && 103119610Sache (rl_undo_list->end == rl_point) && 104119610Sache (rl_undo_list->end - rl_undo_list->start < 20)) 105119610Sache rl_undo_list->end++; 106119610Sache else 107119610Sache rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL); 108119610Sache } 109119610Sache rl_point += l; 110119610Sache rl_end += l; 111119610Sache rl_line_buffer[rl_end] = '\0'; 112119610Sache return l; 113119610Sache} 114119610Sache 115119610Sache/* Delete the string between FROM and TO. FROM is inclusive, TO is not. 116119610Sache Returns the number of characters deleted. */ 117119610Sacheint 118119610Sacherl_delete_text (from, to) 119119610Sache int from, to; 120119610Sache{ 121119610Sache register char *text; 122119610Sache register int diff, i; 123119610Sache 124119610Sache /* Fix it if the caller is confused. */ 125119610Sache if (from > to) 126119610Sache SWAP (from, to); 127119610Sache 128119610Sache /* fix boundaries */ 129119610Sache if (to > rl_end) 130119610Sache { 131119610Sache to = rl_end; 132119610Sache if (from > to) 133119610Sache from = to; 134119610Sache } 135119610Sache if (from < 0) 136119610Sache from = 0; 137119610Sache 138119610Sache text = rl_copy_text (from, to); 139119610Sache 140119610Sache /* Some versions of strncpy() can't handle overlapping arguments. */ 141119610Sache diff = to - from; 142119610Sache for (i = from; i < rl_end - diff; i++) 143119610Sache rl_line_buffer[i] = rl_line_buffer[i + diff]; 144119610Sache 145119610Sache /* Remember how to undo this delete. */ 146119610Sache if (_rl_doing_an_undo == 0) 147119610Sache rl_add_undo (UNDO_DELETE, from, to, text); 148119610Sache else 149119610Sache free (text); 150119610Sache 151119610Sache rl_end -= diff; 152119610Sache rl_line_buffer[rl_end] = '\0'; 153119610Sache return (diff); 154119610Sache} 155119610Sache 156119610Sache/* Fix up point so that it is within the line boundaries after killing 157119610Sache text. If FIX_MARK_TOO is non-zero, the mark is forced within line 158119610Sache boundaries also. */ 159119610Sache 160119610Sache#define _RL_FIX_POINT(x) \ 161119610Sache do { \ 162119610Sache if (x > rl_end) \ 163119610Sache x = rl_end; \ 164119610Sache else if (x < 0) \ 165119610Sache x = 0; \ 166119610Sache } while (0) 167119610Sache 168119610Sachevoid 169119610Sache_rl_fix_point (fix_mark_too) 170119610Sache int fix_mark_too; 171119610Sache{ 172119610Sache _RL_FIX_POINT (rl_point); 173119610Sache if (fix_mark_too) 174119610Sache _RL_FIX_POINT (rl_mark); 175119610Sache} 176119610Sache#undef _RL_FIX_POINT 177119610Sache 178136644Sache/* Replace the contents of the line buffer between START and END with 179136644Sache TEXT. The operation is undoable. To replace the entire line in an 180136644Sache undoable mode, use _rl_replace_text(text, 0, rl_end); */ 181119610Sacheint 182119610Sache_rl_replace_text (text, start, end) 183119610Sache const char *text; 184119610Sache int start, end; 185119610Sache{ 186119610Sache int n; 187119610Sache 188119610Sache rl_begin_undo_group (); 189119610Sache rl_delete_text (start, end + 1); 190119610Sache rl_point = start; 191119610Sache n = rl_insert_text (text); 192119610Sache rl_end_undo_group (); 193119610Sache 194119610Sache return n; 195119610Sache} 196119610Sache 197119610Sache/* Replace the current line buffer contents with TEXT. If CLEAR_UNDO is 198119610Sache non-zero, we free the current undo list. */ 199119610Sachevoid 200119610Sacherl_replace_line (text, clear_undo) 201119610Sache const char *text; 202119610Sache int clear_undo; 203119610Sache{ 204119610Sache int len; 205119610Sache 206119610Sache len = strlen (text); 207119610Sache if (len >= rl_line_buffer_len) 208119610Sache rl_extend_line_buffer (len); 209119610Sache strcpy (rl_line_buffer, text); 210119610Sache rl_end = len; 211119610Sache 212119610Sache if (clear_undo) 213119610Sache rl_free_undo_list (); 214119610Sache 215119610Sache _rl_fix_point (1); 216119610Sache} 217119610Sache 218119610Sache/* **************************************************************** */ 219119610Sache/* */ 220119610Sache/* Readline character functions */ 221119610Sache/* */ 222119610Sache/* **************************************************************** */ 223119610Sache 224119610Sache/* This is not a gap editor, just a stupid line input routine. No hair 225119610Sache is involved in writing any of the functions, and none should be. */ 226119610Sache 227119610Sache/* Note that: 228119610Sache 229119610Sache rl_end is the place in the string that we would place '\0'; 230119610Sache i.e., it is always safe to place '\0' there. 231119610Sache 232119610Sache rl_point is the place in the string where the cursor is. Sometimes 233119610Sache this is the same as rl_end. 234119610Sache 235119610Sache Any command that is called interactively receives two arguments. 236119610Sache The first is a count: the numeric arg pased to this command. 237119610Sache The second is the key which invoked this command. 238119610Sache*/ 239119610Sache 240119610Sache/* **************************************************************** */ 241119610Sache/* */ 242119610Sache/* Movement Commands */ 243119610Sache/* */ 244119610Sache/* **************************************************************** */ 245119610Sache 246119610Sache/* Note that if you `optimize' the display for these functions, you cannot 247119610Sache use said functions in other functions which do not do optimizing display. 248119610Sache I.e., you will have to update the data base for rl_redisplay, and you 249119610Sache might as well let rl_redisplay do that job. */ 250119610Sache 251119610Sache/* Move forward COUNT bytes. */ 252119610Sacheint 253119610Sacherl_forward_byte (count, key) 254119610Sache int count, key; 255119610Sache{ 256119610Sache if (count < 0) 257119610Sache return (rl_backward_byte (-count, key)); 258119610Sache 259119610Sache if (count > 0) 260119610Sache { 261119610Sache int end = rl_point + count; 262119610Sache#if defined (VI_MODE) 263119610Sache int lend = rl_end > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end; 264119610Sache#else 265119610Sache int lend = rl_end; 266119610Sache#endif 267119610Sache 268119610Sache if (end > lend) 269119610Sache { 270119610Sache rl_point = lend; 271119610Sache rl_ding (); 272119610Sache } 273119610Sache else 274119610Sache rl_point = end; 275119610Sache } 276119610Sache 277119610Sache if (rl_end < 0) 278119610Sache rl_end = 0; 279119610Sache 280119610Sache return 0; 281119610Sache} 282119610Sache 283119610Sache#if defined (HANDLE_MULTIBYTE) 284119610Sache/* Move forward COUNT characters. */ 285119610Sacheint 286119610Sacherl_forward_char (count, key) 287119610Sache int count, key; 288119610Sache{ 289119610Sache int point; 290119610Sache 291119610Sache if (MB_CUR_MAX == 1 || rl_byte_oriented) 292119610Sache return (rl_forward_byte (count, key)); 293119610Sache 294119610Sache if (count < 0) 295119610Sache return (rl_backward_char (-count, key)); 296119610Sache 297119610Sache if (count > 0) 298119610Sache { 299119610Sache point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); 300119610Sache 301119610Sache#if defined (VI_MODE) 302119610Sache if (rl_end <= point && rl_editing_mode == vi_mode) 303119610Sache point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO); 304119610Sache#endif 305119610Sache 306119610Sache if (rl_point == point) 307119610Sache rl_ding (); 308119610Sache 309119610Sache rl_point = point; 310119610Sache 311119610Sache if (rl_end < 0) 312119610Sache rl_end = 0; 313119610Sache } 314119610Sache 315119610Sache return 0; 316119610Sache} 317119610Sache#else /* !HANDLE_MULTIBYTE */ 318119610Sacheint 319119610Sacherl_forward_char (count, key) 320119610Sache int count, key; 321119610Sache{ 322119610Sache return (rl_forward_byte (count, key)); 323119610Sache} 324119610Sache#endif /* !HANDLE_MULTIBYTE */ 325119610Sache 326119610Sache/* Backwards compatibility. */ 327119610Sacheint 328119610Sacherl_forward (count, key) 329119610Sache int count, key; 330119610Sache{ 331119610Sache return (rl_forward_char (count, key)); 332119610Sache} 333119610Sache 334119610Sache/* Move backward COUNT bytes. */ 335119610Sacheint 336119610Sacherl_backward_byte (count, key) 337119610Sache int count, key; 338119610Sache{ 339119610Sache if (count < 0) 340119610Sache return (rl_forward_byte (-count, key)); 341119610Sache 342119610Sache if (count > 0) 343119610Sache { 344119610Sache if (rl_point < count) 345119610Sache { 346119610Sache rl_point = 0; 347119610Sache rl_ding (); 348119610Sache } 349119610Sache else 350119610Sache rl_point -= count; 351119610Sache } 352119610Sache 353119610Sache if (rl_point < 0) 354119610Sache rl_point = 0; 355119610Sache 356119610Sache return 0; 357119610Sache} 358119610Sache 359119610Sache#if defined (HANDLE_MULTIBYTE) 360119610Sache/* Move backward COUNT characters. */ 361119610Sacheint 362119610Sacherl_backward_char (count, key) 363119610Sache int count, key; 364119610Sache{ 365119610Sache int point; 366119610Sache 367119610Sache if (MB_CUR_MAX == 1 || rl_byte_oriented) 368119610Sache return (rl_backward_byte (count, key)); 369119610Sache 370119610Sache if (count < 0) 371119610Sache return (rl_forward_char (-count, key)); 372119610Sache 373119610Sache if (count > 0) 374119610Sache { 375119610Sache point = rl_point; 376119610Sache 377119610Sache while (count > 0 && point > 0) 378119610Sache { 379119610Sache point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO); 380119610Sache count--; 381119610Sache } 382119610Sache if (count > 0) 383119610Sache { 384119610Sache rl_point = 0; 385119610Sache rl_ding (); 386119610Sache } 387119610Sache else 388119610Sache rl_point = point; 389119610Sache } 390119610Sache 391119610Sache return 0; 392119610Sache} 393119610Sache#else 394119610Sacheint 395119610Sacherl_backward_char (count, key) 396119610Sache int count, key; 397119610Sache{ 398119610Sache return (rl_backward_byte (count, key)); 399119610Sache} 400119610Sache#endif 401119610Sache 402119610Sache/* Backwards compatibility. */ 403119610Sacheint 404119610Sacherl_backward (count, key) 405119610Sache int count, key; 406119610Sache{ 407119610Sache return (rl_backward_char (count, key)); 408119610Sache} 409119610Sache 410119610Sache/* Move to the beginning of the line. */ 411119610Sacheint 412119610Sacherl_beg_of_line (count, key) 413119610Sache int count, key; 414119610Sache{ 415119610Sache rl_point = 0; 416119610Sache return 0; 417119610Sache} 418119610Sache 419119610Sache/* Move to the end of the line. */ 420119610Sacheint 421119610Sacherl_end_of_line (count, key) 422119610Sache int count, key; 423119610Sache{ 424119610Sache rl_point = rl_end; 425119610Sache return 0; 426119610Sache} 427119610Sache 428157184Sache/* Move forward a word. We do what Emacs does. Handles multibyte chars. */ 429119610Sacheint 430119610Sacherl_forward_word (count, key) 431119610Sache int count, key; 432119610Sache{ 433119610Sache int c; 434119610Sache 435119610Sache if (count < 0) 436119610Sache return (rl_backward_word (-count, key)); 437119610Sache 438119610Sache while (count) 439119610Sache { 440119610Sache if (rl_point == rl_end) 441119610Sache return 0; 442119610Sache 443119610Sache /* If we are not in a word, move forward until we are in one. 444119610Sache Then, move forward until we hit a non-alphabetic character. */ 445157184Sache c = _rl_char_value (rl_line_buffer, rl_point); 446157184Sache 447157184Sache if (_rl_walphabetic (c) == 0) 448119610Sache { 449157184Sache rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); 450157184Sache while (rl_point < rl_end) 451119610Sache { 452157184Sache c = _rl_char_value (rl_line_buffer, rl_point); 453157184Sache if (_rl_walphabetic (c)) 454119610Sache break; 455157184Sache rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); 456119610Sache } 457119610Sache } 458119610Sache 459119610Sache if (rl_point == rl_end) 460119610Sache return 0; 461119610Sache 462157184Sache rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); 463157184Sache while (rl_point < rl_end) 464119610Sache { 465157184Sache c = _rl_char_value (rl_line_buffer, rl_point); 466157184Sache if (_rl_walphabetic (c) == 0) 467119610Sache break; 468157184Sache rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); 469119610Sache } 470157184Sache 471119610Sache --count; 472119610Sache } 473119610Sache 474119610Sache return 0; 475119610Sache} 476119610Sache 477157184Sache/* Move backward a word. We do what Emacs does. Handles multibyte chars. */ 478119610Sacheint 479119610Sacherl_backward_word (count, key) 480119610Sache int count, key; 481119610Sache{ 482157184Sache int c, p; 483119610Sache 484119610Sache if (count < 0) 485119610Sache return (rl_forward_word (-count, key)); 486119610Sache 487119610Sache while (count) 488119610Sache { 489157184Sache if (rl_point == 0) 490119610Sache return 0; 491119610Sache 492119610Sache /* Like rl_forward_word (), except that we look at the characters 493119610Sache just before point. */ 494119610Sache 495157184Sache p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); 496157184Sache c = _rl_char_value (rl_line_buffer, p); 497157184Sache 498157184Sache if (_rl_walphabetic (c) == 0) 499119610Sache { 500157184Sache rl_point = p; 501157184Sache while (rl_point > 0) 502119610Sache { 503157184Sache p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); 504157184Sache c = _rl_char_value (rl_line_buffer, p); 505157184Sache if (_rl_walphabetic (c)) 506119610Sache break; 507157184Sache rl_point = p; 508119610Sache } 509119610Sache } 510119610Sache 511119610Sache while (rl_point) 512119610Sache { 513157184Sache p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); 514157184Sache c = _rl_char_value (rl_line_buffer, p); 515157184Sache if (_rl_walphabetic (c) == 0) 516119610Sache break; 517119610Sache else 518157184Sache rl_point = p; 519119610Sache } 520119610Sache 521119610Sache --count; 522119610Sache } 523119610Sache 524119610Sache return 0; 525119610Sache} 526119610Sache 527119610Sache/* Clear the current line. Numeric argument to C-l does this. */ 528119610Sacheint 529119610Sacherl_refresh_line (ignore1, ignore2) 530119610Sache int ignore1, ignore2; 531119610Sache{ 532119610Sache int curr_line; 533119610Sache 534119610Sache curr_line = _rl_current_display_line (); 535119610Sache 536119610Sache _rl_move_vert (curr_line); 537119610Sache _rl_move_cursor_relative (0, rl_line_buffer); /* XXX is this right */ 538119610Sache 539119610Sache _rl_clear_to_eol (0); /* arg of 0 means to not use spaces */ 540119610Sache 541119610Sache rl_forced_update_display (); 542119610Sache rl_display_fixed = 1; 543119610Sache 544119610Sache return 0; 545119610Sache} 546119610Sache 547119610Sache/* C-l typed to a line without quoting clears the screen, and then reprints 548119610Sache the prompt and the current input line. Given a numeric arg, redraw only 549119610Sache the current line. */ 550119610Sacheint 551119610Sacherl_clear_screen (count, key) 552119610Sache int count, key; 553119610Sache{ 554119610Sache if (rl_explicit_arg) 555119610Sache { 556119610Sache rl_refresh_line (count, key); 557119610Sache return 0; 558119610Sache } 559119610Sache 560119610Sache _rl_clear_screen (); /* calls termcap function to clear screen */ 561119610Sache rl_forced_update_display (); 562119610Sache rl_display_fixed = 1; 563119610Sache 564119610Sache return 0; 565119610Sache} 566119610Sache 567119610Sacheint 568119610Sacherl_arrow_keys (count, c) 569119610Sache int count, c; 570119610Sache{ 571119610Sache int ch; 572119610Sache 573119610Sache RL_SETSTATE(RL_STATE_MOREINPUT); 574119610Sache ch = rl_read_key (); 575119610Sache RL_UNSETSTATE(RL_STATE_MOREINPUT); 576119610Sache 577119610Sache switch (_rl_to_upper (ch)) 578119610Sache { 579119610Sache case 'A': 580119610Sache rl_get_previous_history (count, ch); 581119610Sache break; 582119610Sache 583119610Sache case 'B': 584119610Sache rl_get_next_history (count, ch); 585119610Sache break; 586119610Sache 587119610Sache case 'C': 588119610Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 589119610Sache rl_forward_char (count, ch); 590119610Sache else 591119610Sache rl_forward_byte (count, ch); 592119610Sache break; 593119610Sache 594119610Sache case 'D': 595119610Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 596119610Sache rl_backward_char (count, ch); 597119610Sache else 598119610Sache rl_backward_byte (count, ch); 599119610Sache break; 600119610Sache 601119610Sache default: 602119610Sache rl_ding (); 603119610Sache } 604119610Sache 605119610Sache return 0; 606119610Sache} 607119610Sache 608119610Sache/* **************************************************************** */ 609119610Sache/* */ 610119610Sache/* Text commands */ 611119610Sache/* */ 612119610Sache/* **************************************************************** */ 613119610Sache 614119610Sache#ifdef HANDLE_MULTIBYTE 615119610Sachestatic char pending_bytes[MB_LEN_MAX]; 616119610Sachestatic int pending_bytes_length = 0; 617119610Sachestatic mbstate_t ps = {0}; 618119610Sache#endif 619119610Sache 620119610Sache/* Insert the character C at the current location, moving point forward. 621119610Sache If C introduces a multibyte sequence, we read the whole sequence and 622119610Sache then insert the multibyte char into the line buffer. */ 623119610Sacheint 624119610Sache_rl_insert_char (count, c) 625119610Sache int count, c; 626119610Sache{ 627119610Sache register int i; 628119610Sache char *string; 629119610Sache#ifdef HANDLE_MULTIBYTE 630119610Sache int string_size; 631119610Sache char incoming[MB_LEN_MAX + 1]; 632119610Sache int incoming_length = 0; 633119610Sache mbstate_t ps_back; 634119610Sache static int stored_count = 0; 635119610Sache#endif 636119610Sache 637119610Sache if (count <= 0) 638119610Sache return 0; 639119610Sache 640119610Sache#if defined (HANDLE_MULTIBYTE) 641119610Sache if (MB_CUR_MAX == 1 || rl_byte_oriented) 642119610Sache { 643119610Sache incoming[0] = c; 644119610Sache incoming[1] = '\0'; 645119610Sache incoming_length = 1; 646119610Sache } 647119610Sache else 648119610Sache { 649119610Sache wchar_t wc; 650119610Sache size_t ret; 651119610Sache 652119610Sache if (stored_count <= 0) 653119610Sache stored_count = count; 654119610Sache else 655119610Sache count = stored_count; 656119610Sache 657119610Sache ps_back = ps; 658119610Sache pending_bytes[pending_bytes_length++] = c; 659119610Sache ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps); 660119610Sache 661119610Sache if (ret == (size_t)-2) 662119610Sache { 663119610Sache /* Bytes too short to compose character, try to wait for next byte. 664119610Sache Restore the state of the byte sequence, because in this case the 665119610Sache effect of mbstate is undefined. */ 666119610Sache ps = ps_back; 667119610Sache return 1; 668119610Sache } 669119610Sache else if (ret == (size_t)-1) 670119610Sache { 671119610Sache /* Invalid byte sequence for the current locale. Treat first byte 672119610Sache as a single character. */ 673119610Sache incoming[0] = pending_bytes[0]; 674119610Sache incoming[1] = '\0'; 675119610Sache incoming_length = 1; 676119610Sache pending_bytes_length--; 677119610Sache memmove (pending_bytes, pending_bytes + 1, pending_bytes_length); 678119610Sache /* Clear the state of the byte sequence, because in this case the 679119610Sache effect of mbstate is undefined. */ 680119610Sache memset (&ps, 0, sizeof (mbstate_t)); 681119610Sache } 682119610Sache else if (ret == (size_t)0) 683119610Sache { 684119610Sache incoming[0] = '\0'; 685119610Sache incoming_length = 0; 686119610Sache pending_bytes_length--; 687119610Sache /* Clear the state of the byte sequence, because in this case the 688119610Sache effect of mbstate is undefined. */ 689119610Sache memset (&ps, 0, sizeof (mbstate_t)); 690119610Sache } 691119610Sache else 692119610Sache { 693119610Sache /* We successfully read a single multibyte character. */ 694119610Sache memcpy (incoming, pending_bytes, pending_bytes_length); 695119610Sache incoming[pending_bytes_length] = '\0'; 696119610Sache incoming_length = pending_bytes_length; 697119610Sache pending_bytes_length = 0; 698119610Sache } 699119610Sache } 700119610Sache#endif /* HANDLE_MULTIBYTE */ 701119610Sache 702119610Sache /* If we can optimize, then do it. But don't let people crash 703119610Sache readline because of extra large arguments. */ 704119610Sache if (count > 1 && count <= 1024) 705119610Sache { 706119610Sache#if defined (HANDLE_MULTIBYTE) 707119610Sache string_size = count * incoming_length; 708119610Sache string = (char *)xmalloc (1 + string_size); 709119610Sache 710119610Sache i = 0; 711119610Sache while (i < string_size) 712119610Sache { 713119610Sache strncpy (string + i, incoming, incoming_length); 714119610Sache i += incoming_length; 715119610Sache } 716119610Sache incoming_length = 0; 717119610Sache stored_count = 0; 718119610Sache#else /* !HANDLE_MULTIBYTE */ 719119610Sache string = (char *)xmalloc (1 + count); 720119610Sache 721119610Sache for (i = 0; i < count; i++) 722119610Sache string[i] = c; 723119610Sache#endif /* !HANDLE_MULTIBYTE */ 724119610Sache 725119610Sache string[i] = '\0'; 726119610Sache rl_insert_text (string); 727119610Sache free (string); 728119610Sache 729119610Sache return 0; 730119610Sache } 731119610Sache 732119610Sache if (count > 1024) 733119610Sache { 734119610Sache int decreaser; 735119610Sache#if defined (HANDLE_MULTIBYTE) 736119610Sache string_size = incoming_length * 1024; 737119610Sache string = (char *)xmalloc (1 + string_size); 738119610Sache 739119610Sache i = 0; 740119610Sache while (i < string_size) 741119610Sache { 742119610Sache strncpy (string + i, incoming, incoming_length); 743119610Sache i += incoming_length; 744119610Sache } 745119610Sache 746119610Sache while (count) 747119610Sache { 748119610Sache decreaser = (count > 1024) ? 1024 : count; 749119610Sache string[decreaser*incoming_length] = '\0'; 750119610Sache rl_insert_text (string); 751119610Sache count -= decreaser; 752119610Sache } 753119610Sache 754119610Sache free (string); 755119610Sache incoming_length = 0; 756119610Sache stored_count = 0; 757119610Sache#else /* !HANDLE_MULTIBYTE */ 758119610Sache char str[1024+1]; 759119610Sache 760119610Sache for (i = 0; i < 1024; i++) 761119610Sache str[i] = c; 762119610Sache 763119610Sache while (count) 764119610Sache { 765119610Sache decreaser = (count > 1024 ? 1024 : count); 766119610Sache str[decreaser] = '\0'; 767119610Sache rl_insert_text (str); 768119610Sache count -= decreaser; 769119610Sache } 770119610Sache#endif /* !HANDLE_MULTIBYTE */ 771119610Sache 772119610Sache return 0; 773119610Sache } 774119610Sache 775119610Sache if (MB_CUR_MAX == 1 || rl_byte_oriented) 776119610Sache { 777119610Sache /* We are inserting a single character. 778119610Sache If there is pending input, then make a string of all of the 779119610Sache pending characters that are bound to rl_insert, and insert 780119610Sache them all. */ 781119610Sache if (_rl_any_typein ()) 782119610Sache _rl_insert_typein (c); 783119610Sache else 784119610Sache { 785119610Sache /* Inserting a single character. */ 786119610Sache char str[2]; 787119610Sache 788119610Sache str[1] = '\0'; 789119610Sache str[0] = c; 790119610Sache rl_insert_text (str); 791119610Sache } 792157184Sache } 793119610Sache#if defined (HANDLE_MULTIBYTE) 794119610Sache else 795119610Sache { 796119610Sache rl_insert_text (incoming); 797119610Sache stored_count = 0; 798119610Sache } 799119610Sache#endif 800119610Sache 801119610Sache return 0; 802119610Sache} 803119610Sache 804119610Sache/* Overwrite the character at point (or next COUNT characters) with C. 805119610Sache If C introduces a multibyte character sequence, read the entire sequence 806119610Sache before starting the overwrite loop. */ 807119610Sacheint 808119610Sache_rl_overwrite_char (count, c) 809119610Sache int count, c; 810119610Sache{ 811119610Sache int i; 812119610Sache#if defined (HANDLE_MULTIBYTE) 813119610Sache char mbkey[MB_LEN_MAX]; 814119610Sache int k; 815119610Sache 816119610Sache /* Read an entire multibyte character sequence to insert COUNT times. */ 817119610Sache if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0) 818119610Sache k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX); 819119610Sache#endif 820119610Sache 821136644Sache rl_begin_undo_group (); 822136644Sache 823119610Sache for (i = 0; i < count; i++) 824119610Sache { 825119610Sache#if defined (HANDLE_MULTIBYTE) 826119610Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 827119610Sache rl_insert_text (mbkey); 828119610Sache else 829119610Sache#endif 830119610Sache _rl_insert_char (1, c); 831119610Sache 832136644Sache if (rl_point < rl_end) 833136644Sache rl_delete (1, c); 834119610Sache } 835119610Sache 836136644Sache rl_end_undo_group (); 837136644Sache 838119610Sache return 0; 839119610Sache} 840119610Sache 841119610Sacheint 842119610Sacherl_insert (count, c) 843119610Sache int count, c; 844119610Sache{ 845119610Sache return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c) 846119610Sache : _rl_overwrite_char (count, c)); 847119610Sache} 848119610Sache 849119610Sache/* Insert the next typed character verbatim. */ 850157184Sachestatic int 851157184Sache_rl_insert_next (count) 852157184Sache int count; 853119610Sache{ 854119610Sache int c; 855119610Sache 856119610Sache RL_SETSTATE(RL_STATE_MOREINPUT); 857119610Sache c = rl_read_key (); 858119610Sache RL_UNSETSTATE(RL_STATE_MOREINPUT); 859119610Sache 860119610Sache#if defined (HANDLE_SIGNALS) 861157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK) == 0) 862157184Sache _rl_restore_tty_signals (); 863119610Sache#endif 864119610Sache 865119610Sache return (_rl_insert_char (count, c)); 866119610Sache} 867119610Sache 868157184Sache#if defined (READLINE_CALLBACKS) 869157184Sachestatic int 870157184Sache_rl_insert_next_callback (data) 871157184Sache _rl_callback_generic_arg *data; 872157184Sache{ 873157184Sache int count; 874157184Sache 875157184Sache count = data->count; 876157184Sache 877157184Sache /* Deregister function, let rl_callback_read_char deallocate data */ 878157184Sache _rl_callback_func = 0; 879157184Sache _rl_want_redisplay = 1; 880157184Sache 881157184Sache return _rl_insert_next (count); 882157184Sache} 883157184Sache#endif 884157184Sache 885157184Sacheint 886157184Sacherl_quoted_insert (count, key) 887157184Sache int count, key; 888157184Sache{ 889157184Sache /* Let's see...should the callback interface futz with signal handling? */ 890157184Sache#if defined (HANDLE_SIGNALS) 891157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK) == 0) 892157184Sache _rl_disable_tty_signals (); 893157184Sache#endif 894157184Sache 895157184Sache#if defined (READLINE_CALLBACKS) 896157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK)) 897157184Sache { 898157184Sache _rl_callback_data = _rl_callback_data_alloc (count); 899157184Sache _rl_callback_func = _rl_insert_next_callback; 900157184Sache return (0); 901157184Sache } 902157184Sache#endif 903157184Sache 904157184Sache return _rl_insert_next (count); 905157184Sache} 906157184Sache 907119610Sache/* Insert a tab character. */ 908119610Sacheint 909119610Sacherl_tab_insert (count, key) 910119610Sache int count, key; 911119610Sache{ 912119610Sache return (_rl_insert_char (count, '\t')); 913119610Sache} 914119610Sache 915119610Sache/* What to do when a NEWLINE is pressed. We accept the whole line. 916119610Sache KEY is the key that invoked this command. I guess it could have 917119610Sache meaning in the future. */ 918119610Sacheint 919119610Sacherl_newline (count, key) 920119610Sache int count, key; 921119610Sache{ 922119610Sache rl_done = 1; 923119610Sache 924119610Sache if (_rl_history_preserve_point) 925119610Sache _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; 926119610Sache 927119610Sache RL_SETSTATE(RL_STATE_DONE); 928119610Sache 929119610Sache#if defined (VI_MODE) 930119610Sache if (rl_editing_mode == vi_mode) 931119610Sache { 932119610Sache _rl_vi_done_inserting (); 933136644Sache if (_rl_vi_textmod_command (_rl_vi_last_command) == 0) /* XXX */ 934136644Sache _rl_vi_reset_last (); 935119610Sache } 936119610Sache#endif /* VI_MODE */ 937119610Sache 938119610Sache /* If we've been asked to erase empty lines, suppress the final update, 939119610Sache since _rl_update_final calls rl_crlf(). */ 940119610Sache if (rl_erase_empty_line && rl_point == 0 && rl_end == 0) 941119610Sache return 0; 942119610Sache 943119610Sache if (readline_echoing_p) 944119610Sache _rl_update_final (); 945119610Sache return 0; 946119610Sache} 947119610Sache 948119610Sache/* What to do for some uppercase characters, like meta characters, 949119610Sache and some characters appearing in emacs_ctlx_keymap. This function 950119610Sache is just a stub, you bind keys to it and the code in _rl_dispatch () 951119610Sache is special cased. */ 952119610Sacheint 953119610Sacherl_do_lowercase_version (ignore1, ignore2) 954119610Sache int ignore1, ignore2; 955119610Sache{ 956119610Sache return 0; 957119610Sache} 958119610Sache 959119610Sache/* This is different from what vi does, so the code's not shared. Emacs 960119610Sache rubout in overwrite mode has one oddity: it replaces a control 961119610Sache character that's displayed as two characters (^X) with two spaces. */ 962119610Sacheint 963119610Sache_rl_overwrite_rubout (count, key) 964119610Sache int count, key; 965119610Sache{ 966119610Sache int opoint; 967119610Sache int i, l; 968119610Sache 969119610Sache if (rl_point == 0) 970119610Sache { 971119610Sache rl_ding (); 972119610Sache return 1; 973119610Sache } 974119610Sache 975119610Sache opoint = rl_point; 976119610Sache 977119610Sache /* L == number of spaces to insert */ 978119610Sache for (i = l = 0; i < count; i++) 979119610Sache { 980119610Sache rl_backward_char (1, key); 981119610Sache l += rl_character_len (rl_line_buffer[rl_point], rl_point); /* not exactly right */ 982119610Sache } 983119610Sache 984119610Sache rl_begin_undo_group (); 985119610Sache 986119610Sache if (count > 1 || rl_explicit_arg) 987119610Sache rl_kill_text (opoint, rl_point); 988119610Sache else 989119610Sache rl_delete_text (opoint, rl_point); 990119610Sache 991119610Sache /* Emacs puts point at the beginning of the sequence of spaces. */ 992136644Sache if (rl_point < rl_end) 993136644Sache { 994136644Sache opoint = rl_point; 995136644Sache _rl_insert_char (l, ' '); 996136644Sache rl_point = opoint; 997136644Sache } 998119610Sache 999119610Sache rl_end_undo_group (); 1000119610Sache 1001119610Sache return 0; 1002119610Sache} 1003119610Sache 1004119610Sache/* Rubout the character behind point. */ 1005119610Sacheint 1006119610Sacherl_rubout (count, key) 1007119610Sache int count, key; 1008119610Sache{ 1009119610Sache if (count < 0) 1010119610Sache return (rl_delete (-count, key)); 1011119610Sache 1012119610Sache if (!rl_point) 1013119610Sache { 1014119610Sache rl_ding (); 1015119610Sache return -1; 1016119610Sache } 1017119610Sache 1018119610Sache if (rl_insert_mode == RL_IM_OVERWRITE) 1019119610Sache return (_rl_overwrite_rubout (count, key)); 1020119610Sache 1021119610Sache return (_rl_rubout_char (count, key)); 1022119610Sache} 1023119610Sache 1024119610Sacheint 1025119610Sache_rl_rubout_char (count, key) 1026119610Sache int count, key; 1027119610Sache{ 1028119610Sache int orig_point; 1029119610Sache unsigned char c; 1030119610Sache 1031119610Sache /* Duplicated code because this is called from other parts of the library. */ 1032119610Sache if (count < 0) 1033119610Sache return (rl_delete (-count, key)); 1034119610Sache 1035119610Sache if (rl_point == 0) 1036119610Sache { 1037119610Sache rl_ding (); 1038119610Sache return -1; 1039119610Sache } 1040119610Sache 1041157184Sache orig_point = rl_point; 1042119610Sache if (count > 1 || rl_explicit_arg) 1043119610Sache { 1044157184Sache rl_backward_char (count, key); 1045119610Sache rl_kill_text (orig_point, rl_point); 1046119610Sache } 1047157184Sache else if (MB_CUR_MAX == 1 || rl_byte_oriented) 1048119610Sache { 1049157184Sache c = rl_line_buffer[--rl_point]; 1050157184Sache rl_delete_text (rl_point, orig_point); 1051157184Sache /* The erase-at-end-of-line hack is of questionable merit now. */ 1052119610Sache if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos) 1053119610Sache { 1054119610Sache int l; 1055119610Sache l = rl_character_len (c, rl_point); 1056119610Sache _rl_erase_at_end_of_line (l); 1057119610Sache } 1058119610Sache } 1059157184Sache else 1060157184Sache { 1061157184Sache rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); 1062157184Sache rl_delete_text (rl_point, orig_point); 1063157184Sache } 1064119610Sache 1065119610Sache return 0; 1066119610Sache} 1067119610Sache 1068119610Sache/* Delete the character under the cursor. Given a numeric argument, 1069119610Sache kill that many characters instead. */ 1070119610Sacheint 1071119610Sacherl_delete (count, key) 1072119610Sache int count, key; 1073119610Sache{ 1074165670Sache int xpoint; 1075165670Sache 1076119610Sache if (count < 0) 1077119610Sache return (_rl_rubout_char (-count, key)); 1078119610Sache 1079119610Sache if (rl_point == rl_end) 1080119610Sache { 1081119610Sache rl_ding (); 1082119610Sache return -1; 1083119610Sache } 1084119610Sache 1085119610Sache if (count > 1 || rl_explicit_arg) 1086119610Sache { 1087165670Sache xpoint = rl_point; 1088119610Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1089119610Sache rl_forward_char (count, key); 1090119610Sache else 1091119610Sache rl_forward_byte (count, key); 1092119610Sache 1093165670Sache rl_kill_text (xpoint, rl_point); 1094165670Sache rl_point = xpoint; 1095119610Sache } 1096119610Sache else 1097119610Sache { 1098165670Sache xpoint = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); 1099165670Sache rl_delete_text (rl_point, xpoint); 1100119610Sache } 1101157191Sache return 0; 1102119610Sache} 1103119610Sache 1104119610Sache/* Delete the character under the cursor, unless the insertion 1105119610Sache point is at the end of the line, in which case the character 1106119610Sache behind the cursor is deleted. COUNT is obeyed and may be used 1107119610Sache to delete forward or backward that many characters. */ 1108119610Sacheint 1109119610Sacherl_rubout_or_delete (count, key) 1110119610Sache int count, key; 1111119610Sache{ 1112119610Sache if (rl_end != 0 && rl_point == rl_end) 1113119610Sache return (_rl_rubout_char (count, key)); 1114119610Sache else 1115119610Sache return (rl_delete (count, key)); 1116119610Sache} 1117119610Sache 1118119610Sache/* Delete all spaces and tabs around point. */ 1119119610Sacheint 1120119610Sacherl_delete_horizontal_space (count, ignore) 1121119610Sache int count, ignore; 1122119610Sache{ 1123119610Sache int start = rl_point; 1124119610Sache 1125119610Sache while (rl_point && whitespace (rl_line_buffer[rl_point - 1])) 1126119610Sache rl_point--; 1127119610Sache 1128119610Sache start = rl_point; 1129119610Sache 1130119610Sache while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 1131119610Sache rl_point++; 1132119610Sache 1133119610Sache if (start != rl_point) 1134119610Sache { 1135119610Sache rl_delete_text (start, rl_point); 1136119610Sache rl_point = start; 1137119610Sache } 1138157184Sache 1139157184Sache if (rl_point < 0) 1140157184Sache rl_point = 0; 1141157184Sache 1142119610Sache return 0; 1143119610Sache} 1144119610Sache 1145119610Sache/* Like the tcsh editing function delete-char-or-list. The eof character 1146119610Sache is caught before this is invoked, so this really does the same thing as 1147119610Sache delete-char-or-list-or-eof, as long as it's bound to the eof character. */ 1148119610Sacheint 1149119610Sacherl_delete_or_show_completions (count, key) 1150119610Sache int count, key; 1151119610Sache{ 1152119610Sache if (rl_end != 0 && rl_point == rl_end) 1153119610Sache return (rl_possible_completions (count, key)); 1154119610Sache else 1155119610Sache return (rl_delete (count, key)); 1156119610Sache} 1157119610Sache 1158119610Sache#ifndef RL_COMMENT_BEGIN_DEFAULT 1159119610Sache#define RL_COMMENT_BEGIN_DEFAULT "#" 1160119610Sache#endif 1161119610Sache 1162119610Sache/* Turn the current line into a comment in shell history. 1163119610Sache A K*rn shell style function. */ 1164119610Sacheint 1165119610Sacherl_insert_comment (count, key) 1166119610Sache int count, key; 1167119610Sache{ 1168119610Sache char *rl_comment_text; 1169119610Sache int rl_comment_len; 1170119610Sache 1171119610Sache rl_beg_of_line (1, key); 1172119610Sache rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT; 1173119610Sache 1174119610Sache if (rl_explicit_arg == 0) 1175119610Sache rl_insert_text (rl_comment_text); 1176119610Sache else 1177119610Sache { 1178119610Sache rl_comment_len = strlen (rl_comment_text); 1179119610Sache if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len)) 1180119610Sache rl_delete_text (rl_point, rl_point + rl_comment_len); 1181119610Sache else 1182119610Sache rl_insert_text (rl_comment_text); 1183119610Sache } 1184119610Sache 1185119610Sache (*rl_redisplay_function) (); 1186119610Sache rl_newline (1, '\n'); 1187119610Sache 1188119610Sache return (0); 1189119610Sache} 1190119610Sache 1191119610Sache/* **************************************************************** */ 1192119610Sache/* */ 1193119610Sache/* Changing Case */ 1194119610Sache/* */ 1195119610Sache/* **************************************************************** */ 1196119610Sache 1197119610Sache/* The three kinds of things that we know how to do. */ 1198119610Sache#define UpCase 1 1199119610Sache#define DownCase 2 1200119610Sache#define CapCase 3 1201119610Sache 1202119610Sache/* Uppercase the word at point. */ 1203119610Sacheint 1204119610Sacherl_upcase_word (count, key) 1205119610Sache int count, key; 1206119610Sache{ 1207119610Sache return (rl_change_case (count, UpCase)); 1208119610Sache} 1209119610Sache 1210119610Sache/* Lowercase the word at point. */ 1211119610Sacheint 1212119610Sacherl_downcase_word (count, key) 1213119610Sache int count, key; 1214119610Sache{ 1215119610Sache return (rl_change_case (count, DownCase)); 1216119610Sache} 1217119610Sache 1218119610Sache/* Upcase the first letter, downcase the rest. */ 1219119610Sacheint 1220119610Sacherl_capitalize_word (count, key) 1221119610Sache int count, key; 1222119610Sache{ 1223119610Sache return (rl_change_case (count, CapCase)); 1224119610Sache} 1225119610Sache 1226119610Sache/* The meaty function. 1227119610Sache Change the case of COUNT words, performing OP on them. 1228119610Sache OP is one of UpCase, DownCase, or CapCase. 1229119610Sache If a negative argument is given, leave point where it started, 1230119610Sache otherwise, leave it where it moves to. */ 1231119610Sachestatic int 1232119610Sacherl_change_case (count, op) 1233119610Sache int count, op; 1234119610Sache{ 1235157184Sache int start, next, end; 1236157184Sache int inword, c, nc, nop; 1237157184Sache#if defined (HANDLE_MULTIBYTE) 1238157184Sache wchar_t wc, nwc; 1239157184Sache char mb[MB_LEN_MAX+1]; 1240165670Sache int mlen; 1241165670Sache mbstate_t mps; 1242157184Sache#endif 1243119610Sache 1244119610Sache start = rl_point; 1245119610Sache rl_forward_word (count, 0); 1246119610Sache end = rl_point; 1247119610Sache 1248157184Sache if (op != UpCase && op != DownCase && op != CapCase) 1249157184Sache { 1250157184Sache rl_ding (); 1251157184Sache return -1; 1252157184Sache } 1253157184Sache 1254119610Sache if (count < 0) 1255119610Sache SWAP (start, end); 1256119610Sache 1257157184Sache#if defined (HANDLE_MULTIBYTE) 1258165670Sache memset (&mps, 0, sizeof (mbstate_t)); 1259157184Sache#endif 1260157184Sache 1261119610Sache /* We are going to modify some text, so let's prepare to undo it. */ 1262119610Sache rl_modifying (start, end); 1263119610Sache 1264157184Sache inword = 0; 1265157184Sache while (start < end) 1266119610Sache { 1267157184Sache c = _rl_char_value (rl_line_buffer, start); 1268157184Sache /* This assumes that the upper and lower case versions are the same width. */ 1269157184Sache next = MB_NEXTCHAR (rl_line_buffer, start, 1, MB_FIND_NONZERO); 1270157184Sache 1271157184Sache if (_rl_walphabetic (c) == 0) 1272119610Sache { 1273157184Sache inword = 0; 1274157184Sache start = next; 1275157184Sache continue; 1276157184Sache } 1277119610Sache 1278157184Sache if (op == CapCase) 1279157184Sache { 1280157184Sache nop = inword ? DownCase : UpCase; 1281157184Sache inword = 1; 1282157184Sache } 1283157184Sache else 1284157184Sache nop = op; 1285157184Sache if (MB_CUR_MAX == 1 || rl_byte_oriented || isascii (c)) 1286157184Sache { 1287157184Sache nc = (nop == UpCase) ? _rl_to_upper (c) : _rl_to_lower (c); 1288157184Sache rl_line_buffer[start] = nc; 1289157184Sache } 1290157184Sache#if defined (HANDLE_MULTIBYTE) 1291157184Sache else 1292157184Sache { 1293165670Sache mbrtowc (&wc, rl_line_buffer + start, end - start, &mps); 1294157184Sache nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc); 1295157184Sache if (nwc != wc) /* just skip unchanged characters */ 1296157184Sache { 1297165670Sache mlen = wcrtomb (mb, nwc, &mps); 1298165670Sache if (mlen > 0) 1299165670Sache mb[mlen] = '\0'; 1300157184Sache /* Assume the same width */ 1301165670Sache strncpy (rl_line_buffer + start, mb, mlen); 1302157184Sache } 1303157184Sache } 1304157184Sache#endif 1305119610Sache 1306157184Sache start = next; 1307157184Sache } 1308119610Sache 1309119610Sache rl_point = end; 1310119610Sache return 0; 1311119610Sache} 1312119610Sache 1313119610Sache/* **************************************************************** */ 1314119610Sache/* */ 1315119610Sache/* Transposition */ 1316119610Sache/* */ 1317119610Sache/* **************************************************************** */ 1318119610Sache 1319119610Sache/* Transpose the words at point. If point is at the end of the line, 1320119610Sache transpose the two words before point. */ 1321119610Sacheint 1322119610Sacherl_transpose_words (count, key) 1323119610Sache int count, key; 1324119610Sache{ 1325119610Sache char *word1, *word2; 1326119610Sache int w1_beg, w1_end, w2_beg, w2_end; 1327119610Sache int orig_point = rl_point; 1328119610Sache 1329119610Sache if (!count) 1330119610Sache return 0; 1331119610Sache 1332119610Sache /* Find the two words. */ 1333119610Sache rl_forward_word (count, key); 1334119610Sache w2_end = rl_point; 1335119610Sache rl_backward_word (1, key); 1336119610Sache w2_beg = rl_point; 1337119610Sache rl_backward_word (count, key); 1338119610Sache w1_beg = rl_point; 1339119610Sache rl_forward_word (1, key); 1340119610Sache w1_end = rl_point; 1341119610Sache 1342119610Sache /* Do some check to make sure that there really are two words. */ 1343119610Sache if ((w1_beg == w2_beg) || (w2_beg < w1_end)) 1344119610Sache { 1345119610Sache rl_ding (); 1346119610Sache rl_point = orig_point; 1347119610Sache return -1; 1348119610Sache } 1349119610Sache 1350119610Sache /* Get the text of the words. */ 1351119610Sache word1 = rl_copy_text (w1_beg, w1_end); 1352119610Sache word2 = rl_copy_text (w2_beg, w2_end); 1353119610Sache 1354119610Sache /* We are about to do many insertions and deletions. Remember them 1355119610Sache as one operation. */ 1356119610Sache rl_begin_undo_group (); 1357119610Sache 1358119610Sache /* Do the stuff at word2 first, so that we don't have to worry 1359119610Sache about word1 moving. */ 1360119610Sache rl_point = w2_beg; 1361119610Sache rl_delete_text (w2_beg, w2_end); 1362119610Sache rl_insert_text (word1); 1363119610Sache 1364119610Sache rl_point = w1_beg; 1365119610Sache rl_delete_text (w1_beg, w1_end); 1366119610Sache rl_insert_text (word2); 1367119610Sache 1368119610Sache /* This is exactly correct since the text before this point has not 1369119610Sache changed in length. */ 1370119610Sache rl_point = w2_end; 1371119610Sache 1372119610Sache /* I think that does it. */ 1373119610Sache rl_end_undo_group (); 1374119610Sache free (word1); 1375119610Sache free (word2); 1376119610Sache 1377119610Sache return 0; 1378119610Sache} 1379119610Sache 1380119610Sache/* Transpose the characters at point. If point is at the end of the line, 1381119610Sache then transpose the characters before point. */ 1382119610Sacheint 1383119610Sacherl_transpose_chars (count, key) 1384119610Sache int count, key; 1385119610Sache{ 1386119610Sache#if defined (HANDLE_MULTIBYTE) 1387119610Sache char *dummy; 1388157184Sache int i; 1389119610Sache#else 1390119610Sache char dummy[2]; 1391119610Sache#endif 1392157184Sache int char_length, prev_point; 1393119610Sache 1394119610Sache if (count == 0) 1395119610Sache return 0; 1396119610Sache 1397119610Sache if (!rl_point || rl_end < 2) 1398119610Sache { 1399119610Sache rl_ding (); 1400119610Sache return -1; 1401119610Sache } 1402119610Sache 1403119610Sache rl_begin_undo_group (); 1404119610Sache 1405119610Sache if (rl_point == rl_end) 1406119610Sache { 1407157184Sache rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); 1408119610Sache count = 1; 1409119610Sache } 1410119610Sache 1411119610Sache prev_point = rl_point; 1412157184Sache rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); 1413119610Sache 1414119610Sache#if defined (HANDLE_MULTIBYTE) 1415119610Sache char_length = prev_point - rl_point; 1416119610Sache dummy = (char *)xmalloc (char_length + 1); 1417119610Sache for (i = 0; i < char_length; i++) 1418119610Sache dummy[i] = rl_line_buffer[rl_point + i]; 1419119610Sache dummy[i] = '\0'; 1420119610Sache#else 1421119610Sache dummy[0] = rl_line_buffer[rl_point]; 1422119610Sache dummy[char_length = 1] = '\0'; 1423119610Sache#endif 1424119610Sache 1425119610Sache rl_delete_text (rl_point, rl_point + char_length); 1426119610Sache 1427119610Sache rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); 1428119610Sache 1429119610Sache _rl_fix_point (0); 1430119610Sache rl_insert_text (dummy); 1431119610Sache rl_end_undo_group (); 1432119610Sache 1433119610Sache#if defined (HANDLE_MULTIBYTE) 1434119610Sache free (dummy); 1435119610Sache#endif 1436119610Sache 1437119610Sache return 0; 1438119610Sache} 1439119610Sache 1440119610Sache/* **************************************************************** */ 1441119610Sache/* */ 1442119610Sache/* Character Searching */ 1443119610Sache/* */ 1444119610Sache/* **************************************************************** */ 1445119610Sache 1446119610Sacheint 1447119610Sache#if defined (HANDLE_MULTIBYTE) 1448119610Sache_rl_char_search_internal (count, dir, smbchar, len) 1449119610Sache int count, dir; 1450119610Sache char *smbchar; 1451119610Sache int len; 1452119610Sache#else 1453119610Sache_rl_char_search_internal (count, dir, schar) 1454119610Sache int count, dir, schar; 1455119610Sache#endif 1456119610Sache{ 1457119610Sache int pos, inc; 1458119610Sache#if defined (HANDLE_MULTIBYTE) 1459119610Sache int prepos; 1460119610Sache#endif 1461119610Sache 1462119610Sache pos = rl_point; 1463119610Sache inc = (dir < 0) ? -1 : 1; 1464119610Sache while (count) 1465119610Sache { 1466119610Sache if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end)) 1467119610Sache { 1468119610Sache rl_ding (); 1469119610Sache return -1; 1470119610Sache } 1471119610Sache 1472119610Sache#if defined (HANDLE_MULTIBYTE) 1473119610Sache pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY) 1474119610Sache : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY); 1475119610Sache#else 1476119610Sache pos += inc; 1477119610Sache#endif 1478119610Sache do 1479119610Sache { 1480119610Sache#if defined (HANDLE_MULTIBYTE) 1481119610Sache if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len)) 1482119610Sache#else 1483119610Sache if (rl_line_buffer[pos] == schar) 1484119610Sache#endif 1485119610Sache { 1486119610Sache count--; 1487119610Sache if (dir < 0) 1488119610Sache rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY) 1489119610Sache : pos; 1490119610Sache else 1491119610Sache rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY) 1492119610Sache : pos; 1493119610Sache break; 1494119610Sache } 1495119610Sache#if defined (HANDLE_MULTIBYTE) 1496119610Sache prepos = pos; 1497119610Sache#endif 1498119610Sache } 1499119610Sache#if defined (HANDLE_MULTIBYTE) 1500119610Sache while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos 1501119610Sache : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos); 1502119610Sache#else 1503119610Sache while ((dir < 0) ? pos-- : ++pos < rl_end); 1504119610Sache#endif 1505119610Sache } 1506119610Sache return (0); 1507119610Sache} 1508119610Sache 1509119610Sache/* Search COUNT times for a character read from the current input stream. 1510119610Sache FDIR is the direction to search if COUNT is non-negative; otherwise 1511119610Sache the search goes in BDIR. So much is dependent on HANDLE_MULTIBYTE 1512119610Sache that there are two separate versions of this function. */ 1513119610Sache#if defined (HANDLE_MULTIBYTE) 1514119610Sachestatic int 1515119610Sache_rl_char_search (count, fdir, bdir) 1516119610Sache int count, fdir, bdir; 1517119610Sache{ 1518119610Sache char mbchar[MB_LEN_MAX]; 1519119610Sache int mb_len; 1520119610Sache 1521119610Sache mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX); 1522119610Sache 1523119610Sache if (count < 0) 1524119610Sache return (_rl_char_search_internal (-count, bdir, mbchar, mb_len)); 1525119610Sache else 1526119610Sache return (_rl_char_search_internal (count, fdir, mbchar, mb_len)); 1527119610Sache} 1528119610Sache#else /* !HANDLE_MULTIBYTE */ 1529119610Sachestatic int 1530119610Sache_rl_char_search (count, fdir, bdir) 1531119610Sache int count, fdir, bdir; 1532119610Sache{ 1533119610Sache int c; 1534119610Sache 1535119610Sache RL_SETSTATE(RL_STATE_MOREINPUT); 1536119610Sache c = rl_read_key (); 1537119610Sache RL_UNSETSTATE(RL_STATE_MOREINPUT); 1538119610Sache 1539119610Sache if (count < 0) 1540119610Sache return (_rl_char_search_internal (-count, bdir, c)); 1541119610Sache else 1542119610Sache return (_rl_char_search_internal (count, fdir, c)); 1543119610Sache} 1544119610Sache#endif /* !HANDLE_MULTIBYTE */ 1545119610Sache 1546157184Sache#if defined (READLINE_CALLBACKS) 1547157184Sachestatic int 1548157184Sache_rl_char_search_callback (data) 1549157184Sache _rl_callback_generic_arg *data; 1550157184Sache{ 1551157184Sache _rl_callback_func = 0; 1552157184Sache _rl_want_redisplay = 1; 1553157184Sache 1554157184Sache return (_rl_char_search (data->count, data->i1, data->i2)); 1555157184Sache} 1556157184Sache#endif 1557157184Sache 1558119610Sacheint 1559119610Sacherl_char_search (count, key) 1560119610Sache int count, key; 1561119610Sache{ 1562157184Sache#if defined (READLINE_CALLBACKS) 1563157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK)) 1564157184Sache { 1565157184Sache _rl_callback_data = _rl_callback_data_alloc (count); 1566157184Sache _rl_callback_data->i1 = FFIND; 1567157184Sache _rl_callback_data->i2 = BFIND; 1568157184Sache _rl_callback_func = _rl_char_search_callback; 1569157184Sache return (0); 1570157184Sache } 1571157184Sache#endif 1572157184Sache 1573119610Sache return (_rl_char_search (count, FFIND, BFIND)); 1574119610Sache} 1575119610Sache 1576119610Sacheint 1577119610Sacherl_backward_char_search (count, key) 1578119610Sache int count, key; 1579119610Sache{ 1580157184Sache#if defined (READLINE_CALLBACKS) 1581157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK)) 1582157184Sache { 1583157184Sache _rl_callback_data = _rl_callback_data_alloc (count); 1584157184Sache _rl_callback_data->i1 = BFIND; 1585157184Sache _rl_callback_data->i2 = FFIND; 1586157184Sache _rl_callback_func = _rl_char_search_callback; 1587157184Sache return (0); 1588157184Sache } 1589157184Sache#endif 1590157184Sache 1591119610Sache return (_rl_char_search (count, BFIND, FFIND)); 1592119610Sache} 1593119610Sache 1594119610Sache/* **************************************************************** */ 1595119610Sache/* */ 1596119610Sache/* The Mark and the Region. */ 1597119610Sache/* */ 1598119610Sache/* **************************************************************** */ 1599119610Sache 1600119610Sache/* Set the mark at POSITION. */ 1601119610Sacheint 1602119610Sache_rl_set_mark_at_pos (position) 1603119610Sache int position; 1604119610Sache{ 1605119610Sache if (position > rl_end) 1606119610Sache return -1; 1607119610Sache 1608119610Sache rl_mark = position; 1609119610Sache return 0; 1610119610Sache} 1611119610Sache 1612119610Sache/* A bindable command to set the mark. */ 1613119610Sacheint 1614119610Sacherl_set_mark (count, key) 1615119610Sache int count, key; 1616119610Sache{ 1617119610Sache return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point)); 1618119610Sache} 1619119610Sache 1620119610Sache/* Exchange the position of mark and point. */ 1621119610Sacheint 1622119610Sacherl_exchange_point_and_mark (count, key) 1623119610Sache int count, key; 1624119610Sache{ 1625119610Sache if (rl_mark > rl_end) 1626119610Sache rl_mark = -1; 1627119610Sache 1628119610Sache if (rl_mark == -1) 1629119610Sache { 1630119610Sache rl_ding (); 1631119610Sache return -1; 1632119610Sache } 1633119610Sache else 1634119610Sache SWAP (rl_point, rl_mark); 1635119610Sache 1636119610Sache return 0; 1637119610Sache} 1638