⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 display.c

📁 UNIX下SH的实现源码
💻 C
📖 第 1 页 / 共 4 页
字号:
      temp = pmtlen + out + 2;      if (temp >= line_size)	{	  line_size = (temp + 1024) - (temp % 1024);	  visible_line = xrealloc (visible_line, line_size);	  line = invisible_line = xrealloc (invisible_line, line_size);	}      strncpy (line + out,  prompt_this_line, pmtlen);      out += pmtlen;      line[out] = '\0';      wrap_offset = 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)	  #define CHECK_LPOS() \      do { \	lpos++; \	if (lpos >= 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)  /* inv_lbreaks[i] is where line i starts in the buffer. */  inv_lbreaks[newlines = 0] = 0;  lpos = out - wrap_offset;  /* XXX - what if lpos is already >= screenwidth before we start drawing the     contents of the command line? */  while (lpos >= screenwidth)    {      /* XXX - possible fix from Darin Johnson <darin@acuson.com> for prompt	 string with invisible characters that is longer than the screen	 width.  XXX - this doesn't work right if invisible characters have	 to be put on the second screen line -- it adds too much (the number	 of invisible chars after the screenwidth). */      temp = ((newlines + 1) * screenwidth) + ((newlines == 0) ? wrap_offset : 0);      inv_lbreaks[++newlines] = temp;      lpos -= screenwidth;    }  lb_linenum = 0;  for (in = 0; in < rl_end; in++)    {      c = (unsigned char)rl_line_buffer[in];      if (out + 8 >= line_size)		/* XXX - 8 for \t */	{	  line_size *= 2;	  visible_line = xrealloc (visible_line, line_size);	  invisible_line = xrealloc (invisible_line, line_size);	  line = invisible_line;	}      if (in == rl_point)	{	  c_pos = out;	  lb_linenum = newlines;	}      if (META_CHAR (c))	{	  if (_rl_output_meta_chars == 0)	    {	      sprintf (line + out, "\\%o", c);	      if (lpos + 4 >= screenwidth)		{		  temp = 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 temp, newout;#if 0	  newout = (out | (int)7) + 1;#else	  newout = out + 8 - lpos % 8;#endif	  temp = newout - out;	  if (lpos + temp >= screenwidth)	    {	      register int temp2;	      temp2 = 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 && term_up && *term_up)	{	  line[out++] = '\0';	/* XXX - sentinel */	  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	{	  line[out++] = c;	  CHECK_LPOS();	}    }  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;  /* C_POS == position in buffer where cursor should be placed. */  /* PWP: now is when things get a bit hairy.  The visible and invisible     line buffers are really multiple lines, which would wrap every     (screenwidth - 1) characters.  Go through each in turn, 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, let long lines display in a single terminal line, and     horizontally scroll it. */  if (_rl_horizontal_scroll_mode == 0 && term_up && *term_up)    {      int nleft, pos, changed_screen_line;      if (!rl_display_fixed || forced_display)	{	  forced_display = 0;	  /* If we have more than a screenful of material to display, then	     only display a screenful.  We should display the last screen,	     not the first.  */	  if (out >= screenchars)	    out = screenchars - 1;	  /* The first line is at character position 0 in the buffer.  The	     second and subsequent lines start at inv_lbreaks[N], offset by	     OFFSET (which has already been calculated above).  */#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 each line in the buffer, do the updating display. */	  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 this is the line with the prompt, we might need to		 compensate for invisible characters in the new line. Do		 this only if there is not more than one new line (which		 implies that we completely overwrite the old visible line)		 and the new line is shorter than the old.  Make sure we are		 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))		{		  nleft = 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) ? strlen (tt) : 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 term_up,		 the physical cursor position on the screen stays the same,		 but the buffer position needs to be adjusted to account		 for invisible characters. */	      if (cursor_linenum == 0 && wrap_offset)		_rl_last_c_pos += wrap_offset;	    }	  /* We have to reprint the prompt if it contains invisible	     characters, since it's not generally OK to just reprint	     the characters from the current cursor position.  But we	     only need to reprint it if the cursor is before the last	     invisible character in the prompt string. */	  nleft = visible_length + wrap_offset;	  if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&	      _rl_last_c_pos <= last_invisible && local_prompt)	    {#if defined (__MSDOS__)	      putc ('\r', rl_outstream);#else	      if (term_cr)		tputs (term_cr, 1, _rl_output_character_function);#endif	      _rl_output_some_chars (local_prompt, nleft);	      _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 cursor position. */	  nleft = c_pos - pos;	  /* Since _rl_backspace() doesn't know about invisible characters in the	     prompt, and there's no good way to tell it, we compensate for	     those characters here and call _rl_backspace() directly. */	  if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)	    {	      _rl_backspace (_rl_last_c_pos - nleft);	      _rl_last_c_pos = nleft;	    }	  if (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 = c_pos - wrap_offset;      nleft  = 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 = c_pos - (last_lmargin ? last_lmargin : wrap_offset);      t = 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, compute the starting offset so that the cursor is about	 two-thirds of the way across the screen. */      if (phys_c_pos > screenwidth - 2)	{	  lmargin = c_pos - (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;	}      else if (ndisp < screenwidth - 2)		/* XXX - was -1 */	lmargin = 0;      else if (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 = ((c_pos - 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	 the whole line, indicate that with a special character at the	 right edge of the screen.  If LMARGIN is 0, we need to take the	 wrap offset into account. */      t = lmargin + M_OFFSET (lmargin, wrap_offset) + 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,		       screenwidth + visible_wrap_offset,		       screenwidth + (lmargin ? 0 : wrap_offset),		       0);	  /* If the visible new line is shorter than the old, but the number	     of invisible characters is greater, and we are at the end of	     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 = screenwidth - t;	      _rl_clear_to_eol (nleft);	    }	  visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);	  if (visible_first_line_len > screenwidth)	    visible_first_line_len = screenwidth;	  _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);	  last_lmargin = lmargin;	}    }  fflush (rl_outstream);  /* Swap visible and non-visible lines. */  {    char *temp = visible_line;    int *itemp = vis_lbreaks, ntemp = vis_lbsize;    visible_line = invisible_line;    invisible_line = temp;    vis_lbreaks = inv_lbreaks;    inv_lbreaks = itemp;    vis_lbsize = inv_lbsize;    inv_lbsize = ntemp;    rl_display_fixed = 0;    /* If we are displaying on a single line, and last_lmargin is > 0, we       are not displaying any invisible characters, so set visible_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   line on the screen; vis:			     /old first difference	/beginning of line   |	      /old last same       /old EOL	v		     v	      v		    vold:	eddie> Oh, my little gruntle-buggy is to me, as lurgid asnew:	eddie> Oh, my little buggy says to me, as lurgid as	^		     ^	^			   ^	\beginning of line   |	\new last same	   \new end of line			     \new first difference   All are character pointers for the sake of speed.  Special cases for   no differences, as well as for end of line additions must be handled.   Could be made even smarter, but this works well enough */static voidupdate_line (old, new, current_line, omax, nmax, inv_botlin)     register char *old, *new;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -