📄 char_io.c
字号:
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. */static 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. */static 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. */static 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);}static intreal_get_cmdline (char *cmdline){ /* 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. */ int c; /* The index for the history. */ int history = -1; /* The kill buffer. */ char *kill_buf = (char *) KILL_BUF; buf = (char *) CMDLINE_BUF; 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 ((char)(c = /*ASCII_CHAR*/ (getkey ())) != '\n' && (char)c != '\r') { /* If READLINE is non-zero, handle readline-like key bindings. */ if (readline) { //switch (c) // { if ((char)c == 9) //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. */#if 0 for (i = lpos; i > 0 && buf[i - 1] != ' '; i--) ;#else for (i = lpos; i > 0; i--) { if (buf[i - 1] == ' ') { /* find backslashes immediately before the space */ for (ret = i - 2; ret >= 0; ret--) { if (buf[ret] != '\\') break; } if (! ((i - ret) & 1)) /* the space not backslashed */ break; } }#endif /* 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; else if (c == KEY_HOME || (char)c == 1) //case 1: /* C-a go to beginning of line */ cl_backward (lpos); //break; else if (c == KEY_END || (char)c == 5) //case 5: /* C-e go to end of line */ cl_forward (llen - lpos); //break; else if (c == KEY_RIGHT || (char)c == 6) //case 6: /* C-f forward one character */ { if (lpos < llen) cl_forward (1); } //break; else if (c == KEY_LEFT || (char)c == 2) //case 2: /* C-b backward one character */ { if (lpos > 0) cl_backward (1); } //break; else if ((char)c == 21) //case 21: /* C-u kill to beginning of line */ { if (lpos) { int count; /* Copy the string being deleted to KILL_BUF. */ grub_memmove (kill_buf, buf, lpos); kill_buf[lpos] = 0; /* XXX: Not very clever. */ count = lpos; cl_backward (lpos); cl_delete (count); } } //break; else if ((char)c == 11) //case 11: /* C-k kill to end of line */ { if (lpos != llen) { /* Copy the string being deleted to KILL_BUF. */ grub_memmove (kill_buf, buf + lpos, llen - lpos + 1); cl_delete (llen - lpos); } } //break; else if ((char)c == 25) //case 25: /* C-y yank the kill buffer */ cl_insert (kill_buf); //break; else if (c == KEY_UP || (char)c == 16) //case 16: /* C-p fetch the previous command */ { char *p; if (history < 0) /* Save the working buffer. */ grub_strcpy (cmdline, buf); else if (grub_strcmp (get_history (history), buf) != 0) /* If BUF is modified, add it into the history list. */ add_history (buf, history); history++; p = get_history (history); if (! p) { history--; } else { grub_strcpy (buf, p); llen = grub_strlen (buf); lpos = llen; cl_refresh (1, 0); } } //break; else if (c == KEY_DOWN || (char)c == 14) //case 14: /* C-n fetch the next command */ { char *p; if (history >= 0) { if (grub_strcmp (get_history (history), buf) != 0) /* If BUF is modified, add it into the history list. */ add_history (buf, history); history--; p = get_history (history); if (! p) p = cmdline; grub_strcpy (buf, p); llen = grub_strlen (buf); lpos = llen; cl_refresh (1, 0); } } //break; //} } /* ESC, C-d and C-h are always handled. Actually C-d is not functional if READLINE is zero, as the cursor cannot go backward, but that's ok. */ //switch (c) //{ if ((char)c == 27) //case 27: /* ESC immediately return 1 */ return 1; else if (c == KEY_DC || (char)c == 4) //case 4: /* C-d delete character under cursor */ { if (lpos != llen) cl_delete (1); } //break; else if ((char)c == 8 || c == KEY_BACKSPACE //case 8: /* C-h backspace */# ifdef GRUB_UTIL || (char)c == 127 //case KEY_BACKSPACE/*127*/: /* also backspace */# endif ) { if (lpos > 0) { cl_backward (1); cl_delete (1); } } //break; else //default: /* insert printable character into line */ { if ((char)c >= ' ' && (char)c <= '~') { char str[2]; str[0] = (char)c; str[1] = 0; cl_insert (str); } } //} } grub_putchar ('\n'); /* If ECHO_CHAR is NUL, remove the leading spaces. */ lpos = 0; if (! echo_char) while (buf[lpos] == ' ') lpos++; /* Copy the working buffer to CMDLINE. */ grub_memmove (cmdline, buf + lpos, llen - lpos + 1); /* If the readline-like feature is turned on and CMDLINE is not empty, add it into the history list. */ if (readline && lpos < llen) add_history (cmdline, 0); return 0;}/* Don't use this with a MAXLEN greater than 1600 or so! The problem is that GET_CMDLINE depends on the everything fitting on the screen at once. So, the whole screen is about 2000 characters, minus the PROMPT, and space for error and status lines, etc. MAXLEN must be at least 1, and PROMPT and CMDLINE must be valid strings (not NULL or zero-length). If ECHO_CHAR is nonzero, echo it instead of the typed character. */intget_cmdline (char *cmdline){ int old_cursor; int ret; old_cursor = setcursor (1); /* Because it is hard to deal with different conditions simultaneously, less functional cases are handled here. Assume that TERM_NO_ECHO implies TERM_NO_EDIT. */ if (current_term->flags & (TERM_NO_ECHO | TERM_NO_EDIT)) { char *p = cmdline; int c; /* Make sure that MAXLEN is not too large. */ if (maxlen > MAX_CMDLINE) maxlen = MAX_CMDLINE; /* Print only the prompt. The contents of CMDLINE is simply discarded, even if it is not empty. */ grub_printf ("%s", prompt); /* Gather characters until a newline is gotten. */ while ((c = ASCII_CHAR (getkey ())) != '\n' && c != '\r') { /* Return immediately if ESC is pressed. */ if (c == 27) { setcursor (old_cursor); return 1; } /* Printable characters are added into CMDLINE. */ if (c >= ' ' && c <= '~') { if (! (current_term->flags & TERM_NO_ECHO)) grub_putchar (c); /* Preceding space characters must be ignored. */ if (c != ' ' || p != cmdline) *p++ = c; } } *p = 0; if (! (current_term->flags & TERM_NO_ECHO)) grub_putchar ('\n'); setcursor (old_cursor); return 0; } /* Complicated features are left to real_get_cmdline. */ ret = real_get_cmdline (cmdline); setcursor (old_cursor); return ret;}intsafe_parse_maxint (char **str_ptr, int *myint_ptr){ char *ptr = *str_ptr; int myint = 0; int mult = 10, found = 0; int negative = 0; /* * The decimal numbers can be positive or negative, ranging from * 0x80000000(the minimal int) to 0x7fffffff(the maximal int). * The hex numbers are not checked. */ if (*ptr == '-') /* check whether or not the negative sign exists */ { ptr++; negative = 1; } /* * Is this a hex number? */ if (*ptr == '0' && tolower (*(ptr + 1)) == 'x') { ptr += 2; mult = 16;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -