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