📄 console.c
字号:
csi_J(currcons,par[0]); return; case 'K': csi_K(currcons,par[0]); return; case 'L': csi_L(currcons,par[0]); return; case 'M': csi_M(currcons,par[0]); return; case 'P': csi_P(currcons,par[0]); return; case 'c': if (!par[0]) respond_ID(tty); return; case 'g': if (!par[0]) tab_stop[x >> 5] &= ~(1 << (x & 31)); else if (par[0] == 3) { tab_stop[0] = tab_stop[1] = tab_stop[2] = tab_stop[3] = tab_stop[4] = 0; } return; case 'm': csi_m(currcons); return; case 'q': /* DECLL - but only 3 leds */ /* map 0,1,2,3 to 0,1,2,4 */ if (par[0] < 4) setledstate(kbd_table + currcons, (par[0] < 3) ? par[0] : 4); return; case 'r': if (!par[0]) par[0]++; if (!par[1]) par[1] = video_num_lines; /* Minimum allowed region is 2 lines */ if (par[0] < par[1] && par[1] <= video_num_lines) { top=par[0]-1; bottom=par[1]; gotoxay(currcons,0,0); } return; case 's': save_cur(currcons); return; case 'u': restore_cur(currcons); return; case 'X': csi_X(currcons, par[0]); return; case '@': csi_at(currcons,par[0]); return; case ']': /* setterm functions */ setterm_command(currcons); return; } return; case ESpercent: vc_state = ESnormal; switch (c) { case '@': /* defined in ISO 2022 */ utf = 0; return; case 'G': /* prelim official escape code */ case '8': /* retained for compatibility */ utf = 1; return; } return; case ESfunckey: vc_state = ESnormal; return; case EShash: vc_state = ESnormal; if (c == '8') { /* DEC screen alignment test. kludge :-) */ video_erase_char = (video_erase_char & 0xff00) | 'E'; csi_J(currcons, 2); video_erase_char = (video_erase_char & 0xff00) | ' '; do_update_region(currcons, origin, screenbuf_size/2); } return; case ESsetG0: if (c == '0') G0_charset = GRAF_MAP; else if (c == 'B') G0_charset = LAT1_MAP; else if (c == 'U') G0_charset = IBMPC_MAP; else if (c == 'K') G0_charset = USER_MAP; if (charset == 0) translate = set_translate(G0_charset,currcons); vc_state = ESnormal; return; case ESsetG1: if (c == '0') G1_charset = GRAF_MAP; else if (c == 'B') G1_charset = LAT1_MAP; else if (c == 'U') G1_charset = IBMPC_MAP; else if (c == 'K') G1_charset = USER_MAP; if (charset == 1) translate = set_translate(G1_charset,currcons); vc_state = ESnormal; return; default: vc_state = ESnormal; }}static int do_con_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count){#ifdef VT_BUF_VRAM_ONLY#define FLUSH do { } while(0);#else#define FLUSH if (draw_x >= 0) { \ sw->con_putcs(vc_cons[currcons].d, (u16 *)draw_from, (u16 *)draw_to-(u16 *)draw_from, y, draw_x); \ draw_x = -1; \ }#endif int c, tc, ok, n = 0, draw_x = -1; unsigned int currcons; unsigned long draw_from = 0, draw_to = 0; struct vt_struct *vt = (struct vt_struct *)tty->driver_data; u16 himask, charmask; currcons = vt->vc_num; if (!vc_cons_allocated(currcons)) { /* could this happen? */ static int error = 0; if (!error) { error = 1; printk("con_write: tty %d not allocated\n", currcons+1); } return 0; } if (from_user) { /* just to make sure that noone lurks at places he shouldn't see. */ if (verify_area(VERIFY_READ, buf, count)) return 0; /* ?? are error codes legal here ?? */ } himask = hi_font_mask; charmask = himask ? 0x1ff : 0xff; /* undraw cursor first */ if (IS_FG) hide_cursor(currcons); disable_bh(CONSOLE_BH); while (!tty->stopped && count) { enable_bh(CONSOLE_BH); if (from_user) __get_user(c, buf); else c = *buf; buf++; n++; count--; disable_bh(CONSOLE_BH); if (utf) { /* Combine UTF-8 into Unicode */ /* Incomplete characters silently ignored */ if(c > 0x7f) { if (utf_count > 0 && (c & 0xc0) == 0x80) { utf_char = (utf_char << 6) | (c & 0x3f); utf_count--; if (utf_count == 0) tc = c = utf_char; else continue; } else { if ((c & 0xe0) == 0xc0) { utf_count = 1; utf_char = (c & 0x1f); } else if ((c & 0xf0) == 0xe0) { utf_count = 2; utf_char = (c & 0x0f); } else if ((c & 0xf8) == 0xf0) { utf_count = 3; utf_char = (c & 0x07); } else if ((c & 0xfc) == 0xf8) { utf_count = 4; utf_char = (c & 0x03); } else if ((c & 0xfe) == 0xfc) { utf_count = 5; utf_char = (c & 0x01); } else utf_count = 0; continue; } } else { tc = c; utf_count = 0; } } else { /* no utf */ tc = translate[toggle_meta ? (c|0x80) : c]; } /* If the original code was a control character we * only allow a glyph to be displayed if the code is * not normally used (such as for cursor movement) or * if the disp_ctrl mode has been explicitly enabled. * Certain characters (as given by the CTRL_ALWAYS * bitmap) are always displayed as control characters, * as the console would be pretty useless without * them; to display an arbitrary font position use the * direct-to-font zone in UTF-8 mode. */ ok = tc && (c >= 32 || (!utf && !(((disp_ctrl ? CTRL_ALWAYS : CTRL_ACTION) >> c) & 1))) && (c != 127 || disp_ctrl) && (c != 128+27); if (vc_state == ESnormal && ok) { /* Now try to find out how to display it */ tc = conv_uni_to_pc(vc_cons[currcons].d, tc); if ( tc == -4 ) { /* If we got -4 (not found) then see if we have defined a replacement character (U+FFFD) */ tc = conv_uni_to_pc(vc_cons[currcons].d, 0xfffd); /* One reason for the -4 can be that we just did a clear_unimap(); try at least to show something. */ if (tc == -4) tc = c; } else if ( tc == -3 ) { /* Bad hash table -- hope for the best */ tc = c; } if (tc & ~charmask) continue; /* Conversion failed */ if (need_wrap || decim) FLUSH if (need_wrap) { cr(currcons); lf(currcons); } if (decim) insert_char(currcons, 1); scr_writew(himask ? ((attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : (attr << 8) + tc, (u16 *) pos); if (DO_UPDATE && draw_x < 0) { draw_x = x; draw_from = pos; } if (x == video_num_columns - 1) { need_wrap = decawm; draw_to = pos+2; } else { x++; draw_to = (pos+=2); } continue; } FLUSH do_con_trol(tty, currcons, c); } FLUSH enable_bh(CONSOLE_BH); return n;#undef FLUSH}/* * This is the console switching bottom half handler. * * Doing console switching in a bottom half handler allows * us to do the switches asynchronously (needed when we want * to switch due to a keyboard interrupt), while still giving * us the option to easily disable it to avoid races when we * need to write to the console. */static void console_bh(void){ run_task_queue(&con_task_queue); if (want_console >= 0) { if (want_console != fg_console && vc_cons_allocated(want_console)) { hide_cursor(fg_console); change_console(want_console); /* we only changed when the console had already been allocated - a new console is not created in an interrupt routine */ } want_console = -1; } if (do_poke_blanked_console) { /* do not unblank for a LED change */ do_poke_blanked_console = 0; poke_blanked_console(); } if (scrollback_delta) { int currcons = fg_console; clear_selection(); if (vcmode == KD_TEXT) sw->con_scrolldelta(vc_cons[currcons].d, scrollback_delta); scrollback_delta = 0; }}#ifdef CONFIG_VT_CONSOLE/* * Console on virtual terminal * * NOTE NOTE NOTE! This code can do no global locking. In particular, * we can't disable interrupts or bottom half handlers globally, because * we can be called from contexts that hold critical spinlocks, and * trying do get a global lock at this point will lead to deadlocks. */void vt_console_print(struct console *co, const char * b, unsigned count){ int currcons = fg_console; unsigned char c; static unsigned long printing = 0; const ushort *start; ushort cnt = 0; ushort myx = x; /* console busy or not yet initialized */ if (!printable || test_and_set_bit(0, &printing)) return; if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1)) currcons = kmsg_redirect - 1; if (!vc_cons_allocated(currcons)) { /* impossible */ printk("vt_console_print: tty %d not allocated ??\n", currcons+1); goto quit; } if (vcmode != KD_TEXT) goto quit; /* undraw cursor first */ if (IS_FG) hide_cursor(currcons); start = (ushort *)pos; /* Contrived structure to try to emulate original need_wrap behaviour * Problems caused when we have need_wrap set on '\n' character */ while (count--) { c = *b++; if (c == 10 || c == 13 || c == 8 || need_wrap) { if (cnt > 0) { if (IS_VISIBLE) sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x); x += cnt; if (need_wrap) x--; cnt = 0; } if (c == 8) { /* backspace */ bs(currcons); start = (ushort *)pos; myx = x; continue; } if (c != 13) lf(currcons); cr(currcons); start = (ushort *)pos; myx = x; if (c == 10 || c == 13) continue; } scr_writew((attr << 8) + c, (unsigned short *) pos); cnt++; if (myx == video_num_columns - 1) { need_wrap = 1; continue; } pos+=2; myx++; } if (cnt > 0) { if (IS_VISIBLE) sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x); x += cnt; if (x == video_num_columns) { x--; need_wrap = 1; } } set_cursor(currcons); poke_blanked_console();quit: clear_bit(0, &printing);}static kdev_t vt_console_device(struct console *c){ return MKDEV(TTY_MAJOR, c->index ? c->index : fg_console + 1);}struct console vt_console_driver = { "tty", vt_console_print, NULL, vt_console_device, keyboard_wait_for_keypress, unblank_screen, NULL, CON_PRINTBUFFER, -1, 0, NULL};#endif/* * Handling of Linux-specific VC ioctls */int tioclinux(struct tty_struct *tty, unsigned long arg){ char type, data; if (tty->driver.type != TTY_DRIVER_TYPE_CONSOLE) return -EINVAL; if (current->tty != tty && !suser()) return -EPERM; if (get_user(type, (char *)arg)) return -EFAULT; switch (type) { case 2: return set_selection(arg, tty, 1); case 3: return paste_selection(tty); case 4: unblank_screen(); return 0; case 5: return sel_loadlut(arg); case 6: /* * Make it possible to react to Shift+Mousebutton. * Note that 'shift_state' is an undocumented * kernel-internal variable; programs not closely * related to the kernel should not use this. */ data = shift_state; return __put_user(data, (char *) arg); case 7: data = mouse_reporting(); return __put_user(data, (char *) arg); case 10: set_vesa_blanking(arg); return 0; case 11: /* set kmsg redirect */ if (!suser()) return -EPERM; if (get_user(data, (char *)arg+1)) return -EFAULT; kmsg_redirect = data; return 0; case 12: /* get fg_console */ return fg_console; } return -EINVAL;}/* * /dev/ttyN handling */static int con_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count){ int retval; retval = do_con_write(tty, from_user, buf, count); con_flush_chars(tty); return retval;}static void con_put_char(struct tty_struct *tty, unsigned char ch){ do_con_write(tty, 0, &ch, 1);}static int con_write_room(struct tty_struct *tty){ if (tty->stopped) return 0; return 4096; /* No limit, really; we're not buffering */}static int con_chars_in_buffer(struct tty_struct *tty){ return 0; /* we're not buffering */}/* * con_throttle and con_unthrottle are only used for * paste_selection(), which has to stuff in a large number of * characters... */static void con_throttle(struct tty_struct *tty){}static void con_unthrottle(struct tty_struct *tty){ struct vt_struct *vt = (struct vt_struct *) tty->driver_data; wake_up_interruptible(&vt->paste_wait);}/* * Turn the Scroll-Lock LED on when the tty is stopped */static void con_stop(struct tty_struct *tty){ int console_num; if (!tty) return; console_num = MINOR(tty->device) - (tty->driver.minor_start); if (!vc_cons_allocated(console_num)) return; set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -