termlog v0.1 - serialize terminal screen log

181 views
Skip to first unread message

Junn Ohta

unread,
Feb 18, 1997, 3:00:00 AM2/18/97
to

画面制御シーケンスが含まれたVT100/ANSI端末の画面ロ
グから整列された連続文字データを取り出すユーティリ
ティーです。fj.comp.databasesでこんなものがほしい
という話があったのでいいかげんに作ってみました。

ドキュメントとソースプログラムだけなので、ちょきち
ょきしてからコンパイルしてご利用ください。
--
太田純(Junn Ohta) (株)リコー ソフトウェア事業センター
oh...@src.ricoh.co.jp/JCF0...@niftyserve.or.jp

==> termlog.doc <==
============================================================================
VT100/ANSI端末画面ログ整列/連続化ユーティリティー termlog 操作マニュアル
============================================================================

名称
termlog - VT100またはANSI端末の画面ログを連続文字データにする

バージョン
0.1 - 1997/02/18

形式
termlog [-gCOLSxLINES] [-k[ejs]] [-m] [-v] file ...

オプション
-g 画面サイズを指定する(既定値: -g80x24)
-k 入力の日本語コード(「半角カナ」がなければ指定不要)
-m 表示属性(反転、下線)制御シーケンスを保存する
-v 小規模の画面更新でも内容を出力する
file 画面制御シーケンスを含む端末画面ログファイル

使用例
VT100端末の画面ログ(シフトJIS)を連続文字データにする。
% termlog -ks vt100.log

80×36のktermの画面ログを詳細な更新単位で連続文字データにする。
% termlog -g80x36 -v kterm.log

上と同じだが、画面表示属性を透過出力し、lessで表示する。
% termlog -g80x36 -v -m kterm.log | less -r -c

termlogの使用法を表示する。
% termlog

説明
termlogは端末エミュレーターやUNIXのscriptコマンドなどが生成したログ
ファイルから画面制御シーケンスを取り除き、通常文字と改行からなるプレ
ーンテキストを生成する。解釈される画面制御シーケンスはVT100端末およ
びANSI端末のサブセットである。詳細については後述する。

-vオプションを指定しないときの画面出力タイミングは、画面クリアの直前
および入力が尽きた時点である。その他に、画面全体のスクロールによって
画面上方に消えていく行は、そのタイミングで出力される。したがって、画
面制御シーケンスを含まずに画面行数を超える入力ファイルは、見掛け上そ
のまま出力されることになる。

-vオプションを指定すると、原則として画面内容に更新があるたびに現在の
画面が出力される。例外として、画面上の空白に対する上書きは更新として
扱われず、また画面制御シーケンスを含まない通常文字の連続表示について
は、その途中経過を表示しない。-vオプションを指定したときは出力が膨大
になる可能性があるので注意すること。

入力ファイルが表示された画面が80桁24行以外のサイズを持つ場合は、-gオ
プションを指定して正しい画面サイズを指定すること。表示画面サイズと指
定サイズが食い違っていると正しい出力が得られない。

termlogは入力ファイルの日本語コードを変更しない。入力ファイルの日本
語コードが影響するのはいわゆる「半角カナ」のときだけであり、これが含
まれていなければ-kオプションを指定しなくても通常は問題ない。指定する
ときは-ks(シフトJIS)、-ke(EUC)、-kj(JIS)のようにする。

-mオプションを指定すると、入力ファイルにあった表示属性(のうち反転と
下線)を設定するシーケンスが出力にも保存される。画面制御シーケンスを
含む入力を扱えるテキストブラウザー(lessなど)で出力を眺める場合には便
利かもしれない。

画面制御シーケンス
termlogが解釈する特殊文字、画面制御シーケンスは次のものである。

^H (後退) 1カラム左に移動する
^I (タブ) 次のタブストップ(8カラムタブ)に移動する
^J (改行) 次行の同じカラム位置に移動する
^L (紙送り) 画面内容を出力し、画面をクリアする
^M (復帰) 行頭に移動する

ESC 7 カーソル位置と表示属性を保存する(VT100)
ESC 8 カーソル位置と表示属性を復元する(VT100)
ESC D 1行下に移動し、画面端なら順スクロールする
ESC E 次行の行頭に移動する
ESC M 1行上に移動し、画面端なら逆スクロールする
ESC [ Pn A Pn行上の同じカラム位置に移動する
ESC [ Pn B Pn行下の同じカラム位置に移動する
ESC [ Pn C Pnカラム右に移動する
ESC [ Pn D Pnカラム左に移動する
ESC [ Pm ; Pn H Pm行Pnカラムに移動する
ESC [ J カーソル位置から画面末尾までクリアする
ESC [ 1 J 画面先頭からカーソル直前までクリアする
ESC [ 2 J 画面全体をクリアする
ESC [ K カーソル位置から行末までクリアする
ESC [ 1 K 行頭からカーソル直前までクリアする
ESC [ 2 K カーソル行全体をクリアする
ESC [ Pn L カーソル位置にPn行の空行を挿入する(ANSI)
ESC [ Pn M カーソル位置以降のPn行を削除する(ANSI)
ESC [ Pn P カーソル位置以降のPnカラムを削除する
ESC [ Pm ; Pn f ESC [ Pm ; Pn H と同じ
ESC [ 7 m 反転表示属性を設定する
ESC [ 4 m 下線表示属性を設定する
ESC [ m 表示属性を解除する
ESC [ Pm ; Pn r スクロール領域をPm行~Pn行に変更する(VT100)
ESC [ s カーソル位置と表示属性を保存する(ANSI)
ESC [ u カーソル位置と表示属性を復元する(ANSI)

^N JISカタカナ開始
^O JISローマ文字/ASCII開始
ESC $ @ JIS漢字開始
ESC $ B JIS漢字開始
ESC ( B ASCII開始
ESC ( J JISローマ文字開始
ESC ( H JISローマ文字開始
ESC ( I JISカタカナ開始
ESC ( 0 DEC特殊文字(VT100罫線素片)開始

上記以外の特殊文字、画面制御シーケンスは黙って無視される。

動作環境
termlog.cはSunOS4.13上のccおよびgcc、SunOS5.上3のcc、MS-DOS上のTurbo
C++ 1.0およびLSI C-86 v3.30c試食版で動作を確認した。それ以外の処理系
でもおそらく変更の必要なしにコンパイルできると思われる。

バグ
このプログラムは即席で作られ、しかもあまりテストされていない。バグや
仕様上の不備も数多く存在すると思われる。しかし原作者はあまりまじめに
このプログラムを保守しようとは考えていないので、トラブルがあった場合
はできるだけ自力で解決すること。

それはそれとして、利用者による修正・機能改善・移植などのレポートにつ
いては歓迎する。

利用条件
このプログラムの利用・改変・再配布にはいかなる制限もない。原作者はこ
のプログラムに関するすべての著作権を放棄すること、またいかなる場合で
も著作者人格権を主張しないことを表明する。言い換えれば、原作者はこの
プログラムがパブリックドメインに置かれたものとして扱われることを期待
する。商業的利用あるいは各種メディアへの転載・収録などについても、原
作者への連絡は一切不要である。

ただし、原作者はこのプログラムに関していかなる保証も行わない。原作者
はこのプログラムが期待された動作をすること、特定の目的に対して有用で
あることを保証せず、またこのプログラムを利用したことによって生起した
いかなる損害に対する責任も負わないものとする。

原作者
太田純 (Junn Ohta)
Internet: oh...@src.ricoh.co.jp
NIFTY-Serve: JCF00656

履歴
1997/02/18 - テスト版(v0.1)をリリース

============================================================================

==> termlog.c <==
/*
* termlog v0.1 - rearrange and serialize VT100/ANSI terminal screen log
*
* Written by Junn Ohta, 1997/02/18. Public Domain.
*/

char *progname = "termlog";
char *version = "0.1";

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

typedef unsigned long cell;

#define TRUE 1
#define FALSE 0

#define ESC '\033'
#define SO '\016'
#define SI '\017'
#define DEL '\177'
#define SS2 '\216'
#define SS3 '\217'

#define A_NORM 0x00000000L
#define A_REV 0x00010000L
#define A_UL 0x00020000L
#define A_GRAPH 0x00040000L
#define A_KNJ1 0x00100000L
#define A_KNJ2 0x00200000L
#define A_MASK 0x00ff0000L

#define C_MASK 0x0000ffffL

#define SPACE (A_NORM | ' ')

#define KC_NONE 0
#define KC_EUC 1
#define KC_JIS 2
#define KC_SJIS 3

#define M_ASCII 0
#define M_KANJI 1
#define M_KANA 2
#define M_GRAPH 3

#define SJIS1(c) ((c)>=0x81 && (c)<=0x9f || (c)>=0xe0 && (c)<=0xfc)
#define SJIS2(c) ((c)>=0x40 && (c)!=0x7f && (c)<=0xfc)

int kcode = KC_NONE;
int kselk, ksela;
int mode, savemode;

cell **screen;
int lines = 24;
int cols = 80;
int lin, col, attr;
int savelin, savecol, saveattr;
int scrtop, scrend;

int verbose = FALSE;
int keepgr = FALSE;

int scrinit();
void usage();
int termlog();
int csi();
void scrollup();
void scrolldown();
void clearscr();
void sepline();
void flush();
void flushline();

int
main(ac, av)
int ac;
char **av;
{
FILE *fp;

if (scrinit(&ac, &av) < 0)
exit(1);
if (ac == 0) {
termlog(stdin);
exit(0);
}
while (ac > 0) {
fp = fopen(*av, "rb");
if (fp == NULL) {
printf("%s: can't open %s\n", progname, *av);
} else {
termlog(fp);
fclose(fp);
}
ac--, av++;
}
exit(0);
}

int
scrinit(acp, avp)
int *acp;
char ***avp;
{
int i, ret, ac;
char *p, **av;

ac = *acp;
av = *avp;
ret = -1;

ac--, av++;
while (ac > 0 && **av == '-') {
switch ((*av)[1]) {
case 'g':
cols = atoi(*av + 2);
p = strchr(*av + 2, 'x');
if (p)
lines = atoi(p + 1);
if (cols <= 0 || lines <= 0) {
usage();
goto done;
}
break;
case 'k':
switch ((*av)[2]) {
case 'e':
kcode = KC_EUC;
break;
case 'j':
kcode = KC_JIS;
kselk = 'B';
ksela = 'B';
break;
case 's':
kcode = KC_SJIS;
break;
default:
usage();
goto done;
}
break;
case 'm':
keepgr = TRUE;
break;
case 'v':
verbose = TRUE;
break;
default:
usage();
goto done;
}
ac--, av++;
}
if (ac == 0 && isatty(0)) {
usage();
goto done;
}

screen = (cell **)malloc(lines * sizeof(cell *));
if (screen == NULL) {
printf("%s: memory short\n", progname);
goto done;
}
for (i = 0; i < lines; i++) {
screen[i] = (cell *)malloc(cols * sizeof(cell));
if (screen[i] == NULL) {
printf("%s: memory short\n", progname);
goto done;
}
}
ret = 0;

done:
*acp = ac;
*avp = av;
return ret;
}

void
usage()
{
printf("Usage: %s [-gCOLSxLINES] [-k[ejs]] [-m] [-v] file ...\n", progname);
printf("Options:\n");
printf(" -g: set screen size (default: -g80x24)\n");
printf(" -k: set input code (don't care if no kana exists)\n");
printf(" -m: retain graphic renditions (reverse, underline)\n");
printf(" -v: verbose output\n");
}

int
termlog(fp)
FILE *fp;
{
int c, c1, flushed;
cell l;

lin = savelin = 0;
col = savecol = 0;
attr = saveattr = A_NORM;
scrtop = 0;
scrend = lines;
mode = savemode = M_ASCII;
flushed = TRUE;
sepline();
clearscr();

while ((c = getc(fp)) != EOF) {
if (c >= ' ' && c < DEL || (c & 0x80)) {
retry:
if (col >= cols) {
lin++;
if (lin == scrend) {
scrollup(1);
lin = scrend - 1;
} else if (lin == lines) {
lin = lines - 1;
}
col = 0;
}
if (kcode == KC_EUC && c >= 0xa1 && c <= 0xfe ||
kcode == KC_SJIS && SJIS1(c) ||
kcode == KC_NONE && c >= 0x81 && c <= 0xfe ||
mode == M_KANJI) {
if (col == cols - 1) {
if (verbose && !flushed &&
screen[lin][col] != SPACE) {
flush();
flushed = TRUE;
}
screen[lin][col++] = attr|' ';
goto retry;
}
c1 = getc(fp);
if (c1 == EOF)
goto done;
if (kcode == KC_NONE) {
if (c >= 0x81 && c <= 0x9f)
kcode = KC_SJIS;
else if (c >= 0xf0)
kcode = KC_EUC;
}
if (verbose && !flushed &&
screen[lin][col] != SPACE &&
screen[lin][col + 1] != SPACE) {
flush();
flushed = TRUE;
}
l = (unsigned int)(c << 8 | c1);
screen[lin][col++] = A_KNJ1|attr|l;
screen[lin][col++] = A_KNJ2|attr|l;
if (col < cols &&
screen[lin][col] & A_KNJ2)
screen[lin][col] = SPACE;
} else {
if (kcode == KC_EUC && c == SS2) {
c = getc(fp);
if (c == EOF)
goto done;
c |= 0x80;
}
if (mode == M_KANA)
c |= 0x80;
if (verbose && !flushed &&
screen[lin][col] != SPACE) {
flush();
flushed = TRUE;
}
if (mode == M_GRAPH)
screen[lin][col++] = A_GRAPH|attr|c;
else
screen[lin][col++] = attr|c;
if (col < cols &&
screen[lin][col] & A_KNJ2)
screen[lin][col] = SPACE;
}
continue;
}
flushed = FALSE;
switch (c) {
case '\b': /* backspace */
if (col > 0)
col--;
break;
case '\r': /* carriage return */
col = 0;
break;
case '\n': /* linefeed */
lin++;
if (lin == scrend) {
scrollup(1);
lin = scrend - 1;
} else if (lin == lines) {
lin = lines - 1;
}
break;
case '\t': /* tab */
if (col < cols)
col += 8 - (col % 8);
break;
case '\f': /* formfeed */
flush();
clearscr();
break;
case SO: /* shift out */
if (kcode == KC_NONE)
kcode = KC_JIS;
savemode = mode;
mode = M_KANA;
break;
case SI: /* shift in */
if (kcode == KC_NONE)
kcode = KC_JIS;
mode = savemode;
break;
case ESC: /* ESC */
c = getc(fp);
switch (c) {
case EOF:
goto done;
case '$':
c = getc(fp);
switch (c) {
case EOF:
goto done;
case '@':
case 'B':
if (kcode == KC_NONE)
kcode = KC_JIS;
kselk = c;
mode = M_KANJI;
break;
default:
break;
}
break;
case '(':
c = getc(fp);
switch (c) {
case EOF:
goto done;
case 'H':
case 'J':
case 'B':
ksela = c;
mode = M_ASCII;
break;
case 'I':
if (kcode == KC_NONE)
kcode = KC_JIS;
mode = M_KANA;
break;
case '0':
mode = M_GRAPH;
break;
default:
break;
}
break;
case '7': /* save cursor */
savelin = lin;
savecol = col;
saveattr = attr;
break;
case '8': /* restore cursor */
lin = savelin;
col = savecol;
attr = saveattr;
break;
case 'D': /* scroll forward (col unchanged) */
lin++;
if (lin == scrend) {
scrollup(1);
lin = scrend - 1;
} else if (lin == lines) {
lin = lines - 1;
}
break;
case 'E': /* new line */
lin++;
if (lin == scrend) {
scrollup(1);
lin = scrend - 1;
} else if (lin == lines) {
lin = lines - 1;
}
col = 0;
break;
case 'M': /* scroll backward (col unchanged) */
lin--;
if (lin == scrtop - 1) {
scrolldown(1);
lin = scrtop;
} else if (lin == -1) {
lin = 0;
}
break;
case '=': /* keypad application mode */
case '>': /* keypad normal mode */
/* do nothing */
break;
case '#': /* line settings */
c = getc(fp);
if (c == EOF)
goto done;
break;
case '[':
if (csi(fp) == EOF)
goto done;
break;
default:
/* do nothing */
break;
}
break;
default:
break;
}
}
done:
flush();
return 0;
}

int
csi(fp)
FILE *fp;
{
int c, i, j, k, n, np, p[10];
int leader;
cell *tmp;

c = getc(fp);
if (c == EOF)
return EOF;
if (strchr("<=>?", c)) {
leader = c;
c = getc(fp);
if (c == EOF)
return EOF;
}
p[0] = p[1] = 0;
np = 0;
for (;;) {
n = 0;
while (isdigit(c)) {
n *= 10;
n += c - '0';
c = getc(fp);
if (c == EOF)
return EOF;
}
if (np < 10)
p[np++] = n;
if (c != ';')
break;
c = getc(fp);
if (c == EOF)
return EOF;
}
switch (c) {
case 'H': /* move cursor */
case 'f': /* move cursor */
lin = p[0]? p[0] - 1: 0;
col = p[1]? p[1] - 1: 0;
if (lin >= lines)
lin = lines - 1;
if (col >= cols)
col = cols - 1;
break;
case 'A': /* move cursor up */
n = p[0]? p[0]: 1;
if (lin >= scrtop && lin - n < scrtop)
lin = scrtop;
else if (lin - n < 0)
lin = 0;
else
lin -= n;
break;
case 'B': /* move cursor down */
n = p[0]? p[0]: 1;
if (lin < scrend && lin + n >= scrend)
lin = scrend - 1;
else if (lin + n >= lines)
lin = lines - 1;
else
lin += n;
break;
case 'C': /* move cursor right */
n = p[0]? p[0]: 1;
if (col + n >= cols)
col = cols - 1;
else
col += n;
break;
case 'D': /* move cursor left */
n = p[0]? p[0]: 1;
if (col - n < 0)
col = 0;
else
col -= n;
break;
case 'J': /* clear display */
switch (p[0]) {
default:
case 0:
if (lin == 0 && col == 0) {
flush();
clearscr();
break;
}
if (verbose)
flush();
for (j = col; j < cols; j++)
screen[lin][j] = SPACE;
for (i = lin + 1; i < lines; i++)
for (j = 0; j < cols; j++)
screen[i][j] = SPACE;
break;
case 1:
if (verbose)
flush();
for (i = 0; i < lin; i++)
for (j = 0; j < cols; j++)
screen[i][j] = SPACE;
for (j = 0; j < col; j++)
screen[lin][j] = SPACE;
break;
case 2:
flush();
clearscr();
break;
}
break;
case 'K': /* clear line */
switch (p[0]) {
default:
case 0:
j = col;
k = cols;
break;
case 1:
j = 0;
k = col;
break;
case 2:
j = 0;
k = cols;
break;
}
if (verbose) {
for (i = j; i < k; i++) {
if (screen[lin][i] != SPACE) {
flush();
break;
}
}
}
for (i = j; i < k; i++)
screen[lin][i] = SPACE;
break;
case 'L': /* insert line */
n = p[0]? p[0]: 1;
if (lin < scrtop || lin >= scrend)
break;
if (verbose) {
tmp = screen[scrend - 1];
for (i = 0; i < cols; i++)
if (tmp[i] != SPACE)
break;
if (i < cols)
flush();
}
for (i = 0; i < n; i++) {
tmp = screen[scrend - 1];
for (j = scrend - 1; j > lin; j--)
screen[j] = screen[j - 1];
for (j = 0; j < cols; j++)
tmp[j] = SPACE;
screen[lin] = tmp;
}
break;
case 'M': /* delete line */
n = p[0]? p[0]: 1;
if (lin < scrtop || lin >= scrend)
break;
if (verbose) {
tmp = screen[lin];
for (i = 0; i < cols; i++)
if (tmp[i] != SPACE)
break;
if (i < cols)
flush();
}
for (i = 0; i < n; i++) {
tmp = screen[lin];
for (j = lin; j < scrend - 1; j++)
screen[j] = screen[j + 1];
for (j = 0; j < cols; j++)
tmp[j] = SPACE;
screen[scrend - 1] = tmp;
}
break;
case 'P': /* delete character */
n = p[0]? p[0]: 1;
if (verbose) {
j = col + n;
if (j >= cols)
j = cols;
for (i = col; i < j; i++)
if (screen[lin][i] != SPACE)
break;
if (i < j)
flush();
}
for (i = 0; i < n; i++) {
for (j = col; j < cols - 1; j++)
screen[lin][j] = screen[lin][j + 1];
screen[lin][cols - 1] = SPACE;
}
break;
case 'r': /* change scroll region */
if (p[0] < p[1])
break;
if (p[0] == 0 && p[1] == 0) {
scrtop = 0;
scrend = lines;
break;
}
scrtop = p[0]? p[0] - 1: 0;
scrend = p[1]? p[1] - 1: 0;
break;
case 'm': /* set graphics rendition */
if (np == 0)
p[np++] = 0;
for (i = 0; i < np; i++) {
switch (p[i]) {
case 0:
attr &= ~(A_REV|A_UL);
break;
case 4:
attr |= A_UL;
break;
case 7:
attr |= A_REV;
break;
default:
break;
}
}
break;
case 's': /* save cursor (ANSI) */
savelin = lin;
savecol = col;
saveattr = attr;
break;
case 'u': /* restore cursor (ANSI) */
lin = savelin;
col = savecol;
attr = saveattr;
break;
case 'h': /* set mode */
case 'l': /* reset mode */
break;
default:
break;
}
return 0;
}

void
scrollup(n)
int n;
{
int i, j;
cell *tmp;

if (verbose && (scrtop > 0 || scrend < lines))
flush();
for (i = 0; i < n; i++) {
if (scrtop == 0 && scrend == lines)
flushline(0);
tmp = screen[scrtop];
for (j = scrtop; j < scrend - 1; j++)
screen[j] = screen[j + 1];
for (j = 0; j < cols; j++)
tmp[j] = SPACE;
screen[scrend - 1] = tmp;
}
}

void
scrolldown(n)
int n;
{
int i, j;
cell *tmp;

if (verbose)
flush();
for (i = 0; i < n; i++) {
tmp = screen[scrend - 1];
for (j = scrend - 1; j > scrtop; j--)
screen[j] = screen[j - 1];
for (j = 0; j < cols; j++)
tmp[j] = SPACE;
screen[scrtop] = tmp;
}
}

void
clearscr()
{
int i, j;

for (i = 0; i < lines; i++)
for (j = 0; j < cols; j++)
screen[i][j] = SPACE;
}

void
sepline()
{
int i;

for (i = 0; i < cols - 1; i++)
putchar('-');
putchar('\n');
}

void
flush()
{
int i;

for (i = 0; i < lines; i++)
flushline(i);
sepline();
}

void
flushline(n)
int n;
{
int c, j, k, knj;
int rev, newrev, ul, newul;
cell cl;

rev = ul = FALSE;
knj = M_ASCII;
k = cols;
while (k > 0 && screen[n][k - 1] == SPACE)
k--;
for (j = 0; j < k; j++) {
cl = screen[n][j];
c = cl & C_MASK;
if (keepgr) {
newrev = (cl & A_REV) != 0;
newul = (cl & A_UL) != 0;
if (rev && !newrev || ul && !newul)
printf("\033[m");
if (!rev && newrev)
printf("\033[7m");
if (!ul && newul)
printf("\033[4m");
rev = newrev;
ul = newul;
}
if (cl & A_GRAPH) {
if (kcode == KC_JIS && knj != M_ASCII) {
printf("\033(%c", ksela);
knj = M_ASCII;
}
switch (c) {
case 'j': /* bottom right corner */
case 'k': /* top right corner */
case 'l': /* top left corner */
case 'm': /* bottom left corner */
case 'n': /* cross */
case 't': /* left head T */
case 'u': /* right head T */
case 'v': /* bottom head T */
case 'w': /* top head T */
c = '+';
break;
case 'q': /* horizontal line */
c = '-';
break;
case 'x': /* vertical line */
c = '|';
break;
case ' ': /* space */
c = ' ';
break;
default:
c = '?';
break;
}
putchar(c);
} else if (cl & A_KNJ1) {
switch (kcode) {
case KC_JIS:
if (knj != M_KANJI) {
printf("\033$%c", kselk);
knj = M_KANJI;
}
putchar((c >> 8) & 0x7f);
putchar(c & 0x7f);
break;
case KC_NONE:
case KC_EUC:
putchar((c >> 8) & 0x7f | 0x80);
putchar(c & 0x7f | 0x80);
break;
case KC_SJIS:
putchar((c >> 8) & 0xff);
putchar(c & 0xff);
break;
}
} else if (cl & A_KNJ2) {
/* do nothing */
} else if (c & 0x80) { /* kana */
switch (kcode) {
case KC_JIS:
if (knj != M_KANA) {
printf("\033(I");
knj = M_KANA;
}
putchar(c & 0x7f);
break;
case KC_NONE:
case KC_EUC:
putchar(SS2);
putchar(c & 0x7f | 0x80);
case KC_SJIS:
putchar(c & 0xff);
break;
}
} else { /* ascii */
if (kcode == KC_JIS && knj != M_ASCII) {
printf("\033(%c", ksela);
knj = M_ASCII;
}
putchar(c & 0x7f);
}
}
if (knj != M_ASCII)
printf("\033(%c", ksela);
if (keepgr && (rev || ul))
printf("\033[m");
putchar('\n');
}
--
太田純(Junn Ohta) (株)リコー ソフトウェア事業センター
oh...@src.ricoh.co.jp/JCF0...@niftyserve.or.jp

Reply all
Reply to author
Forward
0 new messages