GNU screenのcaption, hardstatus で日本語が文字化けする問題 その2
昨日のエントリー
GNU screend(ry について
使ってて気づいた不具合を修正したのでパッチを再リリースします。
・フォントレンダリング位置がずれる問題を修正
・%= の左側にマルチバイト文字があると終端位置がおかしくなるバグを修正
・hardstatusにたぶん対応
まずは導入方法から。環境はFedora12 x86_64で確認してます。
パッチだけ持ってきたい人は1~2画面ほどスクロールして下さい。
2/10日追記
以下を実行する前に、事前にこのエントリーに貼りつけてあるパッチテキストを
適当な作業ディレクトリに、screen-4.0.3-caption.patch という名前で保存しておいてください。
$ cd <適当な作業ディレクトリ> $ su # yum install rpm-build yum-utils # exit $ yumdownloader --source screen $ ls screen-4.0.3.fc12.src.rpm $ rpm -ivh screen-4.0.3.fc12.src.rpm ..... src.rpmが ~/rpmbuild 以下にインストールされる $ cp screen-4.0.3-caption.patch ~/rpmbuild/SOURCES/ $ cd ~/rpmbuild/SPECS/ $ vi screen.spec # add部分を追記する ... Patch13: screen-4.0.3-resize.patch Patch15: screen-4.0.3-caption.patch # add ... %patch13 -p2 -b .resize %patch15 -p1 -b .caption # add $ rpmbuild -bb screen.spec .... 環境に合わせてi686もしくはx86-64用のrpmが作成される $ cd ../RPMS/i686/ もしくは $ cd ../RPMS/x86-64/ $ su # yum remove screen screenが既に導入済みの場合アンインストール # rpm -ivh screen-4.0.3-15.fc12.i686.rpm もしくは # rpm -ivh screen-4.0.3-15.fc12.x86_64.rpm
んで、以下がpatch本体
コピーして、Linux環境に screen-4.0.3-caption.patch として保存してください。
2010/02/08 02:05am
デバッグコードが残ってたのをこっそり修正 m(__)m
diff -Naur screen-4.0.3-old/display.c screen-4.0.3/display.c --- screen-4.0.3-old/display.c 2010-02-09 01:58:31.740872546 +0900 +++ screen-4.0.3/display.c 2010-02-09 01:56:26.416126479 +0900 @@ -874,13 +874,68 @@ RAW_PUTCHAR(c) int c; { - ASSERT(display); +#ifdef UTF8 + static int utfPhase = 0; + static int utfLength = 0; + static char utfBuffer[4] = + { '\0', '\0', '\0', '\0' }; + static int utfIsError = 0; +#endif + + ASSERT(display); #ifdef FONT # ifdef UTF8 if (D_encoding == UTF8) { - c = (c & 255) | (unsigned char)D_rend.font << 8; + if( D_rendering_status ) + { + if( ( c & 0xc0 ) == 0x80 ) + { + if( ( utfLength == 0 ) && ( utfIsError == 0 ) ) + { + c = ' '; + utfIsError = 1; + } + else if( utfLength == 0 ) + { + return; + } + else + { + utfPhase ++; + if( utfPhase < utfLength ) + utfBuffer[utfPhase] = c; + if( utfPhase == utfLength - 1 ) + { + int index = 0; + for( index = 0; index < utfLength; index ++ ) + AddChar( utfBuffer[index] ); + utfPhase = 0; + utfLength = 0; + return; + } + else + { + return; + } + } + } + else + { + utfPhase = 0; + utfBuffer[utfPhase] = c; + if( ( c & 0x80 ) == 0 ) + utfLength = 1; + else if( ( c & 0xe0 ) == 0xc0 ) + utfLength = 2; + else if( ( c & 0xf0 ) == 0xe0 ) + utfLength = 3; + if( utfLength > 1 ) + return; + } + } + c = (c & 255) | (unsigned char)D_rend.font << 8; # ifdef DW_CHARS if (D_mbcs) { @@ -2457,7 +2512,9 @@ buf = MakeWinMsgEv(hstatusstring, D_fore, '%', (D_HS && D_has_hstatus == HSTATUS_HS && D_WS > 0) ? D_WS : D_width - !D_CLP, &D_hstatusev, 0); if (buf && *buf) { + D_rendering_status = 1; ShowHStatus(buf); + D_rendering_status = 0; if (D_has_hstatus != HSTATUS_IGNORE && D_hstatusev.timeout.tv_sec) evenq(&D_hstatusev); } diff -Naur screen-4.0.3-old/display.h screen-4.0.3/display.h --- screen-4.0.3-old/display.h 2010-02-09 01:58:31.740872546 +0900 +++ screen-4.0.3/display.h 2010-02-09 01:56:32.908996544 +0900 @@ -187,6 +187,7 @@ int d_blankerpid; struct event d_blankerev; #endif + int d_rendering_status; /* rendering caption / status */ }; #ifdef MULTI @@ -301,8 +302,7 @@ #define D_idleev DISPLAY(d_idleev) #define D_blankerev DISPLAY(d_blankerev) #define D_blankerpid DISPLAY(d_blankerpid) - - +#define D_rendering_status DISPLAY(d_rendering_status) #define GRAIN 4096 /* Allocation grain size for output buffer */ #define OBUF_MAX 256 /* default for obuflimit */ diff -Naur screen-4.0.3-old/screen.c screen-4.0.3/screen.c --- screen-4.0.3-old/screen.c 2010-02-09 01:58:31.778751717 +0900 +++ screen-4.0.3/screen.c 2010-02-09 01:56:14.738871018 +0900 @@ -2050,33 +2050,111 @@ int numpad; int padlen; { - char *pn, *pn2; - int i, r; - - padlen = padlen - (p - buf); /* space for rent */ - if (padlen < 0) - padlen = 0; - pn2 = pn = p + padlen; - r = winmsg_numrend; - while (p >= buf) - { - if (r && p - buf == winmsg_rendpos[r - 1]) + if( ( D_encoding != UTF8 ) && ( ( numpad == 0 ) || ( numpad > 1 ) ) ) { - winmsg_rendpos[--r] = pn - buf; - continue; + char *pn, *pn2; + int i, r; + padlen = padlen - (p - buf); /* space for rent */ + if (padlen < 0) + padlen = 0; + pn2 = pn = p + padlen; + r = winmsg_numrend; + while (p >= buf) + { + if (r && p - buf == winmsg_rendpos[r - 1]) + { + winmsg_rendpos[--r] = pn - buf; + continue; + } + *pn-- = *p; + if (*p-- == 127) + { + pn[1] = ' '; + i = numpad > 0 ? (padlen + numpad - 1) / numpad : 0; + padlen -= i; + while (i-- > 0) + *pn-- = ' '; + numpad--; + } + } + return pn2; } - *pn-- = *p; - if (*p-- == 127) + else { - pn[1] = ' '; - i = numpad > 0 ? (padlen + numpad - 1) / numpad : 0; - padlen -= i; - while (i-- > 0) - *pn-- = ' '; - numpad--; + int index = 0, index2 = 0; + int div = 0; // begin right side of byte position. + int lengthRight = 0; // total right display length of %=. + int lengthLeft = 0; // total left display length of %=. + int lengthTarget = 0; // total byte length. + int topRight = 0; + int lengthMove = 0; + + lengthTarget = p - buf; + p = buf; + for( index = 0; index < lengthTarget; index ++ ) + { + if( p[index] == 127 ) + break; + } + p[index] = ' '; + index ++; + div = index; + for( index = 0; index < div; index ++ ) + { + if( ( p[index] & 0x80 ) == 0 ) + { + lengthLeft ++; // display length = 1 + } + else if( ( p[index] & 0xe0 ) == 0xc0 ) + { + // U+0080-U+0FFF + lengthLeft ++; // display length == 1? + index++; // skip next 1 byte. + padlen ++; // fix padlen + } + else if( ( p[index] & 0xf0 ) == 0xe0 ) + { + // U+1000- + lengthLeft += 2; // display length = 2 + index += 2; // skip next 2 byte. + padlen ++; // fix padlen + } + } + for( index = div; index < lengthTarget; index ++ ) + { + if( ( p[index] & 0x80 ) == 0 ) + { + lengthRight ++; + } + else if( ( p[index] & 0xe0 ) == 0xc0 ) + { + lengthRight ++; + index++; + padlen ++; + } + else if( ( p[index] & 0xf0 ) == 0xe0 ) + { + lengthRight += 2; + index += 2; + padlen ++; + } + } + topRight = padlen - ( lengthTarget - div ); + lengthMove = topRight - div; + if( lengthMove > 0 ) + { + for( index = lengthTarget - 1, index2 = 0; index >= div; index --, index2 ++ ) + p[padlen - (index2 + 1)] = p[index]; + for( index = div; index < topRight; index ++ ) + p[index] = ' '; + } + for( index = 0; index < winmsg_numrend; index ++ ) + { + if( winmsg_rendpos[index] >= div ) + winmsg_rendpos[index] += lengthMove; + } + return p; } - } - return pn2; } struct backtick { @@ -2809,6 +2887,8 @@ if (s != winmsg_buf) return 0; + + D_rendering_status = 1; rend = D_rend; p = 0; l = strlen(s); @@ -2818,47 +2898,74 @@ if (p > winmsg_rendpos[i] || winmsg_rendpos[i] > l) break; if (p < winmsg_rendpos[i]) - { - n = winmsg_rendpos[i] - p; - if (n > max) - n = max; - max -= n; - p += n; - while(n-- > 0) - { - if (start-- > 0) - s++; - else - PUTCHARLP(*s++); - } - } - r = winmsg_rend[i]; - if (r == -1) - { - if (rendstackn > 0) - rend = rendstack[--rendstackn]; - } + { + n = winmsg_rendpos[i] - p; + if (n > max) + n = max; + max -= n; + p += n; + while (n-- > 0) + { + if (start-- > 0) + { + s++; + } + else + { + if( D_encoding == UTF8 ) + { + /* multibyte char start */ + if( ( (*s) & 0xf0 ) == 0xe0 ) + { + max ++; + l ++; + } + } + PUTCHARLP (*s++); + } + } + } + r = winmsg_rend[i]; + if (r == -1) + { + if (rendstackn > 0) + rend = rendstack[--rendstackn]; + } else + { + rendstack[rendstackn++] = rend; + ApplyAttrColor (r, &rend); + } + SetRendition (&rend); + } + if (p < l) { - rendstack[rendstackn++] = rend; - ApplyAttrColor(r, &rend); - } - SetRendition(&rend); - } - if (p < l) - { - n = l - p; - if (n > max) - n = max; - while(n-- > 0) - { - if (start-- > 0) - s++; - else - PUTCHARLP(*s++); + n = l - p; + if (n > max) + n = max; + while (n-- > 0) + { + if (start-- > 0) + { + s++; + } + else + { + if( D_encoding == UTF8 ) + { + if( ( (*s) & 0xf0 ) == 0xe0 ) + { + max ++; + l ++; + n ++; + } + } + PUTCHARLP (*s++); + } + } } - } - return 1; + D_rendering_status = 0; + return 1; }