📄 char_io.c
字号:
/* 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, 24, console_putchar, console_checkkey, console_getkey, console_getxy, console_gotoxy, console_cls, console_setcolorstate, console_setcolor, console_setcursor, 0, 0 },#ifdef SUPPORT_SERIAL { "serial", /* A serial device must be initialized. */ TERM_NEED_INIT, 24, serial_putchar, serial_checkkey, serial_getkey, serial_getxy, serial_gotoxy, serial_cls, serial_setcolorstate, 0, 0, 0, 0 },#endif /* SUPPORT_SERIAL */#ifdef SUPPORT_HERCULES { "hercules", 0, 24, hercules_putchar, console_checkkey, console_getkey, hercules_getxy, hercules_gotoxy, hercules_cls, hercules_setcolorstate, hercules_setcolor, hercules_setcursor, 0, 0 }, #endif /* SUPPORT_HERCULES */#ifdef SUPPORT_GRAPHICS { "graphics", TERM_NEED_INIT, /* flags */ 30, /* number of lines */ graphics_putchar, /* putchar */ console_checkkey, /* checkkey */ console_getkey, /* getkey */ graphics_getxy, /* getxy */ graphics_gotoxy, /* gotoxy */ graphics_cls, /* cls */ graphics_setcolorstate, /* setcolorstate */ graphics_setcolor, /* setcolor */ graphics_setcursor, /* nocursor */ graphics_init, /* initialize */ graphics_end /* shutdown */ },#endif /* SUPPORT_GRAPHICS */ /* 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;#endifint quit_print = 0;voidprint_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 + c - 33 : '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++);}#if 1voidgrub_printf (const char *format,...){ int *dataptr = (int *)(void *) &format; char c, str[16]; char pad; int width; dataptr++; while ((c = *(format++)) != 0) { if (c != '%') grub_putchar (c); else { pad = ' '; width = 0; c = *(format++);#ifndef STAGE1_5find_specifier:#endif switch (c) {#ifndef STAGE1_5 case 'd': case 'x': case 'X':#endif case 'u': *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0; width -= grub_strlen (str); if (width > 0) while(width--) grub_putchar (pad); grub_putstr (str); break;#ifndef STAGE1_5 case 'c': if (width > 0) while(--width) grub_putchar (pad); grub_putchar ((*(dataptr++)) & 0xff); break; case 's': width -= grub_strlen ((char *) *(dataptr)); if (width > 0) while(width--) grub_putchar (pad); grub_putstr ((char *) *(dataptr++)); break; case '0': pad = '0'; case '1' ... '9': width = c - '0'; while ((c = *(format++)) >= '0' && c <= '9') { width = width * 10 + c - '0'; } /* format is now pointing to the non-numerical char */#if 1 goto find_specifier;#else switch (c) { case 'd': case 'x': case 'X': case 'u': *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0; width -= grub_strlen (str); if (width > 0) while(--width) grub_putchar (pad); grub_putstr (str); break; case 'c': if (width > 0) while(--width) grub_putchar (pad); grub_putchar ((*(dataptr++)) & 0xff); break; case 's': width -= grub_strlen ((char *) *(dataptr++)); if (width > 0) while(--width) grub_putchar (pad); grub_putstr ((char *) *(dataptr++)); break; }#endif#endif } } }}#elseintgrub_printf (const char *format,...){ /* sorry! this does not work :-( */ return grub_sprintf (NULL, format,...);}#endifintgrub_sprintf (char *buffer, const char *format, ...){ /* Call with buffer==NULL, and it will just printf(). */ /* XXX hohmuth ugly hack -- should unify with printf() */ int *dataptr = (int *)(void *) &format; char c, *ptr, str[16]; char *bp = buffer; dataptr++; while ((c = *(format++)) != 0) { if (c != '%') { if (buffer) *bp++ = c; /* putchar(c); */ else { grub_putchar (c); bp++; } } else switch (c = *(format++)) { case 'd': case 'x': case 'X': case 'u': *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0; ptr = str; if (buffer) { while (*ptr) *bp++ = *(ptr++); /* putchar(*(ptr++)); */ } else { while (*ptr) { grub_putchar (*(ptr++)); bp++; } } break; case 'c': if (buffer) { *bp++ = (*(dataptr++)) & 0xff; } else { grub_putchar ((*(dataptr++)) & 0xff); bp++; } break; case 's': ptr = (char *) (*(dataptr++)); if (buffer) { while ((c = *(ptr++)) != 0) *bp++ = c; /* putchar(c); */ } else { while ((c = *(ptr++)) != 0) { grub_putchar (c); bp++; } } break; } } if (buffer) *bp = 0; return bp - buffer;}#ifndef STAGE1_5#include "grub4dos_version.h"#ifdef GRUB4DOS_VERSIONvoidinit_page (void){ cls (); grub_printf ("GRUB4DOS " GRUB4DOS_VERSION /* ", GNU GRUB %s" */ ", Memory: %dK / %dM, CodeEnd: 0x%X\n", /* version_string, */ saved_mem_lower, saved_mem_upper / 1024, get_code_end());}#elsevoidinit_page (void){ cls (); grub_printf ("GNU GRUB version %s (%dK lower / %dK upper memory)\n", version_string, saved_mem_lower, saved_mem_upper);}#endif/* 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++;}/* 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 char *prompt;int maxlen;int echo_char;int readline;static int xpos, lpos, section;/* The length of PROMPT. */static int plen;/* The length of the command-line. */static int llen;/* The working buffer for the command-line. */static char *buf;static void cl_refresh (int full, int len);static void cl_backward (int count);static void cl_forward (int count);static void cl_insert (const char *str);static void cl_delete (int count);static void cl_init (void); /* Move the cursor backward. */static 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. */static 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. */static 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'); gotoxy (0, (unsigned char) (getxy ())); /* If SECTION is the first section, print the prompt, otherwise, print `<'. */ if (section == 0) { grub_printf ("%s", prompt); len -= plen; pos += plen; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -