📄 fbcon.c
字号:
p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y)); p->cursor_x = conp->vc_x; p->cursor_y = y; switch (mode) { case CM_ERASE: cursor_drawn = 0; break; case CM_MOVE: case CM_DRAW: if (cursor_drawn) p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y)); vbl_cursor_cnt = CURSOR_DRAW_DELAY; cursor_on = 1; break; }}static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp){ struct display *p; if (!cursor_on) return; if (vbl_cursor_cnt && --vbl_cursor_cnt == 0) { p = &fb_display[fg_console]; if (p->dispsw->revc) p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y)); cursor_drawn ^= 1; vbl_cursor_cnt = cursor_blink_rate; }}static int scrollback_phys_max = 0;static int scrollback_max = 0;static int scrollback_current = 0;static __inline__ void ywrap_up(int unit, struct vc_data *conp, struct display *p, int count){ p->yscroll += count; if (p->yscroll >= p->vrows) /* Deal with wrap */ p->yscroll -= p->vrows; p->var.xoffset = 0; p->var.yoffset = p->yscroll*fontheight(p); p->var.vmode |= FB_VMODE_YWRAP; p->fb_info->updatevar(unit, p->fb_info); scrollback_max += count; if (scrollback_max > scrollback_phys_max) scrollback_max = scrollback_phys_max; scrollback_current = 0;}static __inline__ void ywrap_down(int unit, struct vc_data *conp, struct display *p, int count){ p->yscroll -= count; if (p->yscroll < 0) /* Deal with wrap */ p->yscroll += p->vrows; p->var.xoffset = 0; p->var.yoffset = p->yscroll*fontheight(p); p->var.vmode |= FB_VMODE_YWRAP; p->fb_info->updatevar(unit, p->fb_info); scrollback_max -= count; if (scrollback_max < 0) scrollback_max = 0; scrollback_current = 0;}static __inline__ void ypan_up(int unit, struct vc_data *conp, struct display *p, int count){ p->yscroll += count; if (p->yscroll > p->vrows-conp->vc_rows) { p->dispsw->bmove(p, p->vrows-conp->vc_rows, 0, 0, 0, conp->vc_rows, conp->vc_cols); p->yscroll -= p->vrows-conp->vc_rows; } p->var.xoffset = 0; p->var.yoffset = p->yscroll*fontheight(p); p->var.vmode &= ~FB_VMODE_YWRAP; p->fb_info->updatevar(unit, p->fb_info); if (p->dispsw->clear_margins) p->dispsw->clear_margins(conp, p, 1); scrollback_max += count; if (scrollback_max > scrollback_phys_max) scrollback_max = scrollback_phys_max; scrollback_current = 0;}static __inline__ void ypan_down(int unit, struct vc_data *conp, struct display *p, int count){ p->yscroll -= count; if (p->yscroll < 0) { p->dispsw->bmove(p, 0, 0, p->vrows-conp->vc_rows, 0, conp->vc_rows, conp->vc_cols); p->yscroll += p->vrows-conp->vc_rows; } p->var.xoffset = 0; p->var.yoffset = p->yscroll*fontheight(p); p->var.vmode &= ~FB_VMODE_YWRAP; p->fb_info->updatevar(unit, p->fb_info); if (p->dispsw->clear_margins) p->dispsw->clear_margins(conp, p, 1); scrollback_max -= count; if (scrollback_max < 0) scrollback_max = 0; scrollback_current = 0;}static void fbcon_redraw_softback(struct vc_data *conp, struct display *p, long delta){ unsigned short *d, *s; unsigned long n; int line = 0; int count = conp->vc_rows; d = (u16 *)softback_curr; if (d == (u16 *)softback_in) d = (u16 *)conp->vc_origin; n = softback_curr + delta * conp->vc_size_row; softback_lines -= delta; if (delta < 0) { if (softback_curr < softback_top && n < softback_buf) { n += softback_end - softback_buf; if (n < softback_top) { softback_lines -= (softback_top - n) / conp->vc_size_row; n = softback_top; } } else if (softback_curr >= softback_top && n < softback_top) { softback_lines -= (softback_top - n) / conp->vc_size_row; n = softback_top; } } else { if (softback_curr > softback_in && n >= softback_end) { n += softback_buf - softback_end; if (n > softback_in) { n = softback_in; softback_lines = 0; } } else if (softback_curr <= softback_in && n > softback_in) { n = softback_in; softback_lines = 0; } } if (n == softback_curr) return; softback_curr = n; s = (u16 *)softback_curr; if (s == (u16 *)softback_in) s = (u16 *)conp->vc_origin; while (count--) { unsigned short *start; unsigned short *le; unsigned short c; int x = 0; unsigned short attr = 1; start = s; le = advance_row(s, 1); do { c = scr_readw(s); if (attr != (c & 0xff00)) { attr = c & 0xff00; if (s > start) { p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); x += s - start; start = s; } } if (c == scr_readw(d)) { if (s > start) { p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); x += s - start + 1; start = s + 1; } else { x++; start++; } } s++; d++; } while (s < le); if (s > start) p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); line++; if (d == (u16 *)softback_end) d = (u16 *)softback_buf; if (d == (u16 *)softback_in) d = (u16 *)conp->vc_origin; if (s == (u16 *)softback_end) s = (u16 *)softback_buf; if (s == (u16 *)softback_in) s = (u16 *)conp->vc_origin; }}static void fbcon_redraw(struct vc_data *conp, struct display *p, int line, int count, int offset){ unsigned short *d = (unsigned short *) (conp->vc_origin + conp->vc_size_row * line); unsigned short *s = d + offset; while (count--) { unsigned short *start = s; unsigned short *le = advance_row(s, 1); unsigned short c; int x = 0; unsigned short attr = 1; do { c = scr_readw(s); if (attr != (c & 0xff00)) { attr = c & 0xff00; if (s > start) { p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); x += s - start; start = s; } } if (c == scr_readw(d)) { if (s > start) { p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); x += s - start + 1; start = s + 1; } else { x++; start++; } } scr_writew(c, d); console_conditional_schedule(); s++; d++; } while (s < le); if (s > start) p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); console_conditional_schedule(); if (offset > 0) line++; else { line--; /* NOTE: We subtract two lines from these pointers */ s -= conp->vc_size_row; d -= conp->vc_size_row; } }}/** * fbcon_redraw_clear - clear area of the screen * @conp: stucture pointing to current active virtual console * @p: display structure * @sy: starting Y coordinate * @sx: starting X coordinate * @height: height of area to clear * @width: width of area to clear * * Clears a specified area of the screen. All dimensions are in * pixels. * */void fbcon_redraw_clear(struct vc_data *conp, struct display *p, int sy, int sx, int height, int width){ int x, y; for (y=0; y<height; y++) for (x=0; x<width; x++) fbcon_putc(conp, ' ', sy+y, sx+x);}/** * fbcon_redraw_bmove - copy area of screen to another area * @p: display structure * @sy: origin Y coordinate * @sx: origin X coordinate * @dy: destination Y coordinate * @dx: destination X coordinate * @h: height of area to copy * @w: width of area to copy * * Copies an area of the screen to another area of the same screen. * All dimensions are in pixels. * * Note that this function cannot be used together with ypan or * ywrap. * */void fbcon_redraw_bmove(struct display *p, int sy, int sx, int dy, int dx, int h, int w){ if (sy != dy) panic("fbcon_redraw_bmove width sy != dy"); /* h will be always 1, but it does not matter if we are more generic */ while (h-- > 0) { struct vc_data *conp = p->conp; unsigned short *d = (unsigned short *) (conp->vc_origin + conp->vc_size_row * dy + dx * 2); unsigned short *s = d + (dx - sx); unsigned short *start = d; unsigned short *ls = d; unsigned short *le = d + w; unsigned short c; int x = dx; unsigned short attr = 1; do { c = scr_readw(d); if (attr != (c & 0xff00)) { attr = c & 0xff00; if (d > start) { p->dispsw->putcs(conp, p, start, d - start, dy, x); x += d - start; start = d; } } if (s >= ls && s < le && c == scr_readw(s)) { if (d > start) { p->dispsw->putcs(conp, p, start, d - start, dy, x); x += d - start + 1; start = d + 1; } else { x++; start++; } } s++; d++; } while (d < le); if (d > start) p->dispsw->putcs(conp, p, start, d - start, dy, x); sy++; dy++; }}static inline void fbcon_softback_note(struct vc_data *conp, int t, int count){ unsigned short *p; if (conp->vc_num != fg_console) return; p = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row); while (count) { scr_memcpyw((u16 *)softback_in, p, conp->vc_size_row); count--; p = advance_row(p, 1); softback_in += conp->vc_size_row; if (softback_in == softback_end) softback_in = softback_buf; if (softback_in == softback_top) { softback_top += conp->vc_size_row; if (softback_top == softback_end) softback_top = softback_buf; } } softback_curr = softback_in;}static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count){ int unit = conp->vc_num; struct display *p = &fb_display[unit]; int scroll_partial = !(p->scrollmode & __SCROLL_YNOPARTIAL); if (!p->can_soft_blank && console_blanked) return 0; if (!count || vt_cons[unit]->vc_mode != KD_TEXT) return 0; fbcon_cursor(conp, CM_ERASE); /* * ++Geert: Only use ywrap/ypan if the console is in text mode * ++Andrew: Only use ypan on hardware text mode when scrolling the * whole screen (prevents flicker). */ switch (dir) { case SM_UP: if (count > conp->vc_rows) /* Maximum realistic size */ count = conp->vc_rows; if (softback_top) fbcon_softback_note(conp, t, count); if (logo_shown >= 0) goto redraw_up; switch (p->scrollmode & __SCROLL_YMASK) { case __SCROLL_YMOVE: p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count, conp->vc_cols); p->dispsw->clear(conp, p, b-count, 0, count, conp->vc_cols); break; case __SCROLL_YWRAP: if (b-t-count > 3*conp->vc_rows>>2) { if (t > 0) fbcon_bmove(conp, 0, 0, count, 0, t, conp->vc_cols); ywrap_up(unit, conp, p, count); if (conp->vc_rows-b > 0) fbcon_bmove(conp, b-count, 0, b, 0, conp->vc_rows-b, conp->vc_cols); } else if (p->scrollmode & __SCROLL_YPANREDRAW) goto redraw_up; else fbcon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols); fbcon_clear(conp, b-count, 0, count, conp->vc_cols); break; case __SCROLL_YPAN: if (( p->yscroll + count <= 2 * (p->vrows - conp->vc_rows)) && (( !scroll_partial && (b-t == conp->vc_rows)) || ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2)))) { if (t > 0) fbcon_bmove(conp, 0, 0, count, 0, t, conp->vc_cols); ypan_up(unit, conp, p, count); if (conp->vc_rows-b > 0) fbcon_bmove(conp, b-count, 0, b, 0, conp->vc_rows-b, conp->vc_cols); } else if (p->scrollmode & __SCROLL_YPANREDRAW) goto redraw_up; else fbcon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols); fbcon_clear(conp, b-count, 0, count, conp->vc_cols); break; case __SCROLL_YREDRAW: redraw_up: fbcon_redraw(conp, p, t, b-t-count, count*conp->vc_cols); p->dispsw->clear(conp, p, real_y(p, b-count), 0, count, conp->vc_cols); scr_memsetw((unsigned short *)(conp->vc_origin + conp->vc_size_row * (b-count)), conp->vc_video_erase_char, conp->vc_size_row * count); return 1; } break; case SM_DOWN: if (count > conp->vc_rows) /* Maximum realistic size */ count = conp->vc_rows; switch (p->scrollmode & __SCROLL_YMASK) { case __SCROLL_YMOVE: p->dispsw->bmove(p, t, 0, t+count, 0, b-t-count,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -