[PATCH] devc-con: software block cursor for console

Block cursor has much better visibility than the
default underline cursor, but setting VGA hardware cursor
in block mode isn’t pretty, as it blinks too fast.

This modification against devc-con will add a software rendered
block cursor which won’t blink (just like FreeBSD console?).

(The blinking hardware cursor is still enabled in underline mode,
in case you lost it in a reverseful screen.)

  • The source for devc-con to patch is in 6.1 CDROM, Character DDK.

    kabe

Index: devc/con/tto.c

RCS file: /root6.1/CVSroot/devc-con-jp/devc/con/tto.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.2.1
diff -u -r1.1.1.1 -r1.1.2.1
— devc/con/tto.c 2002/12/18 18:31:41 1.1.1.1
+++ devc/con/tto.c 2003/03/27 19:05:00 1.1.2.1
@@ -192,6 +192,12 @@
static int Screen_color = 1;
static int disable_color;

+/* software cursor */
+#if 1 /SOFTCURSOR/
+enum softcur_onoff_t { CUR_OFF=0, CUR_ON=1 };
+static int softcur_show(struct state_entry stp, enum softcur_onoff_t set);
+#endif
+
/

  • Protocol emulation flags
  • The low byte will be sent out with a qnx_ioctl()
    @@ -698,7 +704,7 @@
    break;
    case ‘|’:
    gr = s->g[s->gr = 3];
  •   					break;
    
  •   					break; /*{*/
    

case ‘}’:
gr = s->g[s->gr = 2];
break;
@@ -770,10 +776,10 @@
s->attr &= ~UNDERLINE;
s->attribute = map_attr( s->attr, s->colour, s );
break;

  •   			case '{':						/* Blink on */
    
  •   			case '{':						/* Blink on } */
    

s->attr |= BLINK;
s->attribute |= 0x80;

  •   				break;
    
  •   				break; /*{*/
    

case ‘}’: /* Blink off */
s->attr &= ~BLINK;
s->attribute &= ~0x80;
@@ -1782,6 +1788,9 @@
}

if(cur) {

  •   /*erase softcursor first*/
    
  •   softcur_show(cur, CUR_OFF);
    

/*

  • Limit QNX cursor to visible screen, even if BIOS moves it off screen
  • (which on an IBM PC makes the cursor disappear)
    @@ -1833,7 +1842,10 @@
  • Restore new screen contents
    */
    new->screen = screen;
  •   softcur_show(new, CUR_OFF);
    

memcpy( new->screen, new->buffer, new->buffer_size);

  •   softcur_show(new, CUR_ON);
    

}

invisible = be_invisible;
@@ -1856,8 +1868,10 @@

static int con_put_char_attr( char row, char col, char C, char attr, int n,
struct state_entry *stp ) {

  • /XXXoptimize/softcur_show(stp, CUR_OFF);
    memsetw( (unsigned short *)(stp->screen + ((((unsigned)row) * stp->screen_width) + col) * 2),
    (attr << :sunglasses: | C, n );
  • /XXXoptimize/softcur_show(stp, CUR_ON);
    return(0);
    }

@@ -1866,10 +1880,12 @@
unsigned char *screen = stp->screen;

screen += ((((unsigned)row) * stp->screen_width) + col) * 2;

  • /XXXoptimize/softcur_show(stp, CUR_OFF);
    while( n-- ) {
    *screen++ = *str++;
    *screen++ = attr;
    }
  • /XXXoptimize/softcur_show(stp, CUR_ON);
    return(0);
    }

@@ -1886,12 +1902,47 @@
return(0);
}

+#if 1 /SOFTCURSOR {/
+/* Emulates a “hardware” cursor; thus there’s

    • only one of it and exists across virtual screens.
  • */
    +static struct softcur_t {
  • int prev_row, prev_col;
  • enum softcur_onoff_t onoff;
    +} softcur = {
  • 24, 3, /* initial weirdplace debug;
  •    * if this place reverses, something is wrong */
    
  • CUR_OFF /* initial state /
    +};
    +/
    reversevideo a position in physical screen /
    +/
    TODO: shouldn’t do anything if “invisible” (non-text mode) */
    +static int scr_inverse1( unsigned char row, unsigned char col, struct state_entry *stp)
    +{
  • register unsigned char *p = screen + ((((unsigned)row) * stp->screen_width) + col) * 2 + 1;
  • /* if (invisible) return 0; */
  • *p = (*p & 0x88) | (((*p & 0x07) << 4) | ((*p & 0x70) >> 4));
  • return 0;
    +}
    +/*
    • show/hide the softcursor.
    • When modifying a screen buffer,
    • you must sandwich it with CUR_OFF and CUR_ON call to avoid
    • cursor corruption.
  • */
    +static int softcur_show(struct state_entry *stp, enum softcur_onoff_t set)
    +{
  • if (softcur.onoff == set) return 0;
  • softcur.onoff = !softcur.onoff;
  • return scr_inverse1(stp->cursor_y, stp->cursor_x, stp);
    +}
    +#endif /}/

static int con_set_curs_type( unsigned type, char hidden ) {
unsigned cursor;
unsigned port;
unsigned ctype[] = {
0x0f00, /* off */

  •   0x0d0e, /* underline */
    
  •   0x0e0f, /* underline at bottom */
    

0x000e /* block */
};

@@ -1906,6 +1957,7 @@

  • Keep BIOS up to date
    */
    *((unsigned short *)(bios + 0x60)) = cursor;
  • /* set VGA hardware cursor size */
    port = *((unsigned char )(bios + 0x63)) | (((unsigned char *)(bios + 0x64)) << :sunglasses:;
    out8( port, 10 );
    out8( port+1, cursor >> 8 );
    @@ -1927,13 +1979,21 @@
    *((unsigned char *)(bios + 0x50)) = col;
    *((unsigned char *)(bios + 0x51)) = row;
  • offset = ((unsigned) row) * stp->screen_width + col + Screen_origin / 2;
  • if (softcur.onoff == CUR_ON /&& softcur.blink/) {

  •   /* erase & draw */
    
  •   scr_inverse1(softcur.prev_row, softcur.prev_col, stp);
    
  •   scr_inverse1(row, col, stp);
    
  • }

  • softcur.prev_row=row; softcur.prev_col=col;

  • /* set VGA hardware cursor location */

  • offset = ((unsigned) row) * stp->screen_width + col + Screen_origin / 2;
    port = *((unsigned char )(bios + 0x63)) | (((unsigned char *)(bios + 0x64)) << :sunglasses:;
    out8( port, 14 );
    out8( port+1, offset >> 8 );
    out8( port, 15 );
    out8( port+1, offset & 0xFF );

return(0);
}

@@ -1941,8 +2001,10 @@
unsigned char *screen = stp->screen;

screen += ((((unsigned)row) * stp->screen_width) + col) * 2;

  • /XXXoptimize/softcur_show(stp, CUR_OFF);
    memmove( screen, screen + 2, n*2);
    *((unsigned short )(screen + (n2))) = (fill << :sunglasses: | ’ ';
  • /XXXoptimize/softcur_show(stp, CUR_ON);
    return(0);
    }

@@ -1950,8 +2012,10 @@
unsigned char *screen = stp->screen;

screen += ((((unsigned)row) * stp->screen_width) + col) * 2;

  • /XXXoptimize/softcur_show(stp, CUR_OFF);
    memmove( screen + 2, screen, n*2);
    *((unsigned short *)screen) = (fill << :sunglasses: | ’ ';
  • /XXXoptimize/softcur_show(stp, CUR_ON);
    return(0);
    }

@@ -1981,8 +2045,10 @@
}
#endif
addr = screen + (top * stp->screen_width*2);

  • /XXXoptimize/softcur_show(stp, CUR_OFF);
    memmove( addr + stp->screen_width2, addr, (bottom-top) * stp->screen_width2);
    memsetw( (unsigned short )(screen + (top * stp->screen_width2)), (fill << :sunglasses: | ’ ', stp->screen_width );
  • /XXXoptimize/softcur_show(stp, CUR_ON);
    return(0);
    }

@@ -2010,8 +2076,10 @@
}
#endif
addr = screen + (top * stp->screen_width*2);

  • /XXXoptimize/softcur_show(stp, CUR_OFF);
    memmove( addr, addr + stp->screen_width2, (bottom-top) * stp->screen_width2);
    memsetw( (unsigned short )(screen + (bottom * stp->screen_width2)), (fill << :sunglasses: | ’ ', stp->screen_width );
  • /XXXoptimize/softcur_show(stp, CUR_ON);
    return(0);
    }

@@ -2056,7 +2124,6 @@
stp->esc_flag = STATE_NONE;

if(first) {

  •   first = 0;
    

stp->cursor_x = *(unsigned char *)(bios + 0x50);
stp->cursor_y = *(unsigned char *)(bios + 0x51);
stp->screen = screen;
@@ -2076,6 +2143,13 @@
}

reset_term(stp);

  • if (first) {
  •   con_set_curs_pos( stp->cursor_y, stp->cursor_x, 0, stp ); /*init softcur.prev_x */
    
  •   con_set_curs_type( stp->cursor_type & 0x07, 0 );
    
  •   softcur_show(stp, CUR_ON); /* showit */
    
  •   }
    
  • if (first) first=0;
    }