Bug 15996

Summary: patch adds hw.syscons.sc_mouse_char sysctl variable
Product: Base System Reporter: kbyanc <kbyanc>
Component: kernAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 3.4-STABLE   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff none

Description kbyanc 2000-01-08 18:10:01 UTC
	As discussed in message thread on -hackers (see message ID
	20000106212404.A30244@dcse.fee.vutbr.cz):

		"Nearly everyone who wants to set up their national
		 locale needs to recompile the kernel, since some
		 important characters are hidden under mouse cursor."

	This is because syscons needs to munge 4 character font
	definitions to create the illusion of a graphical mouse cursor in
	text mode.

	The attached patch remedies this situation by creating a new
	sysctl variable hw.syscons.sc_mouse_char which can be used to
	redefine the base character used for creating the mouse pointer
	image at run-time. It defaults to the setting of SC_MOUSE_CHAR
	which can be used to define a preference at compile-time (courtesy
	Kazu).

	It should be noted that on most, if not all, VGA adapters are
	hardwired to copy the 0th bit of into the 9th bit of character
	fonts in the range 0xc0-0xdf, but for all other characters it just
	leaves them blank. If you move the base character for the mouse
	pointer out of this range, you will see gaps in the pointer (or
	for an even weirder effect, have the mouse character range cross 
	the boundary between 9th-bit copied and non-copied character
	definitions).

	However, this is only the case in some video modes (the most
	notable being all 80-character wide text modes, i.e. the default
	80x25). 90-character wide text modes that are available in
	-current's syscons do not perform 9th bit copying (hence how they
	reclaim pixels to use for the extra 10 columns).

	Finally, for a psycadelic experience, you can set the
	hw.syscons.sc_mouse_char to a value like 32 to overwrite the space
	character with the mouse image. Move the mouse around and free
	your mind. :)
	
		Bug reports, bug reports, how can it be
		so many bug reports for FreeBSD
		Not typos or glitches, there's more there it seems,
		like ports, docs, and man pages by hackers like me.		

  -Kelly
Comment 1 Alexey M. Zelkin 2000-01-08 20:28:23 UTC
hi,

On Sat, Jan 08, 2000 at 12:37:11PM -0500, kbyanc@posi.net wrote:
 
> >Number:         15996
> >Category:       kern
> >Synopsis:       patch adds hw.syscons.sc_mouse_char sysctl variable

Why not change its value by default to reasonable value (0x03) instead of
current default value ?

-- 
/* Alexey Zelkin                       && phantom@cris.net    */
/* Tavric National University          && phantom@crimea.edu  */
/* http://www.ccssu.crimea.ua/~phantom && phantom@FreeBSD.org */
Comment 2 kbyanc 2000-01-08 22:51:40 UTC
On Sat, 8 Jan 2000, Alexey Zelkin wrote:

> hi,
> 
> On Sat, Jan 08, 2000 at 12:37:11PM -0500, kbyanc@posi.net wrote:
>  
> > >Number:         15996
> > >Category:       kern
> > >Synopsis:       patch adds hw.syscons.sc_mouse_char sysctl variable
> 
> Why not change its value by default to reasonable value (0x03) instead of
> current default value ?
> 
> -- 
> /* Alexey Zelkin                       && phantom@cris.net    */
> /* Tavric National University          && phantom@crimea.edu  */
> /* http://www.ccssu.crimea.ua/~phantom && phantom@FreeBSD.org */
> 

  Actually, I need to correct a couple of notes in my PR. First, I
misnumbered the character cell bits, where I say 0th bit, I mean the 1st
bit (ie bit 0 is the 1st bit). The is important because I said it got
copied to the 9th bit (which is correct). The other correction is that VGA
adapters don't copy the 1st bit anyway, they copy the 8th bit. That said,
here is the answer to your question:

  The 80-column VGA text modes are actually 720 pixels wide; each
character cell is 9 pixels wide. However, the interface for specifying
character fonts is a bitmask that conveniently uses one byte (8 bits) per
row of the character cell to indicate which pixels should be on or off.
Where does the 9th bit come from? Well...

  On all VGA adapters I've seen they do not do the 9th bit copying trick I
described in the PR for any characters outside the range of 0xc0 - 0cdf
range. This range was chosen because it coincided with the line-drawing
characters in the original IBM fonts. They needed to copy the 8th bit to 
the 9th to extend the lines so they met between cells.
  If you use characters outside of this range, the hardware won't copy
the 8th bit to the 9th bit of the character cell. So you'll see an
annoying vertical line through the mouse cursor as it moves across
character cells (that line being the 9th character bit which is always
off). Presumably, the reason 0xd0 was chosen as the default for
SC_MOUSE_CHAR was to take advantage of the 9th-bit copy trick to make the
cursor look whole (actually, you'll see a bump in the mouse, which
coincides with the 8th bit of the first character cell that it is spanning
being copied and draw twice, but this is preferable to the blank lines).

  So, to finally answer your question: because it'll look bad. :)

  You really want the mouse cursor characters to be taken out of this
range to make it look good. The only problem was that some locales defined
used characters in this range which presents a problem. So, people who
were affected in this way need a way to get the pointer out of their
alphabet. For the rest of us, we'de rather the pointer "look good" :).

  Kelly

--
Kelly Yancey  -  kbyanc@posi.net  -  Richmond, VA
Analyst / E-business Development, Bell Industries  http://www.bellind.com/
Maintainer, BSD Driver Database       http://www.posi.net/freebsd/drivers/
Coordinator, Team FreeBSD        http://www.posi.net/freebsd/Team-FreeBSD/
Comment 3 kbyanc 2000-01-20 03:38:12 UTC
> In principle, any change should go into -CURRENT first, then will be
> merged to -STABLE.  Although the patch for -STABLE will be much
> different from the patch for -CURRENT in our case, I believe this
> principle will still stand.
> 
> We shall first commit the change to -CURRENT and test its concept
> for a while there, then apply the change to -STABLE.
> 
> Kazu
> 

  Here is a patch against -stable as of Jan 19, 2000 which MFC's the
functionality using ioctl rather than sysctl. I also imported the changes
to vidcontrol to facilitate setting the mouse character. I have been using
this on a couple of -stable boxen without incident for several days now.

  Kelly

--- sys/i386/include/console.h.orig	Wed Jan 19 20:59:14 2000
+++ sys/i386/include/console.h	Wed Jan 19 21:07:22 2000
@@ -161,6 +161,7 @@
 #define MOUSE_ACTION		0x07
 #define MOUSE_MOTION_EVENT	0x08
 #define MOUSE_BUTTON_EVENT	0x09
+#define MOUSE_MOUSECHAR		0x0a
 
 struct mouse_info {
 	int	operation;
@@ -168,6 +169,7 @@
 		struct mouse_data data;
 		struct mouse_mode mode;
 		struct mouse_event event;
+		int mouse_char;
 	}u;
 };
 
--- sys/alpha/include/console.h.orig	Wed Jan 19 21:02:10 2000
+++ sys/alpha/include/console.h	Wed Jan 19 21:08:27 2000
@@ -162,6 +162,7 @@
 #define MOUSE_ACTION		0x07
 #define MOUSE_MOTION_EVENT	0x08
 #define MOUSE_BUTTON_EVENT	0x09
+#define MOUSE_MOUSECHAR		0x0a
 
 struct mouse_info {
 	int	operation;
@@ -169,6 +170,7 @@
 		struct mouse_data data;
 		struct mouse_mode mode;
 		struct mouse_event event;
+		int mouse_char;
 	}u;
 };
 
--- usr.sbin/vidcontrol/vidcontrol.c.orig	Wed Jan 19 21:46:52 2000
+++ usr.sbin/vidcontrol/vidcontrol.c	Wed Jan 19 21:52:24 2000
@@ -33,6 +33,7 @@
 
 #include <ctype.h>
 #include <err.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -57,10 +58,11 @@
 static void
 usage()
 {
-	fprintf(stderr, "%s\n%s\n%s\n",
+	fprintf(stderr, "%s\n%s\n%s\n%s\n",
 "usage: vidcontrol [-r fg bg] [-b color] [-c appearance] [-d] [-l scrmap]",
-"                  [-i adapter | mode] [-L] [-m on|off] [-f size file]",
-"                  [-s number] [-t N|off] [-x] [mode] [fgcol [bgcol]] [show]");
+"                  [-i adapter | mode] [-L] [-M char] [-m on|off]",
+"                  [-f size file] [-s number] [-t N|off] [-x] [mode]",
+"                  [fgcol [bgcol]] [show]");
 	exit(1);
 }
 
@@ -390,6 +392,22 @@
 }
 
 void
+set_mouse_char(char *arg)
+{
+	struct mouse_info mouse;
+	long l;
+
+	l = strtol(arg, NULL, 0);
+	if ((l < 0) || (l > UCHAR_MAX)) {
+		warnx("argument to -M must be 0 through %d", UCHAR_MAX);
+		return;
+	}
+	mouse.operation = MOUSE_MOUSECHAR;
+	mouse.u.mouse_char = (int)l;
+	ioctl(0, CONS_MOUSECTL, &mouse);
+}
+
+void
 set_mouse(char *arg)
 {
 	struct mouse_info mouse;
@@ -529,7 +547,7 @@
 	info.size = sizeof(info);
 	if (ioctl(0, CONS_GETINFO, &info) < 0)
 		err(1, "must be on a virtual console");
-	while((opt = getopt(argc, argv, "b:c:df:i:l:Lm:r:s:t:x")) != -1)
+	while((opt = getopt(argc, argv, "b:c:df:i:l:LM:m:r:s:t:x")) != -1)
 		switch(opt) {
 			case 'b':
 				set_border_color(optarg);
@@ -552,6 +570,9 @@
 				break;
 			case 'L':
 				load_default_scrnmap();
+				break;
+			case 'M':
+				set_mouse_char(optarg);
 				break;
 			case 'm':
 				set_mouse(optarg);
--- sys/dev/syscons/syscons.c.orig	Wed Jan 19 20:52:32 2000
+++ sys/dev/syscons/syscons.c	Wed Jan 19 22:27:33 2000
@@ -41,6 +41,8 @@
 #endif
 #include "opt_syscons.h"
 
+#include <limits.h>
+
 #if NSC > 0
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -239,6 +241,7 @@
 #define SC_CONSOLE	255
 vm_offset_t         	Crtat;
 static const int	nsccons = MAXCONS+2;
+static int		sc_mouse_char = SC_MOUSE_CHAR;
 
 #define WRAPHIST(scp, pointer, offset)\
     ((scp)->history + ((((pointer) - (scp)->history) + (scp)->history_size \
@@ -1280,6 +1283,54 @@
 	    }
 	    break;
 
+	case MOUSE_MOUSECHAR:
+	    if (mouse->u.mouse_char < 0) {
+		mouse->u.mouse_char = sc_mouse_char;
+	    } else {
+		char *font = NULL;
+
+		if (mouse->u.mouse_char >= UCHAR_MAX - 4)
+		    return EINVAL;
+
+		/*
+		 * The base character for drawing the mouse pointer has changed.
+		 * Clear the pointer, restore the original font definitions,
+		 * and the redraw the pointer - mangling the new characters.
+		 */
+		s = spltty();
+		remove_mouse_image(cur_console);
+		
+		if (ISTEXTSC(cur_console) &&
+		   (cur_console->font_size != FONT_NONE)) {
+		    if (scp->font_size < 14) {
+			if (fonts_loaded & FONT_8)
+			    font = font_8;
+		    }
+		    else if (scp->font_size >= 16) {
+			if (fonts_loaded & FONT_16)
+			    font = font_16;
+		    }
+		    else {
+			if (fonts_loaded & FONT_14)
+			    font = font_8;
+		    }
+
+		    if (font != NULL) {
+			font_loading_in_progress = TRUE;
+			(*vidsw[scp->ad]->load_font)(scp->adp, 0,
+				cur_console->font_size,
+				font + (sc_mouse_char * cur_console->font_size),
+				sc_mouse_char, 4);
+			font_loading_in_progress = FALSE;
+			(*vidsw[scp->ad]->show_font)(scp->adp, 0);
+		    }
+		}
+
+		sc_mouse_char = mouse->u.mouse_char;
+		splx(s);
+	    }
+	    break;
+
 	default:
 	    return EINVAL;
 	}
@@ -4217,13 +4268,13 @@
     }
 
     if (scp->status & MOUSE_VISIBLE) {
-	if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR)
+	if ((scp->cursor_saveunder & 0xff) == sc_mouse_char)
     	    bcopy(&scp->mouse_cursor[0], cursor, scp->font_size);
-	else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 1)
+	else if ((scp->cursor_saveunder & 0xff) == sc_mouse_char + 1)
     	    bcopy(&scp->mouse_cursor[32], cursor, scp->font_size);
-	else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 2)
+	else if ((scp->cursor_saveunder & 0xff) == sc_mouse_char + 2)
     	    bcopy(&scp->mouse_cursor[64], cursor, scp->font_size);
-	else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 3)
+	else if ((scp->cursor_saveunder & 0xff) == sc_mouse_char + 3)
     	    bcopy(&scp->mouse_cursor[96], cursor, scp->font_size);
 	else
 	    bcopy(font_buffer+((scp->cursor_saveunder & 0xff)*scp->font_size),
@@ -4551,16 +4602,16 @@
 #endif
     font_loading_in_progress = TRUE;
     (*vidsw[scp->ad]->load_font)(scp->adp, 0, 32, scp->mouse_cursor, 
-			   SC_MOUSE_CHAR, 4); 
+			   sc_mouse_char, 4); 
     font_loading_in_progress = FALSE;
 
-    writew(crt_pos, (*(scp->mouse_pos) & 0xff00) | SC_MOUSE_CHAR);
+    writew(crt_pos, (*(scp->mouse_pos) & 0xff00) | sc_mouse_char);
     writew(crt_pos+2*scp->xsize,
-	   (*(scp->mouse_pos + scp->xsize) & 0xff00) | (SC_MOUSE_CHAR + 2));
+	   (*(scp->mouse_pos + scp->xsize) & 0xff00) | (sc_mouse_char + 2));
     if (scp->mouse_xpos < (scp->xsize-1)*8) {
-    	writew(crt_pos + 2, (*(scp->mouse_pos + 1) & 0xff00) | (SC_MOUSE_CHAR + 1));
+    	writew(crt_pos + 2, (*(scp->mouse_pos + 1) & 0xff00) | (sc_mouse_char + 1));
     	writew(crt_pos+2*scp->xsize + 2,
-	       (*(scp->mouse_pos + scp->xsize + 1) & 0xff00) | (SC_MOUSE_CHAR + 3));
+	       (*(scp->mouse_pos + scp->xsize + 1) & 0xff00) | (sc_mouse_char + 3));
     }
     mark_for_update(scp, scp->mouse_pos - scp->scr_buf);
     mark_for_update(scp, scp->mouse_pos + scp->xsize + 1 - scp->scr_buf);

--
Kelly Yancey  -  kbyanc@posi.net  -  Richmond, VA
Analyst / E-business Development, Bell Industries  http://www.bellind.com/
Maintainer, BSD Driver Database       http://www.posi.net/freebsd/drivers/
Coordinator, Team FreeBSD        http://www.posi.net/freebsd/Team-FreeBSD/
Comment 4 yokota freebsd_committer freebsd_triage 2000-01-27 13:16:43 UTC
State Changed
From-To: open->closed

Committed to both -CURRENT and -STABLE.  Thank you.