
From: "Antonino A. Daplas" <adaplas@hotpop.com>

This patch adds support for the bold attribute for monochrome framebuffers.
 This fixes a regression from 2.4 where bold, underline and reverse
attributes are supported.

Signed-off-by: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/video/console/fbcon.c |  121 +++++++++++++++++++++-------------
 25-akpm/drivers/video/console/fbcon.h |    4 -
 25-akpm/drivers/video/fbmem.c         |    3 
 25-akpm/include/linux/fb.h            |    4 -
 4 files changed, 83 insertions(+), 49 deletions(-)

diff -puN drivers/video/console/fbcon.c~fbdev-support-for-bold-attribute-for-monochrome-framebuffers drivers/video/console/fbcon.c
--- 25/drivers/video/console/fbcon.c~fbdev-support-for-bold-attribute-for-monochrome-framebuffers	2004-08-21 13:47:14.936344864 -0700
+++ 25-akpm/drivers/video/console/fbcon.c	2004-08-21 13:47:14.946343344 -0700
@@ -408,7 +408,6 @@ int set_con2fb_map(int unit, int newidx)
 static inline int get_color(struct vc_data *vc, struct fb_info *info,
 			    u16 c, int is_fg)
 {
-	struct display *p = &fb_display[fg_console];
 	int depth = fb_get_color_depth(info);
 	int color = 0;
 
@@ -422,9 +421,8 @@ static inline int get_color(struct vc_da
 		/* 0 or 1 */
 		int fg = (info->fix.visual != FB_VISUAL_MONO01) ? 1 : 0;
 		int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : 1;
-		int reverse = attr_reverse(c, p->inverse);
 
-		color = (is_fg) ? (reverse) ? bg : fg : (reverse) ? fg : bg;
+		color = (is_fg) ? fg : bg;
 		break;
 	}
 	case 2:
@@ -447,13 +445,45 @@ static inline int get_color(struct vc_da
 	return color;
 }
 
-static inline int is_underline(struct fb_info *info, u16 c)
+#define FBCON_ATTRIBUTE_UNDERLINE 1
+#define FBCON_ATTRIBUTE_REVERSE   2
+#define FBCON_ATTRIBUTE_BOLD      4
+
+static inline int get_attribute(struct fb_info *info, u16 c)
+{
+	int attribute = 0;
+
+	if (fb_get_color_depth(info) == 1) {
+		if (attr_underline(c))
+			attribute |= FBCON_ATTRIBUTE_UNDERLINE;
+		if (attr_reverse(c))
+			attribute |= FBCON_ATTRIBUTE_REVERSE;
+		if (attr_bold(c))
+			attribute |= FBCON_ATTRIBUTE_BOLD;
+	}
+
+	return attribute;
+}
+
+static inline void update_attr(u8 *dst, u8 *src, int attribute,
+			       struct vc_data *vc)
 {
-	int underline = 0;
+	int i, offset = (vc->vc_font.height < 10) ? 1 : 2;
+	int width = (vc->vc_font.width + 7) >> 3;
+	unsigned int cellsize = vc->vc_font.height * width;
+	u8 c;
 
-	if (fb_get_color_depth(info) == 1)
-		underline = attr_underline(c);
-	return underline;
+	offset = cellsize - (offset * width);
+	for (i = 0; i < cellsize; i++) {
+		c = src[i];
+		if (attribute & FBCON_ATTRIBUTE_UNDERLINE && i >= offset)
+			c = 0xff;
+		if (attribute & FBCON_ATTRIBUTE_BOLD)
+			c |= c >> 1;
+		if (attribute & FBCON_ATTRIBUTE_REVERSE)
+			c = ~c;
+		dst[i] = c;
+	}
 }
 
 void accel_bmove(struct vc_data *vc, struct fb_info *info, int sy, 
@@ -506,11 +536,11 @@ void accel_putcs(struct vc_data *vc, str
 	unsigned int shift_low = 0, mod = vc->vc_font.width % 8;
 	unsigned int shift_high = 8, pitch, cnt, size, k;
 	unsigned int idx = vc->vc_font.width >> 3;
-	unsigned int underline = is_underline(info, scr_readw(s));
+	unsigned int attribute = get_attribute(info, scr_readw(s));
 	struct fb_image image;
 	u8 *src, *dst, *buf = NULL;
 
-	if (underline) {
+	if (attribute) {
 		buf = kmalloc(cellsize, GFP_KERNEL);
 		if (!buf)
 			return;
@@ -549,17 +579,14 @@ void accel_putcs(struct vc_data *vc, str
 				src = vc->vc_font.data + (scr_readw(s++)&
 							  charmask)*cellsize;
 
-				if (underline) {
-					int offset = (vc->vc_font.height < 10) ? 1 : 2;
-
-					memcpy(buf, src, cellsize);
-					memset(buf + cellsize - offset, 0xff,
-					       offset * width);
+				if (attribute) {
+					update_attr(buf, src, attribute, vc);
 					src = buf;
 				}
+
 				move_unaligned(info, &info->pixmap, dst, pitch,
-						       src, idx, image.height,
-						       shift_high, shift_low, mod);
+					       src, idx, image.height,
+					       shift_high, shift_low, mod);
 				shift_low += mod;
 				dst += (shift_low >= 8) ? width : width - 1;
 				shift_low &= 7;
@@ -569,16 +596,14 @@ void accel_putcs(struct vc_data *vc, str
 			while (k--) {
 				src = vc->vc_font.data + (scr_readw(s++)&
 							  charmask)*cellsize;
-				if (underline) {
-					int offset = (vc->vc_font.height < 10) ? 1 : 2;
 
-					memcpy(buf, src, cellsize);
-					memset(buf + cellsize - offset, 0xff,
-					       offset * width);
+				if (attribute) {
+					update_attr(buf, src, attribute, vc);
 					src = buf;
 				}
+
 				move_aligned(info, &info->pixmap, dst, pitch,
-						     src, idx, image.height);
+					     src, idx, image.height);
 				dst += width;
 			}
 		}
@@ -586,7 +611,9 @@ void accel_putcs(struct vc_data *vc, str
 		image.dx += cnt * vc->vc_font.width;
 		count -= cnt;
 	}
-	kfree(buf);
+
+	if (buf)
+		kfree(buf);
 }
 
 void accel_clear_margins(struct vc_data *vc, struct fb_info *info,
@@ -1074,14 +1101,15 @@ static void fbcon_putc(struct vc_data *v
 
 static void fbcon_cursor(struct vc_data *vc, int mode)
 {
+	struct fb_cursor cursor;
 	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 	struct display *p = &fb_display[vc->vc_num];
 	int w = (vc->vc_font.width + 7) >> 3, c;
 	int y = real_y(p, vc->vc_y), fg, bg;
-	int underline;
-	struct fb_cursor cursor;
-	
+	int attribute;
+	u8 *src;
+
 	if (mode & CM_SOFTBACK) {
 		mode &= ~CM_SOFTBACK;
 		if (softback_lines) {
@@ -1094,8 +1122,22 @@ static void fbcon_cursor(struct vc_data 
 		fbcon_set_origin(vc);
 
  	c = scr_readw((u16 *) vc->vc_pos);
-	underline = is_underline(info, c);
-	cursor.image.data = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
+	attribute = get_attribute(info, c);
+	src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
+	if (attribute) {
+		u8 *dst;
+
+		dst = kmalloc(w * vc->vc_font.height, GFP_ATOMIC);
+		if (!dst)
+			return;
+		if (info->cursor.data)
+			kfree(info->cursor.data);
+		info->cursor.data = dst;
+		update_attr(dst, src, attribute, vc);
+		src = dst;
+	}
+
+	cursor.image.data = src;
 	cursor.set = FB_CUR_SETCUR;
 	cursor.image.depth = 1;
 	
@@ -1139,24 +1181,19 @@ static void fbcon_cursor(struct vc_data 
 			cursor.set |= FB_CUR_SETHOT;
 		}
 
-		if ((cursor.set & FB_CUR_SETSIZE) || ((vc->vc_cursor_type & 0x0f) != p->cursor_shape)
-		    || info->cursor.mask == NULL || info->cursor.ul != attr_underline(c) ||
-		    info->cursor.rev != attr_reverse(c, p->inverse)) {
+		if ((cursor.set & FB_CUR_SETSIZE) ||
+		    ((vc->vc_cursor_type & 0x0f) != p->cursor_shape)
+		    || info->cursor.mask == NULL) {
 			char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
 			int cur_height, size, i = 0;
 			u8 msk = 0xff;
 
-			if (!mask)	return;	
+			if (!mask)
+				return;
 		
 			if (info->cursor.mask)
 				kfree(info->cursor.mask);
 			info->cursor.mask = mask;
-	
-			info->cursor.ul = attr_underline(c);
-			info->cursor.rev = attr_reverse(c, p->inverse);
-
-			if (info->cursor.rev)
-				msk = 0;
 			p->cursor_shape = vc->vc_cursor_type & 0x0f;
 			cursor.set |= FB_CUR_SETSHAPE;
 
@@ -1185,10 +1222,6 @@ static void fbcon_cursor(struct vc_data 
 			while (size--)
 				mask[i++] = ~msk;
 			size = cur_height * w;
-			if (info->cursor.ul)
-				msk = ~msk;
-			if (info->cursor.ul)
-				msk = ~msk;
 			while (size--)
 				mask[i++] = msk;
 		}
diff -puN drivers/video/console/fbcon.h~fbdev-support-for-bold-attribute-for-monochrome-framebuffers drivers/video/console/fbcon.h
--- 25/drivers/video/console/fbcon.h~fbdev-support-for-bold-attribute-for-monochrome-framebuffers	2004-08-21 13:47:14.937344712 -0700
+++ 25-akpm/drivers/video/console/fbcon.h	2004-08-21 13:47:14.946343344 -0700
@@ -69,8 +69,8 @@ extern int set_con2fb_map(int unit, int 
 /* Monochrome */
 #define attr_bold(s) \
 	((s) & 0x200)
-#define attr_reverse(s, inverse) \
-	(((s) & 0x800) ^ (inverse ? 0x800 : 0))
+#define attr_reverse(s) \
+	((s) & 0x800)
 #define attr_underline(s) \
 	((s) & 0x400)
 #define attr_blink(s) \
diff -puN drivers/video/fbmem.c~fbdev-support-for-bold-attribute-for-monochrome-framebuffers drivers/video/fbmem.c
--- 25/drivers/video/fbmem.c~fbdev-support-for-bold-attribute-for-monochrome-framebuffers	2004-08-21 13:47:14.939344408 -0700
+++ 25-akpm/drivers/video/fbmem.c	2004-08-21 13:47:14.948343040 -0700
@@ -981,13 +981,14 @@ fb_cursor(struct fb_info *info, struct f
 	if (copy_from_user(&cursor_user, sprite, sizeof(struct fb_cursor_user)))
 		return -EFAULT;
 
-	memcpy(&cursor, &cursor_user, sizeof(cursor));
+	memcpy(&cursor, &cursor_user, sizeof(cursor_user));
 	cursor.mask = NULL;
 	cursor.image.data = NULL;
 	cursor.image.cmap.red = NULL;
 	cursor.image.cmap.green = NULL;
 	cursor.image.cmap.blue = NULL;
 	cursor.image.cmap.transp = NULL;
+	cursor.data = NULL;
 
 	if (cursor.set & FB_CUR_SETCUR)
 		info->cursor.enable = 1;
diff -puN include/linux/fb.h~fbdev-support-for-bold-attribute-for-monochrome-framebuffers include/linux/fb.h
--- 25/include/linux/fb.h~fbdev-support-for-bold-attribute-for-monochrome-framebuffers	2004-08-21 13:47:14.940344256 -0700
+++ 25-akpm/include/linux/fb.h	2004-08-21 13:47:14.949342888 -0700
@@ -383,11 +383,11 @@ struct fb_cursor {
 	__u16 set;		/* what to set */
 	__u16 enable;		/* cursor on/off */
 	__u16 rop;		/* bitop operation */
-	__u16 ul;               /* underlined? */
-	__u16 rev;              /* reversed? */
 	const char *mask;	/* cursor mask bits */
 	struct fbcurpos hot;	/* cursor hot spot */
 	struct fb_image	image;	/* Cursor image */
+/* all fields below are for fbcon use only */
+	char  *data;             /* copy of bitmap */
 };
 
 #ifdef __KERNEL__
_
