Index: sys/dev/misc/syscons/scvgarndr.c
===================================================================
RCS file: /home/dcvs/src/sys/dev/misc/syscons/scvgarndr.c,v
retrieving revision 1.15
diff -u -r1.15 scvgarndr.c
--- sys/dev/misc/syscons/scvgarndr.c	19 Feb 2006 09:16:26 -0000	1.15
+++ sys/dev/misc/syscons/scvgarndr.c	1 May 2006 10:56:03 -0000
@@ -140,6 +140,35 @@
 {
 }
 
+static void
+remove_mouse(scr_stat *scp, int x, int y)
+{
+	int col, row, pos;
+	int i, j;
+
+	/* XXX: this shouldn't be necessary */
+	if (scp->scr.vtb_buffer == NULL)
+		return;
+
+	/* erase the mouse cursor image */
+	col = x / 8 - scp->xoff;
+	row = y / scp->font_size - scp->yoff;
+
+	for (i = row; i < row + 3; i++) {
+		for (j = col; j < col + 2; j++) {
+			pos = i * scp->xsize + j;
+			if (pos < scp->xsize * scp->ysize) {
+				(*scp->rndr->draw)(scp, pos, 1,
+				    sc_inside_cutmark(scp, pos));
+				*(scp->old_vtb.vtb_buffer + pos) =
+				    *(scp->vtb.vtb_buffer + pos);
+				if (pos == scp->cursor_pos)
+					sc_draw_cursor_image(scp);
+			}
+		}
+	}
+}
+
 /* text mode renderer */
 
 static void
@@ -386,18 +415,13 @@
     }
 }
 
-static void
-remove_txtmouse(scr_stat *scp, int x, int y)
-{
-}
-
 static void 
 vga_txtmouse(scr_stat *scp, int x, int y, int on)
 {
 	if (on)
 		draw_txtmouse(scp, x, y);
 	else
-		remove_txtmouse(scp, x, y);
+ 		remove_mouse(scp, x, y);
 }
 
 #endif /* SC_NO_CUTPASTE */
@@ -774,7 +798,7 @@
 		}
 	} else {
 		if (scp->status & VR_CURSOR_ON)
-			draw_pxlcursor_direct(scp, at, on, flip);
+			vga_vgadraw_direct(scp, at, 1, flip);
 		scp->status &= ~VR_CURSOR_ON;
 	}
 	if (blink)
@@ -802,7 +826,7 @@
 		}
 	} else {
 		if (scp->status & VR_CURSOR_ON)
-			draw_pxlcursor_planar(scp, at, on, flip);
+			vga_vgadraw_planar(scp, at, 1, flip);
 		scp->status &= ~VR_CURSOR_ON;
 	}
 	if (blink)
@@ -938,30 +962,13 @@
 	outw(GDCIDX, 0x0003);		/* data rotate/function select */
 }
 
-static void
-remove_pxlmouse(scr_stat *scp, int x, int y)
-{
-	int col, row;
-	int pos;
-	int i;
-
-	/* erase the mouse cursor image */
-	col = x/8 - scp->xoff;
-	row = y/scp->font_size - scp->yoff;
-	pos = row*scp->xsize + col;
-	i = (col < scp->xsize - 1) ? 2 : 1;
-	(*scp->rndr->draw)(scp, pos, i, FALSE);
-	if (row < scp->ysize - 1)
-		(*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
-}
-
 static void 
 vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
 {
 	if (on)
 		draw_pxlmouse_direct(scp, x, y);
 	else
-		remove_pxlmouse(scp, x, y);
+		remove_mouse(scp, x, y);
 }
 
 static void 
@@ -970,7 +977,7 @@
 	if (on)
 		draw_pxlmouse_planar(scp, x, y);
 	else
-		remove_pxlmouse(scp, x, y);
+		remove_mouse(scp, x, y);
 }
 
 #endif /* SC_NO_CUTPASTE */
Index: sys/dev/misc/syscons/syscons.c
===================================================================
RCS file: /home/dcvs/src/sys/dev/misc/syscons/syscons.c,v
retrieving revision 1.23
diff -u -r1.23 syscons.c
--- sys/dev/misc/syscons/syscons.c	30 Oct 2005 10:07:10 -0000	1.23
+++ sys/dev/misc/syscons/syscons.c	9 May 2006 21:04:42 -0000
@@ -148,7 +148,7 @@
 static void init_scp(sc_softc_t *sc, int vty, scr_stat *scp);
 static timeout_t scrn_timer;
 static int and_region(int *s1, int *e1, int s2, int e2);
-static void scrn_update(scr_stat *scp, int show_cursor);
+static void scrn_update(scr_stat *scp);
 
 #if NSPLASH > 0
 static int scsplash_callback(int event, void *arg);
@@ -1553,7 +1553,7 @@
      */
 
     if (!ISGRAPHSC(scp) && !(scp->sc->flags & SC_SCRN_BLANKED))
-	scrn_update(scp, TRUE);
+	scrn_update(scp);
 }
 
 static void
@@ -1633,7 +1633,7 @@
     /* Update the screen */
     scp = sc->cur_scp;		/* cur_scp may have changed... */
     if (!ISGRAPHSC(scp) && !(sc->flags & SC_SCRN_BLANKED))
-	scrn_update(scp, TRUE);
+	scrn_update(scp);
 
 #if NSPLASH > 0
     /* should we activate the screen saver? */
@@ -1658,12 +1658,14 @@
 }
 
 static void 
-scrn_update(scr_stat *scp, int show_cursor)
+scrn_update(scr_stat *scp)
 {
-    int start;
-    int end;
     int s;
     int e;
+    int start = 0;
+    int end = 0;
+    int cursor_gone = 0;
+    int oldcursor_gone = 0;
 
     /* assert(scp == scp->sc->cur_scp) */
 
@@ -1699,68 +1701,79 @@
     }
 #endif
 
-    /* update screen image */
-    if (scp->start <= scp->end)  {
-	if (scp->mouse_cut_end >= 0) {
-	    /* there is a marked region for cut & paste */
-	    if (scp->mouse_cut_start <= scp->mouse_cut_end) {
-		start = scp->mouse_cut_start;
-		end = scp->mouse_cut_end;
-	    } else {
-		start = scp->mouse_cut_end;
-		end = scp->mouse_cut_start - 1;
-	    }
+    /* update cutmark */
+    if ((scp->mouse_cut_start != scp->mouse_oldcut_start) ||
+	(scp->mouse_cut_end != scp->mouse_oldcut_end)) {
+	start = imin(scp->mouse_cut_start, scp->mouse_oldcut_start);
+	end = imax(scp->mouse_cut_end, scp->mouse_oldcut_end);
+	if (start > end) {
 	    s = start;
-	    e = end;
-	    /* does the cut-mark region overlap with the update region? */
-	    if (and_region(&s, &e, scp->start, scp->end)) {
-		(*scp->rndr->draw)(scp, s, e - s + 1, TRUE);
-		s = 0;
-		e = start - 1;
-		if (and_region(&s, &e, scp->start, scp->end))
-		    (*scp->rndr->draw)(scp, s, e - s + 1, FALSE);
-		s = end + 1;
-		e = scp->xsize*scp->ysize - 1;
-		if (and_region(&s, &e, scp->start, scp->end))
-		    (*scp->rndr->draw)(scp, s, e - s + 1, FALSE);
-	    } else {
-		(*scp->rndr->draw)(scp, scp->start,
-				   scp->end - scp->start + 1, FALSE);
-	    }
+	    start = end;
+	    end = s - 1;
+	}
+	for (e = start; e <= end; e++) {
+	    (*scp->rndr->draw)(scp, e, 1, sc_inside_cutmark(scp, e));
+	    if (e == scp->cursor_pos)
+		cursor_gone++;
+	    if (e == scp->cursor_oldpos)
+		oldcursor_gone++;
+	    scp->old_vtb.vtb_buffer[e] = scp->vtb.vtb_buffer[e];
+	}
+	if ((scp->mouse_cut_end >= 0) &&
+	    (scp->mouse_cut_start > scp->mouse_cut_end)) {
+	    scp->mouse_oldcut_start = scp->mouse_cut_end;
+	    scp->mouse_oldcut_end = scp->mouse_cut_start - 1;
 	} else {
-	    (*scp->rndr->draw)(scp, scp->start,
-			       scp->end - scp->start + 1, FALSE);
+	    scp->mouse_oldcut_start = scp->mouse_cut_start;
+	    scp->mouse_oldcut_end = scp->mouse_cut_end;
 	}
     }
 
-    /* we are not to show the cursor and the mouse pointer... */
-    if (!show_cursor) {
-        scp->end = 0;
-        scp->start = scp->xsize*scp->ysize - 1;
-	--scp->sc->videoio_in_progress;
-	return;
+    /* update differences from last scrn_update */
+    if (scp->start <= scp->end) {
+	for (s = e = scp->start; e <= scp->end; e++) {
+	    if (scp->old_vtb.vtb_buffer[e] == scp->vtb.vtb_buffer[e]) {
+		if (s < e) {
+		    (*scp->rndr->draw)(scp, s, e - s, FALSE);
+		    if ((scp->cursor_pos >= s) && (scp->cursor_pos < e))
+			cursor_gone++;
+		    if ((scp->cursor_oldpos >= s) && (scp->cursor_oldpos < e))
+			oldcursor_gone++;
+		    s = e;
+		}
+		s++;
+	    } else {
+		scp->old_vtb.vtb_buffer[e] = scp->vtb.vtb_buffer[e];
+	    }
+	}
+	if (s < e) {
+	    (*scp->rndr->draw)(scp, s, e - s, FALSE);
+	    if ((scp->cursor_pos >= s) && (scp->cursor_pos < e))
+		cursor_gone++;
+	    if ((scp->cursor_oldpos >= s) && (scp->cursor_oldpos < e))
+		oldcursor_gone++;
+	    for (end = s; end < e; end++)
+		scp->old_vtb.vtb_buffer[end] = scp->vtb.vtb_buffer[end];
+	}
     }
 
     /* update cursor image */
     if (scp->status & CURSOR_ENABLED) {
-	s = scp->start;
-	e = scp->end;
-        /* did cursor move since last time ? */
-        if (scp->cursor_pos != scp->cursor_oldpos) {
-            /* do we need to remove old cursor image ? */
-            if (!and_region(&s, &e, scp->cursor_oldpos, scp->cursor_oldpos))
-                sc_remove_cursor_image(scp);
-            sc_draw_cursor_image(scp);
-        } else {
-            if (and_region(&s, &e, scp->cursor_pos, scp->cursor_pos))
+        /* did cursor move since last time? */
+	if (scp->cursor_pos != scp->cursor_oldpos) {
+	    if (!oldcursor_gone)
+		/* cursor moved but has not been overwritten */
+		sc_remove_cursor_image(scp);
+	    sc_draw_cursor_image(scp);
+	} else {
+	    if (cursor_gone)
 		/* cursor didn't move, but has been overwritten */
 		sc_draw_cursor_image(scp);
 	    else if (scp->sc->flags & SC_BLINK_CURSOR)
 		/* if it's a blinking cursor, update it */
 		(*scp->rndr->blink_cursor)(scp, scp->cursor_pos,
-					   sc_inside_cutmark(scp,
-					       scp->cursor_pos));
-        }
+		    sc_inside_cutmark(scp, scp->cursor_pos));
+	}
     }
 
 #ifndef SC_NO_CUTPASTE
@@ -2329,6 +2342,10 @@
     if (sc->old_scp->kbd_mode == K_XLATE)
 	save_kbd_state(sc->old_scp);
 
+    /* set up the buffer for scrn_update() */
+    sc_vtb_init(&sc->new_scp->old_vtb, VTB_MEMORY, sc->new_scp->xsize,
+	sc->new_scp->ysize, NULL, FALSE);
+
     /* set up the video for the new screen */
     scp = sc->cur_scp = sc->new_scp;
     if (sc->old_scp->mode != scp->mode || ISUNKNOWNSC(sc->old_scp))
@@ -2336,6 +2353,7 @@
     else
 	sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
 		    (void *)sc->adp->va_window, FALSE);
+    sc_vtb_destroy(&sc->old_scp->old_vtb);
     scp->status |= MOUSE_HIDDEN;
     sc_move_cursor(scp, scp->xpos, scp->ypos);
     if (!ISGRAPHSC(scp))
@@ -2448,7 +2466,8 @@
     static scr_stat main_console;
     static dev_t main_devs[MAXCONS];
     static struct tty main_tty;
-    static u_short sc_buffer[ROW*COL];	/* XXX */
+    static uint16_t sc_buffer[ROW*COL];
+    static uint16_t sc_prev_buffer[ROW*COL];
 #ifndef SC_NO_FONT_LOADING
     static u_char font_8[256*8];
     static u_char font_14[256*14];
@@ -2535,6 +2554,8 @@
 	    init_scp(sc, sc->first_vty, scp);
 	    sc_vtb_init(&scp->vtb, VTB_MEMORY, scp->xsize, scp->ysize,
 			(void *)sc_buffer, FALSE);
+	    sc_vtb_init(&scp->old_vtb, VTB_MEMORY, scp->xsize, scp->ysize,
+			(void *)sc_prev_buffer, FALSE);
 	    if (sc_init_emulator(scp, SC_DFLT_TERM))
 		sc_init_emulator(scp, "*");
 	    (*scp->tsw->te_default_attr)(scp,
@@ -2747,6 +2768,11 @@
 	sc_vtb_destroy(&old);
     }
 
+    old = scp->old_vtb;
+    sc_vtb_init(&new, VTB_MEMORY, scp->xsize, scp->ysize, NULL, wait);
+    scp->old_vtb = new;
+    sc_vtb_destroy(&old);
+
 #ifndef SC_NO_SYSMOUSE
     /* move the mouse cursor at the center of the screen */
     sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2);
@@ -2828,6 +2854,7 @@
 	}
     }
     sc_vtb_init(&scp->vtb, VTB_MEMORY, 0, 0, NULL, FALSE);
+    sc_vtb_init(&scp->old_vtb, VTB_MEMORY, 0, 0, NULL, FALSE);
     sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, 0, 0, NULL, FALSE);
     scp->xoff = scp->yoff = 0;
     scp->xpos = scp->ypos = 0;
@@ -2841,6 +2868,8 @@
     scp->cursor_height = imin(sc->cursor_height, scp->font_size);
     scp->mouse_cut_start = scp->xsize*scp->ysize;
     scp->mouse_cut_end = -1;
+    scp->mouse_oldcut_start = scp->mouse_cut_start;
+    scp->mouse_oldcut_end = scp->mouse_cut_end;
     scp->mouse_signal = 0;
     scp->mouse_pid = 0;
     scp->mouse_proc = NULL;
Index: sys/dev/misc/syscons/syscons.h
===================================================================
RCS file: /home/dcvs/src/sys/dev/misc/syscons/syscons.h,v
retrieving revision 1.15
diff -u -r1.15 syscons.h
--- sys/dev/misc/syscons/syscons.h	26 May 2005 16:24:33 -0000	1.15
+++ sys/dev/misc/syscons/syscons.h	9 May 2006 20:29:56 -0000
@@ -251,6 +251,7 @@
 	struct sc_rndr_sw *rndr;		/* renderer */
 	sc_vtb_t	scr;
 	sc_vtb_t	vtb;
+	sc_vtb_t	old_vtb;
 
 	int 		xpos;			/* current X position */
 	int 		ypos;			/* current Y position */
@@ -289,6 +290,8 @@
 	short		mouse_buttons;		/* mouse buttons */
 	int		mouse_cut_start;	/* mouse cut start pos */
 	int		mouse_cut_end;		/* mouse cut end pos */
+	int		mouse_oldcut_start;	/* previous cut start pos */
+	int		mouse_oldcut_end;	/* previous cut end pos */
 	struct proc 	*mouse_proc;		/* proc* of controlling proc */
 	pid_t 		mouse_pid;		/* pid of controlling proc */
 	int		mouse_signal;		/* signal # to report with */
