sldisply.c

来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 2,241 行 · 第 1/4 页

C
2,241
字号

static void write_attributes (SLtt_Char_Type fgbg)
{
   int bg0, fg0;

   if (Worthless_Highlight) return;
   if (fgbg == Current_Fgbg) return;

   /* Before spitting out colors, fix attributes */
   if ((fgbg & ATTR_MASK) != (Current_Fgbg & ATTR_MASK))
     {
	if (Current_Fgbg & ATTR_MASK)
	  {
	     SLtt_write_string(Norm_Vid_Str);
	     /* In case normal video turns off ALL attributes: */
	     if (fgbg & SLTT_ALTC_MASK)
	       Current_Fgbg &= ~SLTT_ALTC_MASK;
	     SLtt_set_alt_char_set (0);
	  }

	if ((fgbg & SLTT_ALTC_MASK)
	    != (Current_Fgbg & SLTT_ALTC_MASK))
	  {
	     SLtt_set_alt_char_set ((int) (fgbg & SLTT_ALTC_MASK));
	  }

	if (fgbg & SLTT_ULINE_MASK) SLtt_write_string (UnderLine_Vid_Str);
	if (fgbg & SLTT_BOLD_MASK) SLtt_bold_video ();
	if (fgbg & SLTT_REV_MASK) SLtt_write_string (Rev_Vid_Str);
	if (fgbg & SLTT_BLINK_MASK)
	  {
	     /* Someday Linux will have a blink mode that set high intensity
	      * background.  Lets be prepared.
	      */
	     if (SLtt_Blink_Mode) SLtt_write_string (Blink_Vid_Str);
	  }
     }

   if (SLtt_Use_Ansi_Colors)
     {
	fg0 = (int) GET_FG(fgbg);
	bg0 = (int) GET_BG(fgbg);
	tt_printf(Color_Escape_Sequence, fg0, bg0);
     }
   Current_Fgbg = fgbg;
}

static int Video_Initialized;

void SLtt_reverse_video (int color)
{
   SLtt_Char_Type fgbg;
   char *esc;

   if (Worthless_Highlight) return;
   if ((color < 0) || (color >= JMAX_COLORS)) return;

   if (Video_Initialized == 0)
     {
	if (color == JNORMAL_COLOR)
	  {
	     SLtt_write_string (Norm_Vid_Str);
	  }
	else SLtt_write_string (Rev_Vid_Str);
	Current_Fgbg = 0xFFFFFFFFU;
	return;
     }

   if (SLtt_Use_Ansi_Colors)
     {
	fgbg = Ansi_Color_Map[color].fgbg;
	if ((esc = Ansi_Color_Map[color].custom_esc) != NULL)
	  {
	     if (fgbg != Current_Fgbg)
	       {
		  Current_Fgbg = fgbg;
		  SLtt_write_string (esc);
		  return;
	       }
	  }
     }
   else fgbg = Ansi_Color_Map[color].mono;

   if (fgbg == Current_Fgbg) return;
   write_attributes (fgbg);
}




void SLtt_normal_video (void)
{
   SLtt_reverse_video(JNORMAL_COLOR);
}

void SLtt_narrow_width (void)
{
    SLtt_write_string("\033[?3l");
}

void SLtt_wide_width (void)
{
    SLtt_write_string("\033[?3h");
}

/* Highest bit represents the character set. */
#define COLOR_MASK 0x7F00

#define COLOR_OF(x) (((unsigned int)(x) & COLOR_MASK) >> 8)
/*
#define COLOR_EQS(a, b) \
   (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)
*/

#define COLOR_EQS(a, b) \
   (SLtt_Use_Ansi_Colors \
    ? (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)\
    :  (Ansi_Color_Map[COLOR_OF(a)].mono == Ansi_Color_Map[COLOR_OF(b)].mono))


#define CHAR_EQS(a, b) (((a) == (b))\
			|| ((((a) & ~COLOR_MASK) == ((b) & ~COLOR_MASK))\
			    && COLOR_EQS((a), (b))))


/* The whole point of this routine is to prevent writing to the last column
 * and last row on terminals with automatic margins.
 */
static void write_string_with_care (char *str)
{
   unsigned int len;

   if (str == NULL) return;

   len = strlen (str);
   if (Automatic_Margins && (Cursor_r + 1 == SLtt_Screen_Rows))
     {
	if (len + (unsigned int) Cursor_c >= (unsigned int) SLtt_Screen_Cols)
	  {
	     /* For now, just do not write there.  Later, something more
	      * sophisticated will be implemented.
	      */
	     if (SLtt_Screen_Cols > Cursor_c)
	       len = SLtt_Screen_Cols - Cursor_c - 1;
	     else len = 0;
	  }
     }
   tt_write (str, len);
}

static void send_attr_str (unsigned short *s)
{
   unsigned char out[256], ch, *p;
   register SLtt_Char_Type attr;
   register unsigned short sh;
   int color, last_color = -1;

   p = out;
   while (0 != (sh = *s++))
     {
	ch = sh & 0xFF;
	color = ((int) sh & 0xFF00) >> 8;
#ifdef SLTT_TRANSP_ACS_PATCH
	if (ch <= ' ' && (color & 0x80)) color &= ~0x80;
#endif
	if (color != last_color)
	  {
	     if (SLtt_Use_Ansi_Colors) attr = Ansi_Color_Map[color & 0x7F].fgbg;
	     else attr = Ansi_Color_Map[color & 0x7F].mono;

	     /* sh => color */
	     if (color & 0x80) /* alternate char set */
	       {
		  if (SLtt_Use_Blink_For_ACS)
		    {
		       if (SLtt_Blink_Mode) attr |= SLTT_BLINK_MASK;
		    }
		  else attr |= SLTT_ALTC_MASK;
	       }


	     if (attr != Current_Fgbg)
	       {
#ifndef SLTT_TRANSP_ACS_PATCH
		  if ((ch != ' ') ||
		      /* it is a space so only consider it different if it
		       * has different attributes.
		       */
		      (attr & BGALL_MASK) != (Current_Fgbg & BGALL_MASK))
#endif
		    {
		       if (p != out)
			 {
			    *p = 0;
			    write_string_with_care ((char *) out);
			    Cursor_c += (int) (p - out);
			    p = out;
			 }

		       if (SLtt_Use_Ansi_Colors && (NULL != Ansi_Color_Map[color & 0x7F].custom_esc))
			 {
			    SLtt_write_string (Ansi_Color_Map[color & 0x7F].custom_esc);
			    /* Just in case the custom escape sequence screwed up
			     * the alt character set state...
			     */
	                    if ((attr & SLTT_ALTC_MASK) != (Current_Fgbg & SLTT_ALTC_MASK))
			      SLtt_set_alt_char_set ((int) (attr & SLTT_ALTC_MASK));
			    Current_Fgbg = attr;
			 }
		       else write_attributes (attr);

		       last_color = color;
		    }
	       }
	  }
	*p++ = ch;
     }
   *p = 0;
   if (p != out) write_string_with_care ((char *) out);
   Cursor_c += (int) (p - out);
}

static void forward_cursor (unsigned int n, int row)
{
   char buf[30];


   if (n <= 4)
     {
	SLtt_normal_video ();
	SLMEMSET (buf, ' ', n);
	buf[n] = 0;
	write_string_with_care (buf);
	Cursor_c += n;
     }
   else if (Curs_F_Str != NULL)
     {
	Cursor_c += n;
	n = tt_sprintf(buf, Curs_F_Str, (int) n, 0);
	tt_write(buf, n);
     }
   else SLtt_goto_rc (row, (int) (Cursor_c + n));
}


#define SPACE_CHAR (0x20 | (JNORMAL_COLOR << 8))

void SLtt_smart_puts(unsigned short *neww, unsigned short *oldd, int len, int row)
{
   register unsigned short *p, *q, *qmax, *pmax, *buf;
   unsigned short buffer[256];
   unsigned int n_spaces;
   unsigned short *space_match, *last_buffered_match;
#ifdef HP_GLITCH_CODE
   int handle_hp_glitch = 0;
#endif

   q = oldd; p = neww;
   qmax = oldd + len;
   pmax = p + len;

   /* Find out where to begin --- while they match, we are ok */
   while (1)
     {
	if (q == qmax) return;
#if SLANG_HAS_KANJI_SUPPORT
	if (*p & 0x80)
	  { /* new is kanji */
	     if ((*q & 0x80) && ((q + 1) < qmax))
	       { /* old is also kanji */
		  if (((0xFF & *q) != (0xFF & *p))
		      || ((0xFF & q[1]) != (0xFF & p[1])))
		    break; /* both kanji, but not match */

		  else
		    { /* kanji match ! */
		       if (!COLOR_EQS(*q, *p)) break;
		       q++; p++;
		       if (!COLOR_EQS(*q, *p)) break;
		       /* really match! */
		       q++; p++;
		       continue;
		    }
	       }
	     else break; /* old is not kanji */
	  }
	else
	  { /* new is not kanji */
	     if (*q & 0x80) break; /* old is kanji */
	  }
#endif
	if (!CHAR_EQS(*q, *p)) break;
	q++; p++;
     }

   /*position the cursor */
   SLtt_goto_rc (row, (int) (p - neww));

#ifdef HP_GLITCH_CODE
   if (Has_HP_Glitch)
     {
	unsigned short *qq = q;
	while (qq < qmax)
	  {
	     if (*qq & 0xFF00)
	       {
		  SLtt_normal_video ();
		  SLtt_del_eol ();
		  qmax = q;
		  handle_hp_glitch = 1;
		  break;
	       }
	     qq++;
	  }
     }
#endif
   /* Find where the last non-blank character on old/new screen is */

   while (qmax > q)
     {
	qmax--;
	if (!CHAR_EQS(*qmax, SPACE_CHAR))
	  {
	     qmax++;
	     break;
	  }
     }

   while (pmax > p)
     {
	pmax--;
	if (!CHAR_EQS(*pmax, SPACE_CHAR))
	  {
	     pmax++;
	     break;
	  }
     }

   last_buffered_match = buf = buffer;		       /* buffer is empty */

#ifdef HP_GLITCH_CODE
   if (handle_hp_glitch)
     {
	while (p < pmax)
	  {
	     *buf++ = *p++;
	  }
     }
#endif

   /* loop using overwrite then skip algorithm until done */
   while (1)
     {
	/* while they do not match and we do not hit a space, buffer them up */
	n_spaces = 0;
	while (p < pmax)
	  {
	     if (CHAR_EQS(*q,SPACE_CHAR) && CHAR_EQS(*p, SPACE_CHAR))
	       {
		  /* If *q is not a space, we would have to overwrite it.
		   * However, if *q is a space, then while *p is also one,
		   * we only need to skip over the blank field.
		   */
		  space_match = p;
		  p++; q++;
		  while ((p < pmax)
			 && CHAR_EQS(*q,SPACE_CHAR)
			 && CHAR_EQS(*p, SPACE_CHAR))
		    {
		       p++;
		       q++;
		    }
		  n_spaces = (unsigned int) (p - space_match);
		  break;
	       }
#if SLANG_HAS_KANJI_SUPPORT
	     if ((*p & 0x80) && ((p + 1) < pmax))
	       { /* new is kanji */
		  if (*q & 0x80)
		    { /* old is also kanji */
 			  if (((0xFF & *q) != (0xFF & *p))
			      || ((0xFF & q[1]) != (0xFF & p[1])))
			 {
			    /* both kanji, but not match */
			    *buf++ = *p++;
			    *buf++ = *p++;
			    q += 2;
			    continue;
			 }
		       else
			 { /* kanji match ? */
			    if (!COLOR_EQS(*q, *p) || !COLOR_EQS(*(q+1), *(p+1)))
			      {
				 /* code is match ,but color is diff */
				 *buf++ = *p++;
				 *buf++ = *p++;
				 continue;
			      }
			    /* really match ! */
			    break;
			 }
		    }
 		  else
		    { /* old is not kanji */
		       *buf++ = *p++;
		       *buf++ = *p++;
		       q += 2;
		       continue;
		    }
	       }
	     else
	       { /* new is not kanji */
 		  if (*q & 0x80)
		    { /* old is kanji */
		       *buf++ = *p++;
		       q++;
		       continue;
		    }
	       }
#endif

	     if (CHAR_EQS(*q, *p)) break;
	     *buf++ = *p++;
	     q++;
	  }
	*buf = 0;

	if (buf != buffer) send_attr_str (buffer);
	buf = buffer;

	if (n_spaces && (p < pmax))
	  {
	     forward_cursor (n_spaces, row);
	  }

	/* Now we overwrote what we could and cursor is placed at position
	 * of a possible match of new and old.  If this is the case, skip
	 * some more.
	 */
#if !SLANG_HAS_KANJI_SUPPORT
	while ((p < pmax) && CHAR_EQS(*p, *q))
	  {
	     *buf++ = *p++;
	     q++;
	  }
#else
	/* Kanji */
	while (p < pmax)
	  {
	     if ((*p & 0x80) && ((p + 1) < pmax))
	       { /* new is kanji */
		  if (*q & 0x80)
		    { /* old is also kanji */
		       if (((0xFF & *q) == (0xFF & *p))
			   && ((0xFF & q[1]) == (0xFF & p[1])))
			 {
			    /* kanji match ? */
			    if (!COLOR_EQS(*q, *p)
				|| !COLOR_EQS(q[1], p[1]))
			      break;

			    *buf++ = *p++;
			    q++;
			    if (p >= pmax)
			      {
				 *buf++ = SPACE_CHAR;
				 p++;
				 break;
			      }
			    else
			      {
				 *buf++ = *p++;
				 q++;
				 continue;
			      }
			 }
		       else break; /* both kanji, but not match */
		    }
		  else break; /* old is not kanji */
	       }
	     else
	       {  /* new is not kanji */
		  if (*q & 0x80) break; /* old is kanji */
		  if (!CHAR_EQS(*q, *p)) break;
		  *buf++ = *p++;
		  q++;
	       }
	  }
#endif
	last_buffered_match = buf;
	if (p >= pmax) break;

	/* jump to new position is it is greater than 5 otherwise
	 * let it sit in the buffer and output it later.
	 */
	if ((int) (buf - buffer) >= 5)
	  {
	     forward_cursor ((unsigned int) (buf - buffer), row);
	     last_buffered_match = buf = buffer;
	  }
     }

   if (buf != buffer)
     {
	if (q < qmax)
	  {
	     if ((buf == last_buffered_match)
		 && ((int) (buf - buffer) >= 5))
	       {
		  forward_cursor ((unsigned int) (buf - buffer), row);
	       }
	     else
	       {
		  *buf = 0;
		  send_attr_str (buffer);
	       }
	  }
     }
   if (q < qmax) SLtt_del_eol ();
   if (Automatic_Margins && (Cursor_c + 1 >= SLtt_Screen_Cols)) Cursor_Set = 0;
}


static void get_color_info (void)
{
   char *fg, *bg;

   SLtt_Use_Ansi_Colors = (NULL != getenv ("COLORTERM"));

   if (-1 == get_default_colors (&fg, &bg))
     return;

   /* Check to see if application has already set them. */
   if (Color_0_Modified)
     return;

   SLtt_set_color (0, NULL, fg, bg);
   SLtt_set_color (1, NULL, bg, fg);
}


/* termcap stuff */

#ifdef __unix__

#ifndef USE_TERMCAP
static char *Tbuf;
static char *Tstr_Buf;

#define tgetstr SLtt_tigetstr
#define tgetent SLtt_tigetent
#define TGETNUM(x) SLtt_tigetnum((x), &Tbuf)
#define TGETFLAG(x) SLtt_tigetflag((x), &Tbuf)
#else

extern char *tgetstr(char *, char **);
extern int tgetent(char *, char *);
extern int tgetnum(char *);
extern int tgetflag(char *);
static char Tstr_Buf[1024];
static char Tbuf[4096];

⌨️ 快捷键说明

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