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

📄 ansicon_write.c

📁 linux syslinux source code
💻 C
字号:
#ident "$Id: ansicon_write.c,v 1.9 2005/01/05 07:45:23 hpa Exp $"/* ----------------------------------------------------------------------- * *    *   Copyright 2004 H. Peter Anvin - All Rights Reserved * *   Permission is hereby granted, free of charge, to any person *   obtaining a copy of this software and associated documentation *   files (the "Software"), to deal in the Software without *   restriction, including without limitation the rights to use, *   copy, modify, merge, publish, distribute, sublicense, and/or *   sell copies of the Software, and to permit persons to whom *   the Software is furnished to do so, subject to the following *   conditions: *    *   The above copyright notice and this permission notice shall *   be included in all copies or substantial portions of the Software. *    *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *   OTHER DEALINGS IN THE SOFTWARE. * * ----------------------------------------------------------------------- *//* * ansicon_write.c * * Write to the screen using ANSI control codes (about as capable as * DOS' ANSI.SYS.) */#include <errno.h>#include <string.h>#include <com32.h>#include <minmax.h>#include <klibc/compiler.h>#include "file.h"struct curxy {  uint8_t x, y;} __attribute__((packed));#define BIOS_CURXY ((struct curxy *)0x450) /* Array for each page */#define BIOS_ROWS (*(uint8_t *)0x484)      /* Minus one; if zero use 24 (= 25 lines) */#define BIOS_COLS (*(uint16_t *)0x44A)#define BIOS_PAGE (*(uint8_t *)0x462)enum ansi_state {  st_init,			/* Normal (no ESC seen) */  st_esc,			/* ESC seen */  st_csi,			/* CSI seen */};#define MAX_PARMS	16struct term_state {  int disabled;  int attr;			/* Current display attribute */  int vtgraphics;		/* VT graphics on/off */  int intensity;  int underline;  int blink;  int reverse;  int fg;  int bg;  int autocr;  struct curxy saved_xy;  uint16_t cursor_type;  enum ansi_state state;  int pvt;			/* Private code? */  int nparms;			/* Number of parameters seen */  int parms[MAX_PARMS];};static const struct term_state default_state ={  .disabled = 0,  .attr = 0x07,			/* Grey on black */  .vtgraphics = 0,  .intensity = 1,  .underline = 0,  .blink = 0,  .reverse = 0,  .fg = 7,  .bg = 0,  .autocr = 0,  .saved_xy = { 0, 0 },  .cursor_type = 0x0607,  .state = st_init,  .pvt = 0,  .nparms = 0,};static struct term_state st;/* DEC VT graphics to codepage 437 table (characters 0x60-0x7F only) */static const char decvt_to_cp437[] =  { 0004, 0261, 0007, 0007, 0007, 0007, 0370, 0361, 0007, 0007, 0331, 0277, 0332, 0300, 0305, 0304,    0304, 0304, 0137, 0137, 0303, 0264, 0301, 0302, 0263, 0363, 0362, 0343, 0330, 0234, 0007, 00 };/* Common setup */static void __constructor ansicon_init(void){  static com32sys_t ireg;	/* Auto-initalized to all zero */  com32sys_t oreg;  /* Initial state */  memcpy(&st, &default_state, sizeof st);  /* Are we disabled? */  ireg.eax.w[0] = 0x000b;  __intcall(0x22, &ireg, &oreg);  if ( (signed char)oreg.ebx.b[1] < 0 ) {    st.disabled = 1;    return;  }  /* Force text mode */  ireg.eax.w[0] = 0x0005;  __intcall(0x22, &ireg, NULL);  /* Get cursor shape */  ireg.eax.b[1] = 0x03;  ireg.ebx.b[1] = BIOS_PAGE;  __intcall(0x10, &ireg, &oreg);  st.cursor_type = oreg.ecx.w[0];}/* Erase a region of the screen */static void ansicon_erase(int x0, int y0, int x1, int y1){  static com32sys_t ireg;    ireg.eax.w[0] = 0x0600;	/* Clear window */  ireg.ebx.b[1] = st.attr;	/* Fill with current attribute */  ireg.ecx.b[0] = x0;  ireg.ecx.b[1] = y0;  ireg.edx.b[0] = x1;  ireg.edx.b[1] = y1;  __intcall(0x10, &ireg, NULL);}/* Show or hide the cursor */static void showcursor(int yes){  static com32sys_t ireg;  ireg.eax.b[1] = 0x01;  ireg.ecx.w[0] = yes ? st.cursor_type : 0x2020;  __intcall(0x10, &ireg, NULL);}static void ansicon_putchar(int ch){  static com32sys_t ireg;  const int rows  = BIOS_ROWS ? BIOS_ROWS+1 : 25;  const int cols  = BIOS_COLS;  const int page  = BIOS_PAGE;  struct curxy xy = BIOS_CURXY[page];  switch ( st.state ) {  case st_init:    switch ( ch ) {    case '\b':      if ( xy.x > 0 ) xy.x--;      break;    case '\t':      {	int nsp = 8 - (xy.x & 7);	while ( nsp-- )	  ansicon_putchar(' ');      }      return;			/* Cursor already updated */    case '\n':    case '\v':    case '\f':      xy.y++;      if ( st.autocr )	xy.x = 0;      break;    case '\r':      xy.x = 0;      break;    case 127:      /* Ignore delete */      break;    case 14:      st.vtgraphics = 1;      break;    case 15:      st.vtgraphics = 0;      break;    case 27:      st.state = st_esc;      break;    default:      /* Print character */      if ( ch >= 32 ) {	if ( st.vtgraphics && (ch & 0xe0) == 0x60 )	  ch = decvt_to_cp437[ch - 0x60];	ireg.eax.b[1] = 0x09;	ireg.eax.b[0] = ch;	ireg.ebx.b[1] = page;	ireg.ebx.b[0] = st.attr;	ireg.ecx.w[0] = 1;	__intcall(0x10, &ireg, NULL);	xy.x++;      }      break;    }    break;        case st_esc:    switch ( ch ) {    case '%':    case '(':    case ')':    case '#':      /* Ignore this plus the subsequent character, allows	 compatibility with Linux sequence to set charset */      break;    case '[':      st.state = st_csi;      st.nparms = st.pvt = 0;      memset(st.parms, 0, sizeof st.parms);      break;    case 'c':      /* Reset terminal */      memcpy(&st, &default_state, sizeof st);      ansicon_erase(0, 0, cols-1, rows-1);      xy.x = xy.y = 1;      break;    default:      /* Ignore sequence */      st.state = st_init;      break;    }    break;        case st_csi:    {      int p0 = st.parms[0] ? st.parms[0] : 1;      if ( ch >= '0' && ch <= '9' ) {	st.parms[st.nparms] = st.parms[st.nparms]*10 + (ch-'0');      } else if ( ch == ';' ) {	st.nparms++;	if ( st.nparms >= MAX_PARMS )	  st.nparms = MAX_PARMS-1;	break;      } else if ( ch == '?' ) {	st.pvt = 1;      } else {	switch ( ch ) {	case 'A':	  {	    int y = xy.y - p0;	    xy.y = (y < 0) ? 0 : y;	  }	  break;	case 'B':	  {	    int y = xy.y + p0;	    xy.y = (y >= rows) ? rows-1 : y;	  }	  break;	case 'C':	  {	    int x = xy.x + p0;	    xy.x = (x >= cols) ? cols-1 : x;	  }	  break;	case 'D':	  {	    int x = xy.x - p0;	    xy.x = (x < 0) ? 0 : x;	  }	  break;	case 'E':	  {	    int y = xy.y + p0;	    xy.y = (y >= rows) ? rows-1 : y;	    xy.x = 0;	  }	  break;	case 'F':	  {	    int y = xy.y - p0;	    xy.y = (y < 0) ? 0 : y;	    xy.x = 0;	  }	  break;	case 'G':	case '\'':	  {	    int x = st.parms[0] - 1;	    xy.x = (x >= cols) ? cols-1 : (x < 0) ? 0 : x;	  }	  break;	case 'H':	case 'f':	  {	    int y = st.parms[0] - 1;	    int x = st.parms[1] - 1;	    xy.x = (x >= cols) ? cols-1 : (x < 0) ? 0 : x;	    xy.y = (y >= rows) ? rows-1 : (y < 0) ? 0 : y;	  }	  break;	case 'J':	  {	    switch ( st.parms[0] ) {	    case 0:	      ansicon_erase(xy.x, xy.y, cols-1, xy.y);	      if ( xy.y < rows-1 )		ansicon_erase(0, xy.y+1, cols-1, rows-1);	      break;	    case 1:	      if ( xy.y > 0 )		ansicon_erase(0, 0, cols-1, xy.y-1);	      if ( xy.y > 0 )		ansicon_erase(0, xy.y, xy.x-1, xy.y);	      break;	    case 2:	      ansicon_erase(0, 0, cols-1, rows-1);	      break;	    default:	      /* Ignore */	      break;	    }	  }	  break;	case 'K':	  {	    switch ( st.parms[0] ) {	    case 0:	      ansicon_erase(xy.x, xy.y, cols-1, xy.y);	      break;	    case 1:	      if ( xy.x > 0 )		ansicon_erase(0, xy.y, xy.x-1, xy.y);	      break;	    case 2:	      ansicon_erase(0, xy.y, cols-1, xy.y);	      break;	  	    default:	      /* Ignore */	      break;	    }	  }	  break;	case 'h':	case 'l':	  {	    int set = (ch == 'h');	    switch ( st.parms[0] ) {	    case 20:	      st.autocr = set;	      break;	    case 25:	      showcursor(set);	      break;	    default:	      /* Ignore */	      break;	    }	  }	  break;	case 'm':	  {	    static const int ansi2pc[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };	    int i;	    for ( i = 0 ; i <= st.nparms ; i++ ) {	      int a = st.parms[i];	      switch ( a ) {	      case 0:		st.fg = 7;		st.bg = 0;		st.intensity = 1;		st.underline = 0;		st.blink = 0;		st.reverse = 0;		break;	      case 1:		st.intensity = 2;		break;	      case 2:		st.intensity = 0;		break;	      case 4:		st.underline = 1;		break;	      case 5:		st.blink = 1;		break;	      case 7:		st.reverse = 1;		break;	      case 21:	      case 22:		st.intensity = 1;		break;	      case 24:		st.underline = 0;		break;	      case 25:		st.blink = 0;		break;	      case 27:		st.reverse = 0;		break;	      case 30 ... 37:		st.fg = ansi2pc[a-30];		break;	      case 38:		st.fg = 7;		st.underline = 1;		break;	      case 39:		st.fg = 7;		st.underline = 0;		break;	      case 40 ... 47:		st.bg = ansi2pc[a-40];		break;	      case 49:		st.bg = 7;		break;	      default:		/* Do nothing */		break;	      }	    }	  	    /* Turn into an attribute code */	    {	      int bg = st.bg;	      int fg;	      if ( st.underline )		fg = 0x01;	      else if ( st.intensity == 0 )		fg = 0x08;	      else		fg = st.fg;	      if ( st.reverse ) {		bg = fg & 0x07;		fg &= 0x08;		fg |= st.bg;	      }	      if ( st.blink )		bg ^= 0x08;	      if ( st.intensity == 2 )		fg ^= 0x08;	      st.attr = (bg << 4) | fg;	    }	  }	  break;	case 's':	  st.saved_xy = xy;	  break;	case 'u':	  xy = st.saved_xy;	  break;	default:		/* Includes CAN and SUB */	  break;		/* Drop unknown sequence */	}	st.state = st_init;      }    }    break;  }  /* If we fell off the end of the screen, adjust */  if ( xy.x >= cols ) {    xy.x = 0;    xy.y++;  }  while ( xy.y >= rows ) {    xy.y--;    ireg.eax.w[0] = 0x0601;    ireg.ebx.b[1] = st.attr;    ireg.ecx.w[0] = 0;    ireg.edx.b[1] = rows-1;    ireg.edx.b[0] = cols-1;    __intcall(0x10, &ireg, NULL); /* Scroll */  }  /* Update cursor position */  ireg.eax.b[1] = 0x02;  ireg.ebx.b[1] = page;  ireg.edx.b[1] = xy.y;  ireg.edx.b[0] = xy.x;  __intcall(0x10, &ireg, NULL);}	      ssize_t __ansicon_write(struct file_info *fp, const void *buf, size_t count){  const unsigned char *bufp = buf;  size_t n = 0;  (void)fp;  if ( st.disabled )    return n;			/* Nothing to do */  while ( count-- ) {    ansicon_putchar(*bufp++);    n++;  }  return n;}const struct output_dev dev_ansicon_w = {  .dev_magic  = __DEV_MAGIC,  .flags      = __DEV_TTY | __DEV_OUTPUT,  .fileflags  = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND,  .write      = __ansicon_write,  .close      = NULL,};

⌨️ 快捷键说明

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