lv 4.51 utf8mb4 パッチ

lv 4.51で、寿司“🍣”やビール“🍺”など、4バイト長のUTF-8(utf8mb4)の文字を含むファイルを表示させるパッチ。クイックハック。メモリの使用量は倍増する。lv の公式サイト(http://www.ff.iij4u.or.jp/~nrt/)は閉鎖された?ようなので、lv 4.51のソースコードは適当なリポジトリから拾う。パッチを当ててコンパイルする手順は下記の通り。

wget http://distfiles.icmpv6.org/distfiles/lv451.tar.gz
tar zxvf lv451.tar.gz
patch -b -p0 < lv451_utf8mb4.patch
cd lv451/build
../src/configure
make
make install # as root

パッチは下記のリンクからダウンロード。

lv451_utf8mb4.patch
--- lv451/src/ichar.h.orig	2003-11-13 12:08:19.000000000 +0900
+++ lv451/src/ichar.h	2020-01-26 07:07:01.000000000 +0900
@@ -12,7 +12,7 @@
  * international character
  */
 
-typedef unsigned short		ic_t;
+typedef int			ic_t;
 
 #define ICHAR_WIDTH		2
 
--- lv451/src/utf.c.orig	2004-01-05 16:23:29.000000000 +0900
+++ lv451/src/utf.c	2020-01-26 07:07:01.000000000 +0900
@@ -199,6 +199,25 @@ utfContinue:
 	    DecodeAddUnicode( state->attr, uni );
 	  }
 	}
+      } else if( 0xf0 == ( 0xf8 & ch ) ){
+        /* 1st of 4 */
+        uni = (ic_t)( 0x07 & ch ) << 18;
+        GetChar( ch );
+        if( 0x80 == ( 0xc0 & ch ) ){
+          /* trailor */
+          uni |= (ic_t)( 0x3f & ch ) << 12;
+          GetChar( ch );
+          if( 0x80 == ( 0xc0 & ch ) ){
+            /* trailor */
+            uni |= (ic_t)( 0x3f & ch ) << 6;
+            GetChar( ch );
+            if( 0x80 == ( 0xc0 & ch ) ){
+              /* trailor */
+              uni |= (ic_t)( 0x3f & ch );
+              DecodeAddUnicode( state->attr, uni );
+            }
+          }
+        }
       } else {
 	decoding_penalty++;
 	DecodeAddControl( ch );
@@ -328,10 +347,15 @@ public void EncodeUTF8( i_str_t *istr, i
 	} else if( ic < 0x0800U ){
 	  EncodeAddChar( attr, 0xc0 | ( ic >> 6 ) );
 	  EncodeAddChar( attr, 0x80 | ( 0x3f & ic ) );
-	} else {
+	} else if( ic < 0x10000U ){
 	  EncodeAddChar( attr, 0xe0 | ( ic >> 12 ) );
 	  EncodeAddChar( attr, 0x80 | ( 0x3f & ( ic >> 6 ) ) );
 	  EncodeAddChar( attr, 0x80 | ( 0x3f & ( ic ) ) );
+	} else {
+          EncodeAddChar( attr, 0xf0 | ( ic >> 18 ) );
+          EncodeAddChar( attr, 0x80 | ( 0x3f & ( ic >> 12 ) ) );
+          EncodeAddChar( attr, 0x80 | ( 0x3f & ( ic >> 6 ) ) );
+          EncodeAddChar( attr, 0x80 | ( 0x3f & ( ic ) ) );
 	}
       }
     } else if( FALSE == EncodeAddPseudo( attr, ic, cset, binary ) ){