⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fbcon.c

📁 Linux程序设计权威指南代码.包含所有章节代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    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);	    s++;	    d++;	} while (s < le);	if (s > start)	    p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x);	if (offset > 0)		line++;	else {		line--;		/* NOTE: We subtract two lines from these pointers */		s -= conp->vc_size_row;		d -= conp->vc_size_row;	}    }}/* This 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 = (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,				 conp->vc_cols);		p->dispsw->clear(conp, p, t, 0,				 count, conp->vc_cols);		break;	    case __SCROLL_YWRAP:		if (b-t-count > 3*conp->vc_rows>>2) {		    if (conp->vc_rows-b > 0)			fbcon_bmove(conp, b, 0, b-count, 0,				    conp->vc_rows-b, conp->vc_cols);		    ywrap_down(unit, conp, p, count);		    if (t > 0)			fbcon_bmove(conp, count, 0, 0, 0, t,				    conp->vc_cols);		} else if (p->scrollmode & __SCROLL_YPANREDRAW)		    goto redraw_down;		else		    fbcon_bmove(conp, t, 0, t+count, 0, b-t-count,				conp->vc_cols);		fbcon_clear(conp, t, 0, count, conp->vc_cols);		break;	    case __SCROLL_YPAN:		if (( count-p->yscroll <= p->vrows-conp->vc_rows) &&		    (( !scroll_partial && (b-t == conp->vc_rows)) ||		     ( scroll_partial  && (b-t-count > 3*conp->vc_rows>>2)))) {		    if (conp->vc_rows-b > 0)			fbcon_bmove(conp, b, 0, b-count, 0,				    conp->vc_rows-b, conp->vc_cols);		    ypan_down(unit, conp, p, count);		    if (t > 0)			fbcon_bmove(conp, count, 0, 0, 0, t,				    conp->vc_cols);		} else if (p->scrollmode & __SCROLL_YPANREDRAW)		    goto redraw_down;		else		    fbcon_bmove(conp, t, 0, t+count, 0, b-t-count,				conp->vc_cols);		fbcon_clear(conp, t, 0, count, conp->vc_cols);		break;	    case __SCROLL_YREDRAW:	    redraw_down:		fbcon_redraw(conp, p, b - 1, b-t-count, -count*conp->vc_cols);		p->dispsw->clear(conp, p, real_y(p, t), 0,				 count, conp->vc_cols);	    	scr_memsetw((unsigned short *)(conp->vc_origin + 	    		    conp->vc_size_row * t), 	    		    conp->vc_video_erase_char,	    		    conp->vc_size_row * count);	    	return 1;	    }    }    return 0;}static void fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,			int height, int width){    int unit = conp->vc_num;    struct display *p = &fb_display[unit];        if (!p->can_soft_blank && console_blanked)	return;    if (!width || !height)	return;    if (((sy <= p->cursor_y) && (p->cursor_y < sy+height) &&	  (sx <= p->cursor_x) && (p->cursor_x < sx+width)) ||	 ((dy <= p->cursor_y) && (p->cursor_y < dy+height) &&	  (dx <= p->cursor_x) && (p->cursor_x < dx+width)))	fbcon_cursor(conp, CM_ERASE|CM_SOFTBACK);    /*  Split blits that cross physical y_wrap case.     *  Pathological case involves 4 blits, better to use recursive     *  code rather than unrolled case     *     *  Recursive invocations don't need to erase the cursor over and     *  over again, so we use fbcon_bmove_rec()     */    fbcon_bmove_rec(p, sy, sx, dy, dx, height, width, p->vrows-p->yscroll);}static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx,			    int height, int width, u_int y_break){    u_int b;    if (sy < y_break && sy+height > y_break) {	b = y_break-sy;	if (dy < sy) {	/* Avoid trashing self */	    fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);	    fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);	} else {	    fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);	    fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);	}	return;    }    if (dy < y_break && dy+height > y_break) {	b = y_break-dy;	if (dy < sy) {	/* Avoid trashing self */	    fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);	    fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);	} else {	    fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);	    fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);	}	return;    }    p->dispsw->bmove(p, real_y(p, sy), sx, real_y(p, dy), dx, height, width);}static int fbcon_switch(struct vc_data *conp){    int unit = conp->vc_num;    struct display *p = &fb_display[unit];    struct fb_info *info = p->fb_info;    if (softback_top) {    	int l = fbcon_softback_size / conp->vc_size_row;	if (softback_lines)	    fbcon_set_origin(conp);        softback_top = softback_curr = softback_in = softback_buf;        softback_lines = 0;	if (l > 5)	    softback_end = softback_buf + l * conp->vc_size_row;	else {	    /* Smaller scrollback makes no sense, and 0 would screw	       the operation totally */	    softback_top = 0;	}    }    if (logo_shown >= 0) {    	struct vc_data *conp2 = vc_cons[logo_shown].d;    	    	if (conp2->vc_top == logo_lines && conp2->vc_bottom == conp2->vc_rows)    		conp2->vc_top = 0;    	logo_shown = -1;    }    p->var.yoffset = p->yscroll = 0;    switch (p->scrollmode & __SCROLL_YMASK) {	case __SCROLL_YWRAP:	    scrollback_phys_max = p->vrows-conp->vc_rows;	    break;	case __SCROLL_YPAN:	    scrollback_phys_max = p->vrows-2*conp->vc_rows;	    if (scrollback_phys_max < 0)		scrollback_phys_max = 0;	    break;	default:	    scrollback_phys_max = 0;	    break;    }    scrollback_max = 0;    scrollback_current = 0;    if (info && info->switch_con)	(*info->switch_con)(unit, info);    if (p->dispsw->clear_margins && vt_cons[unit]->vc_mode == KD_TEXT)	p->dispsw->clear_margins(conp, p, 0);    if (logo_shown == -2) {	logo_shown = fg_console;	fbcon_show_logo(); /* This is protected above by initmem_freed */	update_region(fg_console,		      conp->vc_origin + conp->vc_size_row * conp->vc_top,		      conp->vc_size_row * (conp->vc_bottom - conp->vc_top) / 2);	return 0;    }    return 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -