📄 console.c
字号:
if (s != active_console) return; vga_fill_rect(s->ds, 0, 0, s->ds->width, s->ds->height, color_table[0][COLOR_BLACK]); y1 = s->y_displayed; for(y = 0; y < s->height; y++) { c = s->cells + y1 * s->width; for(x = 0; x < s->width; x++) { vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib)); c++; } if (++y1 == s->total_height) y1 = 0; } dpy_update(s->ds, 0, 0, s->ds->width, s->ds->height); console_show_cursor(s, 1);}static void console_scroll(int ydelta){ TextConsole *s; int i, y1; s = active_console; if (!s || !s->text_console) return; if (ydelta > 0) { for(i = 0; i < ydelta; i++) { if (s->y_displayed == s->y_base) break; if (++s->y_displayed == s->total_height) s->y_displayed = 0; } } else { ydelta = -ydelta; i = s->backscroll_height; if (i > s->total_height - s->height) i = s->total_height - s->height; y1 = s->y_base - i; if (y1 < 0) y1 += s->total_height; for(i = 0; i < ydelta; i++) { if (s->y_displayed == y1) break; if (--s->y_displayed < 0) s->y_displayed = s->total_height - 1; } } console_refresh(s);}static void console_put_lf(TextConsole *s){ TextCell *c; int x, y1; s->x = 0; s->y++; if (s->y >= s->height) { s->y = s->height - 1; if (s->y_displayed == s->y_base) { if (++s->y_displayed == s->total_height) s->y_displayed = 0; } if (++s->y_base == s->total_height) s->y_base = 0; if (s->backscroll_height < s->total_height) s->backscroll_height++; y1 = (s->y_base + s->height - 1) % s->total_height; c = &s->cells[y1 * s->width]; for(x = 0; x < s->width; x++) { c->ch = ' '; c->t_attrib = s->t_attrib_default; c++; } if (s == active_console && s->y_displayed == s->y_base) { vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0, s->width * FONT_WIDTH, (s->height - 1) * FONT_HEIGHT); vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT, s->width * FONT_WIDTH, FONT_HEIGHT, color_table[0][s->t_attrib_default.bgcol]); dpy_update(s->ds, 0, 0, s->width * FONT_WIDTH, s->height * FONT_HEIGHT); } }}/* Set console attributes depending on the current escape codes. * NOTE: I know this code is not very efficient (checking every color for it * self) but it is more readable and better maintainable. */static void console_handle_escape(TextConsole *s){ int i; if (s->nb_esc_params == 0) { /* ESC[m sets all attributes to default */ s->t_attrib = s->t_attrib_default; return; } for (i=0; i<s->nb_esc_params; i++) { switch (s->esc_params[i]) { case 0: /* reset all console attributes to default */ s->t_attrib = s->t_attrib_default; break; case 1: s->t_attrib.bold = 1; break; case 4: s->t_attrib.uline = 1; break; case 5: s->t_attrib.blink = 1; break; case 7: s->t_attrib.invers = 1; break; case 8: s->t_attrib.unvisible = 1; break; case 22: s->t_attrib.bold = 0; break; case 24: s->t_attrib.uline = 0; break; case 25: s->t_attrib.blink = 0; break; case 27: s->t_attrib.invers = 0; break; case 28: s->t_attrib.unvisible = 0; break; /* set foreground color */ case 30: s->t_attrib.fgcol=COLOR_BLACK; break; case 31: s->t_attrib.fgcol=COLOR_RED; break; case 32: s->t_attrib.fgcol=COLOR_GREEN; break; case 33: s->t_attrib.fgcol=COLOR_YELLOW; break; case 34: s->t_attrib.fgcol=COLOR_BLUE; break; case 35: s->t_attrib.fgcol=COLOR_MAGENTA; break; case 36: s->t_attrib.fgcol=COLOR_CYAN; break; case 37: s->t_attrib.fgcol=COLOR_WHITE; break; /* set background color */ case 40: s->t_attrib.bgcol=COLOR_BLACK; break; case 41: s->t_attrib.bgcol=COLOR_RED; break; case 42: s->t_attrib.bgcol=COLOR_GREEN; break; case 43: s->t_attrib.bgcol=COLOR_YELLOW; break; case 44: s->t_attrib.bgcol=COLOR_BLUE; break; case 45: s->t_attrib.bgcol=COLOR_MAGENTA; break; case 46: s->t_attrib.bgcol=COLOR_CYAN; break; case 47: s->t_attrib.bgcol=COLOR_WHITE; break; } }}static void console_putchar(TextConsole *s, int ch){ TextCell *c; int y1, i, x; switch(s->state) { case TTY_STATE_NORM: switch(ch) { case '\r': /* carriage return */ s->x = 0; break; case '\n': /* newline */ console_put_lf(s); break; case '\b': /* backspace */ if(s->x > 0) s->x--; y1 = (s->y_base + s->y) % s->total_height; c = &s->cells[y1 * s->width + s->x]; c->ch = ' '; c->t_attrib = s->t_attrib; update_xy(s, s->x, s->y); break; case '\t': /* tabspace */ if (s->x + (8 - (s->x % 8)) > s->width) { console_put_lf(s); } else { s->x = s->x + (8 - (s->x % 8)); } break; case '\a': /* alert aka. bell */ /* TODO: has to be implemented */ break; case 27: /* esc (introducing an escape sequence) */ s->state = TTY_STATE_ESC; break; default: y1 = (s->y_base + s->y) % s->total_height; c = &s->cells[y1 * s->width + s->x]; c->ch = ch; c->t_attrib = s->t_attrib; update_xy(s, s->x, s->y); s->x++; if (s->x >= s->width) console_put_lf(s); break; } break; case TTY_STATE_ESC: /* check if it is a terminal escape sequence */ if (ch == '[') { for(i=0;i<MAX_ESC_PARAMS;i++) s->esc_params[i] = 0; s->nb_esc_params = 0; s->state = TTY_STATE_CSI; } else { s->state = TTY_STATE_NORM; } break; case TTY_STATE_CSI: /* handle escape sequence parameters */ if (ch >= '0' && ch <= '9') { if (s->nb_esc_params < MAX_ESC_PARAMS) { s->esc_params[s->nb_esc_params] = s->esc_params[s->nb_esc_params] * 10 + ch - '0'; } } else { s->nb_esc_params++; if (ch == ';') break; s->state = TTY_STATE_NORM; switch(ch) { case 'D': if (s->x > 0) s->x--; break; case 'C': if (s->x < (s->width - 1)) s->x++; break; case 'K': /* clear to eol */ y1 = (s->y_base + s->y) % s->total_height; for(x = s->x; x < s->width; x++) { c = &s->cells[y1 * s->width + x]; c->ch = ' '; c->t_attrib = s->t_attrib_default; c++; update_xy(s, x, s->y); } break; default: break; } console_handle_escape(s); break; } }}void console_select(unsigned int index){ TextConsole *s; if (index >= MAX_CONSOLES) return; s = consoles[index]; if (s) { active_console = s; if (s->text_console) { if (s->g_width != s->ds->width || s->g_height != s->ds->height) { s->g_width = s->ds->width; s->g_height = s->ds->height; text_console_resize(s); } console_refresh(s); } else { vga_hw_invalidate(); } }}static int console_puts(CharDriverState *chr, const uint8_t *buf, int len){ TextConsole *s = chr->opaque; int i; console_show_cursor(s, 0); for(i = 0; i < len; i++) { console_putchar(s, buf[i]); } console_show_cursor(s, 1); return len;}static void console_chr_add_read_handler(CharDriverState *chr, IOCanRWHandler *fd_can_read, IOReadHandler *fd_read, void *opaque){ TextConsole *s = chr->opaque; s->fd_read = fd_read; s->fd_opaque = opaque;}static void console_send_event(CharDriverState *chr, int event){ TextConsole *s = chr->opaque; int i; if (event == CHR_EVENT_FOCUS) { for(i = 0; i < nb_consoles; i++) { if (consoles[i] == s) { console_select(i); break; } } }}/* called when an ascii key is pressed */void kbd_put_keysym(int keysym){ TextConsole *s; uint8_t buf[16], *q; int c; s = active_console; if (!s || !s->text_console) return; switch(keysym) { case QEMU_KEY_CTRL_UP: console_scroll(-1); break; case QEMU_KEY_CTRL_DOWN: console_scroll(1); break; case QEMU_KEY_CTRL_PAGEUP: console_scroll(-10); break; case QEMU_KEY_CTRL_PAGEDOWN: console_scroll(10); break; default: if (s->fd_read) { /* convert the QEMU keysym to VT100 key string */ q = buf; if (keysym >= 0xe100 && keysym <= 0xe11f) { *q++ = '\033'; *q++ = '['; c = keysym - 0xe100; if (c >= 10) *q++ = '0' + (c / 10); *q++ = '0' + (c % 10); *q++ = '~'; } else if (keysym >= 0xe120 && keysym <= 0xe17f) { *q++ = '\033'; *q++ = '['; *q++ = keysym & 0xff; } else { *q++ = keysym; } s->fd_read(s->fd_opaque, buf, q - buf); } break; }}static TextConsole *new_console(DisplayState *ds, int text){ TextConsole *s; int i; if (nb_consoles >= MAX_CONSOLES) return NULL; s = qemu_mallocz(sizeof(TextConsole)); if (!s) { return NULL; } if (!active_console || (active_console->text_console && !text)) active_console = s; s->ds = ds; s->text_console = text; if (text) { consoles[nb_consoles++] = s; } else { /* HACK: Put graphical consoles before text consoles. */ for (i = nb_consoles; i > 0; i--) { if (!consoles[i - 1]->text_console) break; consoles[i] = consoles[i - 1]; } consoles[i] = s; } return s;}TextConsole *graphic_console_init(DisplayState *ds, vga_hw_update_ptr update, vga_hw_invalidate_ptr invalidate, vga_hw_screen_dump_ptr screen_dump, void *opaque){ TextConsole *s; s = new_console(ds, 0); if (!s) return NULL; s->hw_update = update; s->hw_invalidate = invalidate; s->hw_screen_dump = screen_dump; s->hw = opaque; return s;}int is_graphic_console(void){ return !active_console->text_console;}CharDriverState *text_console_init(DisplayState *ds){ CharDriverState *chr; TextConsole *s; int i,j; static int color_inited; chr = qemu_mallocz(sizeof(CharDriverState)); if (!chr) return NULL; s = new_console(ds, 1); if (!s) { free(chr); return NULL; } chr->opaque = s; chr->chr_write = console_puts; chr->chr_add_read_handler = console_chr_add_read_handler; chr->chr_send_event = console_send_event; if (!color_inited) { color_inited = 1; for(j = 0; j < 2; j++) { for(i = 0; i < 8; i++) { color_table[j][i] = col_expand(s->ds, vga_get_color(s->ds, color_table_rgb[j][i])); } } } s->y_displayed = 0; s->y_base = 0; s->total_height = DEFAULT_BACKSCROLL; s->x = 0; s->y = 0; s->g_width = s->ds->width; s->g_height = s->ds->height; /* Set text attribute defaults */ s->t_attrib_default.bold = 0; s->t_attrib_default.uline = 0; s->t_attrib_default.blink = 0; s->t_attrib_default.invers = 0; s->t_attrib_default.unvisible = 0; s->t_attrib_default.fgcol = COLOR_WHITE; s->t_attrib_default.bgcol = COLOR_BLACK; /* set current text attributes to default */ s->t_attrib = s->t_attrib_default; text_console_resize(s); return chr;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -