#define READLINE_LIBRARY
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#include <sys/types.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "posixstat.h"
#if defined (HAVE_STDLIB_H)
# include <stdlib.h>
#else
# include "ansi_stdlib.h"
#endif
#include <stdio.h>
#ifdef __MSDOS__
# include <pc.h>
#endif
#include "rldefs.h"
#include "rlmbutil.h"
#include "tcap.h"
#include "readline.h"
#include "history.h"
#include "rlprivate.h"
#include "xmalloc.h"
#if !defined (strchr) && !defined (__STDC__)
extern char *strchr (), *strrchr ();
#endif
#if defined (HACK_TERMCAP_MOTION)
extern char *_rl_term_forward_char;
#endif
static void update_line PARAMS((char *, char *, int, int, int, int));
static void space_to_eol PARAMS((int));
static void delete_chars PARAMS((int));
static void insert_some_chars PARAMS((char *, int, int));
static void cr PARAMS((void));
#if defined (HANDLE_MULTIBYTE)
static int _rl_col_width PARAMS((const char *, int, int));
static int *_rl_wrapped_line;
#else
# define _rl_col_width(l, s, e) (((e) <= (s)) ? 0 : (e) - (s))
#endif
static int *inv_lbreaks, *vis_lbreaks;
static int inv_lbsize, vis_lbsize;
#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
rl_voidfunc_t *rl_redisplay_function = rl_redisplay;
int rl_display_fixed = 0;
int _rl_suppress_redisplay = 0;
char *rl_display_prompt = (char *)NULL;
int _rl_last_c_pos = 0;
int _rl_last_v_pos = 0;
int _rl_vis_botlin = 0;
static int last_lmargin;
static char *visible_line = (char *)NULL;
static char *invisible_line = (char *)NULL;
static char msg_buf[128];
static int forced_display;
static int line_size = 1024;
static char *local_prompt, *local_prompt_prefix;
static int prompt_visible_length, prompt_prefix_length;
static int visible_wrap_offset;
static int wrap_offset;
static int prompt_last_invisible;
static int visible_first_line_len;
static int prompt_invis_chars_first_line;
static int prompt_last_screen_line;
static char *
expand_prompt (pmt, lp, lip, niflp)
char *pmt;
int *lp, *lip, *niflp;
{
char *r, *ret, *p;
int l, rl, last, ignoring, ninvis, invfl;
if (strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
{
r = savestring (pmt);
if (lp)
*lp = strlen (r);
return r;
}
l = strlen (pmt);
r = ret = (char *)xmalloc (l + 1);
invfl = 0;
for (rl = ignoring = last = ninvis = 0, p = pmt; p && *p; p++)
{
if (*p == RL_PROMPT_START_IGNORE)
{
ignoring++;
continue;
}
else if (ignoring && *p == RL_PROMPT_END_IGNORE)
{
ignoring = 0;
last = r - ret - 1;
continue;
}
else
{
*r++ = *p;
if (!ignoring)
rl++;
else
ninvis++;
if (rl == _rl_screenwidth)
invfl = ninvis;
}
}
if (rl < _rl_screenwidth)
invfl = ninvis;
*r = '\0';
if (lp)
*lp = rl;
if (lip)
*lip = last;
if (niflp)
*niflp = invfl;
return ret;
}
char *
_rl_strip_prompt (pmt)
char *pmt;
{
char *ret;
ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL);
return ret;
}
int
rl_expand_prompt (prompt)
char *prompt;
{
char *p, *t;
int c;
FREE (local_prompt);
FREE (local_prompt_prefix);
local_prompt = local_prompt_prefix = (char *)0;
prompt_last_invisible = prompt_visible_length = 0;
if (prompt == 0 || *prompt == 0)
return (0);
p = strrchr (prompt, '\n');
if (!p)
{
local_prompt = expand_prompt (prompt, &prompt_visible_length,
&prompt_last_invisible,
&prompt_invis_chars_first_line);
local_prompt_prefix = (char *)0;
return (prompt_visible_length);
}
else
{
t = ++p;
local_prompt = expand_prompt (p, &prompt_visible_length,
&prompt_last_invisible,
&prompt_invis_chars_first_line);
c = *t; *t = '\0';
local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
(int *)NULL,
&prompt_invis_chars_first_line);
*t = c;
return (prompt_prefix_length);
}
}
static void
init_line_structures (minsize)
int minsize;
{
register int n;
if (invisible_line == 0)
{
if (line_size < minsize)
line_size = minsize;
visible_line = (char *)xmalloc (line_size);
invisible_line = (char *)xmalloc (line_size);
}
else if (line_size < minsize)
{
line_size *= 2;
if (line_size < minsize)
line_size = minsize;
visible_line = (char *)xrealloc (visible_line, line_size);
invisible_line = (char *)xrealloc (invisible_line, line_size);
}
for (n = minsize; n < line_size; n++)
{
visible_line[n] = 0;
invisible_line[n] = 1;
}
if (vis_lbreaks == 0)
{
inv_lbsize = vis_lbsize = 256;
inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
#if defined (HANDLE_MULTIBYTE)
_rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int));
#endif
inv_lbreaks[0] = vis_lbreaks[0] = 0;
}
}
void
rl_redisplay ()
{
register int in, out, c, linenum, cursor_linenum;
register char *line;
int c_pos, inv_botlin, lb_botlin, lb_linenum;
int newlines, lpos, temp;
char *prompt_this_line;
#if defined (HANDLE_MULTIBYTE)
wchar_t wc;
size_t wc_bytes;
int wc_width;
mbstate_t ps;
int _rl_wrapped_multicolumn = 0;
#endif
if (!readline_echoing_p)
return;
if (!rl_display_prompt)
rl_display_prompt = "";
if (invisible_line == 0)
{
init_line_structures (0);
rl_on_new_line ();
}
c_pos = -1;
line = invisible_line;
out = inv_botlin = 0;
if (_rl_mark_modified_lines && current_history () && rl_undo_list)
{
line[out++] = '*';
line[out] = '\0';
}
if (visible_line[0] != invisible_line[0])
rl_display_fixed = 0;
if (rl_display_prompt == rl_prompt || local_prompt)
{
int local_len = local_prompt ? strlen (local_prompt) : 0;
if (local_prompt_prefix && forced_display)
_rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
if (local_len > 0)
{
temp = local_len + out + 2;
if (temp >= line_size)
{
line_size = (temp + 1024) - (temp % 1024);
visible_line = (char *)xrealloc (visible_line, line_size);
line = invisible_line = (char *)xrealloc (invisible_line, line_size);
}
strncpy (line + out, local_prompt, local_len);
out += local_len;
}
line[out] = '\0';
wrap_offset = local_len - prompt_visible_length;
}
else
{
int pmtlen;
prompt_this_line = strrchr (rl_display_prompt, '\n');
if (!prompt_this_line)
prompt_this_line = rl_display_prompt;
else
{
prompt_this_line++;
pmtlen = prompt_this_line - rl_display_prompt;
if (forced_display)
{
_rl_output_some_chars (rl_display_prompt, pmtlen);
if (pmtlen < 2 || prompt_this_line[-2] != '\r')
cr ();
}
}
pmtlen = strlen (prompt_this_line);
temp = pmtlen + out + 2;
if (temp >= line_size)
{
line_size = (temp + 1024) - (temp % 1024);
visible_line = (char *)xrealloc (visible_line, line_size);
line = invisible_line = (char *)xrealloc (invisible_line, line_size);
}
strncpy (line + out, prompt_this_line, pmtlen);
out += pmtlen;
line[out] = '\0';
wrap_offset = prompt_invis_chars_first_line = 0;
}
#define CHECK_INV_LBREAKS() \
do { \
if (newlines >= (inv_lbsize - 2)) \
{ \
inv_lbsize *= 2; \
inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
} \
} while (0)
#if defined (HANDLE_MULTIBYTE)
#define CHECK_LPOS() \
do { \
lpos++; \
if (lpos >= _rl_screenwidth) \
{ \
if (newlines >= (inv_lbsize - 2)) \
{ \
inv_lbsize *= 2; \
inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
_rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \
} \
inv_lbreaks[++newlines] = out; \
_rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \
lpos = 0; \
} \
} while (0)
#else
#define CHECK_LPOS() \
do { \
lpos++; \
if (lpos >= _rl_screenwidth) \
{ \
if (newlines >= (inv_lbsize - 2)) \
{ \
inv_lbsize *= 2; \
inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
} \
inv_lbreaks[++newlines] = out; \
lpos = 0; \
} \
} while (0)
#endif
inv_lbreaks[newlines = 0] = 0;
lpos = out - wrap_offset;
#if defined (HANDLE_MULTIBYTE)
memset (_rl_wrapped_line, 0, vis_lbsize);
#endif
while (lpos >= _rl_screenwidth)
{
temp = ((newlines + 1) * _rl_screenwidth) +
#if 0
((newlines == 0) ? prompt_invis_chars_first_line : 0) +
#else
((newlines == 0 && local_prompt_prefix == 0) ? prompt_invis_chars_first_line : 0) +
#endif
((newlines == 1) ? wrap_offset : 0);
inv_lbreaks[++newlines] = temp;
lpos -= _rl_screenwidth;
}
prompt_last_screen_line = newlines;
lb_linenum = 0;
#if defined (HANDLE_MULTIBYTE)
in = 0;
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
memset (&ps, 0, sizeof (mbstate_t));
wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
}
else
wc_bytes = 1;
while (in < rl_end)
#else
for (in = 0; in < rl_end; in++)
#endif
{
c = (unsigned char)rl_line_buffer[in];
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
if (wc_bytes == (size_t)-1 || wc_bytes == (size_t)-2)
{
wc_bytes = 1;
wc_width = 1;
memset (&ps, 0, sizeof (mbstate_t));
}
else if (wc_bytes == (size_t)0)
break;
else
{
temp = wcwidth (wc);
wc_width = (temp < 0) ? 1 : temp;
}
}
#endif
if (out + 8 >= line_size)
{
line_size *= 2;
visible_line = (char *)xrealloc (visible_line, line_size);
invisible_line = (char *)xrealloc (invisible_line, line_size);
line = invisible_line;
}
if (in == rl_point)
{
c_pos = out;
lb_linenum = newlines;
}
#if defined (HANDLE_MULTIBYTE)
if (META_CHAR (c) && _rl_output_meta_chars == 0)
#else
if (META_CHAR (c))
#endif
{
if (_rl_output_meta_chars == 0)
{
sprintf (line + out, "\\%o", c);
if (lpos + 4 >= _rl_screenwidth)
{
temp = _rl_screenwidth - lpos;
CHECK_INV_LBREAKS ();
inv_lbreaks[++newlines] = out + temp;
lpos = 4 - temp;
}
else
lpos += 4;
out += 4;
}
else
{
line[out++] = c;
CHECK_LPOS();
}
}
#if defined (DISPLAY_TABS)
else if (c == '\t')
{
register int newout;
#if 0
newout = (out | (int)7) + 1;
#else
newout = out + 8 - lpos % 8;
#endif
temp = newout - out;
if (lpos + temp >= _rl_screenwidth)
{
register int temp2;
temp2 = _rl_screenwidth - lpos;
CHECK_INV_LBREAKS ();
inv_lbreaks[++newlines] = out + temp2;
lpos = temp - temp2;
while (out < newout)
line[out++] = ' ';
}
else
{
while (out < newout)
line[out++] = ' ';
lpos += temp;
}
}
#endif
else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
{
line[out++] = '\0';
CHECK_INV_LBREAKS ();
inv_lbreaks[++newlines] = out;
lpos = 0;
}
else if (CTRL_CHAR (c) || c == RUBOUT)
{
line[out++] = '^';
CHECK_LPOS();
line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
CHECK_LPOS();
}
else
{
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
register int i;
_rl_wrapped_multicolumn = 0;
if (_rl_screenwidth < lpos + wc_width)
for (i = lpos; i < _rl_screenwidth; i++)
{
line[out++] = ' ';
_rl_wrapped_multicolumn++;
CHECK_LPOS();
}
if (in == rl_point)
{
c_pos = out;
lb_linenum = newlines;
}
for (i = in; i < in+wc_bytes; i++)
line[out++] = rl_line_buffer[i];
for (i = 0; i < wc_width; i++)
CHECK_LPOS();
}
else
{
line[out++] = c;
CHECK_LPOS();
}
#else
line[out++] = c;
CHECK_LPOS();
#endif
}
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
in += wc_bytes;
wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
}
else
in++;
#endif
}
line[out] = '\0';
if (c_pos < 0)
{
c_pos = out;
lb_linenum = newlines;
}
inv_botlin = lb_botlin = newlines;
CHECK_INV_LBREAKS ();
inv_lbreaks[newlines+1] = out;
cursor_linenum = lb_linenum;
if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
{
int nleft, pos, changed_screen_line;
if (!rl_display_fixed || forced_display)
{
forced_display = 0;
if (out >= _rl_screenchars)
{
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
else
out = _rl_screenchars - 1;
}
#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
for (linenum = 0; linenum <= inv_botlin; linenum++)
{
update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
if (linenum == 0 &&
inv_botlin == 0 && _rl_last_c_pos == out &&
(wrap_offset > visible_wrap_offset) &&
(_rl_last_c_pos < visible_first_line_len))
{
nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
if (nleft)
_rl_clear_to_eol (nleft);
}
if (linenum == 0)
visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
}
if (_rl_vis_botlin > inv_botlin)
{
char *tt;
for (; linenum <= _rl_vis_botlin; linenum++)
{
tt = VIS_CHARS (linenum);
_rl_move_vert (linenum);
_rl_move_cursor_relative (0, tt);
_rl_clear_to_eol
((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
}
}
_rl_vis_botlin = inv_botlin;
changed_screen_line = _rl_last_v_pos != cursor_linenum;
if (changed_screen_line)
{
_rl_move_vert (cursor_linenum);
if (cursor_linenum == 0 && wrap_offset)
_rl_last_c_pos += wrap_offset;
}
nleft = prompt_visible_length + wrap_offset;
if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
_rl_last_c_pos <= prompt_last_invisible && local_prompt)
{
#if defined (__MSDOS__)
putc ('\r', rl_outstream);
#else
if (_rl_term_cr)
tputs (_rl_term_cr, 1, _rl_output_character_function);
#endif
_rl_output_some_chars (local_prompt, nleft);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
_rl_last_c_pos = _rl_col_width(local_prompt, 0, nleft);
else
_rl_last_c_pos = nleft;
}
pos = inv_lbreaks[cursor_linenum];
nleft = c_pos - pos;
if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
{
_rl_backspace (_rl_last_c_pos - nleft);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
_rl_last_c_pos = _rl_col_width (&visible_line[pos], 0, nleft);
else
_rl_last_c_pos = nleft;
}
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
_rl_move_cursor_relative (nleft, &invisible_line[pos]);
else if (nleft != _rl_last_c_pos)
_rl_move_cursor_relative (nleft, &invisible_line[pos]);
}
}
else
{
#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
int lmargin, ndisp, nleft, phys_c_pos, t;
_rl_last_v_pos = 0;
ndisp = c_pos - wrap_offset;
nleft = prompt_visible_length + wrap_offset;
phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset);
t = _rl_screenwidth / 3;
if (phys_c_pos > _rl_screenwidth - 2)
{
lmargin = c_pos - (2 * t);
if (lmargin < 0)
lmargin = 0;
if (wrap_offset && lmargin > 0 && lmargin < nleft)
lmargin = nleft;
}
else if (ndisp < _rl_screenwidth - 2)
lmargin = 0;
else if (phys_c_pos < 1)
{
lmargin = ((c_pos - 1) / t) * t;
if (wrap_offset && lmargin > 0 && lmargin < nleft)
lmargin = nleft;
}
else
lmargin = last_lmargin;
if (lmargin > 0)
line[lmargin] = '<';
t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
if (t < out)
line[t - 1] = '>';
if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
{
forced_display = 0;
update_line (&visible_line[last_lmargin],
&invisible_line[lmargin],
0,
_rl_screenwidth + visible_wrap_offset,
_rl_screenwidth + (lmargin ? 0 : wrap_offset),
0);
t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
(_rl_last_c_pos == out) &&
t < visible_first_line_len)
{
nleft = _rl_screenwidth - t;
_rl_clear_to_eol (nleft);
}
visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
if (visible_first_line_len > _rl_screenwidth)
visible_first_line_len = _rl_screenwidth;
_rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
last_lmargin = lmargin;
}
}
fflush (rl_outstream);
{
char *vtemp = visible_line;
int *itemp = vis_lbreaks, ntemp = vis_lbsize;
visible_line = invisible_line;
invisible_line = vtemp;
vis_lbreaks = inv_lbreaks;
inv_lbreaks = itemp;
vis_lbsize = inv_lbsize;
inv_lbsize = ntemp;
rl_display_fixed = 0;
if (_rl_horizontal_scroll_mode && last_lmargin)
visible_wrap_offset = 0;
else
visible_wrap_offset = wrap_offset;
}
}
static void
update_line (old, new, current_line, omax, nmax, inv_botlin)
register char *old, *new;
int current_line, omax, nmax, inv_botlin;
{
register char *ofd, *ols, *oe, *nfd, *nls, *ne;
int temp, lendiff, wsatend, od, nd;
int current_invis_chars;
int col_lendiff, col_temp;
#if defined (HANDLE_MULTIBYTE)
mbstate_t ps_new, ps_old;
int new_offset, old_offset, tmp;
#endif
temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
&& _rl_last_v_pos == current_line - 1)
{
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
wchar_t wc;
mbstate_t ps;
int tempwidth, bytes;
size_t ret;
if (_rl_wrapped_line[current_line] > 0)
_rl_clear_to_eol (_rl_wrapped_line[current_line]);
memset (&ps, 0, sizeof (mbstate_t));
ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
if (ret == (size_t)-1 || ret == (size_t)-2)
{
tempwidth = 1;
ret = 1;
}
else if (ret == 0)
tempwidth = 0;
else
tempwidth = wcwidth (wc);
if (tempwidth > 0)
{
int count;
bytes = ret;
for (count = 0; count < bytes; count++)
putc (new[count], rl_outstream);
_rl_last_c_pos = tempwidth;
_rl_last_v_pos++;
memset (&ps, 0, sizeof (mbstate_t));
ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
if (ret != 0 && bytes != 0)
{
if (ret == (size_t)-1 || ret == (size_t)-2)
memmove (old+bytes, old+1, strlen (old+1));
else
memmove (old+bytes, old+ret, strlen (old+ret));
memcpy (old, new, bytes);
}
}
else
{
putc (' ', rl_outstream);
_rl_last_c_pos = 1;
_rl_last_v_pos++;
if (old[0] && new[0])
old[0] = new[0];
}
}
else
#endif
{
if (new[0])
putc (new[0], rl_outstream);
else
putc (' ', rl_outstream);
_rl_last_c_pos = 1;
_rl_last_v_pos++;
if (old[0] && new[0])
old[0] = new[0];
}
}
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
memset (&ps_new, 0, sizeof(mbstate_t));
memset (&ps_old, 0, sizeof(mbstate_t));
new_offset = old_offset = 0;
for (ofd = old, nfd = new;
(ofd - old < omax) && *ofd &&
_rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
{
old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
ofd = old + old_offset;
nfd = new + new_offset;
}
}
else
#endif
for (ofd = old, nfd = new;
(ofd - old < omax) && *ofd && (*ofd == *nfd);
ofd++, nfd++)
;
for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
if (ofd == oe && nfd == ne)
return;
wsatend = 1;
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
while ((ols > ofd) && (nls > nfd))
{
memset (&ps_old, 0, sizeof (mbstate_t));
memset (&ps_new, 0, sizeof (mbstate_t));
_rl_adjust_point (old, ols - old, &ps_old);
_rl_adjust_point (new, nls - new, &ps_new);
if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
break;
if (*ols == ' ')
wsatend = 0;
ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
}
}
else
{
#endif
ols = oe - 1;
nls = ne - 1;
while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
{
if (*ols != ' ')
wsatend = 0;
ols--;
nls--;
}
#if defined (HANDLE_MULTIBYTE)
}
#endif
if (wsatend)
{
ols = oe;
nls = ne;
}
#if defined (HANDLE_MULTIBYTE)
else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
#else
else if (*ols != *nls)
#endif
{
if (*ols)
{
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
else
ols++;
}
if (*nls)
{
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
else
nls++;
}
}
current_invis_chars = W_OFFSET (current_line, wrap_offset);
if (_rl_last_v_pos != current_line)
{
_rl_move_vert (current_line);
if (current_line == 0 && visible_wrap_offset)
_rl_last_c_pos += visible_wrap_offset;
}
lendiff = local_prompt ? strlen (local_prompt) : 0;
od = ofd - old;
if (current_line == 0 && !_rl_horizontal_scroll_mode &&
_rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
od >= lendiff && _rl_last_c_pos <= prompt_last_invisible)
{
#if defined (__MSDOS__)
putc ('\r', rl_outstream);
#else
tputs (_rl_term_cr, 1, _rl_output_character_function);
#endif
_rl_output_some_chars (local_prompt, lendiff);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
_rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff);
else
_rl_last_c_pos = lendiff;
}
_rl_move_cursor_relative (od, old);
lendiff = (nls - nfd) - (ols - ofd);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old);
else
col_lendiff = lendiff;
if (current_line == 0 && !_rl_horizontal_scroll_mode &&
current_invis_chars != visible_wrap_offset)
{
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
lendiff += visible_wrap_offset - current_invis_chars;
col_lendiff += visible_wrap_offset - current_invis_chars;
}
else
{
lendiff += visible_wrap_offset - current_invis_chars;
col_lendiff = lendiff;
}
}
temp = ne - nfd;
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
col_temp = _rl_col_width (new, nfd - new, ne - new);
else
col_temp = temp;
if (col_lendiff > 0)
{
int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
{
if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
lendiff <= prompt_visible_length || !current_invis_chars))
{
insert_some_chars (nfd, lendiff, col_lendiff);
_rl_last_c_pos += col_lendiff;
}
else if (*ols == 0)
{
_rl_output_some_chars (nfd, lendiff);
_rl_last_c_pos += col_lendiff;
}
else
{
_rl_output_some_chars (nfd, temp);
_rl_last_c_pos += col_temp;
return;
}
temp = nls - nfd;
if ((temp - lendiff) > 0)
{
_rl_output_some_chars (nfd + lendiff, temp - lendiff);
#if 0
_rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
#else
_rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff);
#endif
}
}
else
{
_rl_output_some_chars (nfd, temp);
_rl_last_c_pos += col_temp;
}
}
else
{
if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
{
if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
-lendiff == visible_wrap_offset)
col_lendiff = 0;
if (col_lendiff)
delete_chars (-col_lendiff);
temp = nls - nfd;
if (temp > 0)
{
_rl_output_some_chars (nfd, temp);
_rl_last_c_pos += _rl_col_width (nfd, 0, temp);;
}
}
else
{
if (temp > 0)
{
_rl_output_some_chars (nfd, temp);
_rl_last_c_pos += col_temp;
}
lendiff = (oe - old) - (ne - new);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new);
else
col_lendiff = lendiff;
if (col_lendiff)
{
if (_rl_term_autowrap && current_line < inv_botlin)
space_to_eol (col_lendiff);
else
_rl_clear_to_eol (col_lendiff);
}
}
}
}
int
rl_on_new_line ()
{
if (visible_line)
visible_line[0] = '\0';
_rl_last_c_pos = _rl_last_v_pos = 0;
_rl_vis_botlin = last_lmargin = 0;
if (vis_lbreaks)
vis_lbreaks[0] = vis_lbreaks[1] = 0;
visible_wrap_offset = 0;
return 0;
}
int
rl_on_new_line_with_prompt ()
{
int prompt_size, i, l, real_screenwidth, newlines;
char *prompt_last_line;
prompt_size = strlen (rl_prompt) + 1;
init_line_structures (prompt_size);
strcpy (visible_line, rl_prompt);
strcpy (invisible_line, rl_prompt);
prompt_last_line = strrchr (rl_prompt, '\n');
if (!prompt_last_line)
prompt_last_line = rl_prompt;
l = strlen (prompt_last_line);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
_rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l);
else
_rl_last_c_pos = l;
real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
_rl_last_v_pos = l / real_screenwidth;
if (l > 0 && (l % real_screenwidth) == 0)
_rl_output_some_chars ("\n", 1);
last_lmargin = 0;
newlines = 0; i = 0;
while (i <= l)
{
_rl_vis_botlin = newlines;
vis_lbreaks[newlines++] = i;
i += real_screenwidth;
}
vis_lbreaks[newlines] = l;
visible_wrap_offset = 0;
return 0;
}
int
rl_forced_update_display ()
{
if (visible_line)
{
register char *temp = visible_line;
while (*temp)
*temp++ = '\0';
}
rl_on_new_line ();
forced_display++;
(*rl_redisplay_function) ();
return 0;
}
void
_rl_move_cursor_relative (new, data)
int new;
const char *data;
{
register int i;
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX == 1 || rl_byte_oriented)
{
if (_rl_last_c_pos == new)
return;
}
else if (_rl_last_c_pos == _rl_col_width (data, 0, new))
return;
#else
if (_rl_last_c_pos == new) return;
#endif
i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
if (new == 0 || CR_FASTER (new, _rl_last_c_pos) ||
(_rl_term_autowrap && i == _rl_screenwidth))
{
#if defined (__MSDOS__)
putc ('\r', rl_outstream);
#else
tputs (_rl_term_cr, 1, _rl_output_character_function);
#endif
_rl_last_c_pos = 0;
}
if (_rl_last_c_pos < new)
{
#if defined (HACK_TERMCAP_MOTION)
if (_rl_term_forward_char)
{
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
int width;
width = _rl_col_width (data, _rl_last_c_pos, new);
for (i = 0; i < width; i++)
tputs (_rl_term_forward_char, 1, _rl_output_character_function);
}
else
{
for (i = _rl_last_c_pos; i < new; i++)
tputs (_rl_term_forward_char, 1, _rl_output_character_function);
}
}
else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
tputs (_rl_term_cr, 1, _rl_output_character_function);
for (i = 0; i < new; i++)
putc (data[i], rl_outstream);
}
else
for (i = _rl_last_c_pos; i < new; i++)
putc (data[i], rl_outstream);
#else
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
tputs (_rl_term_cr, 1, _rl_output_character_function);
for (i = 0; i < new; i++)
putc (data[i], rl_outstream);
}
else
for (i = _rl_last_c_pos; i < new; i++)
putc (data[i], rl_outstream);
#endif
}
#if defined (HANDLE_MULTIBYTE)
else if (_rl_last_c_pos >= new)
#else
else if (_rl_last_c_pos > new)
#endif
{
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
_rl_backspace (_rl_last_c_pos - _rl_col_width (data, 0, new));
else
_rl_backspace (_rl_last_c_pos - new);
}
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
_rl_last_c_pos = _rl_col_width (data, 0, new);
else
_rl_last_c_pos = new;
}
void
_rl_move_vert (to)
int to;
{
register int delta, i;
if (_rl_last_v_pos == to || to > _rl_screenheight)
return;
if ((delta = to - _rl_last_v_pos) > 0)
{
for (i = 0; i < delta; i++)
putc ('\n', rl_outstream);
#if defined (__MSDOS__)
putc ('\r', rl_outstream);
#else
tputs (_rl_term_cr, 1, _rl_output_character_function);
#endif
_rl_last_c_pos = 0;
}
else
{
#ifdef __MSDOS__
int row, col;
fflush (rl_outstream);
ScreenGetCursor (&row, &col);
ScreenSetCursor (row + delta, col);
i = -delta;
#else
if (_rl_term_up && *_rl_term_up)
for (i = 0; i < -delta; i++)
tputs (_rl_term_up, 1, _rl_output_character_function);
#endif
}
_rl_last_v_pos = to;
}
int
rl_show_char (c)
int c;
{
int n = 1;
if (META_CHAR (c) && (_rl_output_meta_chars == 0))
{
fprintf (rl_outstream, "M-");
n += 2;
c = UNMETA (c);
}
#if defined (DISPLAY_TABS)
if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
#else
if (CTRL_CHAR (c) || c == RUBOUT)
#endif
{
fprintf (rl_outstream, "C-");
n += 2;
c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
}
putc (c, rl_outstream);
fflush (rl_outstream);
return n;
}
int
rl_character_len (c, pos)
register int c, pos;
{
unsigned char uc;
uc = (unsigned char)c;
if (META_CHAR (uc))
return ((_rl_output_meta_chars == 0) ? 4 : 1);
if (uc == '\t')
{
#if defined (DISPLAY_TABS)
return (((pos | 7) + 1) - pos);
#else
return (2);
#endif
}
if (CTRL_CHAR (c) || c == RUBOUT)
return (2);
return ((ISPRINT (uc)) ? 1 : 2);
}
#if defined (USE_VARARGS)
int
#if defined (PREFER_STDARG)
rl_message (const char *format, ...)
#else
rl_message (va_alist)
va_dcl
#endif
{
va_list args;
#if defined (PREFER_VARARGS)
char *format;
#endif
#if defined (PREFER_STDARG)
va_start (args, format);
#else
va_start (args);
format = va_arg (args, char *);
#endif
#if defined (HAVE_VSNPRINTF)
vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args);
#else
vsprintf (msg_buf, format, args);
msg_buf[sizeof(msg_buf) - 1] = '\0';
#endif
va_end (args);
rl_display_prompt = msg_buf;
(*rl_redisplay_function) ();
return 0;
}
#else
int
rl_message (format, arg1, arg2)
char *format;
{
sprintf (msg_buf, format, arg1, arg2);
msg_buf[sizeof(msg_buf) - 1] = '\0';
rl_display_prompt = msg_buf;
(*rl_redisplay_function) ();
return 0;
}
#endif
int
rl_clear_message ()
{
rl_display_prompt = rl_prompt;
(*rl_redisplay_function) ();
return 0;
}
int
rl_reset_line_state ()
{
rl_on_new_line ();
rl_display_prompt = rl_prompt ? rl_prompt : "";
forced_display = 1;
return 0;
}
static char *saved_local_prompt;
static char *saved_local_prefix;
static int saved_last_invisible;
static int saved_visible_length;
void
rl_save_prompt ()
{
saved_local_prompt = local_prompt;
saved_local_prefix = local_prompt_prefix;
saved_last_invisible = prompt_last_invisible;
saved_visible_length = prompt_visible_length;
local_prompt = local_prompt_prefix = (char *)0;
prompt_last_invisible = prompt_visible_length = 0;
}
void
rl_restore_prompt ()
{
FREE (local_prompt);
FREE (local_prompt_prefix);
local_prompt = saved_local_prompt;
local_prompt_prefix = saved_local_prefix;
prompt_last_invisible = saved_last_invisible;
prompt_visible_length = saved_visible_length;
}
char *
_rl_make_prompt_for_search (pchar)
int pchar;
{
int len;
char *pmt;
rl_save_prompt ();
if (saved_local_prompt == 0)
{
len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
pmt = (char *)xmalloc (len + 2);
if (len)
strcpy (pmt, rl_prompt);
pmt[len] = pchar;
pmt[len+1] = '\0';
}
else
{
len = *saved_local_prompt ? strlen (saved_local_prompt) : 0;
pmt = (char *)xmalloc (len + 2);
if (len)
strcpy (pmt, saved_local_prompt);
pmt[len] = pchar;
pmt[len+1] = '\0';
local_prompt = savestring (pmt);
prompt_last_invisible = saved_last_invisible;
prompt_visible_length = saved_visible_length + 1;
}
return pmt;
}
void
_rl_erase_at_end_of_line (l)
int l;
{
register int i;
_rl_backspace (l);
for (i = 0; i < l; i++)
putc (' ', rl_outstream);
_rl_backspace (l);
for (i = 0; i < l; i++)
visible_line[--_rl_last_c_pos] = '\0';
rl_display_fixed++;
}
void
_rl_clear_to_eol (count)
int count;
{
#ifndef __MSDOS__
if (_rl_term_clreol)
tputs (_rl_term_clreol, 1, _rl_output_character_function);
else
#endif
if (count)
space_to_eol (count);
}
static void
space_to_eol (count)
int count;
{
register int i;
for (i = 0; i < count; i++)
putc (' ', rl_outstream);
_rl_last_c_pos += count;
}
void
_rl_clear_screen ()
{
#if defined (__GO32__)
ScreenClear ();
ScreenSetCursor (0, 0);
#else
if (_rl_term_clrpag)
tputs (_rl_term_clrpag, 1, _rl_output_character_function);
else
rl_crlf ();
#endif
}
static void
insert_some_chars (string, count, col)
char *string;
int count, col;
{
#if defined(__MSDOS__) || defined(__MINGW32__)
_rl_output_some_chars (string, count);
#else
if (MB_CUR_MAX == 1 || rl_byte_oriented)
if (count != col)
fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col);
if (_rl_term_IC)
{
char *buffer;
buffer = tgoto (_rl_term_IC, 0, col);
tputs (buffer, 1, _rl_output_character_function);
_rl_output_some_chars (string, count);
}
else
{
register int i;
if (_rl_term_im && *_rl_term_im)
tputs (_rl_term_im, 1, _rl_output_character_function);
if (_rl_term_ic && *_rl_term_ic)
{
for (i = col; i--; )
tputs (_rl_term_ic, 1, _rl_output_character_function);
}
_rl_output_some_chars (string, count);
if (_rl_term_ei && *_rl_term_ei)
tputs (_rl_term_ei, 1, _rl_output_character_function);
}
#endif
}
static void
delete_chars (count)
int count;
{
if (count > _rl_screenwidth)
return;
#if !defined(__MSDOS__) && !defined(__MINGW32__)
if (_rl_term_DC && *_rl_term_DC)
{
char *buffer;
buffer = tgoto (_rl_term_DC, count, count);
tputs (buffer, count, _rl_output_character_function);
}
else
{
if (_rl_term_dc && *_rl_term_dc)
while (count--)
tputs (_rl_term_dc, 1, _rl_output_character_function);
}
#endif
}
void
_rl_update_final ()
{
int full_lines;
full_lines = 0;
if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
{
_rl_vis_botlin--;
full_lines = 1;
}
_rl_move_vert (_rl_vis_botlin);
if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
{
char *last_line;
last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
_rl_move_cursor_relative (_rl_screenwidth - 1, last_line);
_rl_clear_to_eol (0);
putc (last_line[_rl_screenwidth - 1], rl_outstream);
}
_rl_vis_botlin = 0;
rl_crlf ();
fflush (rl_outstream);
rl_display_fixed++;
}
static void
cr ()
{
if (_rl_term_cr)
{
#if defined (__MSDOS__)
putc ('\r', rl_outstream);
#else
tputs (_rl_term_cr, 1, _rl_output_character_function);
#endif
_rl_last_c_pos = 0;
}
}
static void
redraw_prompt (t)
char *t;
{
char *oldp, *oldl, *oldlprefix;
int oldlen, oldlast, oldplen, oldninvis;
oldp = rl_display_prompt;
oldl = local_prompt;
oldlprefix = local_prompt_prefix;
oldlen = prompt_visible_length;
oldplen = prompt_prefix_length;
oldlast = prompt_last_invisible;
oldninvis = prompt_invis_chars_first_line;
rl_display_prompt = t;
local_prompt = expand_prompt (t, &prompt_visible_length,
&prompt_last_invisible,
&prompt_invis_chars_first_line);
local_prompt_prefix = (char *)NULL;
rl_forced_update_display ();
rl_display_prompt = oldp;
local_prompt = oldl;
local_prompt_prefix = oldlprefix;
prompt_visible_length = oldlen;
prompt_prefix_length = oldplen;
prompt_last_invisible = oldlast;
prompt_invis_chars_first_line = oldninvis;
}
void
_rl_redisplay_after_sigwinch ()
{
char *t;
if (_rl_term_cr)
{
#if defined (__MSDOS__)
putc ('\r', rl_outstream);
#else
tputs (_rl_term_cr, 1, _rl_output_character_function);
#endif
_rl_last_c_pos = 0;
#if defined (__MSDOS__)
space_to_eol (_rl_screenwidth);
putc ('\r', rl_outstream);
#else
if (_rl_term_clreol)
tputs (_rl_term_clreol, 1, _rl_output_character_function);
else
{
space_to_eol (_rl_screenwidth);
tputs (_rl_term_cr, 1, _rl_output_character_function);
}
#endif
if (_rl_last_v_pos > 0)
_rl_move_vert (0);
}
else
rl_crlf ();
t = strrchr (rl_display_prompt, '\n');
if (t)
redraw_prompt (++t);
else
rl_forced_update_display ();
}
void
_rl_clean_up_for_exit ()
{
if (readline_echoing_p)
{
_rl_move_vert (_rl_vis_botlin);
_rl_vis_botlin = 0;
fflush (rl_outstream);
rl_restart_output (1, 0);
}
}
void
_rl_erase_entire_line ()
{
cr ();
_rl_clear_to_eol (0);
cr ();
fflush (rl_outstream);
}
int
_rl_current_display_line ()
{
int ret, nleft;
if (rl_display_prompt == rl_prompt)
nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
else
nleft = _rl_last_c_pos - _rl_screenwidth;
if (nleft > 0)
ret = 1 + nleft / _rl_screenwidth;
else
ret = 0;
return ret;
}
#if defined (HANDLE_MULTIBYTE)
static int
_rl_col_width (str, start, end)
const char *str;
int start, end;
{
wchar_t wc;
mbstate_t ps = {0};
int tmp, point, width, max;
if (end <= start)
return 0;
point = 0;
max = end;
while (point < start)
{
tmp = mbrlen (str + point, max, &ps);
if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
{
point++;
max--;
memset (&ps, 0, sizeof (mbstate_t));
}
else if (tmp == 0)
break;
else
{
point += tmp;
max -= tmp;
}
}
width = point - start;
while (point < end)
{
tmp = mbrtowc (&wc, str + point, max, &ps);
if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
{
point++;
max--;
width++;
memset (&ps, 0, sizeof (mbstate_t));
}
else if (tmp == 0)
break;
else
{
point += tmp;
max -= tmp;
tmp = wcwidth(wc);
width += (tmp >= 0) ? tmp : 1;
}
}
width += point - end;
return width;
}
#endif