TheGNUGeneralPublicLicenseisoftenshippedwithGNUsoftware,and isgenerallykeptinafilecalledCOPYINGorLICENSE.Ifyoudonot haveacopyofthelicense,writetotheFreeSoftwareFoundation,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA. */ #define READLINE_LIBRARY
#ifdefined (HAVE_CONFIG_H) # include "config_readline.h" #endif
#include <sys/types.h>
#ifdefined (HAVE_UNISTD_H) # include <unistd.h> #endif/* HAVE_UNISTD_H */
#include"posixstat.h"
#ifdefined (HAVE_STDLIB_H) # include <stdlib.h> #else # include "ansi_stdlib.h" #endif/* HAVE_STDLIB_H */
#include <stdio.h>
/* System-specific feature definitions and include files. */ #include"rldefs.h" #include"rlmbutil.h"
/* Termcap library stuff. */ #include"tcap.h"
/* Some standard library routines. */ #include"readline.h" #include"history.h"
/* Heuristic used to decide whether it is faster to move from CUR to NEW bybackinguporoutputtingacarriagereturnandmovingforward.CUR
and NEW are either both buffer positions or absolute screen positions. */ #define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
/* _rl_last_c_pos is an absolute cursor position in multibyte locales and a bufferindexinothers.Thismacroisusedwhendecidingwhetherthe currentcursorpositionisinthemiddleofapromptstringcontaining
invisible characters. */ #define PROMPT_ENDING_INDEX \
((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1)
/* This is the stuff that is hard for me. I never seem to write good
display routines in C. Let's see how I do this time. */
/* (PWP) Well... Good for a simple line updater, but totally ignores theproblemsofinputlineslongerthanthescreenwidth.
update_lineandthecodethatcallsitmakesamultipleline, automaticallywrappinglineupdate.Carefulattentionneeds
to be paid to the vertical position variables. */
/* Keep two buffers; one which reflects the current contents of the screen,andtheothertodrawwhatwethinkthenewcontentsshould be.Thencomparethebuffers,andmakewhateverchangestothe screenitselfthatweshould.Finally,makethebufferthatwe justdrewintobetheonewhichreflectsthecurrentcontentsofthe screen,andplacethecursorwhereitbelongs.
Commandsthatwanttocanfixthedisplaythemselves,andthenlet thisfunctionknowthatthedisplayhasbeenfixedbysettingthe
RL_DISPLAY_FIXED variable. This is good for efficiency. */
/* Global variables declared here. */ /* What YOU turn on when you have handled all redisplay yourself. */ int rl_display_fixed = 0;
int _rl_suppress_redisplay = 0; int _rl_want_redisplay = 0;
/* The stuff that gets printed out before the actual text of the line.
This is usually pointing to rl_prompt. */ constchar *rl_display_prompt = (constchar *)NULL;
/* Pseudo-global variables declared here. */
/* The visible cursor position. If you print some text, adjust this. */ /* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale supportingmultibytecharacters,andanabsolutecursorpositionwhen insuchalocale.Thisisanartifactofthedonatedmultibytesupport.
Care must be taken when modifying its value. */ int _rl_last_c_pos = 0; int _rl_last_v_pos = 0;
/* Number of lines currently on screen minus 1. */ int _rl_vis_botlin = 0;
/* Variables used only in this file. */ /* The last left edge of text that was displayed. This is used when
doing horizontal scrolling. It shifts in thirds of a screenwidth. */ staticint last_lmargin;
/* The line display buffers. One is the line currently displayed on
the screen. The other is the line about to be displayed. */ staticchar *visible_line = (char *)NULL; staticchar *invisible_line = (char *)NULL;
/* A buffer for `modeline' messages. */ staticchar msg_buf[128];
/* Non-zero forces the redisplay even if we thought it was unnecessary. */ staticint forced_display;
/* Default and initial buffer size. Can grow. */ staticint line_size = 1024;
/* Variables to keep track of the expanded prompt string, which may
include invisible characters. */
/* The number of invisible characters in the line currently being
displayed on the screen. */ staticint visible_wrap_offset;
/* The number of invisible characters in the prompt string. Static so it
can be shared between rl_redisplay and update_line */ staticint wrap_offset;
/* The index of the last invisible character in the prompt string. */ staticint prompt_last_invisible;
/* The length (buffer offset) of the first line of the last (possibly
multi-line) buffer displayed on the screen. */ staticint visible_first_line_len;
/* Number of invisible characters on the first physical line of the prompt. Onlyvalidwhenthenumberofphysicalcharactersinthepromptexceeds
(or is equal to) _rl_screenwidth. */ staticint prompt_invis_chars_first_line;
staticint prompt_physical_chars;
/* Variables to save and restore prompt and display information. */
/* These are getting numerous enough that it's time to create a struct. */
/* Expand the prompt string S and return the number of visible charactersin*LP,ifLPisnotnull.Thisiscurrentlymore-or-less aplaceholderforexpansion.LIP,ifnon-nullisaplacetostorethe indexofthelastinvisiblecharacterinthereturnedstring.NIFLP, ifnon-zero,isaplacetostorethenumberofinvisiblecharactersin thefirstpromptline.Thepreviousareusedasbytecounts--indexes
into a character buffer. */
/* Current implementation: \001(^A)startnon-visiblecharacters \002(^B)endnon-visiblecharacters allcharactersexcept\001and\002(followinga\001)arecopiedto thereturnedstring;allcharactersexceptthosebetween\001and
\002 are assumed to be `visible'. */
staticchar *
expand_prompt (pmt, lp, lip, niflp, vlp) char *pmt; int *lp, *lip, *niflp, *vlp;
{ char *r, *ret, *p, *igstart; int l, rl, last, ignoring, ninvis, invfl, invflset, physchars; #ifdefined (HANDLE_MULTIBYTE) int ind, pind; #endif
/* Short-circuit if we can. */ 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 : (int)strlen (r); return r;
}
l = strlen (pmt);
r = ret = (char *)xmalloc (l + 1);
invfl = 0; /* invisible chars in first line of prompt */
invflset = 0; /* we only want to set invfl once */
igstart = 0; 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 */ if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */
{
ignoring = 1;
igstart = p; continue;
} elseif (ignoring && *p == RL_PROMPT_END_IGNORE)
{
ignoring = 0; if (p != (igstart + 1))
last = r - ret - 1; continue;
} else
{ #ifdefined (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;
physchars += _rl_col_width (pmt, pind, ind);
} else
ninvis += ind - pind;
p--; /* compensate for later increment */
} else #endif
{
*r++ = *p; if (!ignoring)
{
rl++; /* visible length byte counter */
physchars++;
} else
ninvis++; /* invisible chars byte counter */
}
*r = '\0'; if (lp)
*lp = rl; if (lip)
*lip = last; if (niflp)
*niflp = invfl; if (vlp)
*vlp = physchars; return ret;
}
/* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
PMT and return the rest of PMT. */ char *
_rl_strip_prompt (pmt) char *pmt;
{ char *ret;
p = strrchr (prompt, '\n'); if (!p)
{ /* 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_physical_chars);
local_prompt_prefix = (char *)0;
local_prompt_len = local_prompt ? strlen (local_prompt) : 0; return (prompt_visible_length);
} else
{ /* The prompt spans multiple lines. */
t = ++p;
local_prompt = expand_prompt (p, &prompt_visible_length,
&prompt_last_invisible,
(int *)NULL,
&prompt_physical_chars);
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,
(int *)NULL);
*t = c;
local_prompt_len = local_prompt ? strlen (local_prompt) : 0; return (prompt_prefix_length);
}
}
/* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated arraysoflinebreakmarkers.MINSIZEistheminimumsizeofVISIBLE_LINE andINVISIBLE_LINE;ifitisgreaterthanLINE_SIZE,LINE_SIZEis increased.Ifthelineshavealreadybeenallocated,thisensuresthat
they can hold at least MINSIZE characters. */ staticvoid
init_line_structures (minsize) int minsize;
{ registerint n;
if (invisible_line == 0) /* initialize it */
{ if (line_size < minsize)
line_size = minsize;
visible_line = (char *)xmalloc (line_size);
invisible_line = (char *)xmalloc (line_size);
} elseif (line_size < minsize) /* ensure it can hold MINSIZE chars */
{
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;
}
/* Draw the line into the buffer. */
cpos_buffer_position = -1;
line = invisible_line;
out = inv_botlin = 0;
/* 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 visiblelinehasadifferentmodificationstatethantheoneabout
to become visible, then correct the caller's misconception. */ if (visible_line[0] != invisible_line[0])
rl_display_fixed = 0;
/* If the prompt to be displayed is the `primary' readline prompt (the onepassedtoreadline()),usethevalueswehavealreadyexpanded. Ifnot,usewhat'salreadyinrl_display_prompt.WRAP_OFFSETisthe
number of non-visible characters in the prompt string. */ if (rl_display_prompt == rl_prompt || local_prompt)
{ if (local_prompt_prefix && forced_display)
_rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
if (local_prompt_len > 0)
{
temp = local_prompt_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_prompt_len);
out += local_prompt_len;
}
line[out] = '\0';
wrap_offset = local_prompt_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; /* temp var */ if (forced_display)
{
_rl_output_some_chars (rl_display_prompt, pmtlen); /* Make sure we are at column zero even after a newline,
regardless of the state of terminal output processing. */ if (pmtlen < 2 || prompt_this_line[-2] != '\r')
cr ();
}
}
/* inv_lbreaks[i] is where line i starts in the buffer. */
inv_lbreaks[newlines = 0] = 0; #if0
lpos = out - wrap_offset; #else
lpos = prompt_physical_chars + modmark; #endif
#ifdefined (HANDLE_MULTIBYTE)
memset (_rl_wrapped_line, 0, vis_lbsize);
num = 0; #endif
/* prompt_invis_chars_first_line is the number of invisible characters in thefirstphysicallineoftheprompt. wrap_offset-prompt_invis_chars_first_lineisthenumberofinvis
chars on the second line. */
/* what if lpos is already >= _rl_screenwidth before we start drawing the
contents of the command line? */ while (lpos >= _rl_screenwidth)
{ /* fix from Darin Johnson <darin@acuson.com> for prompt string with invisiblecharactersthatislongerthanthescreenwidth.The prompt_invis_chars_first_linevariablecouldbemadeintoanarray sayinghowmanyinvisiblecharactersthereareperline,butthat's probablytoomuchworkforthebenefitgained.Howmanypeoplehave promptsthatexceedtwophysicallines?
Additional logic fix from Edward Catmur <ed@catmur.co.uk> */ #ifdefined (HANDLE_MULTIBYTE) int z; if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
n0 = num;
temp = local_prompt_len; while (num < temp)
{
z = _rl_col_width (local_prompt, n0, num); if (z > _rl_screenwidth)
{
num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY); break;
} elseif (z == _rl_screenwidth) break;
num++;
}
temp = num;
} else #endif/* !HANDLE_MULTIBYTE */
temp = ((newlines + 1) * _rl_screenwidth);
/* Now account for invisible characters in the current line. */
temp += ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line
: ((newlines == 1) ? wrap_offset : 0))
: ((newlines == 0) ? wrap_offset :0));
/* Draw the rest of the line (after the prompt) into invisible_line, keeping trackofwherethecursoris(cpos_buffer_position),thenumberofthelinecontaining thecursor(lb_linenum),thelastlinenumber(inv_botlin). Itmaintainsanarrayoflinebreaksfordisplay(inv_lbreaks).
This handles expanding tabs for display and displaying meta characters. */
lb_linenum = 0; #ifdefined (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 = (unsignedchar)rl_line_buffer[in];
#ifdefined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{ if (MB_INVALIDCH (wc_bytes))
{ /* Byte sequence is invalid or shortened. Assume that the
first byte represents a character. */
wc_bytes = 1; /* Assume that a character occupies a single column. */
wc_width = 1;
memset (&ps, 0, sizeof (mbstate_t));
} elseif (MB_NULLWCH (wc_bytes)) break; /* Found '\0' */ else
{
temp = wcwidth (wc);
wc_width = (temp >= 0) ? temp : 1;
}
} #endif
if (_rl_screenwidth < lpos + wc_width) for (i = lpos; i < _rl_screenwidth; i++)
{ /* The space will be removed in update_line() */
line[out++] = ' ';
_rl_wrapped_multicolumn++;
CHECK_LPOS();
} if (in == rl_point)
{
cpos_buffer_position = out;
lb_linenum = newlines;
} for (i = in; i < in+(int)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
}
#ifdefined (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
/* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed.
CURSOR_LINENUM == line number where the cursor should be placed. */
/* PWP: now is when things get a bit hairy. The visible and invisible linebuffersarereallymultiplelines,whichwouldwrapevery (screenwidth-1)characters.Gothrougheachinturn,finding
the changed region and updating it. The line order is top to bottom. */
/* If we can move the cursor up and down, then use multiple lines, otherwise,letlonglinesdisplayinasingleterminalline,and
horizontally scroll it. */
if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
{ int nleft, pos, changed_screen_line, tx; char empty_str[1] = { 0 };
if (!rl_display_fixed || forced_display)
{
forced_display = 0;
/* If we have more than a screenful of material to display, then onlydisplayascreenful.Weshoulddisplaythelastscreen,
not the first. */ 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;
}
/* The first line is at character position 0 in the buffer. The secondandsubsequentlinesstartatinv_lbreaks[N],offsetby
OFFSET (which has already been calculated above). */
/* For each line in the buffer, do the updating display. */ for (linenum = 0; linenum <= inv_botlin; linenum++)
{ /* This can lead us astray if we execute a program that changes
the locale from a non-multibyte to a multibyte one. */
o_cpos = _rl_last_c_pos;
cpos_adjusted = 0;
update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
/* If this is the line with the prompt, we might need to compensateforinvisiblecharactersinthenewline.Do thisonlyifthereisnotmorethanonenewline(which impliesthatwecompletelyoverwritetheoldvisibleline) andthenewlineisshorterthantheold.Makesureweare
at the end of the new line before clearing. */ if (linenum == 0 &&
inv_botlin == 0 && _rl_last_c_pos == out &&
(wrap_offset > visible_wrap_offset) &&
(_rl_last_c_pos < visible_first_line_len))
{ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
nleft = _rl_screenwidth - _rl_last_c_pos; else
nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos; if (nleft)
_rl_clear_to_eol (nleft);
}
/* Since the new first line is now visible, save its length. */ if (linenum == 0)
visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
}
/* We may have deleted some lines. If so, clear the left over
blank ones at the bottom out. */ 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) ? (int)strlen (tt) : _rl_screenwidth);
}
}
_rl_vis_botlin = inv_botlin;
/* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
different screen line during this redisplay. */
changed_screen_line = _rl_last_v_pos != cursor_linenum; if (changed_screen_line)
{
_rl_move_vert (cursor_linenum); /* If we moved up to the line with the prompt using _rl_term_up, thephysicalcursorpositiononthescreenstaysthesame, butthebufferpositionneedstobeadjustedtoaccount
for invisible characters. */ if ((MB_CUR_MAX == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
_rl_last_c_pos += wrap_offset;
}
/* We have to reprint the prompt if it contains invisible characters,sinceit'snotgenerallyOKtojustreprint thecharactersfromthecurrentcursorposition.Butwe onlyneedtoreprintitifthecursorisbeforethelast
invisible character in the prompt string. */
nleft = prompt_visible_length + wrap_offset; if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 && #if0
_rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt) #else
_rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt) #endif
{ #ifdefined (__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) - wrap_offset; else
_rl_last_c_pos = nleft;
}
/* Where on that line? And where does that line start
in the buffer? */
pos = inv_lbreaks[cursor_linenum]; /* nleft == number of characters in the line buffer between the
start of the line and the desired cursor position. */
nleft = cpos_buffer_position - pos;
/* NLEFT is now a number of characters in a buffer. When in a multibytelocale,however,_rl_last_c_posisanabsolutecursor positionthatdoesn'ttakeinvisiblecharactersintheprompt
into account. We use a fudge factor to compensate. */
/* Since _rl_backspace() doesn't know about invisible characters in the prompt,andthere'snogoodwaytotellit,wecompensatefor
those characters here and call _rl_backspace() directly. */ if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
{ /* TX == new physical cursor position in multibyte locale. */ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
tx = _rl_col_width (&visible_line[pos], 0, nleft) - visible_wrap_offset; else
tx = nleft; if (_rl_last_c_pos > tx)
{
_rl_backspace (_rl_last_c_pos - tx); /* XXX */
_rl_last_c_pos = tx;
}
}
/* We need to note that in a multibyte locale we are dealing with _rl_last_c_posasanabsolutecursorposition,butmovingtoa pointspecifiedbyabufferposition(NLEFT)thatdoesn'ttake
invisible characters into account. */ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
_rl_move_cursor_relative (nleft, &invisible_line[pos]); elseif (nleft != _rl_last_c_pos)
_rl_move_cursor_relative (nleft, &invisible_line[pos]);
}
} else/* Do horizontal scrolling. */
{ #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0) int lmargin, ndisp, nleft, phys_c_pos, t;
/* Always at top line. */
_rl_last_v_pos = 0;
/* Compute where in the buffer the displayed line should start. This
will be LMARGIN. */
/* The number of characters that will be displayed before the cursor. */
ndisp = cpos_buffer_position - wrap_offset;
nleft = prompt_visible_length + wrap_offset; /* Where the new cursor position will be on the screen. This can be
longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset);
t = _rl_screenwidth / 3;
/* If the number of characters had already exceeded the screenwidth,
last_lmargin will be > 0. */
/* If the number of characters to be displayed is more than the screen width,computethestartingoffsetsothatthecursorisabout
two-thirds of the way across the screen. */ if (phys_c_pos > _rl_screenwidth - 2)
{
lmargin = cpos_buffer_position - (2 * t); if (lmargin < 0)
lmargin = 0; /* If the left margin would be in the middle of a prompt with
invisible characters, don't display the prompt at all. */ if (wrap_offset && lmargin > 0 && lmargin < nleft)
lmargin = nleft;
} elseif (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */
lmargin = 0; elseif (phys_c_pos < 1)
{ /* If we are moving back towards the beginning of the line and
the last margin is no longer correct, compute a new one. */
lmargin = ((cpos_buffer_position - 1) / t) * t; /* XXX */ if (wrap_offset && lmargin > 0 && lmargin < nleft)
lmargin = nleft;
} else
lmargin = last_lmargin;
/* If the first character on the screen isn't the first character
in the display line, indicate this with a special character. */ if (lmargin > 0)
line[lmargin] = '<';
/* If SCREENWIDTH characters starting at LMARGIN do not encompass thewholeline,indicatethatwithaspecialcharacteratthe rightedgeofthescreen.IfLMARGINis0,weneedtotakethe
wrap offset into account. */
t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth; if (t < out)
line[t - 1] = '>';
/* If the visible new line is shorter than the old, but the number ofinvisiblecharactersisgreater,andweareattheendof
the new line, we need to clear to eol. */
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_display_fixed = 0; /* If we are displaying on a single line, and last_lmargin is > 0, we arenotdisplayinganyinvisiblecharacters,sosetvisible_wrap_offset
to 0. */ if (_rl_horizontal_scroll_mode && last_lmargin)
visible_wrap_offset = 0; else
visible_wrap_offset = wrap_offset;
}
}
/* PWP: update_line() is based on finding the middle difference of each lineonthescreen;vis:
Could be made even smarter, but this works well enough */ staticvoid
update_line (old, new, current_line, omax, nmax, inv_botlin) registerchar *old, *new; int current_line, omax, nmax, inv_botlin;
{ registerchar *ofd, *ols, *oe, *nfd, *nls, *ne; int temp, lendiff, wsatend, od, nd; int current_invis_chars; int col_lendiff, col_temp; #ifdefined (HANDLE_MULTIBYTE)
mbstate_t ps_new, ps_old; int new_offset, old_offset; #endif
/* If we're at the right edge of a terminal that supports xn, we're readytowraparound,sodoso.Thisfixesproblemswithknowing theexactcursorpositionandcut-and-pastewithcertainterminal emulators.Inthiscalculation,TEMPisthephysicalscreen
position of the cursor. */ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
temp = _rl_last_c_pos; else
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)
{ #ifdefined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{ wchar_t wc;
mbstate_t ps; int tempwidth, bytes;
size_t ret;
/* This fixes only double-column characters, but if the wrapped charactercomsumesmorethanthreecolumns,spaceswillbe
inserted in the string buffer. */ if (_rl_wrapped_line[current_line] > 0)
_rl_clear_to_eol (_rl_wrapped_line[current_line]);
/* Find first difference. */ #ifdefined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{ /* See if the old line is a subset of the new line, so that the
only change is adding characters. */
temp = (omax < nmax) ? omax : nmax; if (memcmp (old, new, temp) == 0)
{
ofd = old + temp;
nfd = new + temp;
} else
{
memset (&ps_new, 0, sizeof(mbstate_t));
memset (&ps_old, 0, sizeof(mbstate_t));
/* Move to the end of the screen line. ND and OD are used to keep track ofthedistancebetweenneandnewandoeandold,respectively,to
move a subtraction out of each loop. */ for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++); for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
/* If no difference, continue to next line. */ if (ofd == oe && nfd == ne) return;
wsatend = 1; /* flag for trailing whitespace */
#ifdefined (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));
#if0 /* On advice from jir@yamato.ibm.com */
_rl_adjust_point (old, ols - old, &ps_old);
_rl_adjust_point (new, nls - new, &ps_new); #endif
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/* HANDLE_MULTIBYTE */
ols = oe - 1; /* find last same */
nls = ne - 1; while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
{ if (*ols != ' ')
wsatend = 0;
ols--;
nls--;
} #ifdefined (HANDLE_MULTIBYTE)
} #endif
if (wsatend)
{
ols = oe;
nls = ne;
} #ifdefined (HANDLE_MULTIBYTE) /* This may not work for stateful encoding, but who cares? To handle statefulencodingproperly,wehavetoscaneachstringfromthe
beginning and compare. */ elseif (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0) #else elseif (*ols != *nls) #endif
{ if (*ols) /* don't step past the NUL */
{ 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++;
}
}
/* count of invisible characters in the current invisible line. */
current_invis_chars = W_OFFSET (current_line, wrap_offset); if (_rl_last_v_pos != current_line)
{
_rl_move_vert (current_line); if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
_rl_last_c_pos += visible_wrap_offset;
}
/* If this is the first line and there are invisible characters in the promptstring,andthepromptstringhasnotchanged,andthecurrent cursorpositionisbeforethelastinvisiblecharacterintheprompt, andtheindexofthecharactertomovetoispasttheendoftheprompt string,thenredrawtheentirepromptstring.Wecanonlydothis reliablyiftheterminalsupportsa`cr'capability.
Thisisnotanefficiencyhack--thereisaproblemwithredrawing portionsofthepromptstringiftheycontainterminalescape sequences(likedrawingthe`unbold'sequencewithoutacorresponding
`bold') that manifests itself on certain terminals. */
lendiff = local_prompt_len;
od = ofd - old; /* index of first difference in visible line */ 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_ENDING_INDEX)
{ #ifdefined (__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)
{ /* We take wrap_offset into account here so we can pass correct
information to _rl_move_cursor_relative. */
_rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff) - wrap_offset;
cpos_adjusted = 1;
} else
_rl_last_c_pos = lendiff;
}
/* When this function returns, _rl_last_c_pos is correct, and an absolute cursorpostioninmultibytemode,butabufferindexwhennotina
multibyte locale. */
_rl_move_cursor_relative (od, old); #if1 #ifdefined (HANDLE_MULTIBYTE) /* We need to indicate that the cursor position is correct in the presence of invisiblecharactersinthepromptstring.Let'sseeifsettingthiswhen
we make sure we're at the end of the drawn prompt string works. */ if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_last_c_pos == prompt_physical_chars)
cpos_adjusted = 1; #endif #endif
/* if (len (new) > len (old)) lendiff==differenceinbuffer col_lendiff==differenceonscreen
When not using multibyte characters, these are equal */
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 we are changing the number of invisible characters in a line, and thespotoffirstdifferenceisbeforetheendoftheinvisiblechars,
lendiff needs to be adjusted. */ 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;
}
}
/* Insert (diff (len (old), len (new)) ch. */
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) /* XXX - was lendiff */
{ /* Non-zero if we're increasing the number of lines. */ int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin; /* Sometimes it is cheaper to print the characters rather than usetheterminal'scapabilities.Ifwe'regrowingthenumber oflines,makesureweactuallycausethenewlinetowrap
around on auto-wrapping terminals. */ if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
{ /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and _rl_horizontal_scroll_mode==1,insertingthecharacterswith _rl_term_ICor_rl_term_icwillscrewupthescreenbecauseofthe
invisible characters. We need to just draw them. */ 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;
} elseif ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
{ /* At the end of a line the characters do not have to
be "inserted". They can just be placed on the screen. */ /* However, this screws up the rest of this block, which
assumes you've done the insert because you can. */
_rl_output_some_chars (nfd, lendiff);
_rl_last_c_pos += col_lendiff;
} else
{ /* We have horizontal scrolling and we are not inserting at theend.Wehaveinvisiblecharactersinthisline.This
is a dumb update. */
_rl_output_some_chars (nfd, temp);
_rl_last_c_pos += col_temp; return;
} /* Copy (new) chars to screen from first diff to last match. */
temp = nls - nfd; if ((temp - lendiff) > 0)
{
_rl_output_some_chars (nfd + lendiff, temp - lendiff); #if1 /* XXX -- this bears closer inspection. Fixes a redisplay bug reportedagainstbash-3.0-alphabyAndreasSchwabinvolving multibytecharactersandpromptstringswithinvisible
characters, but was previously disabled. */
_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
{ /* cannot insert chars, write to EOL */
_rl_output_some_chars (nfd, temp);
_rl_last_c_pos += col_temp; /* If we're in a multibyte locale and were before the last invisible charinthecurrentline(whichimplieswejustoutputsomeinvisible characters)weneedtoadjust_rl_last_c_pos,sinceitrepresents
a physical character position. */
}
} else/* Delete characters from line. */
{ /* If possible and inexpensive to use terminal deletion, then do so. */ if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
{ /* If all we're doing is erasing the invisible characters in the promptstring,don'tbother.Itscrewsuptheassumptions
about what's on the screen. */ if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
-lendiff == visible_wrap_offset)
col_lendiff = 0;
if (col_lendiff)
delete_chars (-col_lendiff); /* delete (diff) characters */
/* Copy (new) chars to screen from first diff to last match */
temp = nls - nfd; if (temp > 0)
{
_rl_output_some_chars (nfd, temp);
_rl_last_c_pos += _rl_col_width (nfd, 0, temp);;
}
} /* Otherwise, print over the existing material. */ else
{ if (temp > 0)
{
_rl_output_some_chars (nfd, temp);
_rl_last_c_pos += col_temp; /* XXX */
}
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);
}
}
}
}
/* Tell the update routines that we have moved onto a new (empty) line. */ int
rl_on_new_line ()
{ if (visible_line)
visible_line[0] = '\0';
/* Tell the update routines that we have moved onto a new line with the promptalreadydisplayed.Codeoriginallyfromtheversionofreadline distributedwithCLISP.rl_expand_promptmusthavealreadybeencalled
(explicitly or implicitly). This still doesn't work exactly right. */ int
rl_on_new_line_with_prompt ()
{ int prompt_size, i, l, real_screenwidth, newlines; char *prompt_last_line, *lprompt;
/* Initialize visible_line and invisible_line to ensure that they can hold
the already-displayed prompt. */
prompt_size = strlen (rl_prompt) + 1;
init_line_structures (prompt_size);
/* Make sure the line structures hold the already-displayed prompt for
redisplay. */
lprompt = local_prompt ? local_prompt : rl_prompt;
strcpy (visible_line, lprompt);
strcpy (invisible_line, lprompt);
/* If the prompt contains newlines, take the last tail. */
prompt_last_line = strrchr (rl_prompt, '\n'); if (!prompt_last_line)
prompt_last_line = rl_prompt;
/* Dissect prompt_last_line into screen lines. Note that here we have tousetherealscreenwidth.Readline'snotionofscreenwidthmightbe
one less, see terminal.c. */
real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
_rl_last_v_pos = l / real_screenwidth; /* If the prompt length is a multiple of real_screenwidth, we don't know whetherthecursorisattheendofthelastline,oralreadyatthe
beginning of the next line. Output a newline just to be safe. */ 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;
rl_display_prompt = rl_prompt; /* XXX - make sure it's set */
return0;
}
/* Actually update the display, period. */ int
rl_forced_update_display ()
{ registerchar *temp;
if (visible_line)
{
temp = visible_line; while (*temp)
*temp++ = '\0';
}
rl_on_new_line ();
forced_display++;
(*rl_redisplay_function) (); return0;
}
/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices. (Well,whenwedon'thavemultibytecharacters,_rl_last_c_posisa bufferindex.) DATAisthecontentsofthescreenlineofinterest;i.e.,where
the movement is being done. */ void
_rl_move_cursor_relative (new, data) intnew; constchar *data;
{ registerint i; int woff; /* number of invisible chars on current line */ int cpos, dpos; /* current and desired cursor positions */
woff = W_OFFSET (_rl_last_v_pos, wrap_offset);
cpos = _rl_last_c_pos; #ifdefined (HANDLE_MULTIBYTE) /* If we have multibyte characters, NEW is indexed by the buffer point in amultibytestring,but_rl_last_c_posisthedisplayposition.In thiscase,NEW'sdisplaypositionisnotobviousandmustbe calculated.Weneedtoaccountforinvisiblecharactersinthisline,
as long as we are past them and they are counted by _rl_col_width. */ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
dpos = _rl_col_width (data, 0, new); if (dpos > prompt_last_invisible) /* XXX - don't use woff here */
{
dpos -= woff; /* Since this will be assigned to _rl_last_c_pos at the end (more precisely,_rl_last_c_pos==dposwhenthisfunctionreturns),
let the caller know. */
cpos_adjusted = 1;
}
} else #endif
dpos = new;
/* If we don't have to do anything, then return. */ if (cpos == dpos) return;
/* It may be faster to output a CR, and then move forwards instead
of moving backwards. */ /* i == current physical cursor position. */ #ifdefined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
i = _rl_last_c_pos; else #endif
i = _rl_last_c_pos - woff; if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
(_rl_term_autowrap && i == _rl_screenwidth))
{ #ifdefined (__MSDOS__)
putc ('\r', rl_outstream); #else
tputs (_rl_term_cr, 1, _rl_output_character_function); #endif/* !__MSDOS__ */
cpos = _rl_last_c_pos = 0;
}
if (cpos < dpos)
{ /* Move the cursor forward. We do it by printing the command tomovethecursorforwardifthereisone,elseprintthat
portion of the output buffer again. Which is cheaper? */
/* The above comment is left here for posterity. It is faster toprintonecharacter(non-control)thantoprintacontrol sequencetellingtheterminaltomoveforwardonecharacter. Thatkindofcontrolisforpeoplewhodon'tknowwhatthe
data is underneath the cursor. */
/* However, we need a handle on where the current display position is inthebufferfortheimmediatelyprecedingcommenttobetrue. Inmultibytelocales,wedon'tcurrentlyhavethatinfoavailable. Withoutit,wedon'tknowwherethedatawehavetodisplaybegins inthebufferandwehavetogobacktothebeginningofthescreen line.Inthiscase,wecanusetheterminalsequencetomoveforward
if it's available. */ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{ if (_rl_term_forward_char)
{ for (i = cpos; i < dpos; i++)
tputs (_rl_term_forward_char, 1, _rl_output_character_function);
} else
{
tputs (_rl_term_cr, 1, _rl_output_character_function); for (i = 0; i < new; i++)
putc (data[i], rl_outstream);
}
} else for (i = cpos; i < new; i++)
putc (data[i], rl_outstream);
}
#ifdefined (HANDLE_MULTIBYTE) /* NEW points to the buffer point, but _rl_last_c_pos is the display point. Thebytelengthofthestringisprobablybiggerthanthecolumnwidth ofthestring,whichmeansthatifNEW==_rl_last_c_pos,thenNEW's
display point is less than _rl_last_c_pos. */ #endif elseif (cpos > dpos)
_rl_backspace (cpos - dpos);
_rl_last_c_pos = dpos;
}
/* PWP: move the cursor up or down. */ void
_rl_move_vert (to) int to;
{ registerint 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); #ifdefined (__MSDOS__)
putc ('\r', rl_outstream); #else
tputs (_rl_term_cr, 1, _rl_output_character_function); #endif
_rl_last_c_pos = 0;
} else
{ /* delta < 0 */ if (_rl_term_up && *_rl_term_up) for (i = 0; i < -delta; i++)
tputs (_rl_term_up, 1, _rl_output_character_function);
}
_rl_last_v_pos = to; /* Now TO is here */
}
/* Physically print C on rl_outstream. This is for functions which know
how to optimize the display. Return the number of characters output. */ 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);
}
#ifdefined (DISPLAY_TABS) if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT) #else if (CTRL_CHAR (c) || c == RUBOUT) #endif/* !DISPLAY_TABS */
{
fprintf (rl_outstream, "C-");
n += 2;
c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
}
return ((ISPRINT (uc)) ? 1 : 2);
} /* How to print things in the "echo-area". The prompt is treated as a
mini-modeline. */ staticint msg_saved_prompt = 0;
/* How to clear things from the "echo-area". */ int
rl_clear_message ()
{
rl_display_prompt = rl_prompt; if (msg_saved_prompt)
{
rl_restore_prompt ();
msg_saved_prompt = 0;
}
(*rl_redisplay_function) (); return0;
}
/* can test saved_local_prompt to see if prompt info has been saved. */
saved_local_prompt = saved_local_prefix = (char *)0;
saved_local_length = 0;
saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
saved_invis_chars_first_line = saved_physical_chars = 0;
}
char *
_rl_make_prompt_for_search (pchar) int pchar;
{ int len; char *pmt, *p;
rl_save_prompt ();
/* We've saved the prompt, and can do anything with the various prompt stringsweneedbeforethey'rerestored.Wewanttheunexpanded
portion of the prompt string after any final newline. */
p = rl_prompt ? strrchr (rl_prompt, '\n') : 0; if (p == 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
{
p++;
len = strlen (p);
pmt = (char *)xmalloc (len + 2); if (len)
strcpy (pmt, p);
pmt[len] = pchar;
pmt[len+1] = '\0';
}
/* will be overwritten by expand_prompt, called from rl_message */
prompt_physical_chars = saved_physical_chars + 1; return pmt;
}
/* Quick redisplay hack when erasing characters at the end of the line. */ void
_rl_erase_at_end_of_line (l) int l;
{ registerint 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++;
}
/* Clear to the end of the line. COUNT is the minimum
number of character spaces to clear, */ void
_rl_clear_to_eol (count) int count;
{ if (_rl_term_clreol)
tputs (_rl_term_clreol, 1, _rl_output_character_function); elseif (count)
space_to_eol (count);
}
/* Clear to the end of the line using spaces. COUNT is the minimum
number of character spaces to clear, */ staticvoid
space_to_eol (count) int count;
{ registerint i;
for (i = 0; i < count; i++)
putc (' ', rl_outstream);
/* If we have to turn on insert-mode, then do so. */ if (_rl_term_im && *_rl_term_im)
tputs (_rl_term_im, 1, _rl_output_character_function);
/* If there is a special command for inserting characters, then
use that first to open up the space. */ if (_rl_term_ic && *_rl_term_ic)
{ for (i = col; i--; )
tputs (_rl_term_ic, 1, _rl_output_character_function);
}
/* Print the text. */
_rl_output_some_chars (string, count);
/* If there is a string to turn off insert mode, we had best use
it now. */ if (_rl_term_ei && *_rl_term_ei)
tputs (_rl_term_ei, 1, _rl_output_character_function);
} #endif/* __MSDOS__ || __MINGW32__ */
}
/* Delete COUNT characters from the display line. */ staticvoid
delete_chars (count) int count;
{ if (count > _rl_screenwidth) /* XXX */ return;
full_lines = 0; /* If the cursor is the only thing on an otherwise-blank last line,
compensate so we don't print an extra CRLF. */ 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 we've wrapped lines, remove the final xterm line-wrap flag. */ 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]];
cpos_buffer_position = -1; /* don't know where we are in buffer */
_rl_move_cursor_relative (_rl_screenwidth - 1, last_line); /* XXX */
_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++;
}
/* Move to the start of the current line. */ staticvoid
cr ()
{ if (_rl_term_cr)
{ #ifdefined (__MSDOS__)
putc ('\r', rl_outstream); #else
tputs (_rl_term_cr, 1, _rl_output_character_function); #endif
_rl_last_c_pos = 0;
}
}
/* Redraw the last line of a multi-line prompt that may possibly contain terminalescapesequences.Calledwiththecursoratcolumn0ofthe
line to draw the prompt on. */ staticvoid
redraw_prompt (t) char *t;
{ constchar *oldp;
/* Redisplay the current line after a SIGWINCH is received. */ void
_rl_redisplay_after_sigwinch ()
{ constchar *t;
/* Clear the current line and put the cursor at column 0. Make sure
the right thing happens if we have wrapped to a new screen line. */ if (_rl_term_cr)
{ #ifdefined (__MSDOS__)
putc ('\r', rl_outstream); #else
tputs (_rl_term_cr, 1, _rl_output_character_function); #endif
_rl_last_c_pos = 0; #ifdefined (__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 ();
/* Redraw only the last line of a multi-line prompt. */
t = strrchr (rl_display_prompt, '\n'); if (t)
redraw_prompt (++t); else
rl_forced_update_display ();
}
/* return the `current display line' of the cursor -- the number of lines to
move up to get to the first screen line of the current readline line. */ int
_rl_current_display_line ()
{ int ret, nleft;
/* Find out whether or not there might be invisible characters in the
editing buffer. */ 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;
}
#ifdefined (HANDLE_MULTIBYTE) /* Calculate the number of screen columns occupied by STR from START to END. Inthecaseofmultibytecharacterswithstatefulencoding,wehaveto
scan from the beginning of the string to take the state into account. */ staticint
_rl_col_width (str, start, end) constchar *str; int start, end;
{ wchar_t wc;
mbstate_t ps; int tmp, point, width, max;
if (end <= start) return0;
memset (&ps, 0, sizeof (mbstate_t));
point = 0;
max = end;
while (point < start)
{
tmp = mbrlen (str + point, max, &ps); if (MB_INVALIDCH ((size_t)tmp))
{ /* In this case, the bytes are invalid or too short to compose a multibytecharacter,soweassumethatthefirstbyterepresents
a single character. */
point++;
max--;
/* Clear the state of the byte sequence, because in this case the
effect of mbstate is undefined. */
memset (&ps, 0, sizeof (mbstate_t));
} elseif (MB_NULLWCH (tmp)) break; /* Found '\0' */ else
{
point += tmp;
max -= tmp;
}
}
/* If START is not a byte that starts a character, then POINT will be greaterthanSTART.Inthiscase,assumethat(POINT-START)gives
a byte count that is the number of columns of difference. */
width = point - start;
while (point < end)
{
tmp = mbrtowc (&wc, str + point, max, &ps); if (MB_INVALIDCH ((size_t)tmp))
{ /* In this case, the bytes are invalid or too short to compose a multibytecharacter,soweassumethatthefirstbyterepresents
a single character. */
point++;
max--;
/* and assume that the byte occupies a single column. */
width++;
/* Clear the state of the byte sequence, because in this case the
effect of mbstate is undefined. */
memset (&ps, 0, sizeof (mbstate_t));
} elseif (MB_NULLWCH (tmp)) break; /* Found '\0' */ else
{
point += tmp;
max -= tmp;
tmp = wcwidth(wc);
width += (tmp >= 0) ? tmp : 1;
}
}
width += point - end;
return width;
} #endif/* HANDLE_MULTIBYTE */
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.46 Sekunden
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.