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