From: ghod@drycas.club.cc.cmu.edu Subject: [PATCH] Non-blinking block cursor Date: 4 May 1993 23:30:50 -0400
Greetings again:
You might remember that a while back I posted asking if anyone knew how to
make the standard text console cursor stop blinking. The replies I got
(thanks to all who sent 'em) told me that nothing could make the hardware
generated cursor stop blinking except maybe a sharp blow with a sledgehammer.
Being the stubborn (read: thick-headed) type, I decided to go ahead and create
my own non-blinking block cursor by patching the Linux console driver.
Appended to this message you will find a context diff to be applied to
linux/kernel/chr_drv/console.c that will replace the standard blinking
underline cursor with a non-blinking block cursor (just like an xterm cursor).
This patch does two things: 1) it shuts off the hardware cursor (actually,
it reduces it to 0 scan lines, which makes it invisible) and 2) it replaces
the set_cursor() function with a new function that draws a cursor on the
screen by toggling the inverse attribute on the cursor location. A few
extra calls to set_cursor() were also added to insure the cursor is un-drawn
when the cursor position changes and to insure that it will be re-drawn
correctly when switching from one virtual console to another. I'm running
with a patched kernel now and so far everything is working great. (I'm
running VMSnews which does enough VT-100 manipulation to make you vomit
and the screen is still in perfect shape).
This patch is meant to be applied to Linux version 0.99 pl9, however
it ought to work with pl8, pl7 and maybe even pl6. Also, Linus
has just made a set of ALPHA diffs available (check nic.funet.fi in the
usual place) which introduce a small change to the console driver
(specifically, the function that generates the 'beep' has been removed and
apparently migrated to a different module). I'm building a new kernel with
these diffs as I write this (with the cursor patch included) and all seems to
be going well. If you're going to use the ALPHA diffs, apply them first then
apply this patch afterwards -- you'll notice the last hunk will be offset
slightly, but other than that it should work fine.
The mods are set up such that you can chose what kind of cursor you'll
end up with when you compile the kernel. If NOBLINK is defined, the
non-blinking cursor will be used, otherwise the 'noblink' mods will be
ignored and you'll get the standard cursor back. You will notice that I
have hard-coded NOBLINK on (you'll find a #define NOBLINK right up at the
top just after the #includes) so you'll get the non-blinking cursor by
default. I thought about adding an extra line to 'make config' for this
feature, but I decided against it for simplicity's sake. And this way,
all the mods are confined to one file.
Lastly, please note that I have only tested this patch using the standard
(NORMAL_VGA) VGA mode, with color. I don't forsee any problems with SVGA
or mono modes, but I make no promises. As they say: your mileage may vary.
By all means feel free to send me bug/incompatibity reports. If it turns
out to be bullet-proof enough, I may send it to Linus and see if he thinks
it's worth putting in the standard release.
Share and enjoy!
-Bill Paul
ghod@drycas.club.cc.cmu.edu
=============================SNIP SNIP SNIP================================
*** console.c.old Thu Apr 15 19:41:00 1993
--- console.c Tue May 4 21:37:25 1993
***************
*** 35,40 ****
--- 35,45 ----
* <g-hunt@ee.utah.edu>
*/
+ /*
+ * Non-blinking software block cursor mods by Bill Paul 4/30/93
+ * <ghod@drycas.club.cc.cmu.edu>
+ */
+
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/tty.h>
***************
*** 52,57 ****
--- 57,69 ----
#include "vt_kern.h"
#define NPAR 16
+ #define NOBLINK
+
+ #ifdef NOBLINK
+ #define CURSOR_TYPE "non-blinking (software)"
+ #else
+ #define CURSOR_TYPE "hardware"
+ #endif
extern void vt_init(void);
extern void register_console(void (*proc)(const char *));
***************
*** 575,599 ****
--- 587,641 ----
static inline void hide_cursor(int currcons)
{
+ #ifdef NOBLINK
+ *(unsigned char *) (pos+1) = attr;
+ #else
outb_p(14, video_port_reg);
outb_p(0xff&((scr_end-video_mem_base)>>9), video_port_val);
outb_p(15, video_port_reg);
outb_p(0xff&((scr_end-video_mem_base)>>1), video_port_val);
+ #endif
}
static inline void set_cursor(int currcons)
+
+ /*
+ * With NOBLINK defined, the hardware cursor is turned off. Instead of
+ * moving the hardware cursor around, we toggle the reverse/normal attribute
+ * of the current screen position. This requires additional calls to
+ * set_cursor. We're not just plunking the cursor down whereever the
+ * console print routines leaves off: we need to be called once to un-draw
+ * the cursor and then again after the screen has been modified to put
+ * the cursor back. We also have to do a sanity check to insure the kernel
+ * doesn't die a screaming death trying to modify an extremely invalid screen
+ * position at boot time.
+ */
+
{
if (currcons != fg_console || console_blanked)
return;
+
+ #ifndef NOBLINK
cli();
+ #endif
if (deccm) {
+ #ifdef NOBLINK
+ if (pos)
+ *(char *) (pos+1) =
+ (*(unsigned char *)(pos+1) & 0x88) |
+ (((*(unsigned char *)(pos+1) >> 4) |
+ (*(unsigned char *)(pos+1) << 4)) & 0x77);
+ #else
outb_p(14, video_port_reg);
outb_p(0xff&((pos-video_mem_base)>>9), video_port_val);
outb_p(15, video_port_reg);
outb_p(0xff&((pos-video_mem_base)>>1), video_port_val);
+ #endif
} else
hide_cursor(currcons);
+ #ifndef NOBLINK
sti();
+ #endif
}
static void respond_string(char * p, int currcons, struct tty_struct * tty)
***************
*** 901,906 ****
--- 943,953 ----
printk("con_write: illegal tty (%d)\n", currcons);
return;
}
+
+ #ifdef NOBLINK
+ set_cursor(currcons);
+ #endif
+
while (!tty->stopped && (c = get_tty_queue(&tty->write_q)) >= 0) {
if (state == ESnormal && translate[c]) {
if (need_wrap) {
***************
*** 1331,1341 ****
gotoxy(currcons,orig_x,orig_y);
update_screen(fg_console);
printable = 1;
! printk("Console: %s %s %dx%d, %d virtual consoles\n",
can_do_color?"colour":"mono",
display_desc,
video_num_columns,video_num_lines,
! NR_CONSOLES);
register_console(console_print);
return kmem_start;
}
--- 1378,1402 ----
gotoxy(currcons,orig_x,orig_y);
update_screen(fg_console);
printable = 1;
!
! #ifdef NOBLINK
! /*
! * Turn the hardware cursor off. Actually, what we really do is reduce the
! * cursor's height to 0 scan lines, which makes it invisible. Same thing. :)
! * From here on, we never touch the hardware cursor again.
! */
! cli();
! outb_p(10,video_port_reg);
! outb_p(15,video_port_val);
! sti();
! #endif
!
! printk("Console: %s %s %dx%d, %d virtual consoles, %s cursor\n",
can_do_color?"colour":"mono",
display_desc,
video_num_columns,video_num_lines,
! NR_CONSOLES,
! CURSOR_TYPE);
register_console(console_print);
return kmem_start;
}
***************
*** 1400,1405 ****
--- 1461,1469 ----
if (new_console == fg_console || lock)
return;
lock = 1;
+ #ifdef NOBLINK
+ set_cursor(fg_console);
+ #endif
kbdsave(new_console);
get_scrmem(fg_console);
fg_console = new_console;
***************
*** 1460,1465 ****
--- 1524,1534 ----
if (!printable || currcons<0 || currcons>=NR_CONSOLES)
return;
+
+ #ifdef NOBLINK
+ set_cursor(currcons);
+ #endif
+
while ((c = *(b++)) != 0) {
if (c == 10 || c == 13 || need_wrap) {
if (c != 13)