f. Fixed a bug in redisplay triggered when the prompt string contains
invisible characters.
+g. Fixed some display (and other) bugs encountered in multibyte locales
+ when a non-ascii character was the last character on a line.
+
+h. Fixed some display bugs caused by multibyte characters in prompt strings.
+
3. New Features in Bash
a. printf builtin understands two new escape sequences: \" and \?.
avoids the N**2 behavior of having to count from the beginning
of the string each time you want to back up one character. Changes
to remove_pattern and match_pattern
+
+ 1/12
+ ----
+lib/readline/display.c
+ - make expand_prompt count multbyte characters in the prompt string
+ by using _rl_find_next_mbchar (and copying possibly more than one
+ byte) instead of a simple increment and single byte copy
+
+ 1/13
+ ----
+lib/readline/display.c
+ - expand_prompt takes a new reference argument -- it returns
+ the actual count of (possibly multibyte) characters displayed
+ on the screen
+ - don't short-circuit in expand_prompt unless we're not going to
+ be using any multibyte characters
+ - change calls to expand_prompt to pass an argument for the
+ number of physical characters the prompt occupies
+ (prompt_physical_chars)
+ - initialize `lpos' (the physical cursor position) from
+ prompt_physical_chars in rl_redisplay
+
+lib/readline/mbutil.c
+ - in _rl_find_prev_mbchar_internal, if mbrtowc returns -1 or -2, and
+ we assume that the character is a single-byte char, make sure we
+ update `prev' so it doesn't get lost. Fixes problems encountered
+ when a non-ascii char is the last char on the line and we're moving
+ back past it with ^B, and other display problems caused by the same
+ situation
+
'configure.in'
],
{
- 'AC_FUNC_FORK' => 1,
- 'AC_SUBST' => 1,
- 'AC_CONFIG_AUX_DIR' => 1,
- 'AC_CANONICAL_HOST' => 1,
- 'AC_HEADER_MAJOR' => 1,
- 'AC_C_INLINE' => 1,
- 'AC_FUNC_MALLOC' => 1,
- 'm4_pattern_allow' => 1,
- 'AC_FUNC_GETGROUPS' => 1,
- 'AC_TYPE_MODE_T' => 1,
- 'AC_FUNC_FSEEKO' => 1,
- 'AM_PROG_CC_C_O' => 1,
'AC_STRUCT_ST_BLOCKS' => 1,
- 'AC_FUNC_GETLOADAVG' => 1,
- 'AC_C_VOLATILE' => 1,
- 'AC_FUNC_LSTAT' => 1,
- 'AC_FUNC_GETPGRP' => 1,
- 'AC_PROG_AWK' => 1,
- 'AC_FUNC_SETPGRP' => 1,
- 'AC_CONFIG_SUBDIRS' => 1,
- 'AC_FUNC_OBSTACK' => 1,
- 'AC_FUNC_MMAP' => 1,
- 'AM_MAINTAINER_MODE' => 1,
- 'AC_FUNC_MEMCMP' => 1,
- 'AM_AUTOMAKE_VERSION' => 1,
- 'AC_FUNC_STRCOLL' => 1,
+ 'AC_FUNC_CLOSEDIR_VOID' => 1,
'AC_CHECK_TYPES' => 1,
- 'AC_HEADER_DIRENT' => 1,
- 'AC_CHECK_MEMBERS' => 1,
- 'm4_include' => 1,
- 'AC_TYPE_SIGNAL' => 1,
- 'AC_TYPE_PID_T' => 1,
- 'AC_FUNC_SETVBUF_REVERSED' => 1,
- 'AC_CHECK_FUNCS' => 1,
- 'AC_CHECK_LIB' => 1,
- 'AC_HEADER_STAT' => 1,
- 'AC_PROG_LEX' => 1,
- 'AC_TYPE_SIZE_T' => 1,
- 'AC_HEADER_TIME' => 1,
- 'AC_FUNC_STRTOD' => 1,
- 'include' => 1,
- 'AC_STRUCT_TIMEZONE' => 1,
- 'AC_HEADER_STDC' => 1,
- 'AC_PROG_LIBTOOL' => 1,
- 'AM_GNU_GETTEXT' => 1,
- 'AC_FUNC_STRFTIME' => 1,
- 'AC_FUNC_ALLOCA' => 1,
- 'AC_C_CONST' => 1,
- 'AC_INIT' => 1,
- 'AM_CONDITIONAL' => 1,
- 'AC_LIBSOURCE' => 1,
- 'AC_PROG_GCC_TRADITIONAL' => 1,
+ 'AC_PROG_CC' => 1,
'AC_TYPE_OFF_T' => 1,
- 'AC_CHECK_HEADERS' => 1,
- 'AC_FUNC_WAIT3' => 1,
- 'AC_FUNC_STRERROR_R' => 1,
- 'AC_FUNC_UTIME_NULL' => 1,
- 'AC_PATH_X' => 1,
+ 'AC_PROG_YACC' => 1,
'AC_PROG_CPP' => 1,
- 'AC_FUNC_ERROR_AT_LINE' => 1,
- 'AC_DECL_SYS_SIGLIST' => 1,
- 'AC_PROG_LN_S' => 1,
- 'AC_PROG_CXX' => 1,
- 'AC_FUNC_VPRINTF' => 1,
- 'AC_FUNC_CHOWN' => 1,
- 'm4_pattern_forbid' => 1,
+ 'AC_C_INLINE' => 1,
'AC_TYPE_UID_T' => 1,
+ 'AC_STRUCT_TM' => 1,
+ 'AC_FUNC_MKTIME' => 1,
+ 'AC_FUNC_MEMCMP' => 1,
+ 'AC_CONFIG_HEADERS' => 1,
+ 'AC_CHECK_HEADERS' => 1,
+ 'AC_HEADER_SYS_WAIT' => 1,
+ 'AC_CHECK_MEMBERS' => 1,
+ 'AC_HEADER_MAJOR' => 1,
+ 'AC_PROG_LIBTOOL' => 1,
+ 'AC_FUNC_REALLOC' => 1,
'AC_FUNC_MBRTOWC' => 1,
'AC_FUNC_SELECT_ARGTYPES' => 1,
- 'AC_STRUCT_TM' => 1,
- 'AC_PROG_CC' => 1,
- 'AC_PROG_INSTALL' => 1,
- 'AC_PROG_RANLIB' => 1,
'AH_OUTPUT' => 1,
- 'AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK' => 1,
- 'AC_FUNC_STAT' => 1,
- 'AC_FUNC_REALLOC' => 1,
- 'AC_CANONICAL_SYSTEM' => 1,
+ 'AC_FUNC_MMAP' => 1,
+ 'AC_FUNC_SETVBUF_REVERSED' => 1,
+ 'AC_FUNC_ERROR_AT_LINE' => 1,
+ 'AC_FUNC_STRCOLL' => 1,
+ 'AC_C_VOLATILE' => 1,
+ 'AC_FUNC_GETPGRP' => 1,
+ 'AC_TYPE_PID_T' => 1,
+ 'm4_pattern_allow' => 1,
+ 'AC_FUNC_UTIME_NULL' => 1,
+ 'AC_PROG_RANLIB' => 1,
+ 'm4_include' => 1,
+ 'AC_FUNC_STRERROR_R' => 1,
+ 'AC_FUNC_GETMNTENT' => 1,
+ 'AC_PROG_GCC_TRADITIONAL' => 1,
+ 'AC_STRUCT_TIMEZONE' => 1,
+ 'include' => 1,
+ 'AM_AUTOMAKE_VERSION' => 1,
+ 'AC_LIBSOURCE' => 1,
+ 'AC_SUBST' => 1,
+ 'AC_CHECK_LIB' => 1,
+ 'AC_C_CONST' => 1,
+ 'AC_FUNC_VPRINTF' => 1,
+ 'AC_TYPE_SIGNAL' => 1,
+ 'AC_FUNC_GETGROUPS' => 1,
+ 'AC_CANONICAL_HOST' => 1,
+ 'AC_HEADER_STDC' => 1,
+ 'AC_FUNC_STRTOD' => 1,
+ 'AC_PROG_LEX' => 1,
+ 'AC_FUNC_OBSTACK' => 1,
+ 'AM_MAINTAINER_MODE' => 1,
+ 'AC_INIT' => 1,
+ 'AC_PROG_LN_S' => 1,
+ 'AC_FUNC_SETPGRP' => 1,
+ 'AC_CONFIG_SUBDIRS' => 1,
'AC_PROG_MAKE_SET' => 1,
- 'AC_CONFIG_HEADERS' => 1,
- 'AC_FUNC_CLOSEDIR_VOID' => 1,
+ 'AC_HEADER_TIME' => 1,
+ 'AC_FUNC_FORK' => 1,
+ 'AC_PROG_AWK' => 1,
+ 'AC_FUNC_CHOWN' => 1,
'AC_FUNC_STRNLEN' => 1,
- 'AC_HEADER_SYS_WAIT' => 1,
'AM_INIT_AUTOMAKE' => 1,
+ 'AC_FUNC_ALLOCA' => 1,
+ 'AC_DEFINE_TRACE_LITERAL' => 1,
+ 'AC_FUNC_STRFTIME' => 1,
+ 'AC_PATH_X' => 1,
'AC_REPLACE_FNMATCH' => 1,
+ 'AC_FUNC_WAIT3' => 1,
+ 'm4_pattern_forbid' => 1,
+ 'AC_CHECK_FUNCS' => 1,
+ 'AC_FUNC_STAT' => 1,
+ 'AC_CONFIG_AUX_DIR' => 1,
+ 'AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK' => 1,
+ 'AC_FUNC_MALLOC' => 1,
+ 'AC_FUNC_GETLOADAVG' => 1,
+ 'AC_PROG_INSTALL' => 1,
+ 'AC_HEADER_DIRENT' => 1,
+ 'AM_PROG_CC_C_O' => 1,
+ 'AC_TYPE_SIZE_T' => 1,
+ 'AC_FUNC_FSEEKO' => 1,
+ 'AC_TYPE_MODE_T' => 1,
+ 'AC_DECL_SYS_SIGLIST' => 1,
+ 'AM_GNU_GETTEXT' => 1,
+ 'AM_CONDITIONAL' => 1,
'AC_CONFIG_FILES' => 1,
- 'AC_PROG_YACC' => 1,
- 'AC_FUNC_GETMNTENT' => 1,
- 'AC_DEFINE_TRACE_LITERAL' => 1,
- 'AC_FUNC_MKTIME' => 1
+ 'AC_FUNC_LSTAT' => 1,
+ 'AC_CANONICAL_SYSTEM' => 1,
+ 'AC_HEADER_STAT' => 1,
+ 'AC_PROG_CXX' => 1
}
], 'Request' )
);
static int prompt_last_screen_line;
+static int prompt_physical_chars;
+
/* Expand the prompt string S and return the number of visible
characters in *LP, if LP is not null. This is currently more-or-less
a placeholder for expansion. LIP, if non-null is a place to store the
index of the last invisible character in the returned string. NIFLP,
if non-zero, is a place to store the number of invisible characters in
- the first prompt line. */
+ the first prompt line. The previous are used as byte counts -- indexes
+ into a character buffer. */
/* Current implementation:
\001 (^A) start non-visible characters
\002 are assumed to be `visible'. */
static char *
-expand_prompt (pmt, lp, lip, niflp)
+expand_prompt (pmt, lp, lip, niflp, vlp)
char *pmt;
- int *lp, *lip, *niflp;
+ int *lp, *lip, *niflp, *vlp;
{
char *r, *ret, *p;
- int l, rl, last, ignoring, ninvis, invfl;
+ int l, rl, last, ignoring, ninvis, invfl, ind, pind, physchars;
/* Short-circuit if we can. */
- if (strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
+ if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
{
r = savestring (pmt);
if (lp)
*lp = strlen (r);
+ if (lip)
+ *lip = 0;
+ if (niflp)
+ *niflp = 0;
+ if (vlp)
+ *vlp = lp ? *lp : strlen (r);
return r;
}
invfl = 0; /* invisible chars in first line of prompt */
- for (rl = ignoring = last = ninvis = 0, p = pmt; p && *p; p++)
+ for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++)
{
/* This code strips the invisible character string markers
RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
}
else
{
- *r++ = *p;
- if (!ignoring)
- rl++;
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ pind = p - pmt;
+ ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO);
+ l = ind - pind;
+ while (l--)
+ *r++ = *p++;
+ if (!ignoring)
+ rl += ind - pind;
+ else
+ ninvis += ind - pind;
+ p--; /* compensate for later increment */
+ }
else
- ninvis++;
- if (rl == _rl_screenwidth)
+#endif
+ {
+ *r++ = *p;
+ if (!ignoring)
+ rl++; /* visible length byte counter */
+ else
+ ninvis++; /* invisible chars byte counter */
+ }
+
+ if (rl >= _rl_screenwidth)
invfl = ninvis;
+
+ if (ignoring == 0)
+ physchars++;
}
}
*lip = last;
if (niflp)
*niflp = invfl;
+ if (vlp)
+ *vlp = physchars;
return ret;
}
{
char *ret;
- ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL);
+ ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
return ret;
}
/* The prompt is only one logical line, though it might wrap. */
local_prompt = expand_prompt (prompt, &prompt_visible_length,
&prompt_last_invisible,
- &prompt_invis_chars_first_line);
+ &prompt_invis_chars_first_line,
+ &prompt_physical_chars);
local_prompt_prefix = (char *)0;
return (prompt_visible_length);
}
t = ++p;
local_prompt = expand_prompt (p, &prompt_visible_length,
&prompt_last_invisible,
+ (int *)NULL,
(int *)NULL);
c = *t; *t = '\0';
/* The portion of the prompt string up to and including the
final newline is now null-terminated. */
local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
(int *)NULL,
- &prompt_invis_chars_first_line);
+ &prompt_invis_chars_first_line,
+ &prompt_physical_chars);
*t = c;
return (prompt_prefix_length);
}
register int in, out, c, linenum, cursor_linenum;
register char *line;
int c_pos, inv_botlin, lb_botlin, lb_linenum;
- int newlines, lpos, temp;
+ int newlines, lpos, temp, modmark;
char *prompt_this_line;
#if defined (HANDLE_MULTIBYTE)
wchar_t wc;
/* Mark the line as modified or not. We only do this for history
lines. */
+ modmark = 0;
if (_rl_mark_modified_lines && current_history () && rl_undo_list)
{
line[out++] = '*';
line[out] = '\0';
+ modmark = 1;
}
/* If someone thought that the redisplay was handled, but the currently
/* inv_lbreaks[i] is where line i starts in the buffer. */
inv_lbreaks[newlines = 0] = 0;
+#if 0
lpos = out - wrap_offset;
+#else
+ lpos = prompt_physical_chars + modmark;
+#endif
+
#if defined (HANDLE_MULTIBYTE)
memset (_rl_wrapped_line, 0, vis_lbsize);
#endif
char *t;
{
char *oldp, *oldl, *oldlprefix;
- int oldlen, oldlast, oldplen, oldninvis;
+ int oldlen, oldlast, oldplen, oldninvis, oldphyschars;
/* Geez, I should make this a struct. */
oldp = rl_display_prompt;
oldplen = prompt_prefix_length;
oldlast = prompt_last_invisible;
oldninvis = prompt_invis_chars_first_line;
+ oldphyschars = prompt_physical_chars;
rl_display_prompt = t;
local_prompt = expand_prompt (t, &prompt_visible_length,
&prompt_last_invisible,
- &prompt_invis_chars_first_line);
+ &prompt_invis_chars_first_line,
+ &prompt_physical_chars);
local_prompt_prefix = (char *)NULL;
rl_forced_update_display ();
prompt_prefix_length = oldplen;
prompt_last_invisible = oldlast;
prompt_invis_chars_first_line = oldninvis;
+ prompt_physical_chars = oldphyschars;
}
/* Redisplay the current line after a SIGWINCH is received. */
/* clear the state of the byte sequence, because
in this case effect of mbstate is undefined */
memset(&ps, 0, sizeof (mbstate_t));
+
+ /* Since we're assuming that this byte represents a single
+ non-zero-width character, don't forget about it. */
+ prev = point;
}
else if (MB_NULLWCH (tmp))
break; /* Found '\0' char. Can this happen? */
categories */
static char *lang;
+/* Called to reset all of the locale variables to their appropriate values
+ if (and only if) LC_ALL has not been assigned a value. */
static int reset_locale_vars __P((void));
static void locale_setblanks __P((void));
return (locale);
}
+/* Called to reset all of the locale variables to their appropriate values
+ if (and only if) LC_ALL has not been assigned a value. DO NOT CALL THIS
+ IF LC_ALL HAS BEEN ASSIGNED A VALUE. */
static int
reset_locale_vars ()
{
-BUILD_DIR=/usr/local/build/bash/bash-current
+BUILD_DIR=/usr/local/build/chet/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR