1119610Sache/* misc.c -- miscellaneous bindable readline functions. */
2119610Sache
3157184Sache/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
4119610Sache
5119610Sache   This file is part of the GNU Readline Library, a library for
6119610Sache   reading lines of text with interactive input and history editing.
7119610Sache
8119610Sache   The GNU Readline Library is free software; you can redistribute it
9119610Sache   and/or modify it under the terms of the GNU General Public License
10119610Sache   as published by the Free Software Foundation; either version 2, or
11119610Sache   (at your option) any later version.
12119610Sache
13119610Sache   The GNU Readline Library is distributed in the hope that it will be
14119610Sache   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15119610Sache   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16119610Sache   GNU General Public License for more details.
17119610Sache
18119610Sache   The GNU General Public License is often shipped with GNU software, and
19119610Sache   is generally kept in a file called COPYING or LICENSE.  If you do not
20119610Sache   have a copy of the license, write to the Free Software Foundation,
21119610Sache   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
22119610Sache#define READLINE_LIBRARY
23119610Sache
24119610Sache#if defined (HAVE_CONFIG_H)
25119610Sache#  include <config.h>
26119610Sache#endif
27119610Sache
28119610Sache#if defined (HAVE_UNISTD_H)
29119610Sache#  include <unistd.h>
30119610Sache#endif /* HAVE_UNISTD_H */
31119610Sache
32119610Sache#if defined (HAVE_STDLIB_H)
33119610Sache#  include <stdlib.h>
34119610Sache#else
35119610Sache#  include "ansi_stdlib.h"
36119610Sache#endif /* HAVE_STDLIB_H */
37119610Sache
38119610Sache#if defined (HAVE_LOCALE_H)
39119610Sache#  include <locale.h>
40119610Sache#endif
41119610Sache
42119610Sache#include <stdio.h>
43119610Sache
44119610Sache/* System-specific feature definitions and include files. */
45119610Sache#include "rldefs.h"
46119610Sache#include "rlmbutil.h"
47119610Sache
48119610Sache/* Some standard library routines. */
49119610Sache#include "readline.h"
50119610Sache#include "history.h"
51119610Sache
52119610Sache#include "rlprivate.h"
53119610Sache#include "rlshell.h"
54119610Sache#include "xmalloc.h"
55119610Sache
56119610Sachestatic int rl_digit_loop PARAMS((void));
57119610Sachestatic void _rl_history_set_point PARAMS((void));
58119610Sache
59119610Sache/* Forward declarations used in this file */
60119610Sachevoid _rl_free_history_entry PARAMS((HIST_ENTRY *));
61119610Sache
62119610Sache/* If non-zero, rl_get_previous_history and rl_get_next_history attempt
63119610Sache   to preserve the value of rl_point from line to line. */
64119610Sacheint _rl_history_preserve_point = 0;
65119610Sache
66157184Sache_rl_arg_cxt _rl_argcxt;
67157184Sache
68119610Sache/* Saved target point for when _rl_history_preserve_point is set.  Special
69119610Sache   value of -1 means that point is at the end of the line. */
70119610Sacheint _rl_history_saved_point = -1;
71119610Sache
72119610Sache/* **************************************************************** */
73119610Sache/*								    */
74119610Sache/*			Numeric Arguments			    */
75119610Sache/*								    */
76119610Sache/* **************************************************************** */
77119610Sache
78157184Sacheint
79157184Sache_rl_arg_overflow ()
80119610Sache{
81157184Sache  if (rl_numeric_arg > 1000000)
82157184Sache    {
83157184Sache      _rl_argcxt = 0;
84157184Sache      rl_explicit_arg = rl_numeric_arg = 0;
85157184Sache      rl_ding ();
86157184Sache      rl_restore_prompt ();
87157184Sache      rl_clear_message ();
88157184Sache      RL_UNSETSTATE(RL_STATE_NUMERICARG);
89157184Sache      return 1;
90157184Sache    }
91157184Sache  return 0;
92157184Sache}
93119610Sache
94157184Sachevoid
95157184Sache_rl_arg_init ()
96157184Sache{
97119610Sache  rl_save_prompt ();
98157184Sache  _rl_argcxt = 0;
99119610Sache  RL_SETSTATE(RL_STATE_NUMERICARG);
100157184Sache}
101119610Sache
102157184Sacheint
103157184Sache_rl_arg_getchar ()
104157184Sache{
105157184Sache  int c;
106119610Sache
107157184Sache  rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
108157184Sache  RL_SETSTATE(RL_STATE_MOREINPUT);
109157184Sache  c = rl_read_key ();
110157184Sache  RL_UNSETSTATE(RL_STATE_MOREINPUT);
111119610Sache
112157184Sache  return c;
113157184Sache}
114119610Sache
115157184Sache/* Process C as part of the current numeric argument.  Return -1 if the
116157184Sache   argument should be aborted, 0 if we should not read any more chars, and
117157184Sache   1 if we should continue to read chars. */
118157184Sacheint
119157184Sache_rl_arg_dispatch (cxt, c)
120157184Sache     _rl_arg_cxt cxt;
121157184Sache     int c;
122157184Sache{
123157184Sache  int key, r;
124157184Sache
125157184Sache  key = c;
126157184Sache
127157184Sache  /* If we see a key bound to `universal-argument' after seeing digits,
128157184Sache      it ends the argument but is otherwise ignored. */
129157184Sache  if (_rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
130157184Sache    {
131157184Sache      if ((cxt & NUM_SAWDIGITS) == 0)
132119610Sache	{
133157184Sache	  rl_numeric_arg *= 4;
134157184Sache	  return 1;
135119610Sache	}
136157184Sache      else if (RL_ISSTATE (RL_STATE_CALLBACK))
137157184Sache        {
138157184Sache          _rl_argcxt |= NUM_READONE;
139157184Sache          return 0;	/* XXX */
140157184Sache        }
141119610Sache      else
142119610Sache	{
143157184Sache	  RL_SETSTATE(RL_STATE_MOREINPUT);
144157184Sache	  key = rl_read_key ();
145157184Sache	  RL_UNSETSTATE(RL_STATE_MOREINPUT);
146119610Sache	  rl_restore_prompt ();
147119610Sache	  rl_clear_message ();
148119610Sache	  RL_UNSETSTATE(RL_STATE_NUMERICARG);
149173403Sache	  if (key < 0)
150173403Sache	    return -1;
151119610Sache	  return (_rl_dispatch (key, _rl_keymap));
152119610Sache	}
153119610Sache    }
154119610Sache
155157184Sache  c = UNMETA (c);
156157184Sache
157157184Sache  if (_rl_digit_p (c))
158157184Sache    {
159157184Sache      r = _rl_digit_value (c);
160157184Sache      rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) +  r : r;
161157184Sache      rl_explicit_arg = 1;
162157184Sache      _rl_argcxt |= NUM_SAWDIGITS;
163157184Sache    }
164157184Sache  else if (c == '-' && rl_explicit_arg == 0)
165157184Sache    {
166157184Sache      rl_numeric_arg = 1;
167157184Sache      _rl_argcxt |= NUM_SAWMINUS;
168157184Sache      rl_arg_sign = -1;
169157184Sache    }
170157184Sache  else
171157184Sache    {
172157184Sache      /* Make M-- command equivalent to M--1 command. */
173157184Sache      if ((_rl_argcxt & NUM_SAWMINUS) && rl_numeric_arg == 1 && rl_explicit_arg == 0)
174157184Sache	rl_explicit_arg = 1;
175157184Sache      rl_restore_prompt ();
176157184Sache      rl_clear_message ();
177157184Sache      RL_UNSETSTATE(RL_STATE_NUMERICARG);
178157184Sache
179157184Sache      r = _rl_dispatch (key, _rl_keymap);
180157184Sache      if (RL_ISSTATE (RL_STATE_CALLBACK))
181157184Sache	{
182157184Sache	  /* At worst, this will cause an extra redisplay.  Otherwise,
183157184Sache	     we have to wait until the next character comes in. */
184157184Sache	  if (rl_done == 0)
185157184Sache	    (*rl_redisplay_function) ();
186157184Sache	  r = 0;
187157184Sache	}
188157184Sache      return r;
189157184Sache    }
190157184Sache
191157184Sache  return 1;
192119610Sache}
193119610Sache
194157184Sache/* Handle C-u style numeric args, as well as M--, and M-digits. */
195157184Sachestatic int
196157184Sacherl_digit_loop ()
197119610Sache{
198157184Sache  int c, r;
199119610Sache
200157184Sache  while (1)
201157184Sache    {
202157184Sache      if (_rl_arg_overflow ())
203157184Sache	return 1;
204157184Sache
205157184Sache      c = _rl_arg_getchar ();
206157184Sache
207157184Sache      if (c < 0)
208157184Sache	{
209157184Sache	  _rl_abort_internal ();
210157184Sache	  return -1;
211157184Sache	}
212157184Sache
213157184Sache      r = _rl_arg_dispatch (_rl_argcxt, c);
214157184Sache      if (r <= 0 || (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
215157184Sache        break;
216157184Sache    }
217165670Sache
218165670Sache  return r;
219119610Sache}
220119610Sache
221119610Sache/* Create a default argument. */
222157184Sachevoid
223157184Sache_rl_reset_argument ()
224119610Sache{
225119610Sache  rl_numeric_arg = rl_arg_sign = 1;
226119610Sache  rl_explicit_arg = 0;
227157184Sache  _rl_argcxt = 0;
228119610Sache}
229119610Sache
230157184Sache/* Start a numeric argument with initial value KEY */
231157184Sacheint
232157184Sacherl_digit_argument (ignore, key)
233157184Sache     int ignore, key;
234157184Sache{
235157184Sache  _rl_arg_init ();
236157184Sache  if (RL_ISSTATE (RL_STATE_CALLBACK))
237157184Sache    {
238157184Sache      _rl_arg_dispatch (_rl_argcxt, key);
239157184Sache      rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
240157184Sache      return 0;
241157184Sache    }
242157184Sache  else
243157184Sache    {
244157184Sache      rl_execute_next (key);
245157184Sache      return (rl_digit_loop ());
246157184Sache    }
247157184Sache}
248157184Sache
249119610Sache/* C-u, universal argument.  Multiply the current argument by 4.
250119610Sache   Read a key.  If the key has nothing to do with arguments, then
251119610Sache   dispatch on it.  If the key is the abort character then abort. */
252119610Sacheint
253119610Sacherl_universal_argument (count, key)
254119610Sache     int count, key;
255119610Sache{
256157184Sache  _rl_arg_init ();
257119610Sache  rl_numeric_arg *= 4;
258157184Sache
259157184Sache  return (RL_ISSTATE (RL_STATE_CALLBACK) ? 0 : rl_digit_loop ());
260119610Sache}
261119610Sache
262157184Sacheint
263157184Sache_rl_arg_callback (cxt)
264157184Sache     _rl_arg_cxt cxt;
265157184Sache{
266157184Sache  int c, r;
267157184Sache
268157184Sache  c = _rl_arg_getchar ();
269157184Sache
270157184Sache  if (_rl_argcxt & NUM_READONE)
271157184Sache    {
272157184Sache      _rl_argcxt &= ~NUM_READONE;
273157184Sache      rl_restore_prompt ();
274157184Sache      rl_clear_message ();
275157184Sache      RL_UNSETSTATE(RL_STATE_NUMERICARG);
276157184Sache      rl_execute_next (c);
277157184Sache      return 0;
278157184Sache    }
279157184Sache
280157184Sache  r = _rl_arg_dispatch (cxt, c);
281157184Sache  return (r != 1);
282157184Sache}
283157184Sache
284157184Sache/* What to do when you abort reading an argument. */
285157184Sacheint
286157184Sacherl_discard_argument ()
287157184Sache{
288157184Sache  rl_ding ();
289157184Sache  rl_clear_message ();
290157184Sache  _rl_reset_argument ();
291157184Sache
292157184Sache  return 0;
293157184Sache}
294157184Sache
295119610Sache/* **************************************************************** */
296119610Sache/*								    */
297119610Sache/*			History Utilities			    */
298119610Sache/*								    */
299119610Sache/* **************************************************************** */
300119610Sache
301119610Sache/* We already have a history library, and that is what we use to control
302119610Sache   the history features of readline.  This is our local interface to
303119610Sache   the history mechanism. */
304119610Sache
305119610Sache/* While we are editing the history, this is the saved
306119610Sache   version of the original line. */
307119610SacheHIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
308119610Sache
309119610Sache/* Set the history pointer back to the last entry in the history. */
310119610Sachevoid
311119610Sache_rl_start_using_history ()
312119610Sache{
313119610Sache  using_history ();
314119610Sache  if (_rl_saved_line_for_history)
315119610Sache    _rl_free_history_entry (_rl_saved_line_for_history);
316119610Sache
317119610Sache  _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
318119610Sache}
319119610Sache
320119610Sache/* Free the contents (and containing structure) of a HIST_ENTRY. */
321119610Sachevoid
322119610Sache_rl_free_history_entry (entry)
323119610Sache     HIST_ENTRY *entry;
324119610Sache{
325119610Sache  if (entry == 0)
326119610Sache    return;
327157184Sache
328157184Sache  FREE (entry->line);
329157184Sache  FREE (entry->timestamp);
330157184Sache
331119610Sache  free (entry);
332119610Sache}
333119610Sache
334119610Sache/* Perhaps put back the current line if it has changed. */
335119610Sacheint
336119610Sacherl_maybe_replace_line ()
337119610Sache{
338119610Sache  HIST_ENTRY *temp;
339119610Sache
340119610Sache  temp = current_history ();
341119610Sache  /* If the current line has changed, save the changes. */
342119610Sache  if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
343119610Sache    {
344119610Sache      temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
345119610Sache      free (temp->line);
346157184Sache      FREE (temp->timestamp);
347119610Sache      free (temp);
348119610Sache    }
349119610Sache  return 0;
350119610Sache}
351119610Sache
352119610Sache/* Restore the _rl_saved_line_for_history if there is one. */
353119610Sacheint
354119610Sacherl_maybe_unsave_line ()
355119610Sache{
356119610Sache  if (_rl_saved_line_for_history)
357119610Sache    {
358136644Sache      /* Can't call with `1' because rl_undo_list might point to an undo
359136644Sache	 list from a history entry, as in rl_replace_from_history() below. */
360119610Sache      rl_replace_line (_rl_saved_line_for_history->line, 0);
361119610Sache      rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
362119610Sache      _rl_free_history_entry (_rl_saved_line_for_history);
363119610Sache      _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
364119610Sache      rl_point = rl_end;	/* rl_replace_line sets rl_end */
365119610Sache    }
366119610Sache  else
367119610Sache    rl_ding ();
368119610Sache  return 0;
369119610Sache}
370119610Sache
371119610Sache/* Save the current line in _rl_saved_line_for_history. */
372119610Sacheint
373119610Sacherl_maybe_save_line ()
374119610Sache{
375119610Sache  if (_rl_saved_line_for_history == 0)
376119610Sache    {
377119610Sache      _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
378119610Sache      _rl_saved_line_for_history->line = savestring (rl_line_buffer);
379157184Sache      _rl_saved_line_for_history->timestamp = (char *)NULL;
380119610Sache      _rl_saved_line_for_history->data = (char *)rl_undo_list;
381119610Sache    }
382136644Sache
383119610Sache  return 0;
384119610Sache}
385119610Sache
386119610Sacheint
387119610Sache_rl_free_saved_history_line ()
388119610Sache{
389119610Sache  if (_rl_saved_line_for_history)
390119610Sache    {
391119610Sache      _rl_free_history_entry (_rl_saved_line_for_history);
392119610Sache      _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
393119610Sache    }
394119610Sache  return 0;
395119610Sache}
396119610Sache
397119610Sachestatic void
398119610Sache_rl_history_set_point ()
399119610Sache{
400119610Sache  rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1)
401119610Sache		? _rl_history_saved_point
402119610Sache		: rl_end;
403119610Sache  if (rl_point > rl_end)
404119610Sache    rl_point = rl_end;
405119610Sache
406119610Sache#if defined (VI_MODE)
407136644Sache  if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap)
408119610Sache    rl_point = 0;
409119610Sache#endif /* VI_MODE */
410119610Sache
411119610Sache  if (rl_editing_mode == emacs_mode)
412119610Sache    rl_mark = (rl_point == rl_end ? 0 : rl_end);
413119610Sache}
414119610Sache
415119610Sachevoid
416119610Sacherl_replace_from_history (entry, flags)
417119610Sache     HIST_ENTRY *entry;
418119610Sache     int flags;			/* currently unused */
419119610Sache{
420136644Sache  /* Can't call with `1' because rl_undo_list might point to an undo list
421136644Sache     from a history entry, just like we're setting up here. */
422119610Sache  rl_replace_line (entry->line, 0);
423119610Sache  rl_undo_list = (UNDO_LIST *)entry->data;
424119610Sache  rl_point = rl_end;
425119610Sache  rl_mark = 0;
426119610Sache
427119610Sache#if defined (VI_MODE)
428119610Sache  if (rl_editing_mode == vi_mode)
429119610Sache    {
430119610Sache      rl_point = 0;
431119610Sache      rl_mark = rl_end;
432119610Sache    }
433119610Sache#endif
434119610Sache}
435119610Sache
436119610Sache/* **************************************************************** */
437119610Sache/*								    */
438119610Sache/*			History Commands			    */
439119610Sache/*								    */
440119610Sache/* **************************************************************** */
441119610Sache
442119610Sache/* Meta-< goes to the start of the history. */
443119610Sacheint
444119610Sacherl_beginning_of_history (count, key)
445119610Sache     int count, key;
446119610Sache{
447119610Sache  return (rl_get_previous_history (1 + where_history (), key));
448119610Sache}
449119610Sache
450119610Sache/* Meta-> goes to the end of the history.  (The current line). */
451119610Sacheint
452119610Sacherl_end_of_history (count, key)
453119610Sache     int count, key;
454119610Sache{
455119610Sache  rl_maybe_replace_line ();
456119610Sache  using_history ();
457119610Sache  rl_maybe_unsave_line ();
458119610Sache  return 0;
459119610Sache}
460119610Sache
461119610Sache/* Move down to the next history line. */
462119610Sacheint
463119610Sacherl_get_next_history (count, key)
464119610Sache     int count, key;
465119610Sache{
466119610Sache  HIST_ENTRY *temp;
467119610Sache
468119610Sache  if (count < 0)
469119610Sache    return (rl_get_previous_history (-count, key));
470119610Sache
471119610Sache  if (count == 0)
472119610Sache    return 0;
473119610Sache
474119610Sache  rl_maybe_replace_line ();
475119610Sache
476119610Sache  /* either not saved by rl_newline or at end of line, so set appropriately. */
477119610Sache  if (_rl_history_saved_point == -1 && (rl_point || rl_end))
478119610Sache    _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
479119610Sache
480119610Sache  temp = (HIST_ENTRY *)NULL;
481119610Sache  while (count)
482119610Sache    {
483119610Sache      temp = next_history ();
484119610Sache      if (!temp)
485119610Sache	break;
486119610Sache      --count;
487119610Sache    }
488119610Sache
489119610Sache  if (temp == 0)
490119610Sache    rl_maybe_unsave_line ();
491119610Sache  else
492119610Sache    {
493119610Sache      rl_replace_from_history (temp, 0);
494119610Sache      _rl_history_set_point ();
495119610Sache    }
496119610Sache  return 0;
497119610Sache}
498119610Sache
499119610Sache/* Get the previous item out of our interactive history, making it the current
500119610Sache   line.  If there is no previous history, just ding. */
501119610Sacheint
502119610Sacherl_get_previous_history (count, key)
503119610Sache     int count, key;
504119610Sache{
505119610Sache  HIST_ENTRY *old_temp, *temp;
506119610Sache
507119610Sache  if (count < 0)
508119610Sache    return (rl_get_next_history (-count, key));
509119610Sache
510119610Sache  if (count == 0)
511119610Sache    return 0;
512119610Sache
513119610Sache  /* either not saved by rl_newline or at end of line, so set appropriately. */
514119610Sache  if (_rl_history_saved_point == -1 && (rl_point || rl_end))
515119610Sache    _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
516119610Sache
517119610Sache  /* If we don't have a line saved, then save this one. */
518119610Sache  rl_maybe_save_line ();
519119610Sache
520119610Sache  /* If the current line has changed, save the changes. */
521119610Sache  rl_maybe_replace_line ();
522119610Sache
523119610Sache  temp = old_temp = (HIST_ENTRY *)NULL;
524119610Sache  while (count)
525119610Sache    {
526119610Sache      temp = previous_history ();
527119610Sache      if (temp == 0)
528119610Sache	break;
529119610Sache
530119610Sache      old_temp = temp;
531119610Sache      --count;
532119610Sache    }
533119610Sache
534119610Sache  /* If there was a large argument, and we moved back to the start of the
535119610Sache     history, that is not an error.  So use the last value found. */
536119610Sache  if (!temp && old_temp)
537119610Sache    temp = old_temp;
538119610Sache
539119610Sache  if (temp == 0)
540119610Sache    rl_ding ();
541119610Sache  else
542119610Sache    {
543119610Sache      rl_replace_from_history (temp, 0);
544119610Sache      _rl_history_set_point ();
545119610Sache    }
546136644Sache
547119610Sache  return 0;
548119610Sache}
549119610Sache
550119610Sache/* **************************************************************** */
551119610Sache/*								    */
552119610Sache/*			    Editing Modes			    */
553119610Sache/*								    */
554119610Sache/* **************************************************************** */
555119610Sache/* How to toggle back and forth between editing modes. */
556119610Sacheint
557119610Sacherl_vi_editing_mode (count, key)
558119610Sache     int count, key;
559119610Sache{
560119610Sache#if defined (VI_MODE)
561119610Sache  _rl_set_insert_mode (RL_IM_INSERT, 1);	/* vi mode ignores insert mode */
562119610Sache  rl_editing_mode = vi_mode;
563119610Sache  rl_vi_insertion_mode (1, key);
564119610Sache#endif /* VI_MODE */
565119610Sache
566119610Sache  return 0;
567119610Sache}
568119610Sache
569119610Sacheint
570119610Sacherl_emacs_editing_mode (count, key)
571119610Sache     int count, key;
572119610Sache{
573119610Sache  rl_editing_mode = emacs_mode;
574119610Sache  _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
575119610Sache  _rl_keymap = emacs_standard_keymap;
576119610Sache  return 0;
577119610Sache}
578119610Sache
579119610Sache/* Function for the rest of the library to use to set insert/overwrite mode. */
580119610Sachevoid
581119610Sache_rl_set_insert_mode (im, force)
582119610Sache     int im, force;
583119610Sache{
584119610Sache#ifdef CURSOR_MODE
585119610Sache  _rl_set_cursor (im, force);
586119610Sache#endif
587119610Sache
588119610Sache  rl_insert_mode = im;
589119610Sache}
590119610Sache
591119610Sache/* Toggle overwrite mode.  A positive explicit argument selects overwrite
592119610Sache   mode.  A negative or zero explicit argument selects insert mode. */
593119610Sacheint
594119610Sacherl_overwrite_mode (count, key)
595119610Sache     int count, key;
596119610Sache{
597119610Sache  if (rl_explicit_arg == 0)
598119610Sache    _rl_set_insert_mode (rl_insert_mode ^ 1, 0);
599119610Sache  else if (count > 0)
600119610Sache    _rl_set_insert_mode (RL_IM_OVERWRITE, 0);
601119610Sache  else
602119610Sache    _rl_set_insert_mode (RL_IM_INSERT, 0);
603119610Sache
604119610Sache  return 0;
605119610Sache}
606