Index: sys/dev/vt/hw/fb/vt_fb.c =================================================================== --- sys/dev/vt/hw/fb/vt_fb.c +++ sys/dev/vt/hw/fb/vt_fb.c @@ -341,10 +341,8 @@ y = row * vf->vf_height + vw->vw_draw_area.tr_begin.tp_row; - c = VTBUF_GET_FIELD(&vw->vw_buf, row, col); + vtbuf_getchar(&vw->vw_buf, row, col, &c, &fg, &bg); pattern = vtfont_lookup(vf, c); - vt_determine_colors(c, - VTBUF_ISCURSOR(&vw->vw_buf, row, col), &fg, &bg); vt_fb_bitblt_bitmap(vd, vw, pattern, NULL, vf->vf_width, vf->vf_height, Index: sys/dev/vt/hw/vga/vt_vga.c =================================================================== --- sys/dev/vt/hw/vga/vt_vga.c +++ sys/dev/vt/hw/vga/vt_vga.c @@ -645,10 +645,9 @@ col = (i - vw->vw_draw_area.tr_begin.tp_col) / vf->vf_width; row = (y - vw->vw_draw_area.tr_begin.tp_row) / vf->vf_height; - c = VTBUF_GET_FIELD(vb, row, col); + vtbuf_getchar(vb, row, col, &c, &fg, &bg); src = vtfont_lookup(vf, c); - vt_determine_colors(c, VTBUF_ISCURSOR(vb, row, col), &fg, &bg); if ((used_colors_list[fg] & 0x1) != 0x1) used_colors++; if ((used_colors_list[bg] & 0x2) != 0x2) @@ -868,9 +867,7 @@ * Get next character and its associated fg/bg * colors. */ - c = VTBUF_GET_FIELD(vb, row, col); - vt_determine_colors(c, VTBUF_ISCURSOR(vb, row, col), - &fg, &bg); + vtbuf_getchar(vb, row, col, &c, &fg, &bg); /* * Convert character to CP437, which is the Index: sys/dev/vt/vt.h =================================================================== --- sys/dev/vt/vt.h +++ sys/dev/vt/vt.h @@ -63,6 +63,8 @@ #endif #define VT_CONSWINDOW 0 +#define VT_DESTRUCTIVE_CURSOR 0x2212 +#define VT_CURSOR_BLINK_RATE (hz / 2) #if defined(SC_TWOBUTTON_MOUSE) || defined(VT_TWOBUTTON_MOUSE) #define VT_MOUSE_PASTEBUTTON MOUSE_BUTTON3DOWN /* right button */ @@ -197,6 +199,7 @@ int vb_roffset; /* (b) History rows offset. */ int vb_curroffset; /* (b) Saved rows offset. */ term_pos_t vb_cursor; /* (u) Cursor position. */ + int vb_cursor_attrs; /* (u) Cursor style attrs */ term_pos_t vb_mark_start; /* (b) Copy region start. */ term_pos_t vb_mark_end; /* (b) Copy region end. */ int vb_mark_last; /* Last mouse event. */ @@ -216,6 +219,8 @@ void vtbuf_init_early(struct vt_buf *); void vtbuf_init(struct vt_buf *, const term_pos_t *); void vtbuf_grow(struct vt_buf *, const term_pos_t *, unsigned int); +void vtbuf_getchar(const struct vt_buf *vb, u_int row, u_int col, + term_char_t *c, term_color_t *fg, term_color_t *bg); void vtbuf_putchar(struct vt_buf *, const term_pos_t *, term_char_t); void vtbuf_cursor_position(struct vt_buf *, const term_pos_t *); void vtbuf_scroll_mode(struct vt_buf *vb, int yes); @@ -296,6 +301,7 @@ struct proc *vw_proc; struct vt_mode vw_smode; /* switch mode */ struct callout vw_proc_dead_timer; + struct callout vw_cursor_blinker; /* (?) Blinking cursor timer */ struct vt_window *vw_switch_to; }; @@ -436,7 +442,7 @@ /* Utilities. */ void vt_compute_drawable_area(struct vt_window *); -void vt_determine_colors(term_char_t c, int cursor, +void vt_determine_colors(term_char_t c, int invert, term_color_t *fg, term_color_t *bg); int vt_is_cursor_in_area(const struct vt_device *vd, const term_rect_t *area); Index: sys/dev/vt/vt_buf.c =================================================================== --- sys/dev/vt/vt_buf.c +++ sys/dev/vt/vt_buf.c @@ -635,6 +635,21 @@ } void +vtbuf_getchar(const struct vt_buf *vb, u_int row, u_int col, term_char_t *c, + term_color_t *fg, term_color_t *bg) +{ + int is_cursor, char_cursor; + + is_cursor = VTBUF_ISCURSOR(vb, row, col); + char_cursor = (vb->vb_cursor_attrs >> 16) & + CONS_CHAR_CURSOR; + *c = VTBUF_GET_FIELD(vb, row, col); + vt_determine_colors(*c, is_cursor && !char_cursor, fg, bg); + if (is_cursor && char_cursor) + *c = vb->vb_cursor_attrs & 0xffff; +} + +void vtbuf_putchar(struct vt_buf *vb, const term_pos_t *p, term_char_t c) { term_char_t *row; Index: sys/dev/vt/vt_core.c =================================================================== --- sys/dev/vt/vt_core.c +++ sys/dev/vt/vt_core.c @@ -178,6 +178,8 @@ #endif static void vt_suspend_handler(void *priv); static void vt_resume_handler(void *priv); +static void vt_change_cursor_style(struct vt_device *vd, int attrs); +static void vt_blink_cursor(void *arg); SET_DECLARE(vt_drv_set, struct vt_driver); @@ -1063,13 +1065,10 @@ } void -vt_determine_colors(term_char_t c, int cursor, +vt_determine_colors(term_char_t c, int invert, term_color_t *fg, term_color_t *bg) { term_color_t tmp; - int invert; - - invert = 0; *fg = TCHAR_FGCOLOR(c); if (TCHAR_FORMAT(c) & TF_BOLD) @@ -1079,9 +1078,7 @@ *bg = TCOLOR_LIGHT(*bg); if (TCHAR_FORMAT(c) & TF_REVERSE) - invert ^= 1; - if (cursor) - invert ^= 1; + invert = !invert; if (invert) { tmp = *fg; @@ -1559,6 +1556,27 @@ VT_UNLOCK(vd); } +static void +vt_change_cursor_style(struct vt_device *vd, int attrs) +{ + struct vt_window *vw = vd->vd_curwindow; + int blink_active; + + blink_active = callout_active(&vw->vw_cursor_blinker); + vw->vw_buf.vb_cursor_attrs = attrs << 16; + + if (attrs & CONS_CHAR_CURSOR) + vw->vw_buf.vb_cursor_attrs |= VT_DESTRUCTIVE_CURSOR; + if (attrs & CONS_BLINK_CURSOR && !blink_active) { + callout_reset(&vw->vw_cursor_blinker, VT_CURSOR_BLINK_RATE, + &vt_blink_cursor, vw); + } else if (!(attrs & CONS_BLINK_CURSOR) && blink_active) { + callout_stop(&vw->vw_cursor_blinker); + vtbuf_cursor_visibility(&vw->vw_buf, 1); + vt_flush(vd); + } +} + static int vt_change_font(struct vt_window *vw, struct vt_font *vf) { @@ -2205,6 +2223,9 @@ case CONS_BLANKTIME: /* XXX */ return (0); + case CONS_CURSORTYPE: + vt_change_cursor_style(vd, *(int *)data & CONS_CURSOR_ATTRS); + return 0; case CONS_GET: /* XXX */ *(int *)data = M_CG640x480; @@ -2564,6 +2585,7 @@ terminal_set_winsize(tm, &wsz); vd->vd_windows[window] = vw; callout_init(&vw->vw_proc_dead_timer, 0); + callout_init(&vw->vw_cursor_blinker, 0); return (vw); } @@ -2588,6 +2610,7 @@ } if (!(vw->vw_flags & VWF_READY)) { callout_init(&vw->vw_proc_dead_timer, 0); + callout_init(&vw->vw_cursor_blinker, 0); terminal_maketty(vw->vw_terminal, "v%r", VT_UNIT(vw)); vw->vw_flags |= VWF_READY; if (vw->vw_flags & VWF_CONSOLE) { @@ -2844,3 +2867,13 @@ vt_proc_window_switch(vd->vd_savedwindow); vd->vd_savedwindow = NULL; } + +static void +vt_blink_cursor(void *arg) +{ + struct vt_window *vw = arg; + vtbuf_cursor_visibility(&vw->vw_buf, + !(vw->vw_buf.vb_flags & VBF_CURSOR)); + vt_flush(vw->vw_device); + callout_schedule(&vw->vw_cursor_blinker, VT_CURSOR_BLINK_RATE); +}