Introduce a new function vgafb_scroll() to scroll a window on the screen and update vgabios.c to use only that function for scrolling. This makes the low-level vgafb_move_chars() and vgafb_clear_chars() local to vgafb.c, and it simplifies the callers.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/vgabios.c | 57 ++++++++++++--------------------------------- vgasrc/vgabios.h | 6 ++--- vgasrc/vgafb.c | 70 ++++++++++++++++++++++++++++++++++++++------------------ 3 files changed, 64 insertions(+), 69 deletions(-)
diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c index cfb6ba2..2c8cc79 100644 --- a/vgasrc/vgabios.c +++ b/vgasrc/vgabios.c @@ -198,15 +198,10 @@ write_teletype(struct cursorpos *pcp, struct carattr ca) if (pcp->y > nbrows) { pcp->y--;
- struct cursorpos dest = {0, 0, pcp->page}; - struct cursorpos src = {0, 1, pcp->page}; - struct cursorpos size = {GET_BDA(video_cols), nbrows}; - vgafb_move_chars(dest, src, size); - - struct cursorpos clr = {0, nbrows, pcp->page}; + struct cursorpos win = {0, 0, pcp->page}; + struct cursorpos winsize = {GET_BDA(video_cols), nbrows+1}; struct carattr attr = {' ', 0, 0}; - struct cursorpos clrsize = {GET_BDA(video_cols), 1}; - vgafb_clear_chars(clr, attr, clrsize); + vgafb_scroll(win, winsize, 1, attr); } }
@@ -400,6 +395,7 @@ handle_1005(struct bregs *regs) static void verify_scroll(struct bregs *regs, int dir) { + // Verify parameters u8 ulx = regs->cl, uly = regs->ch, lrx = regs->dl, lry = regs->dh; u16 nbrows = GET_BDA(video_rows) + 1; if (lry >= nbrows) @@ -410,41 +406,16 @@ verify_scroll(struct bregs *regs, int dir) int wincols = lrx - ulx + 1, winrows = lry - uly + 1; if (wincols <= 0 || winrows <= 0) return; - - u8 page = GET_BDA(video_page); - int clearlines = regs->al, movelines = winrows - clearlines; - if (!clearlines || movelines <= 0) { - // Clear whole area. - struct cursorpos clr = {ulx, uly, page}; - struct carattr attr = {' ', regs->bh, 1}; - struct cursorpos clrsize = {wincols, winrows}; - vgafb_clear_chars(clr, attr, clrsize); - return; - } - - if (dir > 0) { - // Normal scroll - struct cursorpos dest = {ulx, uly, page}; - struct cursorpos src = {ulx, uly + clearlines, page}; - struct cursorpos size = {wincols, movelines}; - vgafb_move_chars(dest, src, size); - - struct cursorpos clr = {ulx, uly + movelines, page}; - struct carattr attr = {' ', regs->bh, 1}; - struct cursorpos clrsize = {wincols, clearlines}; - vgafb_clear_chars(clr, attr, clrsize); - } else { - // Scroll down - struct cursorpos dest = {ulx, uly + clearlines, page}; - struct cursorpos src = {ulx, uly, page}; - struct cursorpos size = {wincols, movelines}; - vgafb_move_chars(dest, src, size); - - struct cursorpos clr = {ulx, uly, page}; - struct carattr attr = {' ', regs->bh, 1}; - struct cursorpos clrsize = {wincols, clearlines}; - vgafb_clear_chars(clr, attr, clrsize); - } + int lines = regs->al; + if (lines >= winrows) + lines = 0; + lines *= dir; + + // Scroll (or clear) window + struct cursorpos win = {ulx, uly, GET_BDA(video_page)}; + struct cursorpos winsize = {wincols, winrows}; + struct carattr attr = {' ', regs->bh, 1}; + vgafb_scroll(win, winsize, lines, attr); }
static void diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h index 831f694..9fbfb14 100644 --- a/vgasrc/vgabios.h +++ b/vgasrc/vgabios.h @@ -126,10 +126,8 @@ extern struct video_func_static static_functionality; void init_gfx_op(struct gfx_op *op, struct vgamode_s *vmode_g); void handle_gfx_op(struct gfx_op *op); void *text_address(struct cursorpos cp); -void vgafb_move_chars(struct cursorpos dest - , struct cursorpos src, struct cursorpos movesize); -void vgafb_clear_chars(struct cursorpos dest - , struct carattr ca, struct cursorpos movesize); +void vgafb_scroll(struct cursorpos win, struct cursorpos winsize + , int lines, struct carattr ca); void vgafb_write_char(struct cursorpos cp, struct carattr ca); struct carattr vgafb_read_char(struct cursorpos cp); void vgafb_write_pixel(u8 color, u16 x, u16 y); diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c index 58c60ad..bd1c8dd 100644 --- a/vgasrc/vgafb.c +++ b/vgasrc/vgafb.c @@ -346,7 +346,7 @@ handle_gfx_op(struct gfx_op *op) // Move characters when in graphics mode. static void gfx_move_chars(struct vgamode_s *vmode_g, struct cursorpos dest - , struct cursorpos src, struct cursorpos movesize) + , struct cursorpos movesize, int lines) { struct gfx_op op; init_gfx_op(&op, vmode_g); @@ -355,23 +355,23 @@ gfx_move_chars(struct vgamode_s *vmode_g, struct cursorpos dest int cheight = GET_BDA(char_height); op.y = dest.y * cheight; op.ylen = movesize.y * cheight; - op.srcy = src.y * cheight; + op.srcy = op.y + lines * cheight; op.op = GO_MEMMOVE; handle_gfx_op(&op); }
// Clear area of screen in graphics mode. static void -gfx_clear_chars(struct vgamode_s *vmode_g, struct cursorpos dest - , struct carattr ca, struct cursorpos clearsize) +gfx_clear_chars(struct vgamode_s *vmode_g, struct cursorpos win + , struct cursorpos winsize, struct carattr ca) { struct gfx_op op; init_gfx_op(&op, vmode_g); - op.x = dest.x * 8; - op.xlen = clearsize.x * 8; + op.x = win.x * 8; + op.xlen = winsize.x * 8; int cheight = GET_BDA(char_height); - op.y = dest.y * cheight; - op.ylen = clearsize.y * cheight; + op.y = win.y * cheight; + op.ylen = winsize.y * cheight; op.pixels[0] = ca.attr; if (vga_emulate_text()) op.pixels[0] = ca.attr >> 4; @@ -580,45 +580,71 @@ text_address(struct cursorpos cp) }
// Move characters on screen. -void -vgafb_move_chars(struct cursorpos dest - , struct cursorpos src, struct cursorpos movesize) +static void +vgafb_move_chars(struct cursorpos dest, struct cursorpos movesize, int lines) { struct vgamode_s *vmode_g = get_current_mode(); if (!vmode_g) return; - vgafb_set_swcursor(0);
if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) { - gfx_move_chars(vmode_g, dest, src, movesize); + gfx_move_chars(vmode_g, dest, movesize, lines); return; }
int stride = GET_BDA(video_cols) * 2; - memmove_stride(GET_GLOBAL(vmode_g->sstart) - , text_address(dest), text_address(src) + void *dest_addr = text_address(dest), *src_addr = dest_addr + lines * stride; + memmove_stride(GET_GLOBAL(vmode_g->sstart), dest_addr, src_addr , movesize.x * 2, stride, movesize.y); }
// Clear area of screen. -void -vgafb_clear_chars(struct cursorpos dest - , struct carattr ca, struct cursorpos clearsize) +static void +vgafb_clear_chars(struct cursorpos win, struct cursorpos winsize + , struct carattr ca) { struct vgamode_s *vmode_g = get_current_mode(); if (!vmode_g) return; - vgafb_set_swcursor(0);
if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) { - gfx_clear_chars(vmode_g, dest, ca, clearsize); + gfx_clear_chars(vmode_g, win, winsize, ca); return; }
int stride = GET_BDA(video_cols) * 2; u16 attr = ((ca.use_attr ? ca.attr : 0x07) << 8) | ca.car; - memset16_stride(GET_GLOBAL(vmode_g->sstart), text_address(dest), attr - , clearsize.x * 2, stride, clearsize.y); + memset16_stride(GET_GLOBAL(vmode_g->sstart), text_address(win), attr + , winsize.x * 2, stride, winsize.y); +} + +// Scroll characters within a window on the screen +void +vgafb_scroll(struct cursorpos win, struct cursorpos winsize + , int lines, struct carattr ca) +{ + vgafb_set_swcursor(0); + if (!lines) { + // Clear window + vgafb_clear_chars(win, winsize, ca); + } else if (lines > 0) { + // Scroll the window up (eg, from page down key) + winsize.y -= lines; + vgafb_move_chars(win, winsize, lines); + + win.y += winsize.y; + winsize.y = lines; + vgafb_clear_chars(win, winsize, ca); + } else { + // Scroll the window down (eg, from page up key) + win.y -= lines; + winsize.y += lines; + vgafb_move_chars(win, winsize, lines); + + win.y += lines; + winsize.y = -lines; + vgafb_clear_chars(win, winsize, ca); + } }
// Write a character to the screen.
On Thu, Jul 21, 2016 at 11:01:10AM -0400, Kevin O'Connor wrote:
Introduce a new function vgafb_scroll() to scroll a window on the screen and update vgabios.c to use only that function for scrolling. This makes the low-level vgafb_move_chars() and vgafb_clear_chars() local to vgafb.c, and it simplifies the callers.
FYI, I have committed this change.
-Kevin