📄 console.c
字号:
lock = 1; if (is_switch) { currcons = fg_console; hide_cursor(currcons); if (fg_console != new_console) { struct vc_data **display = vc_cons[new_console].d->vc_display_fg; old_console = (*display) ? (*display)->vc_num : fg_console; *display = vc_cons[new_console].d; fg_console = new_console; currcons = old_console; if (!IS_VISIBLE) { save_screen(currcons); set_origin(currcons); } currcons = new_console; if (old_console == new_console) redraw = 0; } } else { currcons = new_console; hide_cursor(currcons); } if (redraw) { set_origin(currcons); set_palette(currcons); if (sw->con_switch(vc_cons[currcons].d) && vcmode != KD_GRAPHICS) /* Update the screen contents */ do_update_region(currcons, origin, screenbuf_size/2); } set_cursor(currcons); if (is_switch) { set_leds(); compute_shiftstate(); } lock = 0;}/* * Allocation, freeing and resizing of VTs. */int vc_cons_allocated(unsigned int i){ return (i < MAX_NR_CONSOLES && vc_cons[i].d);}static void visual_init(int currcons, int init){ /* ++Geert: sw->con_init determines console size */ sw = conswitchp;#ifndef VT_SINGLE_DRIVER if (con_driver_map[currcons]) sw = con_driver_map[currcons];#endif cons_num = currcons; display_fg = &master_display_fg; vc_cons[currcons].d->vc_uni_pagedir_loc = &vc_cons[currcons].d->vc_uni_pagedir; vc_cons[currcons].d->vc_uni_pagedir = 0; hi_font_mask = 0; complement_mask = 0; can_do_color = 0; sw->con_init(vc_cons[currcons].d, init); if (!complement_mask) complement_mask = can_do_color ? 0x7700 : 0x0800; s_complement_mask = complement_mask; video_size_row = video_num_columns<<1; screenbuf_size = video_num_lines*video_size_row;}int vc_allocate(unsigned int currcons) /* return 0 on success */{ if (currcons >= MAX_NR_CONSOLES) return -ENXIO; if (!vc_cons[currcons].d) { long p, q; /* prevent users from taking too much memory */ if (currcons >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE)) return -EPERM; /* due to the granularity of kmalloc, we waste some memory here */ /* the alloc is done in two steps, to optimize the common situation of a 25x80 console (structsize=216, screenbuf_size=4000) */ /* although the numbers above are not valid since long ago, the point is still up-to-date and the comment still has its value even if only as a historical artifact. --mj, July 1998 */ p = (long) kmalloc(structsize, GFP_KERNEL); if (!p) return -ENOMEM; vc_cons[currcons].d = (struct vc_data *)p; vt_cons[currcons] = (struct vt_struct *)(p+sizeof(struct vc_data)); visual_init(currcons, 1); if (!*vc_cons[currcons].d->vc_uni_pagedir_loc) con_set_default_unimap(currcons); q = (long)kmalloc(screenbuf_size, GFP_KERNEL); if (!q) { kfree_s((char *) p, structsize); vc_cons[currcons].d = NULL; vt_cons[currcons] = NULL; return -ENOMEM; } screenbuf = (unsigned short *) q; kmalloced = 1; vc_init(currcons, video_num_lines, video_num_columns, 1); } return 0;}/* * Change # of rows and columns (0 means unchanged/the size of fg_console) * [this is to be used together with some user program * like resize that changes the hardware videomode] */int vc_resize(unsigned int lines, unsigned int cols, unsigned int first, unsigned int last){ unsigned int cc, ll, ss, sr, todo = 0; unsigned int currcons = fg_console, i; unsigned short *newscreens[MAX_NR_CONSOLES]; cc = (cols ? cols : video_num_columns); ll = (lines ? lines : video_num_lines); sr = cc << 1; ss = sr * ll; for (currcons = first; currcons <= last; currcons++) { if (!vc_cons_allocated(currcons) || (cc == video_num_columns && ll == video_num_lines)) newscreens[currcons] = NULL; else { unsigned short *p = (unsigned short *) kmalloc(ss, GFP_USER); if (!p) { for (i = 0; i< currcons; i++) if (newscreens[i]) kfree_s(newscreens[i], ss); return -ENOMEM; } newscreens[currcons] = p; todo++; } } if (!todo) return 0; for (currcons = first; currcons <= last; currcons++) { unsigned int occ, oll, oss, osr; unsigned long ol, nl, nlend, rlth, rrem; if (!newscreens[currcons] || !vc_cons_allocated(currcons)) continue; oll = video_num_lines; occ = video_num_columns; osr = video_size_row; oss = screenbuf_size; video_num_lines = ll; video_num_columns = cc; video_size_row = sr; screenbuf_size = ss; rlth = MIN(osr, sr); rrem = sr - rlth; ol = origin; nl = (long) newscreens[currcons]; nlend = nl + ss; if (ll < oll) ol += (oll - ll) * osr; update_attr(currcons); while (ol < scr_end) { scr_memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth); if (rrem) scr_memsetw((void *)(nl + rlth), video_erase_char, rrem); ol += osr; nl += sr; } if (nlend > nl) scr_memsetw((void *) nl, video_erase_char, nlend - nl); if (kmalloced) kfree_s(screenbuf, oss); screenbuf = newscreens[currcons]; kmalloced = 1; screenbuf_size = ss; set_origin(currcons); /* do part of a reset_terminal() */ top = 0; bottom = video_num_lines; gotoxy(currcons, x, y); save_cur(currcons); if (console_table[currcons]) { struct winsize ws, *cws = &console_table[currcons]->winsize; memset(&ws, 0, sizeof(ws)); ws.ws_row = video_num_lines; ws.ws_col = video_num_columns; if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) && console_table[currcons]->pgrp > 0) kill_pg(console_table[currcons]->pgrp, SIGWINCH, 1); *cws = ws; } if (IS_VISIBLE) update_screen(currcons); } return 0;}void vc_disallocate(unsigned int currcons){ if (vc_cons_allocated(currcons)) { sw->con_deinit(vc_cons[currcons].d); if (kmalloced) kfree_s(screenbuf, screenbuf_size); if (currcons >= MIN_NR_CONSOLES) kfree_s(vc_cons[currcons].d, structsize); vc_cons[currcons].d = NULL; }}/* * VT102 emulator */#define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)#define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)#define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)#define decarm VC_REPEAT#define decckm VC_CKMODE#define kbdapplic VC_APPLIC#define lnm VC_CRLF/* * this is what the terminal answers to a ESC-Z or csi0c query. */#define VT100ID "\033[?1;2c"#define VT102ID "\033[?6c"unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7, 8,12,10,14, 9,13,11,15 };/* the default colour table, for VGA+ colour systems */int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa, 0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff};int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa, 0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff};int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa, 0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff};/* * gotoxy() must verify all boundaries, because the arguments * might also be negative. If the given position is out of * bounds, the cursor is placed at the nearest margin. */static void gotoxy(int currcons, int new_x, int new_y){ int min_y, max_y; if (new_x < 0) x = 0; else if (new_x >= video_num_columns) x = video_num_columns - 1; else x = new_x; if (decom) { min_y = top; max_y = bottom; } else { min_y = 0; max_y = video_num_lines; } if (new_y < min_y) y = min_y; else if (new_y >= max_y) y = max_y - 1; else y = new_y; pos = origin + y*video_size_row + (x<<1); need_wrap = 0;}/* for absolute user moves, when decom is set */static void gotoxay(int currcons, int new_x, int new_y){ gotoxy(currcons, new_x, decom ? (top+new_y) : new_y);}void scrollback(int lines){ int currcons = fg_console; if (!lines) lines = video_num_lines/2; scrolldelta(-lines);}void scrollfront(int lines){ int currcons = fg_console; if (!lines) lines = video_num_lines/2; scrolldelta(lines);}static void lf(int currcons){ /* don't scroll if above bottom of scrolling region, or * if below scrolling region */ if (y+1 == bottom) scrup(currcons,top,bottom,1); else if (y < video_num_lines-1) { y++; pos += video_size_row; } need_wrap = 0;}static void ri(int currcons){ /* don't scroll if below top of scrolling region, or * if above scrolling region */ if (y == top) scrdown(currcons,top,bottom,1); else if (y > 0) { y--; pos -= video_size_row; } need_wrap = 0;}static inline void cr(int currcons){ pos -= x<<1; need_wrap = x = 0;}static inline void bs(int currcons){ if (x) { pos -= 2; x--; need_wrap = 0; }}static inline void del(int currcons){ /* ignored */}static void csi_J(int currcons, int vpar){ unsigned int count; unsigned short * start; switch (vpar) { case 0: /* erase from cursor to end of display */ count = (scr_end-pos)>>1; start = (unsigned short *) pos; if (DO_UPDATE) { /* do in two stages */ sw->con_clear(vc_cons[currcons].d, y, x, 1, video_num_columns-x); sw->con_clear(vc_cons[currcons].d, y+1, 0, video_num_lines-y-1, video_num_columns); } break; case 1: /* erase from start to cursor */ count = ((pos-origin)>>1)+1; start = (unsigned short *) origin; if (DO_UPDATE) { /* do in two stages */ sw->con_clear(vc_cons[currcons].d, 0, 0, y, video_num_columns); sw->con_clear(vc_cons[currcons].d, y, 0, 1, x + 1); } break; case 2: /* erase whole display */ count = video_num_columns * video_num_lines; start = (unsigned short *) origin; if (DO_UPDATE) sw->con_clear(vc_cons[currcons].d, 0, 0, video_num_lines, video_num_columns); break; default: return; } scr_memsetw(start, video_erase_char, 2*count); need_wrap = 0;}static void csi_K(int currcons, int vpar){ unsigned int count; unsigned short * start; switch (vpar) { case 0: /* erase from cursor to end of line */ count = video_num_columns-x; start = (unsigned short *) pos; if (DO_UPDATE) sw->con_clear(vc_cons[currcons].d, y, x, 1, video_num_columns-x); break; case 1: /* erase from start of line to cursor */ start = (unsigned short *) (pos - (x<<1)); count = x+1; if (DO_UPDATE) sw->con_clear(vc_cons[currcons].d, y, 0, 1, x + 1); break; case 2: /* erase whole line */ start = (unsigned short *) (pos - (x<<1)); count = video_num_columns; if (DO_UPDATE) sw->con_clear(vc_cons[currcons].d, y, 0, 1, video_num_columns); break; default: return; } scr_memsetw(start, video_erase_char, 2 * count); need_wrap = 0;}static void csi_X(int currcons, int vpar) /* erase the following vpar positions */{ /* not vt100? */ int count; if (!vpar) vpar++; count = (vpar > video_num_columns-x) ? (video_num_columns-x) : vpar; scr_memsetw((unsigned short *) pos, video_erase_char, 2 * count); if (DO_UPDATE) sw->con_clear(vc_cons[currcons].d, y, x, 1, count); need_wrap = 0;}static void default_attr(int currcons){ intensity = 1; underline = 0; reverse = 0; blink = 0; color = def_color;}static void csi_m(int currcons){ int i; for (i=0;i<=npar;i++) switch (par[i]) { case 0: /* all attributes off */ default_attr(currcons); break; case 1: intensity = 2; break; case 2: intensity = 0; break; case 4: underline = 1; break; case 5: blink = 1; break; case 7: reverse = 1; break; case 10: /* ANSI X3.64-1979 (SCO-ish?) * Select primary font, don't display * control chars if defined, don't set * bit 8 on output. */ translate = set_translate(charset == 0 ? G0_charset : G1_charset,currcons); disp_ctrl = 0; toggle_meta = 0; break; case 11: /* ANSI X3.64-1979 (SCO-ish?) * Select first alternate font, lets * chars < 32 be displayed as ROM chars. */ translate = set_translate(IBMPC_MAP,currcons); disp_ctrl = 1; toggle_meta = 0; break; case 12: /* ANSI X3.64-1979 (SCO-ish?) * Select second alternate font, toggle * high bit before displaying as ROM char. */ translate = set_translate(IBMPC_MAP,currcons); disp_ctrl = 1; toggle_meta = 1; break; case 21: case 22: intensity = 1; break; case 24: underline = 0; break; case 25: blink = 0; break; case 27: reverse = 0; break; case 38: /* ANSI X3.64-1979 (SCO-ish?) * Enables underscore, white foreground * with white underscore (Linux - use * default foreground). */ color = (def_color & 0x0f) | background; underline = 1; break; case 39: /* ANSI X3.64-1979 (SCO-ish?) * Disable underline option. * Reset colour to default? It did this * before... */ color = (def_color & 0x0f) | background; underline = 0; break; case 49: color = (def_color & 0xf0) | foreground; break; default: if (par[i] >= 30 && par[i] <= 37) color = color_table[par[i]-30] | background; else if (par[i] >= 40 && par[i] <= 47)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -