#!/usr/bin/perl
;#
;; $Program='j2ps';
;; $Version='0.05';
;; $Author='Kondo Koichi <kondo_koichi@amath.doshisha.ac.jp>';
;; $Copyright='(C) KONDO Koichi, 1999/11/24, 2003/07/11';
;; $Content='Japanese text to Postscript convertor';
;#
;# ChangeLogs:
;#  19??/??/?? ver.0.01  kon 初期プロトタイプの作成．
;#  1999/11/24 ver.0.02  kon WEBに公開．
;#  19??/??/?? ver.0.03  kon TeXモードの追加．
;#  19??/??/?? ver.0.04  kon Mailモードの変更．
;#  2003/07/11 ver.0.05  kon 作者所属変更．ヘルプメッセージを作成．
;#                           オプション部分の変更．
;#
;; $PerlVer='5';
;#
;#
;# Japanese Code Convertor
require'jcode.pl';

# start!
$start_time=time;

##
## parameters
##

@Trays = ( 'A4','A3','B5','B4' );
@PaperParam{@Trays} = (
    [ '21.0cm','29.7cm' ],
    [ '24.0cm','42.0cm' ],
    [ '18.1cm','25.8cm' ],
    [ '25.8cm','36.8cm' ],
);

@FontType = ( 'Normal','Bold','Italic','BoldItalic','Slant','BoldSlant' );
@FontType{@FontType} = ( 0 .. 5 );

@Font = ( 'Times', 'Courier', 'Helvetica', 'HelveticaNarrow',
           'Palatino','SchoolBook','Symbol' );
@Font{@Font} = ( 0 .. 6 );

@KFont = ( 'Mincho', 'Gothic' );
@KFont{@KFont} = ( 7, 8 );

$Date            = gmtime;
$User            = $ENV{'LOGNAME'}.'@'.$ENV{'HOSTNAME'};
$Paper           = 'A4';
$Orientation     = 'Landscape';
$TopMargin       = &pt(".4inch");
$BottomMargin    = &pt(".7inch");
$LeftMargin      = &pt(".5inch");
$RightMargin     = &pt(".33inch");
$ColumnSep       = &pt(".5cm");
$Columns         = 2;
$FontSize        = 12;
$WesternFont     = $Font{'Times'};
$KanjiFont       = $KFont{'Mincho'};
$FType           = $FontType{'Normal'};
$LineSpace       = 1;
$QPageNo      = 'true';
$PageNo          = 1;
$PageNoFont      = $WesternFont;
$PageNoFontType  = $FType;
$PageNoFontSize  = $FontSize;
$QPartition   = 'true';
$PartitionWidth  = &pt(".1mm");


# Document Mode

%Greek = (
    'alpha',    'a',   'beta',     'b',	  'chi',      'c',    'delta',    'd',
    'epsilon',  'e',   'phi',      'f',   'gamma',    'g',    'eta',      'h',
    'iota',     'i',   'varphi',   'j',   'kappa',    'k',    'lambda',   'l',
    'mu',       'm',   'nu',       'n',   'omicron',  'o',    'pi',       'p',
    'theta',    'q',   'rho',      'r',   'sigma',    's',    'tau',      't',
    'upsilon',  'u',   'varpi',    'v',   'omega',    'w',    'xi',       'x',
    'psi',      'y',   'zeta',     'z',
    'Alpha',    'A',   'Beta',     'B',   'Chi',      'C',    'Delta',    'D',
    'Epsilon',  'E',   'Phi',      'F',   'Gamma',    'G',    'Eta',      'H',
    'Iota',     'I',   'vartheta', 'J',   'Kappa',    'K',    'Lambda',   'L',
    'Mu',       'M',   'Nu',       'N',   'Omicron',  'O',    'Pi',       'P',
    'Theta',    'Q',   'Rho',      'R',   'Sigma',    'S',    'Tau',      'T',
    'Upsilon',  'U',   'varsigma', 'V',   'Omega',    'W',    'Xi',       'X',
    'Psi',      'Y',   'Zeta',     'Z'
);

# C Mode
@mc_keyword=(
    'asm','auto','break','case','catch','char','class','const',
    'continue','default','delete','do','double','else','enum','extern',
    'float','for','friend','goto','if','inline','int','long','new',
    'opetrator','private','protected','public','register','return',
    'short','signed','sizeof','static','struct','static','switch',
    'template','this','throw','try','typedef','union','unsigned',
    'virtual','void','volatile','while'
);


##
## options
##

while($_=$ARGV[0]){
    if(/^-+h$/ || /^-+help$/){ &usage; }
    elsif(/^-v$/ || /^--version$/){
        print"$Program (Version $Version)\nPresented by $Author.\n";
        exit;
    }
    elsif(/^-+paper$/ || /^-+pa$/){
	shift; $Paper=uc($ARGV[0]); shift;    }
    elsif(/^-+portrait$/ || /^-+port$/ || /^-+po$/){
        $Orientation='Portrait'; shift;    }
    elsif(/^-+landscape$/ || /^-+land$/ || /^-+l$/){
        $Orientation='Landscape'; shift;    }
    elsif(/^-+lmargin$/ || /^-+ml$/){
        shift; $LeftMargin=&pt($ARGV[0]); shift;    }
    elsif(/^-+rmargin$/ || /^-+mr$/){
        shift; $RightMargin=&pt($ARGV[0]); shift;    }
    elsif(/^-+bmargin$/ || /^-+mb$/){
        shift; $BottomMargin=&pt($ARGV[0]); shift;    }
    elsif(/^-+tmargin$/ || /^-+mt$/){
        shift; $TopMargin=&pt($ARGV[0]); shift;    }
    elsif(/^-+columnsep$/ || /^-+cs$/){
        shift; $ColumnSep=&pt($ARGV[0]); shift;    }
    elsif(/^-+cols$/ || /^-+col$/ || /^-+c$/){
        shift; $Columns=$ARGV[0]; shift;    }
    elsif(/^-+fsize$/ || /^-+fs$/){
        shift; $FontSize=&pt($ARGV[0]); shift;    }
    elsif(/^-+ftype$/ || /^-+ft$/){
        shift; $FType=$FontType{$ARGV[0]}; shift;    }
    elsif(/^-+font$/ || /^-+fn$/){
        shift; $WesternFont=$Font{$ARGV[0]}; shift;    }
    elsif(/^-+kfont$/ || /^-+kf$/){
        shift; $KanjiFont=$KFont{$ARGV[0]}; shift;    }
    elsif(/^-+page-yes$/ || /^-+pyes$/){
        $QPageNo='true'; shift;    }
    elsif(/^-+page-no$/ || /^-+pno$/){
        $QPageNo='false'; shift;    }
    elsif(/^-+page-num$/ || /^-+pnum$/){
        shift; $PageNo=$ARGV[0]; shift;    }
    elsif(/^-+page-font$/ || /^-+pfont$/){
        shift; $PageNoFont=$Font{$ARGV[0]}; shift;    }
    elsif(/^-+page-type$/ || /^-+ptype$/){
        shift; $PageNoFontType=$FontType{$ARGV[0]}; shift;    }
    elsif(/^-+page-size$/ || /^-+psize$/){
        shift; $PageNoFontSize=&pt($ARGV[0]); shift;    }
    elsif(/^-+partition-yes$/ || /^-+paryes$/){
        $QPartition='true'; shift;    }
    elsif(/^-+partition-no$/ || /^-+parno$/){
        $QPartition='false'; shift;    }
    elsif(/^-+partition-width$/ || /^-+parw$/){
        shift; $PartitionWidth=&pt($ARGV[0]); shift;    }
    elsif(/^-+mode$/){ shift; $Mode=$ARGV[0]; shift; }
    elsif(/^--/){ shift; push(@File,shift); }
    elsif(/^-.*/){ &usage; }
    else{ push(@File,shift); }
}
@ARGV=@File;
@Mode=split(/,/,$Mode);

##
## variables
##

$Title        = @File[0];
( $PaperWidth,$PaperHeight ) = ($PaperParam{$Paper}[0],$PaperParam{$Paper}[1]);
$PaperWidth   = &pt($PaperWidth);
$PaperHeight  = &pt($PaperHeight);
$BoundX       = $PaperWidth;
$BoundY       = $PaperHeight;
&swap($PaperWidth,$PaperHeight) if $Orientation eq 'Landscape';
$TextBoxWidth = ( $PaperWidth - $LeftMargin - $RightMargin
                  - $ColumnSep*($Columns-1) ) / $Columns;
$TextBoxHeight = $PaperHeight - $BottomMargin - $TopMargin;
for($i=0;$i<$Columns;$i++){
    $TextBoxX0 .= " ".($LeftMargin + $TextBoxWidth*$i + $ColumnSep*$i);
    $TextBoxX1 .= " ".($LeftMargin + $TextBoxWidth*($i+1) + $ColumnSep*$i 
                        - $FontSize);
    $TextBoxY0 .= " ".($BottomMargin);
    $TextBoxY1 .= " ".($BottomMargin + $TextBoxHeight - $FontSize);
}

##
## output
##

# header & variables
print << "----";
\%!PS-Adobe-2.0
\%\%Title: $Title
\%\%Creator: $Program Ver.$Version by $Author
\%\%CreationDate: $Date
\%\%For: $User
\%\%Pages: (atend)
\%\%PageOrder: Ascend
\%\%DocumentPaperSizes: $Paper
\%\%Orientation: $Orientation
\%\%BoundingBox: 0 0 $BoundX $BoundY
\%\%EndComments
/\$J2PSDict 100 dict def
\$J2PSDict begin
/xdef { exch def } def
/adef { add def } def
\% variables
/Date ($Date) def
/Paper /$Paper def
/Orientation /$Orientation def
/Columns $Columns def
/Column 0 def
/SheetWidth $PaperWidth def
/SheetHeight $PaperHeight def
/LeftMargin $LeftMargin def
/RightMargin $RightMargin def
/BottomMargin $BottomMargin def
/TopMargin $TopMargin def
/BorderSep $FontSize def
/HeaderHeight $FontSize def
/FooterHeight $FontSize def
/ColumnSep $ColumnSep def
/TextBoxWidth $TextBoxWidth def
/TextBoxHeight $TextBoxHeight def
/TextBoxX0 [$TextBoxX0 ] def
/TextBoxX1 [$TextBoxX1 ] def
/TextBoxY0 [$TextBoxY0 ] def
/TextBoxY1 [$TextBoxY1 ] def
/DefaultFontSize $FontSize def
/FontSize DefaultFontSize def
/LineSpace $LineSpace def
/Color [
 [ 0 0 0 ] [ 1 0 0 ] [ 0 1 0 ] [ 1 1 0 ] \% Black Red Green Yellow
 [ 0 0 1 ] [ 0.625 0.125 0.9375 ] [ 0 1 1 ] [ 1 1 1 ] \% Blue Purple Cyan White
] def
/Font [
 [ /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic ]
 [ /Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique ]
 [ /Helvetica /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique ]
 [ /Helvetica-Narrow /Helvetica-Narrow-Bold
       /Helvetica-Narrow-Oblique /Helvetica-Narrow-BoldOblique ]
 [ /Palatino-Roman /Palatino-Bold /Palatino-Italic /Palatino-BoldItalic ]
 [ /NewCenturySchlbk-Roman /NewCenturySchlbk-Bold
       /NewCenturySchlbk-Italic /NewCenturySchlbk-BoldItalic ]
 [ /Symbol /Symbol /Symbol /Symbol ]
 [ /Ryumin-Light-H /GothicBBB-Medium-H
       /Ryumin-Light-H /GothicBBB-Medium-H ]
 [ /GothicBBB-Medium-H /GothicBBB-Medium-H
       /GothicBBB-Medium-H /GothicBBB-Medium-H ]
] def
/DefaultFontType $FType def
/DefaultWesternFont $WesternFont def
/DefaultKanjiFont $KanjiFont def
/FontType DefaultFontType def
/WesternFont DefaultWesternFont def
/KanjiFont DefaultKanjiFont def
/Language /English def
/QPageNo $QPageNo def
/PageNo $PageNo def
/PageNoFontSize $FontSize def
/PageNoFont $PageNoFont def
/PageNoFontType $PageNoFontType def
/QPartition $QPartition def
/PartitionWidth $PartitionWidth def
/X 0 def /Y 0 def
/OldX X def /OldY Y def
/OldLineY Y def
/TabWidth FontSize 8 mul def
/FontSizeStack 65 array def
/FontTypeStack 65 array def
/WesternFontStack 65 array def
/KanjiFontStack 65 array def
----

# procedures
print << "----";
\% procedures
/cshow { dup stringwidth pop 2 div neg 0 rmoveto show } def
/initStack { 0 1 put } def
/pushStack {
  /value xdef /stack xdef
  /n stack 0 get 1 add def
  stack n value put
  stack 0 n put
} def
/popStack {
  /stack xdef
  /n stack 0 get def
  stack 0 n 1 sub put
  stack n get
} def
/LineSkip { FontSize LineSpace add } def
/initTabWidth { getFont setfont /TabWidth (________) stringwidth pop def } def
/setNextTab {
  /w xdef setCurrentXY /x X0 def
  { /x x w add def x X gt { exit } if } loop /X x def
} def
/TabX { /w xdef X0 exch { w add } repeat } def
/moveTab {
  /m xdef /n xdef
  n TabWidth m div TabX /X xdef
  moveXY checkOverTextBox
} def
/moveNextTab { TabWidth setNextTab moveXY checkOverTextBox } def
/startUp {
  FontSizeStack initStack
  FontTypeStack initStack
  WesternFontStack initStack
  KanjiFontStack initStack
  setPaperOrientation
  setTextBox
  drawPageNo
  drawPartition
  moveLeftTopXY
  /MaxLineSkip LineSkip def
  /OldLineY Y LineSkip add def
  setEnglish
  initTabWidth
} def
\%
/QLandscape { Orientation /Landscape eq } def
/QPortrait { Orientation /Portrait eq } def
/setPaperOrientation {
  QLandscape { $PaperHeight 0 translate 90 rotate } if 
} def
/setNextColumn {
  /Column Column 1 add def
  Column Columns ge { /Column 0 def } if
} def
/setTextBox {
  /X0 TextBoxX0 Column get def
  /X1 TextBoxX1 Column get def
  /Y0 TextBoxY0 Column get def
  /Y1 TextBoxY1 Column get def
} def
/setCurrentXY { currentpoint /Y xdef /X xdef } def
/setLeftX { /X X0 def } def
/setTopY { /Y Y1 def } def
/setLeftTopXY { setLeftX setTopY } def
/setNextLineY { /Y Y MaxLineSkip sub def } def
/changeLineY {
  OldLineY LineSkip sub dup Y lt { /Y xdef } { pop } ifelse
  LineSkip MaxLineSkip gt { /MaxLineSkip LineSkip def } if
} def
/moveXY { X Y moveto } def
/moveLeftX { setLeftX moveXY } def
/moveLeftTopXY { setLeftTopXY moveXY } def
/moveNewLine {
 /OldLineY Y def
 setNextLineY Y Y0 le { moveNewPage } { moveLeftX } ifelse
 /MaxLineSkip LineSkip def
} def
/moveNewPage {
  setNextColumn
  Column 0 eq { moveNewSheet } if
  setTextBox
  incPageNo
  drawPageNo
  drawPartition
  moveLeftTopXY
  /OldLineY Y LineSkip add def
} def
/moveNewSheet { showpage setPaperOrientation } def
/moveBackSpace {
  WesternFont FontType FontSize getWesternFont setfont
  (_) stringwidth pop neg 0 rmoveto
} def
/backupXY { /OldX X def /OldY Y def } def
/checkOverTextBox { setCurrentXY X X1 ge { moveNewLine } if backupXY } def
/getFontName {
 /j xdef /i xdef j 4 ge { /j j 4 sub def } if Font i get j get
} def
/getWesternFont {
  /fs xdef /ft xdef /fn xdef
  fn ft getFontName findfont fs scalefont
  ft 4 ge { [ 1 0 .2 1 0 0 ] makefont } if
} def
/getKanjiFont {
  /fs xdef /ft xdef /fn xdef
  fn ft getFontName findfont fs 0.9 mul scalefont
  ft 2 ge { [ 1 0 .2 1 0 0 ] makefont } if
} def
/getFont {
  QEnglish { WesternFont FontType FontSize getWesternFont } {
    QJapanese {  KanjiFont FontType FontSize getKanjiFont } { pop } ifelse
  } ifelse
} def
/setLanguage { /Language xdef } def
 /setEnglish { /English setLanguage } def
 /setJapanese { /Japanese setLanguage } def
/QEnglish { Language /English eq } def
/QJapanese { Language /Japanese eq } def
/drawString {
  QEnglish { drawEnglishString } {
    QJapanese { drawJapaneseString } { pop } ifelse
  } ifelse
} def
/drawEnglishString {
  getFont setfont { pop pop checkOverTextBox } exch kshow
} def
/drawJapaneseString {
  /str xdef
  getFont setfont
  /buf 2 string def
  /n { str length 2 div } def
  /i 0 def
  1 1 n {
    buf 0 str i get put /i i 1 adef
    buf 1 str i get put /i i 1 adef
    buf show
    checkOverTextBox
  } for
} def
\% font size
/setFontSize { /FontSize xdef setCurrentXY changeLineY moveXY } def
/setDefaultFontSize { DefaultFontSize setFontSize } def
/setFontSizeMag+ { DefaultFontSize exch { 1.2 mul } repeat setFontSize } def
/setFontSizeMag- { DefaultFontSize exch { 1.2 div } repeat setFontSize } def
/pushFontSize { FontSizeStack FontSize pushStack } def
/popFontSize { FontSizeStack popStack setFontSize } def
\% font type
/setFontType { /FontType xdef } def
/setNormal { 0 setFontType } def
/setBold { 1 setFontType } def
/setItalic { 2 setFontType } def
/setBoldItalic { 3 setFontType } def
/setSlant { 4 setFontType } def
/setBoldSlant { 5 setFontType } def
/addBold { FontType 2 mod 0 eq { FontType 1 add setFontType } if } def
/delBold { FontType 2 mod 1 eq { FontType 1 sub setFontType } if } def
/addNormal { 0 FontType 2 mod add setFontType } def
/addItalic { 2 FontType 2 mod add setFontType } def
/addSlant { 4 FontType 2 mod add setFontType } def
/setDefaultFontType { DefaultFontType setFontType } def
/pushFontType { FontTypeStack FontType pushStack } def
/popFontType { FontTypeStack popStack setFontType } def
\% western font
/setWesternFont { /WesternFont xdef } def
/setTimesRoman { 0 setWesternFont } def
/setCourier { 1 setWesternFont } def
/setHelvetica { 2 setWesternFont } def
/setHelveticaNarrow { 3 setWesternFont } def
/setPalatino { 4 setWesternFont } def
/setSchoolBook { 5 setWesternFont } def
/setSymbol { 6 setWesternFont } def
/setDefaultWesternFont { DefaultWesternFont setWesternFont } def
/pushWesternFont { WesternFontStack WesternFont pushStack } def
/popWesternFont { WesternFontStack popStack setWesternFont } def
\% kanji font
/setKanjiFont { /KanjiFont xdef } def
/setMincho { 7 setKanjiFont } def
/setGothic { 8 setKanjiFont } def
/pushKanjiFont { KanjiFontStack KanjiFont pushStack } def
/popKanjiFont { KanjiFontStack popStack setKanjiFont } def
/setDefaultKanjiFont { DefaultKanjiFont setKanjiFont } def
\% color
/setColor { Color exch get /c xdef c 0 get c 1 get c 2 get setrgbcolor } def
/setBlack { 0 setColor } def
/setRed { 1 setColor } def
/setGreen { 2 setColor } def
/setYellow { 3 setColor } def
/setBlue { 4 setColor } def
/setPurple { 5 setColor } def
/setCyan { 6 setColor } def
/setWhite { 7 setColor } def
/incPageNo { /PageNo PageNo 1 adef } def
/drawPageNo {
  QPageNo {
    gsave
      PageNoFont PageNoFontType PageNoFontSize getWesternFont setfont
      X0 TextBoxWidth 2 div add Y0 PageNoFontSize 1.5 mul sub moveto
      PageNo (          ) cvs cshow
    grestore
  } if
} def
/drawPartition {
  QPartition Column Columns 1 sub lt and {
    gsave
      /x X0 TextBoxWidth add ColumnSep 2 div add FontSize 2 div sub def
      /y1 Y1 FontSize add def
      /y0 Y0 PageNoFontSize 2 mul sub def
      PartitionWidth setlinewidth
      x y1 moveto x y0 lineto stroke
    grestore
  } if
} def
\% alias
/S { drawString } def
/E { setEnglish } def
/J { setJapanese} def
/NP { moveNewPage } def
/BR { moveNewLine } def
/LF { moveLeftX } def
/TAB+1 { moveNextTab } def
/TAB { moveTab } def
/BS { moveBackSpace } def
/CK { setBlack } def
/CR { setRed } def
/CG { setGreen } def
/CY { setYellow } def
/CB { setBlue } def
/CP { setPurple } def
/CC { setCyan } def
/CW { setWhite } def
/DT { setDefaultFontType } def
/DF { setDefaultWesternFont } def
/DK { setDefaultKanjiFont } def
/TN { setNormal } def
/TB { setBold } def
/TI { setItalic } def
/TIB { setBoldItalic } def
/TSl { setSlant } def
/TSlB { setBoldSlant } def
/B { addBold } def
/M { delBold } def
/N { addNormal } def
/I { addItalic } def
/Sl { addSlant } def
/T+ { pushFontType } def
/T- { popFontType } def
/B+ { pushFontType addBold } def
/B- { popFontType } def
/I+ { pushFontType addItalic } def
/I- { popFontType } def
/Sl+ { pushFontType addSlant } def
/Sl- { popFontType } def
/FR { setTimesRoman } def
/FC { setCourier } def
/FH { setHelvetica } def
/FHN { setHelveticaNarrow } def
/FP { setPalatino } def
/FSB { setSchoolBook } def
/FSy { setSymbol } def
/F+ { pushWesternFont } def
/F- { popWesternFont } def
/G+ { pushWesternFont setSymbol pushFontType setSlant } def
/G- { popFontType popWesternFont } def
/KM { setMincho } def
/KG { setGothic } def
/K+ { pushKanjiFont } def
/K- { popKanjiFont } def
/FS+ { pushFontSize } def
/FS- { popFontSize } def
/FS0 { setDefaultFontSize } def
/FS1 { 1 setFontSizeMag+ } def    /FS-1 { 1 setFontSizeMag- } def
/FS2 { 2 setFontSizeMag+ } def    /FS-2 { 2 setFontSizeMag- } def
/FS3 { 3 setFontSizeMag+ } def    /FS-3 { 3 setFontSizeMag- } def
/FS4 { 4 setFontSizeMag+ } def    /FS-4 { 4 setFontSizeMag- } def
/FS5 { 5 setFontSizeMag+ } def    /FS-5 { 5 setFontSizeMag- } def
/FS6 { 6 setFontSizeMag+ } def    /FS-6 { 6 setFontSizeMag- } def
/FNT+ { FS+ T+ F+ K+ } def
/FNT- { K- F- T- FS- } def
----

print << "----";
\%\%EndProlog
\% initialization
startUp
\% document
----

$JIN  = '\e\$[B\@]';
$JOUT = '\e\([BJ]';
%tags = (
      "\000",     'null',        # null
      "\001",     'OPR',         # 制御コードの区切り
      "\n",       'BR',          # 改行
      "\f",       'NP',          # 改ページ
      "\r",       'LF',          #
      "\t",       'TAB+1'          # タブ
);

while($line=<>){
    # 日本語を JIS code に変換
    &jcode'convert(*line,'jis');
    # モード
    foreach $mode (@Mode){
        if($mode=~/^mail$/i){ &mode_mail($line); }
        if($mode=~/^c$/i){ &mode_c($line); }
        if($mode=~/^doc$/i){ &mode_doc($line); }
        if($mode=~/^tex$/i){ &mode_tex($line); }
    }
    # 区切りの作成
    &makeSegment($line);
    # 出力
    while($line=~/[\001-\037]/){
        $txt=$`;  $key=$&;  $line=$';
        &toPSText($txt);
        $tag="";
        $tag=$tags{$key} if exists $tags{$key};

        print "($txt) S " if $txt ne "";

        if($tag eq "OPR"){ # 制御コード
            $line=~/^([^\001]*)\001/;
            $txt=$`;  $tag=$1;  $line=$';
        }

        print "$tag " if $tag ne "";
        print "\n"  if ( $tag eq "BR" ||  $tag eq "NP" || $tag eq "LF");

#$tmp1=$key; $tmp2=$line;
#$tmp1=~s/[\000-\037\177-\377]/'<'.sprintf("%X",ord($&)).'>'/ge;
#$tmp2=~s/[\000-\037]/'<'.sprintf("%X",ord($&)).'>'/ge;
#print STDERR "$tmp1\t$tag\t$tmp2\n";

    }
    &toPSText($line);
    print "($line) S\n" if $line ne "";
}
print"\n";

print << "----";
showpage
\%\%Trailer
end
----

# end!
#$prog_time=time-$start_time;
#print STDERR "About $prog_time sec.\n";
exit;

##
## subroutines
##

sub pt{
    my($l)=@_;
    if($l=~/inch$/){ $l=~"s/inch//g"; return int($l*72*1000)/1000; }
    elsif($l=~/mm$/){ $l=~"s/mm//g"; return int($l*72/25.4*1000)/1000; }
    elsif($l=~/cm$/){ $l=~"s/cm//g"; return int($l*72/2.54*1000)/1000; }
    else{ $l=~s/[^0-9]+//g; return $l; }
}

sub swap{ my($tmp)=$_[0]; $_[0]=$_[1]; $_[1]=$tmp; }

sub makeSegment {
    study($_[0]);
    # 太文字の区切り
    if($_[0]=~/\cH/){
	$_[0]=~s/(..)($JOUT)?\cH\cH($JIN)?\1/\02$1\03/g;
	$_[0]=~s/(.)(\cH\1)+/\02$1\03/g;
	$_[0]=~s/\03\02//g;
	$_[0]=~s/\02/\01B+\01/g;  # start
	$_[0]=~s/\03/\01B-\01/g;  # end
    }
    # 下線の区切り
    if($_[0]=~/\cH/){
	$_[0]=~s/__\cH\cH($JIN)?(..)/\02$1$2\03/g;
	$_[0]=~s/_\cH(.)/\02$1\03/g;
	$_[0]=~s/\03\02//g;
	$_[0]=~s/\02/\01I+\01/g; # start
	$_[0]=~s/\03/\01I-\01/g; # end
    }
    # 色の開始
    if($_[0]=~/\e\[0.*m/){
        $_[0]=~s/(\e\[0m)/\01CK\01/g;             # black
	$_[0]=~s/(\e\[0[0145];[34]0m)/\01CK\01/g; # black
	$_[0]=~s/(\e\[0[0145];[34]1m)/\01CR\01/g; # red
	$_[0]=~s/(\e\[0[0145];[34]2m)/\01CG\01/g; # green
	$_[0]=~s/(\e\[0[0145];[34]3m)/\01CY\01/g; # yellow
	$_[0]=~s/(\e\[0[0145];[34]4m)/\01CB\01/g; # blue
	$_[0]=~s/(\e\[0[0145];[34]5m)/\01CP\01/g; # purple
	$_[0]=~s/(\e\[0[0145];[34]6m)/\01CC\01/g; # cyan
	$_[0]=~s/(\e\[0[0145];[34]7m)/\01CW\01/g; # white
    }
    # 日本語の区切り
    if($_[0]=~/\e/){
        $_[0]=~s/$JOUT/\01E\01/g;
        $_[0]=~s/$JIN/\01J\01/g;
    }
    #
#    $_[0]=~s/\t/        /g; # Replace '\t'
}

sub toPSText{
#    $_[0]=~s/\cH/\^H/g;
#    $_[0]=~s/\e/\^\[/g;
    $_[0]=~s/[\000-\037\177-\377]/'<'.sprintf("%X",ord($&)).'>'/ge;
    $_[0]=~s+\\+\\\\+g;     # Replace '\'
    $_[0]=~s+\(+\\\(+g;     # Replace '('
    $_[0]=~s+\)+\\\)+g;     # Replace ')'
}

sub mode_doc{
    # \,{,}
    $_[0]=~s/\\\\/\02/g;
    $_[0]=~s/\\\{/\03/g;
    $_[0]=~s/\\\}/\04/g;

    $_[0]=~s/\\tiny ?/\01FS-4\01/g;
    $_[0]=~s/\\scriptsize ?/\01FS-3\01/g;
    $_[0]=~s/\\footenotesize ?/\01FS-2\01/g;
    $_[0]=~s/\\small ?/\01FS-1\01/g;
    $_[0]=~s/\\normalsize ?/\01FS0\01/g;
    $_[0]=~s/\\large ?/\01FS1\01/g;
    $_[0]=~s/\\Large ?/\01FS2\01/g;
    $_[0]=~s/\\LARGE ?/\01FS3\01/g;
    $_[0]=~s/\\huge ?/\01FS4\01/g;
    $_[0]=~s/\\Huge ?/\01FS5\01/g;
    $_[0]=~s/\\HUGE ?/\01FS6\01/g;

    # western font
    $_[0]=~s/\\times ?/\01FR\01/g;
    $_[0]=~s/\\courier ?/\01FC\01/g;
    $_[0]=~s/\\helvetica\-narrow ?/\01FHN\01/g;
    $_[0]=~s/\\helvetica ?/\01FH\01/g;
    $_[0]=~s/\\palatino ?/\01FP\01/g;
    $_[0]=~s/\\school\-book ?/\01FSB\01/g;
    $_[0]=~s/\\rm ?/\01FR\01/g;
    $_[0]=~s/\\tt ?/\01FC\01/g;
    $_[0]=~s/\\sf ?/\01FH\01/g;

    # kanji fontn
    $_[0]=~s/\\mincho ?/\01KM\01/g;
    $_[0]=~s/\\gothic ?/\01KG\01/g;
    $_[0]=~s/\\mc ?/\01KM\01/g;
    $_[0]=~s/\\gt ?/\01KG\01/g;

    # font type
    $_[0]=~s/\\mdseries ?/\01M\01/g;
    $_[0]=~s/\\bfseries ?/\01B\01/g;
    $_[0]=~s/\\upshape ?/\01N\01/g;
    $_[0]=~s/\\itshape ?/\01I\01/g;
    $_[0]=~s/\\slshape ?/\01Sl\01/g;
    $_[0]=~s/\\bf ?/\01B\01/g;
    $_[0]=~s/\\nr ?/\01N\01/g;
    $_[0]=~s/\\it ?/\01I\01/g;
    $_[0]=~s/\\sl ?/\01Sl\01/g;

    # Greek Alphabets
    $_[0]=~s/\\greek/\01G+\01abcdefghijklmnopqrstuvwxyz\01G-\01/g;
    $_[0]=~s/\\Greek/\01G+\01ABCDEFGHIJKLMNOPQRSTUVWXYZ\01G-\01/g;
    foreach $key (keys %Greek){
        $_[0]=~s/\\$key/"\01G+\01".$Greek{$key}."\01G-\01"/eg;
    }

    # font effective area
    $_[0]=~s/\{/\01FNT+\01/g;
    $_[0]=~s/\}/\01FNT-\01/g;

    # spacing
    $_[0]=~s/\\newline/\01BR\01/g;
    $_[0]=~s/\\newpage/\01NP\01/g;
    $_[0]=~s/\\tab ?/\01TAB+1\01/g;
    $_[0]=~s/[ \t]*\\t([0-9]+)\/([0-9]+) ?/\01\1 \2 TAB\01/g;
    $_[0]=~s/[ \t]*\\t([0-9]+) ?/\01\1 1 TAB\01/g;

    # \,{,}
    $_[0]=~s/\02/\\/g;
    $_[0]=~s/\03/\{/g;
    $_[0]=~s/\04/\}/g;
}

sub mode_mail{ # E-Mail Mode
    if(!defined($mail_header)){
        $_[0]="\001FC FS-2\001$_[0]";
        $mail_header=1;
    }
    if($mail_header==1 && $_[0]=~/^\n$/){
        $_[0]="\001FS0 DF\001$_[0]";
        $mail_header=0;
    }
    if($mail_header==1){
	$_[0]=~s/^(Date:)(.*)/\01B+\01\1\2\01B-\01/g;
	$_[0]=~s/^(To:)(.*)/\01B+\01\1\01I+\01\2\01I- B-\01/g;
	$_[0]=~s/^(From:)(.*)/\01B+\01\1\01I+\01\2\01I- B-\01/g;
	$_[0]=~s/^(Subject:)(.*)/\01B+\01\1\2\01B-\01/g;
	if($_[0]=~m|=\?ISO\-2022\-JP\?B\?([0-9A-Za-z\/\+\=]+)\?\=|gi){
	    $eucjp=base64_decode($1);
	    $_[0]=~s|\=\?ISO\-2022\-JP\?B\?([0-9A-Za-z\/\+\=]+)\?\=|$eucjp|gi;
	}
    }
    $_[0]=~s/^>(.*)/>\01Sl+\01\1\01Sl-\01/g;
    $_[0]=~s/(http:\/\/.*)([\s]+)/\01I+\01\1\01I-\01\2/g;
}

sub mode_c{
    my($k);
    $mc_tkn='0-9\s\(\)\{\}\<\>\[\],\*:';
    $_[0]=~s/(#[^$mc_tkn]+)/\01B+\01\1\01B-\01/g;
    foreach $k (@mc_keyword){
        $_[0]=~s/([$mc_tkn]*)($k)([$mc_tkn]*)/\1\01I+\01\2 \01I-\01\3/g;
    }
}

sub mode_tex{
    $_[0]=~s/(\\[a-zA-z\@]+)/\001 FC \001\1\001 DF \001/g;
}

sub usage{
   print << "----";

  Usage: $Program [options] files

   ファイル files を Postscript に変換する．ファイルは複数指定可能．
   ファイル名に -- を指定するか，一つもファイルをしてしないときは
   標準入力からファイルを入力する．

   -h, -help         このメッセージ．
   -v, -version      バージョンの表示．
   -pa, -paper tray  紙の大きさを tray で指定．
                     tray = 'A4', 'A3', 'B5', or 'B4'.
   -po, -port, -portrait
                     紙を縦向きに指定（デフォルト値：横向き）．
   -l, -land, -landscape
                     紙を横向きに指定（デフォルト値：横向き）．
   -ml, -lmargin width
                     左の余白を width で指定（デフォルト値：.5inch）．
                     widthの単位は cm, mm, inch を用いる．
                     (ex) 1cm, 15mm, .5inch
   -mr, -rmargin width
                     右の余白を width で指定（デフォルト値：.33inch）．
   -mb, -bmargin width
                     下の余白を width で指定（デフォルト値：.7inch）．
   -mt, -tmargin width
                     上の余白を width で指定（デフォルト値：.4inch）．
   -cs, -columnsep width
                     縦欄の間の余白を width で指定（デフォルト値：.5cm）．
   -c, -col, -cols n 縦欄の個数を n で指定（デフォルト値：2）．
   -fn, -font font   フォントを font で指定（デフォルト値：'Times'）．
                     font = 'Times', 'Courier', 'Helvetica',
                            'HelveticaNarrow', 'Palatino',
                            'SchoolBook', 'Symbol'.
   -kf, -kfont kfont 日本語フォントを kfont で指定（デフォルト値：'Mincho'）．
                     kfont = 'Mincho', or 'Gothic'.
   -ft, -ftype ftype フォントタイプを ftype で指定（デフォルト値：'Normal'）．
                     ftype = 'Normal', 'Bold', 'Italic', 'BoldItalic',
                             'Slant', or 'BoldSlant'.
   -fs, -fsize fsize フォントサイズを fsize で指定（デフォルト値：12）．
   -pyes, -page-yes  ページ番号を印刷する（デフォルト値：する）．
   -pno, -page-no    ページ番号を印刷しない（デフォルト値：する）．
   -pnum, -page-num n
                     ページ番号の最初の番号を n で指定（デフォルト値：1）．
   -pfont, -page-font font
                     ページ番号のフォントを font で指定
                    （デフォルト値：本文フォントと同じ）．
   -ptype, -page-type ftype
                     ページ番号のフォントタイプを ftype で指定
                    （デフォルト値：本文フォントタイプと同じ）．
   -psize, -page-size fsize
                     ページ番号のフォントを fsize で指定
                    （デフォルト値：本文フォントタイプと同じ）．
   -paryes, -partition-yes
                     縦欄の間に縦棒を印刷する（デフォルト値：する）．
   -parno, -partition-no
                     縦欄の間に縦棒を印刷しない（デフォルト値：する）．
   -parw, -partition-width width
                     縦欄の間に縦棒の幅を width で指定（デフォルト値：.1mm）．
   -mode mode        印刷モードを mode で指定（デフォルト値：なし）．
                     mode = 'mail', 'tex', 'C', 'doc'

----
    exit;
}

sub base64_decode{
    my($str)=$_[0];
    my $res="";
    $str=~tr|A-Za-z0-9+=/||cd;             # remove non-base64 chars
#    if(length($str) % 4){
#	print"Not base64 data!\n";
#	exit;
#    }
    $str=~s/=+$//;                         # remove padding
    $str=~tr|A-Za-z0-9+/| -_|;             # convert to uuencoded format
    while($str=~/(.{1,60})/gs){
        my $len = chr(32 + length($1)*3/4); # compute length byte
        $res .= unpack("u", $len . $1);     # uudecode
    }
    $res;
}

__END__
