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

📄 char_io.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 2 页
字号:
/* char_io.c - basic console input and output *//* *  GRUB  --  GRand Unified Bootloader *  Copyright (C) 1999,2000,2001,2002,2004  Free Software Foundation, Inc. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <shared.h>#include <term.h>#ifdef SUPPORT_HERCULES# include <hercules.h>#endif#ifdef SUPPORT_SERIAL# include <serial.h>#endif#ifndef STAGE1_5struct term_entry term_table[] =  {    {      "console",      0,      console_putchar,      console_checkkey,      console_getkey,      console_getxy,      console_gotoxy,      console_cls,      console_setcolorstate,      console_setcolor,      console_setcursor    },#ifdef SUPPORT_SERIAL    {      "serial",      /* A serial device must be initialized.  */      TERM_NEED_INIT,      serial_putchar,      serial_checkkey,      serial_getkey,      serial_getxy,      serial_gotoxy,      serial_cls,      serial_setcolorstate,      0,      0    },#endif /* SUPPORT_SERIAL */#ifdef SUPPORT_HERCULES    {      "hercules",      0,      hercules_putchar,      console_checkkey,      console_getkey,      hercules_getxy,      hercules_gotoxy,      hercules_cls,      hercules_setcolorstate,      hercules_setcolor,      hercules_setcursor    },      #endif /* SUPPORT_HERCULES */    /* This must be the last entry.  */    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }  };/* This must be console.  */struct term_entry *current_term = term_table;int max_lines = 24;int count_lines = -1;int use_pager = 1;#endifvoidprint_error (void){  if (errnum > ERR_NONE && errnum < MAX_ERR_NUM)#ifndef STAGE1_5    /* printf("\7\n %s\n", err_list[errnum]); */    printf ("\nError %u: %s\n", errnum, err_list[errnum]);#else /* STAGE1_5 */    printf ("Error %u\n", errnum);#endif /* STAGE1_5 */}char *convert_to_ascii (char *buf, int c,...){  unsigned long num = *((&c) + 1), mult = 10;  char *ptr = buf;#ifndef STAGE1_5  if (c == 'x' || c == 'X')    mult = 16;  if ((num & 0x80000000uL) && c == 'd')    {      num = (~num) + 1;      *(ptr++) = '-';      buf++;    }#endif  do    {      int dig = num % mult;      *(ptr++) = ((dig > 9) ? dig + 'a' - 10 : '0' + dig);    }  while (num /= mult);  /* reorder to correct direction!! */  {    char *ptr1 = ptr - 1;    char *ptr2 = buf;    while (ptr1 > ptr2)      {	int tmp = *ptr1;	*ptr1 = *ptr2;	*ptr2 = tmp;	ptr1--;	ptr2++;      }  }  return ptr;}voidgrub_putstr (const char *str){  while (*str)    grub_putchar (*str++);}voidgrub_printf (const char *format,...){  int *dataptr = (int *) &format;  char c, str[16];    dataptr++;  while ((c = *(format++)) != 0)    {      if (c != '%')	grub_putchar (c);      else	switch (c = *(format++))	  {#ifndef STAGE1_5	  case 'd':	  case 'x':	  case 'X':#endif	  case 'u':	    *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;	    grub_putstr (str);	    break;#ifndef STAGE1_5	  case 'c':	    grub_putchar ((*(dataptr++)) & 0xff);	    break;	  case 's':	    grub_putstr ((char *) *(dataptr++));	    break;#endif	  }    }}#ifndef STAGE1_5intgrub_sprintf (char *buffer, const char *format, ...){  /* XXX hohmuth     ugly hack -- should unify with printf() */  int *dataptr = (int *) &format;  char c, *ptr, str[16];  char *bp = buffer;  dataptr++;  while ((c = *format++) != 0)    {      if (c != '%')	*bp++ = c; /* putchar(c); */      else	switch (c = *(format++))	  {	  case 'd': case 'u': case 'x':	    *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;	    ptr = str;	    while (*ptr)	      *bp++ = *(ptr++); /* putchar(*(ptr++)); */	    break;	  case 'c': *bp++ = (*(dataptr++))&0xff;	    /* putchar((*(dataptr++))&0xff); */	    break;	  case 's':	    ptr = (char *) (*(dataptr++));	    while ((c = *ptr++) != 0)	      *bp++ = c; /* putchar(c); */	    break;	  }    }  *bp = 0;  return bp - buffer;}voidinit_page (void){  cls ();  grub_printf ("\n    GNU GRUB  version %s  (%dK lower / %dK upper memory)\n\n",	  version_string, mbi.mem_lower, mbi.mem_upper);}/* The number of the history entries.  */static int num_history = 0;/* Get the NOth history. If NO is less than zero or greater than or   equal to NUM_HISTORY, return NULL. Otherwise return a valid string.  */static char *get_history (int no){  if (no < 0 || no >= num_history)    return 0;  return (char *) HISTORY_BUF + MAX_CMDLINE * no;}/* Add CMDLINE to the history buffer.  */static voidadd_history (const char *cmdline, int no){  grub_memmove ((char *) HISTORY_BUF + MAX_CMDLINE * (no + 1),		(char *) HISTORY_BUF + MAX_CMDLINE * no,		MAX_CMDLINE * (num_history - no));  grub_strcpy ((char *) HISTORY_BUF + MAX_CMDLINE * no, cmdline);  if (num_history < HISTORY_SIZE)    num_history++;}static intreal_get_cmdline (char *prompt, char *cmdline, int maxlen,		  int echo_char, int readline){  /* This is a rather complicated function. So explain the concept.          A command-line consists of ``section''s. A section is a part of the     line which may be displayed on the screen, but a section is never     displayed with another section simultaneously.     Each section is basically 77 or less characters, but the exception     is the first section, which is 78 or less characters, because the     starting point is special. See below.     The first section contains a prompt and a command-line (or the     first part of a command-line when it is too long to be fit in the     screen). So, in the first section, the number of command-line     characters displayed is 78 minus the length of the prompt (or     less). If the command-line has more characters, `>' is put at the     position 78 (zero-origin), to inform the user of the hidden     characters.     Other sections always have `<' at the first position, since there     is absolutely a section before each section. If there is a section     after another section, this section consists of 77 characters and     `>' at the last position. The last section has 77 or less     characters and doesn't have `>'.     Each section other than the last shares some characters with the     previous section. This region is called ``margin''. If the cursor     is put at the magin which is shared by the first section and the     second, the first section is displayed. Otherwise, a displayed     section is switched to another section, only if the cursor is put     outside that section.  */  /* XXX: These should be defined in shared.h, but I leave these here,     until this code is freezed.  */#define CMDLINE_WIDTH	78#define CMDLINE_MARGIN	10    int xpos, lpos, c, section;  /* The length of PROMPT.  */  int plen;  /* The length of the command-line.  */  int llen;  /* The index for the history.  */  int history = -1;  /* The working buffer for the command-line.  */  char *buf = (char *) CMDLINE_BUF;  /* The kill buffer.  */  char *kill_buf = (char *) KILL_BUF;    /* Nested function definitions for code simplicity.  */  /* The forward declarations of nested functions are prefixed     with `auto'.  */  auto void cl_refresh (int full, int len);  auto void cl_backward (int count);  auto void cl_forward (int count);  auto void cl_insert (const char *str);  auto void cl_delete (int count);  auto void cl_init (void);    /* Move the cursor backward.  */  void cl_backward (int count)    {      lpos -= count;            /* If the cursor is in the first section, display the first section	 instead of the second.  */      if (section == 1 && plen + lpos < CMDLINE_WIDTH)	cl_refresh (1, 0);      else if (xpos - count < 1)	cl_refresh (1, 0);      else	{	  xpos -= count;	  if (current_term->flags & TERM_DUMB)	    {	      int i;	      	      for (i = 0; i < count; i++)		grub_putchar ('\b');	    }	  else	    gotoxy (xpos, getxy () & 0xFF);	}    }  /* Move the cursor forward.  */  void cl_forward (int count)    {      lpos += count;      /* If the cursor goes outside, scroll the screen to the right.  */      if (xpos + count >= CMDLINE_WIDTH)	cl_refresh (1, 0);      else	{	  xpos += count;	  if (current_term->flags & TERM_DUMB)	    {	      int i;	      	      for (i = lpos - count; i < lpos; i++)		{		  if (! echo_char)		    grub_putchar (buf[i]);		  else		    grub_putchar (echo_char);		}	    }	  else	    gotoxy (xpos, getxy () & 0xFF);	}    }  /* Refresh the screen. If FULL is true, redraw the full line, otherwise,     only LEN characters from LPOS.  */  void cl_refresh (int full, int len)    {      int i;      int start;      int pos = xpos;            if (full)	{	  /* Recompute the section number.  */	  if (lpos + plen < CMDLINE_WIDTH)	    section = 0;	  else	    section = ((lpos + plen - CMDLINE_WIDTH)		       / (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) + 1);	  /* From the start to the end.  */	  len = CMDLINE_WIDTH;	  pos = 0;	  grub_putchar ('\r');	  /* If SECTION is the first section, print the prompt, otherwise,	     print `<'.  */	  if (section == 0)	    {	      grub_printf ("%s", prompt);	      len -= plen;	      pos += plen;	    }	  else	    {	      grub_putchar ('<');	      len--;	      pos++;	    }	}      /* Compute the index to start writing BUF and the resulting position	 on the screen.  */      if (section == 0)	{	  int offset = 0;	  	  if (! full)	    offset = xpos - plen;	  	  start = 0;	  xpos = lpos + plen;	  start += offset;	}      else	{	  int offset = 0;	  	  if (! full)	    offset = xpos - 1;	  	  start = ((section - 1) * (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN)		   + CMDLINE_WIDTH - plen - CMDLINE_MARGIN);	  xpos = lpos + 1 - start;	  start += offset;	}      /* Print BUF. If ECHO_CHAR is not zero, put it instead.  */      for (i = start; i < start + len && i < llen; i++)	{	  if (! echo_char)	    grub_putchar (buf[i]);	  else	    grub_putchar (echo_char);	  pos++;	}            /* Fill up the rest of the line with spaces.  */      for (; i < start + len; i++)	{	  grub_putchar (' ');	  pos++;	}            /* If the cursor is at the last position, put `>' or a space,	 depending on if there are more characters in BUF.  */      if (pos == CMDLINE_WIDTH)	{	  if (start + len < llen)	    grub_putchar ('>');	  else	    grub_putchar (' ');	  	  pos++;	}            /* Back to XPOS.  */      if (current_term->flags & TERM_DUMB)	{	  for (i = 0; i < pos - xpos; i++)	    grub_putchar ('\b');	}      else	gotoxy (xpos, getxy () & 0xFF);    }  /* Initialize the command-line.  */  void cl_init (void)    {      /* Distinguish us from other lines and error messages!  */      grub_putchar ('\n');      /* Print full line and set position here.  */      cl_refresh (1, 0);    }  /* Insert STR to BUF.  */  void cl_insert (const char *str)    {      int l = grub_strlen (str);      if (llen + l < maxlen)	{	  if (lpos == llen)	    grub_memmove (buf + lpos, str, l + 1);	  else	    {	      grub_memmove (buf + lpos + l, buf + lpos, llen - lpos + 1);	      grub_memmove (buf + lpos, str, l);	    }	  	  llen += l;	  lpos += l;	  if (xpos + l >= CMDLINE_WIDTH)	    cl_refresh (1, 0);	  else if (xpos + l + llen - lpos > CMDLINE_WIDTH)	    cl_refresh (0, CMDLINE_WIDTH - xpos);	  else	    cl_refresh (0, l + llen - lpos);	}    }  /* Delete COUNT characters in BUF.  */  void cl_delete (int count)    {      grub_memmove (buf + lpos, buf + lpos + count, llen - count + 1);      llen -= count;            if (xpos + llen + count - lpos > CMDLINE_WIDTH)	cl_refresh (0, CMDLINE_WIDTH - xpos);      else	cl_refresh (0, llen + count - lpos);    }  plen = grub_strlen (prompt);  llen = grub_strlen (cmdline);  if (maxlen > MAX_CMDLINE)    {      maxlen = MAX_CMDLINE;      if (llen >= MAX_CMDLINE)	{	  llen = MAX_CMDLINE - 1;	  cmdline[MAX_CMDLINE] = 0;	}    }  lpos = llen;  grub_strcpy (buf, cmdline);  cl_init ();  while ((c = ASCII_CHAR (getkey ())) != '\n' && c != '\r')    {      /* If READLINE is non-zero, handle readline-like key bindings.  */      if (readline)	{	  switch (c)	    {	    case 9:		/* TAB lists completions */	      {		int i;		/* POS points to the first space after a command.  */		int pos = 0;		int ret;		char *completion_buffer = (char *) COMPLETION_BUF;		int equal_pos = -1;		int is_filename;		/* Find the first word.  */		while (buf[pos] == ' ')		  pos++;		while (buf[pos] && buf[pos] != '=' && buf[pos] != ' ')		  pos++;		is_filename = (lpos > pos);		/* Find the position of the equal character after a		   command, and replace it with a space.  */		for (i = pos; buf[i] && buf[i] != ' '; i++)		  if (buf[i] == '=')		    {		      equal_pos = i;		      buf[i] = ' ';		      break;		    }		/* Find the position of the first character in this		   word.  */		for (i = lpos; i > 0 && buf[i - 1] != ' '; i--)		  ;		/* Invalidate the cache, because the user may exchange		   removable disks.  */		buf_drive = -1;		/* Copy this word to COMPLETION_BUFFER and do the		   completion.  */		grub_memmove (completion_buffer, buf + i, lpos - i);		completion_buffer[lpos - i] = 0;		ret = print_completions (is_filename, 1);		errnum = ERR_NONE;		if (ret >= 0)		  {		    /* Found, so insert COMPLETION_BUFFER.  */		    cl_insert (completion_buffer + lpos - i);		    if (ret > 0)		      {			/* There are more than one candidates, so print			   the list.  */			grub_putchar ('\n');			print_completions (is_filename, 0);			errnum = ERR_NONE;		      }		  }		/* Restore the command-line.  */		if (equal_pos >= 0)		  buf[equal_pos] = '=';		if (ret)		  cl_init ();	      }	      break;	    case 1:		/* C-a go to beginning of line */	      cl_backward (lpos);	      break;	    case 5:		/* C-e go to end of line */	      cl_forward (llen - lpos);	      break;	    case 6:		/* C-f forward one character */	      if (lpos < llen)		cl_forward (1);

⌨️ 快捷键说明

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