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