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 860173403Sache if (c < 0) 861173403Sache return -1; 862173403Sache 863119610Sache#if defined (HANDLE_SIGNALS) 864157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK) == 0) 865157184Sache _rl_restore_tty_signals (); 866119610Sache#endif 867119610Sache 868119610Sache return (_rl_insert_char (count, c)); 869119610Sache} 870119610Sache 871157184Sache#if defined (READLINE_CALLBACKS) 872157184Sachestatic int 873157184Sache_rl_insert_next_callback (data) 874157184Sache _rl_callback_generic_arg *data; 875157184Sache{ 876157184Sache int count; 877157184Sache 878157184Sache count = data->count; 879157184Sache 880157184Sache /* Deregister function, let rl_callback_read_char deallocate data */ 881157184Sache _rl_callback_func = 0; 882157184Sache _rl_want_redisplay = 1; 883157184Sache 884157184Sache return _rl_insert_next (count); 885157184Sache} 886157184Sache#endif 887157184Sache 888157184Sacheint 889157184Sacherl_quoted_insert (count, key) 890157184Sache int count, key; 891157184Sache{ 892157184Sache /* Let's see...should the callback interface futz with signal handling? */ 893157184Sache#if defined (HANDLE_SIGNALS) 894157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK) == 0) 895157184Sache _rl_disable_tty_signals (); 896157184Sache#endif 897157184Sache 898157184Sache#if defined (READLINE_CALLBACKS) 899157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK)) 900157184Sache { 901157184Sache _rl_callback_data = _rl_callback_data_alloc (count); 902157184Sache _rl_callback_func = _rl_insert_next_callback; 903157184Sache return (0); 904157184Sache } 905157184Sache#endif 906157184Sache 907157184Sache return _rl_insert_next (count); 908157184Sache} 909157184Sache 910119610Sache/* Insert a tab character. */ 911119610Sacheint 912119610Sacherl_tab_insert (count, key) 913119610Sache int count, key; 914119610Sache{ 915119610Sache return (_rl_insert_char (count, '\t')); 916119610Sache} 917119610Sache 918119610Sache/* What to do when a NEWLINE is pressed. We accept the whole line. 919119610Sache KEY is the key that invoked this command. I guess it could have 920119610Sache meaning in the future. */ 921119610Sacheint 922119610Sacherl_newline (count, key) 923119610Sache int count, key; 924119610Sache{ 925119610Sache rl_done = 1; 926119610Sache 927119610Sache if (_rl_history_preserve_point) 928119610Sache _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; 929119610Sache 930119610Sache RL_SETSTATE(RL_STATE_DONE); 931119610Sache 932119610Sache#if defined (VI_MODE) 933119610Sache if (rl_editing_mode == vi_mode) 934119610Sache { 935119610Sache _rl_vi_done_inserting (); 936136644Sache if (_rl_vi_textmod_command (_rl_vi_last_command) == 0) /* XXX */ 937136644Sache _rl_vi_reset_last (); 938119610Sache } 939119610Sache#endif /* VI_MODE */ 940119610Sache 941119610Sache /* If we've been asked to erase empty lines, suppress the final update, 942119610Sache since _rl_update_final calls rl_crlf(). */ 943119610Sache if (rl_erase_empty_line && rl_point == 0 && rl_end == 0) 944119610Sache return 0; 945119610Sache 946119610Sache if (readline_echoing_p) 947119610Sache _rl_update_final (); 948119610Sache return 0; 949119610Sache} 950119610Sache 951119610Sache/* What to do for some uppercase characters, like meta characters, 952119610Sache and some characters appearing in emacs_ctlx_keymap. This function 953119610Sache is just a stub, you bind keys to it and the code in _rl_dispatch () 954119610Sache is special cased. */ 955119610Sacheint 956119610Sacherl_do_lowercase_version (ignore1, ignore2) 957119610Sache int ignore1, ignore2; 958119610Sache{ 959119610Sache return 0; 960119610Sache} 961119610Sache 962119610Sache/* This is different from what vi does, so the code's not shared. Emacs 963119610Sache rubout in overwrite mode has one oddity: it replaces a control 964119610Sache character that's displayed as two characters (^X) with two spaces. */ 965119610Sacheint 966119610Sache_rl_overwrite_rubout (count, key) 967119610Sache int count, key; 968119610Sache{ 969119610Sache int opoint; 970119610Sache int i, l; 971119610Sache 972119610Sache if (rl_point == 0) 973119610Sache { 974119610Sache rl_ding (); 975119610Sache return 1; 976119610Sache } 977119610Sache 978119610Sache opoint = rl_point; 979119610Sache 980119610Sache /* L == number of spaces to insert */ 981119610Sache for (i = l = 0; i < count; i++) 982119610Sache { 983119610Sache rl_backward_char (1, key); 984119610Sache l += rl_character_len (rl_line_buffer[rl_point], rl_point); /* not exactly right */ 985119610Sache } 986119610Sache 987119610Sache rl_begin_undo_group (); 988119610Sache 989119610Sache if (count > 1 || rl_explicit_arg) 990119610Sache rl_kill_text (opoint, rl_point); 991119610Sache else 992119610Sache rl_delete_text (opoint, rl_point); 993119610Sache 994119610Sache /* Emacs puts point at the beginning of the sequence of spaces. */ 995136644Sache if (rl_point < rl_end) 996136644Sache { 997136644Sache opoint = rl_point; 998136644Sache _rl_insert_char (l, ' '); 999136644Sache rl_point = opoint; 1000136644Sache } 1001119610Sache 1002119610Sache rl_end_undo_group (); 1003119610Sache 1004119610Sache return 0; 1005119610Sache} 1006119610Sache 1007119610Sache/* Rubout the character behind point. */ 1008119610Sacheint 1009119610Sacherl_rubout (count, key) 1010119610Sache int count, key; 1011119610Sache{ 1012119610Sache if (count < 0) 1013119610Sache return (rl_delete (-count, key)); 1014119610Sache 1015119610Sache if (!rl_point) 1016119610Sache { 1017119610Sache rl_ding (); 1018119610Sache return -1; 1019119610Sache } 1020119610Sache 1021119610Sache if (rl_insert_mode == RL_IM_OVERWRITE) 1022119610Sache return (_rl_overwrite_rubout (count, key)); 1023119610Sache 1024119610Sache return (_rl_rubout_char (count, key)); 1025119610Sache} 1026119610Sache 1027119610Sacheint 1028119610Sache_rl_rubout_char (count, key) 1029119610Sache int count, key; 1030119610Sache{ 1031119610Sache int orig_point; 1032119610Sache unsigned char c; 1033119610Sache 1034119610Sache /* Duplicated code because this is called from other parts of the library. */ 1035119610Sache if (count < 0) 1036119610Sache return (rl_delete (-count, key)); 1037119610Sache 1038119610Sache if (rl_point == 0) 1039119610Sache { 1040119610Sache rl_ding (); 1041119610Sache return -1; 1042119610Sache } 1043119610Sache 1044157184Sache orig_point = rl_point; 1045119610Sache if (count > 1 || rl_explicit_arg) 1046119610Sache { 1047157184Sache rl_backward_char (count, key); 1048119610Sache rl_kill_text (orig_point, rl_point); 1049119610Sache } 1050157184Sache else if (MB_CUR_MAX == 1 || rl_byte_oriented) 1051119610Sache { 1052157184Sache c = rl_line_buffer[--rl_point]; 1053157184Sache rl_delete_text (rl_point, orig_point); 1054157184Sache /* The erase-at-end-of-line hack is of questionable merit now. */ 1055119610Sache if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos) 1056119610Sache { 1057119610Sache int l; 1058119610Sache l = rl_character_len (c, rl_point); 1059119610Sache _rl_erase_at_end_of_line (l); 1060119610Sache } 1061119610Sache } 1062157184Sache else 1063157184Sache { 1064157184Sache rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); 1065157184Sache rl_delete_text (rl_point, orig_point); 1066157184Sache } 1067119610Sache 1068119610Sache return 0; 1069119610Sache} 1070119610Sache 1071119610Sache/* Delete the character under the cursor. Given a numeric argument, 1072119610Sache kill that many characters instead. */ 1073119610Sacheint 1074119610Sacherl_delete (count, key) 1075119610Sache int count, key; 1076119610Sache{ 1077165670Sache int xpoint; 1078165670Sache 1079119610Sache if (count < 0) 1080119610Sache return (_rl_rubout_char (-count, key)); 1081119610Sache 1082119610Sache if (rl_point == rl_end) 1083119610Sache { 1084119610Sache rl_ding (); 1085119610Sache return -1; 1086119610Sache } 1087119610Sache 1088119610Sache if (count > 1 || rl_explicit_arg) 1089119610Sache { 1090165670Sache xpoint = rl_point; 1091119610Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1092119610Sache rl_forward_char (count, key); 1093119610Sache else 1094119610Sache rl_forward_byte (count, key); 1095119610Sache 1096165670Sache rl_kill_text (xpoint, rl_point); 1097165670Sache rl_point = xpoint; 1098119610Sache } 1099119610Sache else 1100119610Sache { 1101165670Sache xpoint = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); 1102165670Sache rl_delete_text (rl_point, xpoint); 1103119610Sache } 1104157191Sache return 0; 1105119610Sache} 1106119610Sache 1107119610Sache/* Delete the character under the cursor, unless the insertion 1108119610Sache point is at the end of the line, in which case the character 1109119610Sache behind the cursor is deleted. COUNT is obeyed and may be used 1110119610Sache to delete forward or backward that many characters. */ 1111119610Sacheint 1112119610Sacherl_rubout_or_delete (count, key) 1113119610Sache int count, key; 1114119610Sache{ 1115119610Sache if (rl_end != 0 && rl_point == rl_end) 1116119610Sache return (_rl_rubout_char (count, key)); 1117119610Sache else 1118119610Sache return (rl_delete (count, key)); 1119119610Sache} 1120119610Sache 1121119610Sache/* Delete all spaces and tabs around point. */ 1122119610Sacheint 1123119610Sacherl_delete_horizontal_space (count, ignore) 1124119610Sache int count, ignore; 1125119610Sache{ 1126119610Sache int start = rl_point; 1127119610Sache 1128119610Sache while (rl_point && whitespace (rl_line_buffer[rl_point - 1])) 1129119610Sache rl_point--; 1130119610Sache 1131119610Sache start = rl_point; 1132119610Sache 1133119610Sache while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 1134119610Sache rl_point++; 1135119610Sache 1136119610Sache if (start != rl_point) 1137119610Sache { 1138119610Sache rl_delete_text (start, rl_point); 1139119610Sache rl_point = start; 1140119610Sache } 1141157184Sache 1142157184Sache if (rl_point < 0) 1143157184Sache rl_point = 0; 1144157184Sache 1145119610Sache return 0; 1146119610Sache} 1147119610Sache 1148119610Sache/* Like the tcsh editing function delete-char-or-list. The eof character 1149119610Sache is caught before this is invoked, so this really does the same thing as 1150119610Sache delete-char-or-list-or-eof, as long as it's bound to the eof character. */ 1151119610Sacheint 1152119610Sacherl_delete_or_show_completions (count, key) 1153119610Sache int count, key; 1154119610Sache{ 1155119610Sache if (rl_end != 0 && rl_point == rl_end) 1156119610Sache return (rl_possible_completions (count, key)); 1157119610Sache else 1158119610Sache return (rl_delete (count, key)); 1159119610Sache} 1160119610Sache 1161119610Sache#ifndef RL_COMMENT_BEGIN_DEFAULT 1162119610Sache#define RL_COMMENT_BEGIN_DEFAULT "#" 1163119610Sache#endif 1164119610Sache 1165119610Sache/* Turn the current line into a comment in shell history. 1166119610Sache A K*rn shell style function. */ 1167119610Sacheint 1168119610Sacherl_insert_comment (count, key) 1169119610Sache int count, key; 1170119610Sache{ 1171119610Sache char *rl_comment_text; 1172119610Sache int rl_comment_len; 1173119610Sache 1174119610Sache rl_beg_of_line (1, key); 1175119610Sache rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT; 1176119610Sache 1177119610Sache if (rl_explicit_arg == 0) 1178119610Sache rl_insert_text (rl_comment_text); 1179119610Sache else 1180119610Sache { 1181119610Sache rl_comment_len = strlen (rl_comment_text); 1182119610Sache if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len)) 1183119610Sache rl_delete_text (rl_point, rl_point + rl_comment_len); 1184119610Sache else 1185119610Sache rl_insert_text (rl_comment_text); 1186119610Sache } 1187119610Sache 1188119610Sache (*rl_redisplay_function) (); 1189119610Sache rl_newline (1, '\n'); 1190119610Sache 1191119610Sache return (0); 1192119610Sache} 1193119610Sache 1194119610Sache/* **************************************************************** */ 1195119610Sache/* */ 1196119610Sache/* Changing Case */ 1197119610Sache/* */ 1198119610Sache/* **************************************************************** */ 1199119610Sache 1200119610Sache/* The three kinds of things that we know how to do. */ 1201119610Sache#define UpCase 1 1202119610Sache#define DownCase 2 1203119610Sache#define CapCase 3 1204119610Sache 1205119610Sache/* Uppercase the word at point. */ 1206119610Sacheint 1207119610Sacherl_upcase_word (count, key) 1208119610Sache int count, key; 1209119610Sache{ 1210119610Sache return (rl_change_case (count, UpCase)); 1211119610Sache} 1212119610Sache 1213119610Sache/* Lowercase the word at point. */ 1214119610Sacheint 1215119610Sacherl_downcase_word (count, key) 1216119610Sache int count, key; 1217119610Sache{ 1218119610Sache return (rl_change_case (count, DownCase)); 1219119610Sache} 1220119610Sache 1221119610Sache/* Upcase the first letter, downcase the rest. */ 1222119610Sacheint 1223119610Sacherl_capitalize_word (count, key) 1224119610Sache int count, key; 1225119610Sache{ 1226119610Sache return (rl_change_case (count, CapCase)); 1227119610Sache} 1228119610Sache 1229119610Sache/* The meaty function. 1230119610Sache Change the case of COUNT words, performing OP on them. 1231119610Sache OP is one of UpCase, DownCase, or CapCase. 1232119610Sache If a negative argument is given, leave point where it started, 1233119610Sache otherwise, leave it where it moves to. */ 1234119610Sachestatic int 1235119610Sacherl_change_case (count, op) 1236119610Sache int count, op; 1237119610Sache{ 1238157184Sache int start, next, end; 1239157184Sache int inword, c, nc, nop; 1240157184Sache#if defined (HANDLE_MULTIBYTE) 1241157184Sache wchar_t wc, nwc; 1242157184Sache char mb[MB_LEN_MAX+1]; 1243165670Sache int mlen; 1244165670Sache mbstate_t mps; 1245157184Sache#endif 1246119610Sache 1247119610Sache start = rl_point; 1248119610Sache rl_forward_word (count, 0); 1249119610Sache end = rl_point; 1250119610Sache 1251157184Sache if (op != UpCase && op != DownCase && op != CapCase) 1252157184Sache { 1253157184Sache rl_ding (); 1254157184Sache return -1; 1255157184Sache } 1256157184Sache 1257119610Sache if (count < 0) 1258119610Sache SWAP (start, end); 1259119610Sache 1260157184Sache#if defined (HANDLE_MULTIBYTE) 1261165670Sache memset (&mps, 0, sizeof (mbstate_t)); 1262157184Sache#endif 1263157184Sache 1264119610Sache /* We are going to modify some text, so let's prepare to undo it. */ 1265119610Sache rl_modifying (start, end); 1266119610Sache 1267157184Sache inword = 0; 1268157184Sache while (start < end) 1269119610Sache { 1270157184Sache c = _rl_char_value (rl_line_buffer, start); 1271157184Sache /* This assumes that the upper and lower case versions are the same width. */ 1272157184Sache next = MB_NEXTCHAR (rl_line_buffer, start, 1, MB_FIND_NONZERO); 1273157184Sache 1274157184Sache if (_rl_walphabetic (c) == 0) 1275119610Sache { 1276157184Sache inword = 0; 1277157184Sache start = next; 1278157184Sache continue; 1279157184Sache } 1280119610Sache 1281157184Sache if (op == CapCase) 1282157184Sache { 1283157184Sache nop = inword ? DownCase : UpCase; 1284157184Sache inword = 1; 1285157184Sache } 1286157184Sache else 1287157184Sache nop = op; 1288157184Sache if (MB_CUR_MAX == 1 || rl_byte_oriented || isascii (c)) 1289157184Sache { 1290157184Sache nc = (nop == UpCase) ? _rl_to_upper (c) : _rl_to_lower (c); 1291157184Sache rl_line_buffer[start] = nc; 1292157184Sache } 1293157184Sache#if defined (HANDLE_MULTIBYTE) 1294157184Sache else 1295157184Sache { 1296165670Sache mbrtowc (&wc, rl_line_buffer + start, end - start, &mps); 1297157184Sache nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc); 1298157184Sache if (nwc != wc) /* just skip unchanged characters */ 1299157184Sache { 1300165670Sache mlen = wcrtomb (mb, nwc, &mps); 1301165670Sache if (mlen > 0) 1302165670Sache mb[mlen] = '\0'; 1303157184Sache /* Assume the same width */ 1304165670Sache strncpy (rl_line_buffer + start, mb, mlen); 1305157184Sache } 1306157184Sache } 1307157184Sache#endif 1308119610Sache 1309157184Sache start = next; 1310157184Sache } 1311119610Sache 1312119610Sache rl_point = end; 1313119610Sache return 0; 1314119610Sache} 1315119610Sache 1316119610Sache/* **************************************************************** */ 1317119610Sache/* */ 1318119610Sache/* Transposition */ 1319119610Sache/* */ 1320119610Sache/* **************************************************************** */ 1321119610Sache 1322119610Sache/* Transpose the words at point. If point is at the end of the line, 1323119610Sache transpose the two words before point. */ 1324119610Sacheint 1325119610Sacherl_transpose_words (count, key) 1326119610Sache int count, key; 1327119610Sache{ 1328119610Sache char *word1, *word2; 1329119610Sache int w1_beg, w1_end, w2_beg, w2_end; 1330119610Sache int orig_point = rl_point; 1331119610Sache 1332119610Sache if (!count) 1333119610Sache return 0; 1334119610Sache 1335119610Sache /* Find the two words. */ 1336119610Sache rl_forward_word (count, key); 1337119610Sache w2_end = rl_point; 1338119610Sache rl_backward_word (1, key); 1339119610Sache w2_beg = rl_point; 1340119610Sache rl_backward_word (count, key); 1341119610Sache w1_beg = rl_point; 1342119610Sache rl_forward_word (1, key); 1343119610Sache w1_end = rl_point; 1344119610Sache 1345119610Sache /* Do some check to make sure that there really are two words. */ 1346119610Sache if ((w1_beg == w2_beg) || (w2_beg < w1_end)) 1347119610Sache { 1348119610Sache rl_ding (); 1349119610Sache rl_point = orig_point; 1350119610Sache return -1; 1351119610Sache } 1352119610Sache 1353119610Sache /* Get the text of the words. */ 1354119610Sache word1 = rl_copy_text (w1_beg, w1_end); 1355119610Sache word2 = rl_copy_text (w2_beg, w2_end); 1356119610Sache 1357119610Sache /* We are about to do many insertions and deletions. Remember them 1358119610Sache as one operation. */ 1359119610Sache rl_begin_undo_group (); 1360119610Sache 1361119610Sache /* Do the stuff at word2 first, so that we don't have to worry 1362119610Sache about word1 moving. */ 1363119610Sache rl_point = w2_beg; 1364119610Sache rl_delete_text (w2_beg, w2_end); 1365119610Sache rl_insert_text (word1); 1366119610Sache 1367119610Sache rl_point = w1_beg; 1368119610Sache rl_delete_text (w1_beg, w1_end); 1369119610Sache rl_insert_text (word2); 1370119610Sache 1371119610Sache /* This is exactly correct since the text before this point has not 1372119610Sache changed in length. */ 1373119610Sache rl_point = w2_end; 1374119610Sache 1375119610Sache /* I think that does it. */ 1376119610Sache rl_end_undo_group (); 1377119610Sache free (word1); 1378119610Sache free (word2); 1379119610Sache 1380119610Sache return 0; 1381119610Sache} 1382119610Sache 1383119610Sache/* Transpose the characters at point. If point is at the end of the line, 1384119610Sache then transpose the characters before point. */ 1385119610Sacheint 1386119610Sacherl_transpose_chars (count, key) 1387119610Sache int count, key; 1388119610Sache{ 1389119610Sache#if defined (HANDLE_MULTIBYTE) 1390119610Sache char *dummy; 1391157184Sache int i; 1392119610Sache#else 1393119610Sache char dummy[2]; 1394119610Sache#endif 1395157184Sache int char_length, prev_point; 1396119610Sache 1397119610Sache if (count == 0) 1398119610Sache return 0; 1399119610Sache 1400119610Sache if (!rl_point || rl_end < 2) 1401119610Sache { 1402119610Sache rl_ding (); 1403119610Sache return -1; 1404119610Sache } 1405119610Sache 1406119610Sache rl_begin_undo_group (); 1407119610Sache 1408119610Sache if (rl_point == rl_end) 1409119610Sache { 1410157184Sache rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); 1411119610Sache count = 1; 1412119610Sache } 1413119610Sache 1414119610Sache prev_point = rl_point; 1415157184Sache rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); 1416119610Sache 1417119610Sache#if defined (HANDLE_MULTIBYTE) 1418119610Sache char_length = prev_point - rl_point; 1419119610Sache dummy = (char *)xmalloc (char_length + 1); 1420119610Sache for (i = 0; i < char_length; i++) 1421119610Sache dummy[i] = rl_line_buffer[rl_point + i]; 1422119610Sache dummy[i] = '\0'; 1423119610Sache#else 1424119610Sache dummy[0] = rl_line_buffer[rl_point]; 1425119610Sache dummy[char_length = 1] = '\0'; 1426119610Sache#endif 1427119610Sache 1428119610Sache rl_delete_text (rl_point, rl_point + char_length); 1429119610Sache 1430119610Sache rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); 1431119610Sache 1432119610Sache _rl_fix_point (0); 1433119610Sache rl_insert_text (dummy); 1434119610Sache rl_end_undo_group (); 1435119610Sache 1436119610Sache#if defined (HANDLE_MULTIBYTE) 1437119610Sache free (dummy); 1438119610Sache#endif 1439119610Sache 1440119610Sache return 0; 1441119610Sache} 1442119610Sache 1443119610Sache/* **************************************************************** */ 1444119610Sache/* */ 1445119610Sache/* Character Searching */ 1446119610Sache/* */ 1447119610Sache/* **************************************************************** */ 1448119610Sache 1449119610Sacheint 1450119610Sache#if defined (HANDLE_MULTIBYTE) 1451119610Sache_rl_char_search_internal (count, dir, smbchar, len) 1452119610Sache int count, dir; 1453119610Sache char *smbchar; 1454119610Sache int len; 1455119610Sache#else 1456119610Sache_rl_char_search_internal (count, dir, schar) 1457119610Sache int count, dir, schar; 1458119610Sache#endif 1459119610Sache{ 1460119610Sache int pos, inc; 1461119610Sache#if defined (HANDLE_MULTIBYTE) 1462119610Sache int prepos; 1463119610Sache#endif 1464119610Sache 1465119610Sache pos = rl_point; 1466119610Sache inc = (dir < 0) ? -1 : 1; 1467119610Sache while (count) 1468119610Sache { 1469119610Sache if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end)) 1470119610Sache { 1471119610Sache rl_ding (); 1472119610Sache return -1; 1473119610Sache } 1474119610Sache 1475119610Sache#if defined (HANDLE_MULTIBYTE) 1476119610Sache pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY) 1477119610Sache : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY); 1478119610Sache#else 1479119610Sache pos += inc; 1480119610Sache#endif 1481119610Sache do 1482119610Sache { 1483119610Sache#if defined (HANDLE_MULTIBYTE) 1484119610Sache if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len)) 1485119610Sache#else 1486119610Sache if (rl_line_buffer[pos] == schar) 1487119610Sache#endif 1488119610Sache { 1489119610Sache count--; 1490119610Sache if (dir < 0) 1491119610Sache rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY) 1492119610Sache : pos; 1493119610Sache else 1494119610Sache rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY) 1495119610Sache : pos; 1496119610Sache break; 1497119610Sache } 1498119610Sache#if defined (HANDLE_MULTIBYTE) 1499119610Sache prepos = pos; 1500119610Sache#endif 1501119610Sache } 1502119610Sache#if defined (HANDLE_MULTIBYTE) 1503119610Sache while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos 1504119610Sache : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos); 1505119610Sache#else 1506119610Sache while ((dir < 0) ? pos-- : ++pos < rl_end); 1507119610Sache#endif 1508119610Sache } 1509119610Sache return (0); 1510119610Sache} 1511119610Sache 1512119610Sache/* Search COUNT times for a character read from the current input stream. 1513119610Sache FDIR is the direction to search if COUNT is non-negative; otherwise 1514119610Sache the search goes in BDIR. So much is dependent on HANDLE_MULTIBYTE 1515119610Sache that there are two separate versions of this function. */ 1516119610Sache#if defined (HANDLE_MULTIBYTE) 1517119610Sachestatic int 1518119610Sache_rl_char_search (count, fdir, bdir) 1519119610Sache int count, fdir, bdir; 1520119610Sache{ 1521119610Sache char mbchar[MB_LEN_MAX]; 1522119610Sache int mb_len; 1523119610Sache 1524119610Sache mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX); 1525119610Sache 1526173403Sache if (mb_len <= 0) 1527173403Sache return -1; 1528173403Sache 1529119610Sache if (count < 0) 1530119610Sache return (_rl_char_search_internal (-count, bdir, mbchar, mb_len)); 1531119610Sache else 1532119610Sache return (_rl_char_search_internal (count, fdir, mbchar, mb_len)); 1533119610Sache} 1534119610Sache#else /* !HANDLE_MULTIBYTE */ 1535119610Sachestatic int 1536119610Sache_rl_char_search (count, fdir, bdir) 1537119610Sache int count, fdir, bdir; 1538119610Sache{ 1539119610Sache int c; 1540119610Sache 1541119610Sache RL_SETSTATE(RL_STATE_MOREINPUT); 1542119610Sache c = rl_read_key (); 1543119610Sache RL_UNSETSTATE(RL_STATE_MOREINPUT); 1544119610Sache 1545173403Sache if (c < 0) 1546173403Sache return -1; 1547173403Sache 1548119610Sache if (count < 0) 1549119610Sache return (_rl_char_search_internal (-count, bdir, c)); 1550119610Sache else 1551119610Sache return (_rl_char_search_internal (count, fdir, c)); 1552119610Sache} 1553119610Sache#endif /* !HANDLE_MULTIBYTE */ 1554119610Sache 1555157184Sache#if defined (READLINE_CALLBACKS) 1556157184Sachestatic int 1557157184Sache_rl_char_search_callback (data) 1558157184Sache _rl_callback_generic_arg *data; 1559157184Sache{ 1560157184Sache _rl_callback_func = 0; 1561157184Sache _rl_want_redisplay = 1; 1562157184Sache 1563157184Sache return (_rl_char_search (data->count, data->i1, data->i2)); 1564157184Sache} 1565157184Sache#endif 1566157184Sache 1567119610Sacheint 1568119610Sacherl_char_search (count, key) 1569119610Sache int count, key; 1570119610Sache{ 1571157184Sache#if defined (READLINE_CALLBACKS) 1572157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK)) 1573157184Sache { 1574157184Sache _rl_callback_data = _rl_callback_data_alloc (count); 1575157184Sache _rl_callback_data->i1 = FFIND; 1576157184Sache _rl_callback_data->i2 = BFIND; 1577157184Sache _rl_callback_func = _rl_char_search_callback; 1578157184Sache return (0); 1579157184Sache } 1580157184Sache#endif 1581157184Sache 1582119610Sache return (_rl_char_search (count, FFIND, BFIND)); 1583119610Sache} 1584119610Sache 1585119610Sacheint 1586119610Sacherl_backward_char_search (count, key) 1587119610Sache int count, key; 1588119610Sache{ 1589157184Sache#if defined (READLINE_CALLBACKS) 1590157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK)) 1591157184Sache { 1592157184Sache _rl_callback_data = _rl_callback_data_alloc (count); 1593157184Sache _rl_callback_data->i1 = BFIND; 1594157184Sache _rl_callback_data->i2 = FFIND; 1595157184Sache _rl_callback_func = _rl_char_search_callback; 1596157184Sache return (0); 1597157184Sache } 1598157184Sache#endif 1599157184Sache 1600119610Sache return (_rl_char_search (count, BFIND, FFIND)); 1601119610Sache} 1602119610Sache 1603119610Sache/* **************************************************************** */ 1604119610Sache/* */ 1605119610Sache/* The Mark and the Region. */ 1606119610Sache/* */ 1607119610Sache/* **************************************************************** */ 1608119610Sache 1609119610Sache/* Set the mark at POSITION. */ 1610119610Sacheint 1611119610Sache_rl_set_mark_at_pos (position) 1612119610Sache int position; 1613119610Sache{ 1614119610Sache if (position > rl_end) 1615119610Sache return -1; 1616119610Sache 1617119610Sache rl_mark = position; 1618119610Sache return 0; 1619119610Sache} 1620119610Sache 1621119610Sache/* A bindable command to set the mark. */ 1622119610Sacheint 1623119610Sacherl_set_mark (count, key) 1624119610Sache int count, key; 1625119610Sache{ 1626119610Sache return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point)); 1627119610Sache} 1628119610Sache 1629119610Sache/* Exchange the position of mark and point. */ 1630119610Sacheint 1631119610Sacherl_exchange_point_and_mark (count, key) 1632119610Sache int count, key; 1633119610Sache{ 1634119610Sache if (rl_mark > rl_end) 1635119610Sache rl_mark = -1; 1636119610Sache 1637119610Sache if (rl_mark == -1) 1638119610Sache { 1639119610Sache rl_ding (); 1640119610Sache return -1; 1641119610Sache } 1642119610Sache else 1643119610Sache SWAP (rl_point, rl_mark); 1644119610Sache 1645119610Sache return 0; 1646119610Sache} 1647