Port-atari archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Box drawings char support on x68k and atari kernel for sysinst



Hi,

Currently NetBSD/x68k ite(4) console doesn't support VT220 DEC
special graphics character sets, including box drawing characters:
 https://en.wikipedia.org/wiki/DEC_Special_Graphics

Then per TERM=vt220 value sysinst menuc (or curses) implicitly
assumes the target system supports the DEC graphics chars by
"ESC ( 0" sequence, i.e. smacs/rmacs/acsc in terminfo(5), and
just tries to use box drawing chars.

As a result, NetBSD/x68k (and also other ite(4) based ports
like atari etc.) shows menus as:
---

     lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
     x NetBSD-9.2 Install                            x
     x                                               x
     x a: Install NetBSD to hard disk                x
     x b: Upgrade NetBSD on a hard disk              x
 :
---

This was already reported in PR port-atari/46647:
 https://gnats.netbsd.org/46647


There are two countermeasures for this problem:

(1) prepare and fix the port specific ite(4) terminfo entry
(2) implement DEC graphics by "ESC ( 0" sequence in the kernel ite(4)

x68k already has its own terminfo entry so we can fix it by
adding "acss=, smarc@, rmacs@" in "x68k" terminfo entry.

But on most crunched boot media we cannot have terminfo db and only
libterminfo embedded TERM values (ansi dumb vt100 vt220 wsvt25 xterm)
 https://nxr.netbsd.org/xref/src/lib/libterminfo/genterms?r=1.4#40
are provided, so we can't use own TERM on the sysinst.

With the following dumb patch, we can add "boot media specific
terminfo embedded compiled terms" using HACKED_CURSES in libhack:

 https://github.com/tsutsui/netbsd-src/compare/trunk...libhack-md-compiled_term


This still can't solve all ports because other ite(4) based ports
(amiga and atari) don't have their own terminfo entry.
They assume (claim) vt220 even in src/etc/etc.atari/ttys etc.

Anyway, box drawings chars could be required on other console
applications, so I've implemented DEC special graphics support
by "ESC ( 0" sequence for x68k (and atari) ite(4) driver.


For x68k, ite(4) already supports JISROMA (half width Japanese KANA)
encoding so switching encoding part (in ite.c) is trivial.

To handle box drawing chars I don't bother to add extra glyphs for them
but just replace them with '+', '-', and '|' chars (in ite_XX.c layer
that handles drawing per passed character code into VRAM),
as other applications (maybe curses) do.

I think the changes are port specific and trivial enough so
there is no concerns, but any comments are appreciated.

The changes for x68k are attatched, or on GitHub:
 https://github.com/tsutsui/netbsd-src/compare/trunk...x68k-ite-decgraph

---
diff --git a/sys/arch/x68k/dev/ite.c b/sys/arch/x68k/dev/ite.c
index 1417266b047c..aadc849c92ef 100644
--- a/sys/arch/x68k/dev/ite.c
+++ b/sys/arch/x68k/dev/ite.c
@@ -1286,7 +1286,7 @@ iteputchar(int c, struct ite_softc *ip)
 			case 'B':	/* ASCII */
 			case 'A':	/* ISO latin 1 */
 			case '<':	/* user preferred suplemental */
-			case '0':	/* dec special graphics */
+			case '0':	/* DEC special graphics */
 
 			/* 96-character sets: */
 			case '-':	/* G1 */
@@ -1430,6 +1430,10 @@ iteputchar(int c, struct ite_softc *ip)
 				ip->G0 = CSET_JISROMA;
 				ip->escape = 0;
 				return;
+			case '0': /* DEC special graphics */
+				ip->G0 = CSET_DECGRAPH;
+				ip->escape = 0;
+				return;
 			case 'A': /* British or ISO-Latin-1 */
 			case 'H': /* Swedish */
 			case 'K': /* German */
@@ -2311,6 +2315,62 @@ itecheckwrap(struct ite_softc *ip)
 #endif
 }
 
+/*
+ * A convertion table from DEC special graphics characters to ASCII characters.
+ * Mostly for box drawing on sysinst(8).
+ */
+const uint8_t ite_decgraph2ascii[128] = {
+	/* same as ASCII from 0x00 to 0x5e */
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
+
+	/* special graphics characters from 0x5f to 0x7e */
+	' ',	/* 0x5f NBSP */
+	'*',	/* 0x60 diamond */
+	' ',	/* 0x61 medium shade */
+	' ',	/* 0x62 HT */
+	' ',	/* 0x63 FF */
+	' ',	/* 0x64 CR */
+	' ',	/* 0x65 LF */
+	' ',	/* 0x66 degree symbol */
+	' ',	/* 0x67 plus-minus sign */
+	' ',	/* 0x68 NL */
+	' ',	/* 0x69 VT */
+	'+',	/* 0x6a box drawings up left */
+	'+',	/* 0x6b box drawings down left */
+	'+',	/* 0x6c box drawings down right */
+	'+',	/* 0x6d box drawings up right */
+	'+',	/* 0x6e box drawings vertical horizontal */
+	'~',	/* 0x6f scan line 1 */
+	'-',	/* 0x70 scan line 3 */
+	'-',	/* 0x71 scan line 5 */
+	'-',	/* 0x72 scan line 7 */
+	'_',	/* 0x73 scan line 9 */
+	'+',	/* 0x74 box drawings vertical right */
+	'+',	/* 0x75 box drawings vertical left */
+	'+',	/* 0x76 box drawings horizontal up */
+	'+',	/* 0x77 box drawings horizontal down */
+	'|',	/* 0x78 box drawings vertical */
+	'<',	/* 0x79 less than or equal to */
+	'>',	/* 0x7a greater than or equal to */
+	' ',	/* 0x7b pi */
+	' ',	/* 0x7c not equal */
+	' ',	/* 0x7d pound sign */
+	'.',	/* 0x7e middle dot */
+	/* end of special graphics characters */
+	0x7f
+};
+
 #endif
 
 #if NITE > 0 && NKBD > 0
diff --git a/sys/arch/x68k/dev/ite_tv.c b/sys/arch/x68k/dev/ite_tv.c
index 641c98d71b31..6345564d0217 100644
--- a/sys/arch/x68k/dev/ite_tv.c
+++ b/sys/arch/x68k/dev/ite_tv.c
@@ -215,6 +215,7 @@ tv_deinit(struct ite_softc *ip)
 	ip->flags &= ~ITE_INITED; /* XXX? */
 }
 
+static inline char *tv_getfont(int, int);
 typedef void tv_putcfunc(struct ite_softc *, int, char *);
 static tv_putcfunc tv_putc_nm;
 static tv_putcfunc tv_putc_in;
@@ -274,6 +275,21 @@ tv_putc(struct ite_softc *ip, int ch, int y, int x, int mode)
 	CRTC.r21 = 0;
 }
 
+static inline char *
+tv_getfont(int cset, int ch)
+{
+
+	if (cset == CSET_JISKANA) {
+		ch |= 0x80;
+	} else if (cset == CSET_DECGRAPH) {
+		if (ch < 0x80) {
+			ch = ite_decgraph2ascii[ch];
+		}
+	}
+
+	return tv_font[ch];
+}
+
 void
 tv_putc_nm(struct ite_softc *ip, int ch, char *p)
 {
@@ -294,9 +310,7 @@ tv_putc_nm(struct ite_softc *ip, int ch, char *p)
 	}
 
 	/* singlebyte character */
-	if (*ip->GL == CSET_JISKANA)
-		ch |= 0x80;
-	f = tv_font[ch];
+	f = tv_getfont(*ip->GL, ch);
 
 	/* draw plane */
 	for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES)
@@ -323,9 +337,7 @@ tv_putc_in(struct ite_softc *ip, int ch, char *p)
 	}
 
 	/* singlebyte character */
-	if (*ip->GL == CSET_JISKANA)
-		ch |= 0x80;
-	f = tv_font[ch];
+	f = tv_getfont(*ip->GL, ch);
 
 	/* draw plane */
 	for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES)
@@ -354,9 +366,7 @@ tv_putc_bd(struct ite_softc *ip, int ch, char *p)
 	}
 
 	/* singlebyte character */
-	if (*ip->GL == CSET_JISKANA)
-		ch |= 0x80;
-	f = tv_font[ch];
+	f = tv_getfont(*ip->GL, ch);
 
 	/* draw plane */
 	for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) {
@@ -403,9 +413,7 @@ tv_putc_ul(struct ite_softc *ip, int ch, char *p)
 	}
 
 	/* singlebyte character */
-	if (*ip->GL == CSET_JISKANA)
-		ch |= 0x80;
-	f = tv_font[ch];
+	f = tv_getfont(*ip->GL, ch);
 
 	/* draw plane */
 	for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES)
@@ -438,9 +446,7 @@ tv_putc_bd_in(struct ite_softc *ip, int ch, char *p)
 	}
 
 	/* singlebyte character */
-	if (*ip->GL == CSET_JISKANA)
-		ch |= 0x80;
-	f = tv_font[ch];
+	f = tv_getfont(*ip->GL, ch);
 
 	/* draw plane */
 	for (fh = 0; fh < FONTHEIGHT; fh++, p += ROWBYTES) {
@@ -473,9 +479,7 @@ tv_putc_ul_in(struct ite_softc *ip, int ch, char *p)
 	}
 
 	/* singlebyte character */
-	if (*ip->GL == CSET_JISKANA)
-		ch |= 0x80;
-	f = tv_font[ch];
+	f = tv_getfont(*ip->GL, ch);
 
 	/* draw plane */
 	for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES)
@@ -515,9 +519,7 @@ tv_putc_bd_ul(struct ite_softc *ip, int ch, char *p)
 	}
 
 	/* singlebyte character */
-	if (*ip->GL == CSET_JISKANA)
-		ch |= 0x80;
-	f = tv_font[ch];
+	f = tv_getfont(*ip->GL, ch);
 
 	/* draw plane */
 	for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) {
@@ -562,9 +564,7 @@ tv_putc_bd_ul_in(struct ite_softc *ip, int ch, char *p)
 	}
 
 	/* singlebyte character */
-	if (*ip->GL == CSET_JISKANA)
-		ch |= 0x80;
-	f = tv_font[ch];
+	f = tv_getfont(*ip->GL, ch);
 
 	/* draw plane */
 	for (fh = 0; fh < UNDERLINE; fh++, p += ROWBYTES) {
diff --git a/sys/arch/x68k/dev/itevar.h b/sys/arch/x68k/dev/itevar.h
index b8dbf319313a..a9543c20b1bf 100644
--- a/sys/arch/x68k/dev/itevar.h
+++ b/sys/arch/x68k/dev/itevar.h
@@ -223,6 +223,7 @@ enum tab_size { TABSIZE = 8 };
 #define CSET_JIS1978	(3|CSET_MULTI) /* iso2022jp old jis kanji */
 #define CSET_JIS1983	(4|CSET_MULTI) /* iso2022jp new jis kanji */
 #define CSET_JIS1990	(5|CSET_MULTI) /* iso2022jp hojo kanji */
+#define CSET_DECGRAPH	6 /* DEC special graphics characters */
 
 struct consdev;
 
@@ -256,4 +257,7 @@ extern unsigned char kern_font[];
 extern unsigned char kbdled;
 void ite_set_glyph(void);
 void kbd_setLED(void);
+
+/* DEC special graphics character to ASCII table for box drawing etc. */
+extern const uint8_t ite_decgraph2ascii[];
 #endif
---


For atari, the driver already have DEC special graphics glyphs
in their font data so drawing char part (ite_XX.c) layer is trivial.
On the other hand, unlike x68k atari's ite(4) layer doesn't support
switching encoding, so I just pull x68k implementation mechanically.

 https://github.com/tsutsui/netbsd-src/compare/trunk...atari-ite-decgraph

---
diff --git a/sys/arch/atari/dev/ite.c b/sys/arch/atari/dev/ite.c
index cd9a27ad1885..bb38683654ee 100644
--- a/sys/arch/atari/dev/ite.c
+++ b/sys/arch/atari/dev/ite.c
@@ -736,6 +736,12 @@ ite_reset(struct ite_softc *sc)
 	sc->keypad_appmode = 0;
 	sc->imode = 0;
 	sc->key_repeat = 1;
+	sc->G0 = CSET_ASCII;
+	sc->G1 = CSET_DECGRAPH;
+	sc->G2 = 0;
+	sc->G3 = 0;
+	sc->GL = &sc->G0;
+	sc->GR = &sc->G1;
 	memset(sc->tabs, 0, sc->cols);
 	for (i = 0; i < sc->cols; i++)
 		sc->tabs[i] = ((i & 7) == 0);
@@ -1247,6 +1253,14 @@ ite_lf (struct ite_softc *sc)
     }
   SUBR_CURSOR(sc, MOVE_CURSOR);
   clr_attr(sc, ATTR_INV);
+
+  /* reset character set */
+  sc->G0 = CSET_ASCII;
+  sc->G1 = CSET_DECGRAPH;
+  sc->G2 = 0;
+  sc->G3 = 0;
+  sc->GL = &sc->G0;
+  sc->GR = &sc->G1;
 }
 
 static inline void
@@ -1446,7 +1460,7 @@ iteputchar(register int c, struct ite_softc *sc)
 		  case 'B':	/* ASCII */
 		  case 'A':	/* ISO latin 1 */
 		  case '<':	/* user preferred suplemental */
-		  case '0':	/* dec special graphics */
+		  case '0':	/* DEC special graphics */
 		  
 		  /* 96-character sets: */
 		  case '-':	/* G1 */
@@ -1471,27 +1485,32 @@ iteputchar(register int c, struct ite_softc *sc)
 		  
 		  /* locking shift modes (as you might guess, not yet supported..) */
 		  case '`':
-		    sc->GR = sc->G1;
+		    sc->GR = &sc->G1;
 		    sc->escape = 0;
 		    return;
 		    
 		  case 'n':
-		    sc->GL = sc->G2;
+		    sc->GL = &sc->G2;
 		    sc->escape = 0;
 		    return;
 		    
 		  case '}':
-		    sc->GR = sc->G2;
+		    sc->GR = &sc->G2;
 		    sc->escape = 0;
 		    return;
 		    
 		  case 'o':
-		    sc->GL = sc->G3;
+		    sc->GL = &sc->G3;
 		    sc->escape = 0;
 		    return;
 		    
 		  case '|':
-		    sc->GR = sc->G3;
+		    sc->GR = &sc->G3;
+		    sc->escape = 0;
+		    return;
+
+		  case '~':
+		    sc->GR = &sc->G1;
 		    sc->escape = 0;
 		    return;
 		    
@@ -1511,16 +1530,30 @@ iteputchar(register int c, struct ite_softc *sc)
 
 
 		  case '7':
+		    /* save cursor */
 		    sc->save_curx = sc->curx;
 		    sc->save_cury = sc->cury;
 		    sc->save_attribute = sc->attribute;
+		    sc->sc_G0 = sc->G0;
+		    sc->sc_G1 = sc->G1;
+		    sc->sc_G2 = sc->G2;
+		    sc->sc_G3 = sc->G3;
+		    sc->sc_GL = sc->GL;
+		    sc->sc_GR = sc->GR;
 		    sc->escape = 0;
 		    return;
 		    
 		  case '8':
+		    /* restore cursor */
 		    sc->curx = sc->save_curx;
 		    sc->cury = sc->save_cury;
 		    sc->attribute = sc->save_attribute;
+		    sc->G0 = sc->sc_G0;
+		    sc->G1 = sc->sc_G1;
+		    sc->G2 = sc->sc_G2;
+		    sc->G3 = sc->sc_G3;
+		    sc->GL = sc->sc_GL;
+		    sc->GR = sc->sc_GR;
 		    SUBR_CURSOR(sc, MOVE_CURSOR);
 		    sc->escape = 0;
 		    return;
@@ -1551,8 +1584,22 @@ iteputchar(register int c, struct ite_softc *sc)
 		break;
 
 
-	      case '(':
-	      case ')':
+	      case '(': /* designated G0 */
+		switch (c) {
+		case 'B': /* US-ASCII */
+		  sc->G0 = CSET_ASCII;
+		  sc->escape = 0;
+		  return;
+		case '0': /* DEC special graphics */
+		  sc->G0 = CSET_DECGRAPH;
+		  sc->escape = 0;
+		  return;
+		default:
+		  /* not supported */
+		  sc->escape = 0;
+		  return;
+		}
+	      case ')': /* designated G1 */
 		sc->escape = 0;
 		return;
 
@@ -2165,11 +2212,11 @@ iteputchar(register int c, struct ite_softc *sc)
 		break;
 
 	case SO:
-		sc->GL = sc->G1;
+		sc->GL = &sc->G1;
 		break;
 		
 	case SI:
-		sc->GL = sc->G0;
+		sc->GL = &sc->G0;
 		break;
 
 	case ENQ:
diff --git a/sys/arch/atari/dev/ite_cc.c b/sys/arch/atari/dev/ite_cc.c
index cd112b57ec57..2ce5837eef80 100644
--- a/sys/arch/atari/dev/ite_cc.c
+++ b/sys/arch/atari/dev/ite_cc.c
@@ -582,6 +582,15 @@ putc8(struct ite_softc *ip, int c, int dy, int dx, int mode)
 	if (c < ip->font.font_lo || c > ip->font.font_hi)
 		return;
 
+	/*
+	 * Handle DEC special graphics character by 'ESC ( B' sequence.
+	 * Note we assume all font data (fontdata_8x8 and fontdata_8x16)
+	 * contain DEC graphics glyph (for 0x5f to 0x7e) at 0x00 to 0x1F.
+	 */
+	if (*ip->GL == CSET_DECGRAPH) {
+		if (ip->font.font_lo == 0 && c >= 0x5f && c <= 0x7e)
+			c -= 0x5f;
+	}
 	ft = cci->font_cell[c];
 
 	if (!mode) {
diff --git a/sys/arch/atari/dev/ite_et.c b/sys/arch/atari/dev/ite_et.c
index d442e8cd6723..44c44389a163 100644
--- a/sys/arch/atari/dev/ite_et.c
+++ b/sys/arch/atari/dev/ite_et.c
@@ -490,6 +490,16 @@ et_putc(struct ite_softc *ip, int c, int dy, int dx, int mode)
 	u_char	attr;
 	u_short	*cp;
 
+	/*
+	 * Handle DEC special graphics character by 'ESC ( B' sequence.
+	 * Note we assume all font data (fontdata_8x8 and fontdata_8x16)
+	 * contain DEC graphics glyph (for 0x5f to 0x7e) at 0x00 to 0x1F.
+	 */
+	if (*ip->GL == CSET_DECGRAPH) {
+		if (ip->font.font_lo == 0 && c >= 0x5f && c <= 0x7e)
+			c -= 0x5f;
+	}
+
 	attr = (unsigned char) ((mode & ATTR_INV) ? (0x70) : (0x07));
 	if (mode & ATTR_UL)     attr |= 0x01;
 	if (mode & ATTR_BOLD)   attr |= 0x08;
diff --git a/sys/arch/atari/dev/itevar.h b/sys/arch/atari/dev/itevar.h
index 4801c7c643bf..4eba96a7cf1c 100644
--- a/sys/arch/atari/dev/itevar.h
+++ b/sys/arch/atari/dev/itevar.h
@@ -72,12 +72,18 @@ struct ite_softc {
 	u_char			escape;
 	u_char			cursor_opt;
 	u_char			key_repeat;
-	char			GL;
-	char			GR;
 	char			G0;
 	char			G1;
 	char			G2;
 	char			G3;
+	char			*GL;
+	char			*GR;
+	char			sc_G0;
+	char			sc_G1;
+	char			sc_G2;
+	char			sc_G3;
+	char			*sc_GL;
+	char			*sc_GR;
 	char			linefeed_newline;
 	char			auto_wrap;
 	char			cursor_appmode;
@@ -173,6 +179,10 @@ enum tab_size { TABSIZE = 8 };
 
 #ifdef _KERNEL
 
+/* character set */
+#define CSET_ASCII	0	/* US-ASCII */
+#define CSET_DECGRAPH	1	/* DEC special graphics characters */
+
 extern int ite_default_x;
 extern int ite_default_y;
 extern int ite_default_width;

---

If there is no particular comments, I'll commit these changes soon
(hopefully before netbsd-10 cut).
	
---
Izumi Tsutsui


Home | Main Index | Thread Index | Old Index