{$A-,B-,D-,E-,F-,I+,L-,N-,O-,R-,S-,V-}
{Compile with Turbo-Pascal 5.0}
Program Jem2TeX(Input,Output);
{
  This program translates a .JEM file into a .TeX file

  Author: Francois Jalbert
              '
  Date: November 1990 

  Version: 1.0

  Date: January 1991

  Version: 1.01

  Modifications: - Added \hskip0pt plus0.1em between all Japanese symbols which 
                   improved dramatically line breaks and inter-sentence spacing 
                   since [La]TeX could only add glue between whole Japanese 
                   sentences. 
                 - Extra space after punctuation is now an option since it is 
                   not desirable with MuTeX when the text is to go under the
                   staff. 
                 - Font names now use only small letters to be compatible with 
                   the fontlib program supplied with emTeX. 
                 - Command line parameters now supported.
                 - Run-time parameters now supported.
                 - Updated and improved run-time messages.

  Date: April 1991

  Version: 2.00

  Modifications: - Added four kanjis.
                 - If desired, only standard JIS '83 characters are allowed.
                 - If desired, a % is added at each Japanese end of line.
                 - Three file name extensions .JEM .JPN .JAP now supported.
                 - Default extension is .JEM and the program has been renamed.
                 - Three run-time parameter flags now supported.
                 - Japanese comments not translated anymore for reference.
                 - Hyphenation and glue handled separately for better control.
                 - More clever algorithm for Japanese hyphenation.
                 - Space after some punctuation now obtained with \eeee.
                 - Small space around some punctuation introduced with \eee.
                 - Tiny space between Japanese characters with \ee.
                 - Space between Japanese and Roman with \eeee and \eee.
                 - Symbols separated only by [La]TeX comments are now 
                   recognized as consecutive.
                 - MS-kanji (Shift-JIS) now supported.

  Error Levels: 0 - Normal termination.
                1 - Error.
}
Const
  {Highest Bitmap number in JIS24}
  BitmapMax=7806;
  {Highest font number}
  FontMax=60; {Floor of 7806 Div 128}
  {Highest size number}
  SizeMax=7; {magsteps are 0, 0.5, 1, 2, 3, 4, 5}
  {File name extensions in priority order}
  Extension1:String[4]='.jem';
  Extension2:String[4]='.jpn';
  Extension3:String[4]='.jap';
  {Run-time flag of all the same length}
  RunFlag1:String[7]='JEM2TEX';
  RunFlag2:String[7]='JPN2TEX';
  RunFlag3:String[7]='JAP2TEX';
  {Parameter flag}
  Flag1='/'; {DOS style}
  Flag2='-'; {UNIX style}
  {Parameter keywords in approximate decreasing length order}
  Space1:String[10]='EXTRASPACE';
  Space2:String[5]='EXTRA';
  Space3:String[5]='SPACE';
  NoSpace1:String[12]='NOEXTRASPACE';
  NoSpace2:String[7]='NOEXTRA';
  NoSpace3:String[7]='NOSPACE';
  Percent1:String[7]='COMMENT';
  Percent2:String[7]='PERCENT';
  Percent3:String[3]='EOL';
  NoPercent1:String[9]='NOCOMMENT';
  NoPercent2:String[9]='NOPERCENT';
  NoPercent3:String[5]='NOEOL';
  EUC1:String[3]='EUC';
  NoEUC1:String[7]='MSKANJI';
  NoEUC2:String[8]='SHIFTJIS';
  Extended1:String[8]='EXTENDED';
  Standard1:String[8]='STANDARD';
  LaTeX1:String[5]='LATEX';
  TeX1:String[5]='MUTEX';
  TeX2:String[3]='TEX';
  One1:String[4]='1000';
  Two1:String[4]='1095';
  Three1:String[4]='1200';
  Four1:String[4]='1440';
  Five1:String[4]='1728';
  Six1:String[4]='2074';
  Seven1:String[4]='2488';
  One2:String[3]='0.0';
  Two2:String[3]='0.5';
  Three2:String[3]='1.0';
  Four2:String[3]='2.0';
  Five2:String[3]='3.0';
  Six2:String[3]='4.0';
  Seven2:String[3]='5.0';
  One3:String[1]='0';
  Three3:String[1]='1';
  Four3:String[1]='2';
  Five3:String[1]='3';
  Six3:String[1]='4';
  Seven3:String[1]='5';

Type
  InFileType=File Of Byte;
  OutFileType=Text;
  BitmapRange=1..BitmapMax;
  FontRange=0..FontMax;
  FontType=Array [FontRange] Of Boolean;
  SizeRange=1..SizeMax;
  FontsType=Array [SizeRange] Of FontType;
  {Run time parameters}
  RunTimeType=Record
                FileName,Extension:String;
                ExtraSpace,Percent,LaTeX,EUC,Extended:Boolean;
                Size:SizeRange;
              End;
  {Japanese punctuation information}
  PunctuationType=Record
                    {Indicates .,!? present}
                    OldMajorEOL,NewMajorEOL:Boolean;
                    {Indicates :; present}
                    OldMinorEOL,NewMinorEOL:Boolean;
                    {Indicates `"([< and other openings present}
                    OldOpening,NewOpening:Boolean;
                    {Indicates '")]> and other closings present}
                    OldClosing,NewClosing:Boolean;
                    {Indicates Japanese center dot present}
                    OldCenterDot,NewCenterDot:Boolean;
                    {Indicates Hiragana, Katakana, or Kanji present}
                    OldJapanese,NewJapanese:Boolean
                  End;
  {Scanning Information}
  ScanningType=Record
                 {Current pass terminated}
                 Done:Boolean;
                 {Indicates the current pass must produce output}
                 Echo:Boolean;
                 {Indicates the current line is a comment}
                 Comment:Boolean;
                 {Indicates current Bitmap immediately followed previous one}
                 Immediate:Boolean;
                 {Indicates the last Roman character was a letter or digit}
                 WasLetter:Boolean;
                 {Used for glue after a bitmap and before a roman}
                 RomanMajorEOL,RomanMinorEOL,RomanOpening:Boolean;
                 {Non-comment Bitmap found}
                 Found:Boolean;
                 {Processing the first character on the line which could be %}
                 First:Boolean;
                 {Comment line which may contain Bitmaps}
                 CommentLine:String;
                 {Current JIS24 Bitmap number}
                 Bitmap:BitmapRange;
                 {Roman or first part of Bitmap read}
                 Data1:Byte
               End;

Var
  {Input and Output file names}
  InFile:InFileType;
  OutFile:OutFileType;
  {Run time parameters}
  RunTime:RunTimeType;
  {JemTeX fonts used}
  Fonts:FontsType;

{------------------------------ EchoParameters -------------------------------}

Procedure EchoParameters(Var EchoFile:Text; Var RunTime:RunTimeType);
{Echoes the current parameters in EchoFile}
Begin
With RunTime Do
  Begin
  Write(EchoFile,'File='+FileName);
  If ExtraSpace Then Write(EchoFile,'  Space')
  Else Write(EchoFile,'  No Space');
  If Percent Then Write(EchoFile,'  Added %')
  Else Write(EchoFile,'  No Added %');
  If LaTeX Then Write(EchoFile,'  LaTeX')
  Else Write(EchoFile,'  TeX');
  If EUC Then Write(EchoFile,'  EUC')
  Else Write(EchoFile,'  MS-kanji');
  If Extended Then Write(EchoFile,'  Extended')
  Else Write(EchoFile,'  Standard');
  Write(EchoFile,'  Font Size=');
  Case Size Of
    1:Write(EchoFile,'1000');
    2:Write(EchoFile,'1095');
    3:Write(EchoFile,'1200');
    4:Write(EchoFile,'1440');
    5:Write(EchoFile,'1728');
    6:Write(EchoFile,'2074');
    7:Write(EchoFile,'2488')
    End;
  Writeln(EchoFile,'.')
  End
End;

{------------------------------- GetParameters -------------------------------}

Procedure SimpleQuery(Title,ChoiceA,ChoiceB:String; Var Answer:Boolean);
Var
  JChar:Char;
  Valid:Boolean;
Begin
Repeat
  Valid:=True;
  Writeln(Title+':');
  Writeln('   a)  '+ChoiceA);
  Writeln('   b)  '+ChoiceB);
  Write('Your choice? ');
  Readln(JChar);
  JChar:=UpCase(JChar);
  If JChar='A' Then Answer:=True
  Else
    If JChar='B' Then Answer:=False
    Else
      Begin Valid:=False; Write(Chr(7)) End
Until Valid;
Writeln
End;

Procedure SizeQuery(Var Size:SizeRange);
Var
  JChar:Char;
  Valid:Boolean;
Begin
Repeat
  Valid:=True;
  Writeln('Japanese Font Size:');
  Writeln('   a)  1000  magstep(0.0)');
  Writeln('   b)  1095  magstep(0.5)');
  Writeln('   c)  1200  magstep(1.0)');
  Writeln('   d)  1440  magstep(2.0)');
  Writeln('   e)  1728  magstep(3.0)');
  Writeln('   f)  2074  magstep(4.5)');
  Writeln('   g)  2488  magstep(5.0)');
  Write('Your choice? ');
  Readln(JChar);
  JChar:=UpCase(JChar);
  If ('A'<=JChar) And (JChar<='G') Then
    Size:=Ord(JChar)-Ord('A')+1
  Else 
    Begin Valid:=False; Write(Chr(7)) End
Until Valid;
Writeln
End;

Procedure Manual(Var RunTime:RunTimeType);
{Get parameters from user}
Begin
With RunTime Do
  Begin
  Write('Japanese file name? ');
  Readln(FileName);
  Writeln;
 SimpleQuery('Space around Japanese punctuation','Space','No space',ExtraSpace);
 SimpleQuery('Added % at Japanese end of lines','Added %','No added %',Percent);
  SimpleQuery('LaTeX or TeX (MuTeX) output','LaTeX','TeX',LaTeX);
  SimpleQuery('EUC or MS-kanji (Shift-JIS) encoding','EUC','MS-kanji',EUC);
SimpleQuery('Extended JIS ''83 Bitmaps allowed','Extended','Standard',Extended);
  SizeQuery(Size)
  End
End;

Procedure Automate(Var RunTime:RunTimeType);
{Get parameters from command line}
Var
  ParamIndex,Index:Integer;
  Param:String;
Begin
With RunTime Do
  Begin
  {Defaults}
  FileName:='japanese';
  ExtraSpace:=True;
  Percent:=True;
  LaTeX:=True;
  EUC:=True;
  Extended:=True;
  Size:=4;
  {Scan command line parameters}
  For ParamIndex:=1 To ParamCount Do
    Begin
    Param:=ParamStr(ParamIndex);
    If (Param[1]=Flag1) Or (Param[1]=Flag2) Then
      {Not a filename}
      Begin
      {Delete 1 char at the 1st position}
      Delete(Param,1,1);
      {Convert to upper case}
      For Index:=1 To Length(Param) Do Param[Index]:=UpCase(Param[Index]);
      {Scan known keywords}
      If (Param=Space1) Or (Param=Space2) Or (Param=Space3)Then ExtraSpace:=True
      Else
      If (Param=NoSpace1) Or (Param=NoSpace2) Or (Param=NoSpace3) Then
        ExtraSpace:=False
      Else
      If (Param=Percent1) Or (Param=Percent2) Or (Param=Percent3) Then 
        Percent:=True
      Else
      If (Param=NoPercent1) Or (Param=NoPercent2) Or (Param=NoPercent3) Then
        Percent:=False
      Else
      If Param=EUC1 Then EUC:=True
      Else
      If (Param=NoEUC1) Or (Param=NoEUC2) Then EUC:=False
      Else
      If Param=Extended1 Then Extended:=True
      Else
      If Param=Standard1 Then Extended:=False
      Else
      If Param=LaTeX1 Then LaTeX:=True
      Else
      If (Param=TeX1) Or (Param=TeX2) Then LaTeX:=False
      Else
      If (Param=One1) Or (Param=One2) Or (Param=One3) Then Size:=1
      Else
      If (Param=Two1) Or (Param=Two2) Then Size:=2
      Else
      If (Param=Three1) Or (Param=Three2) Or (Param=Three3) Then Size:=3
      Else
      If (Param=Four1) Or (Param=Four2) Or (Param=Four3) Then Size:=4
      Else
      If (Param=Five1) Or (Param=Five2) Or (Param=Five3) Then Size:=5
      Else
      If (Param=Six1) Or (Param=Six2) Or (Param=Six3) Then Size:=6
      Else
      If (Param=Seven1) Or (Param=Seven2) Or (Param=Seven3) Then Size:=7
      Else
        {Unknown keyword}
        Begin
        Writeln(Chr(7)+'Invalid command line parameter: '+Param+'...');
        Halt(1)
        End
      End
    Else
      {Must be a filename, we'll try to open it later}
      FileName:=Param
    End
  End
End;

Procedure GetParameters(Var RunTime:RunTimeType);
{Get parameters from user or command line}
{Current parameter status is echoed on the console}
Begin
If ParamCount=0 Then Manual(RunTime)
Else Automate(RunTime);
EchoParameters(Output,RunTime)
End;

{-------------------------------- OpenFile -----------------------------------}

Function TryExtension(Var InFile:InFileType; Var RunTime:RunTimeType;
                      TriedExtension:String):Boolean;
{Tries to open FileName using TriedExtension}
Begin
With RunTime Do
  Begin
  Extension:=TriedExtension;
  Assign(InFile,FileName+TriedExtension);
  {$I-}Reset(InFile);{$I+}
  {IOResult must be immediately used once only}
  TryExtension:=(IOResult=0)
  End
End;

Procedure OpenFile(Var InFile:InFileType; Var RunTime:RunTimeType);
{Tries to open FileName using all available extensions}
Begin
If TryExtension(InFile,RunTime,Extension1) Then Write(Extension1)
Else
  If TryExtension(InFile,RunTime,Extension2) Then Write(Extension2)
  Else
    If TryExtension(InFile,RunTime,Extension3) Then Write(Extension3)
    Else
      Begin
      Writeln('.');
      Writeln(Chr(7)+'File not found'+'...');
      Halt(1)
      End
End;

{-------------------------------- GetBitmap ----------------------------------}

Procedure PerformScan(Var CommentLine:String; Var RunTime:RunTimeType;
                      Echo:Boolean; Var OutFile:OutFileType); 
{Scans the comment line for run-time JEM2TEX parameters}
{Any Bitmap or unknown parameter stops the scan}
{Current parameter status is echoed in the .TeX file as a [La]TeX comment}
Var Index:Integer;
Begin
{Delete 1 char at the 1st position which is %}
Delete(CommentLine,1,1);
{Convert to upper case}
For Index:=1 To Length(CommentLine) Do
  CommentLine[Index]:=UpCase(CommentLine[Index]);
{Add space at the line end to characterize premature termination}
{Add sentinel at the line end to stop forthcoming loops}
CommentLine:=CommentLine+' %';
{Delete leading blanks}
If CommentLine[1]=' ' Then 
  Repeat Delete(CommentLine,1,1)
  Until CommentLine[1]<>' '; 
{Look for run-time flag at the start of line}
If ( RunFlag1=Copy(CommentLine,1,Length(RunFlag1)) ) Or
   ( RunFlag2=Copy(CommentLine,1,Length(RunFlag1)) ) Or
   ( RunFlag3=Copy(CommentLine,1,Length(RunFlag1)) )
Then
  Begin
  {Remove run-time flag}
  Delete(CommentLine,1,Length(RunFlag1));
  {Scan until sentinel reached}
  Repeat
    {Delete leading blanks}
    If CommentLine[1]=' ' Then 
      Repeat Delete(CommentLine,1,1)
      Until CommentLine[1]<>' '; 
    If (CommentLine[1]=Flag1) Or (CommentLine[1]=Flag2) Then
      {Valid run-time parameter flag}
      Begin
      {Delete 1 char at the 1st position which is flag}
      Delete(CommentLine,1,1);
      {Scan in decreasing length order}
      With RunTime Do
        Begin
        If Space1=Copy(CommentLine,1,Length(Space1)) Then
          Begin Delete(CommentLine,1,Length(Space1)); ExtraSpace:=True End
        Else
        If Space2=Copy(CommentLine,1,Length(Space2)) Then
          Begin Delete(CommentLine,1,Length(Space2)); ExtraSpace:=True End
        Else
        If Space3=Copy(CommentLine,1,Length(Space3)) Then
          Begin Delete(CommentLine,1,Length(Space3)); ExtraSpace:=True End
        Else
        If NoSpace1=Copy(CommentLine,1,Length(NoSpace1)) Then
          Begin Delete(CommentLine,1,Length(NoSpace1)); ExtraSpace:=False End
        Else
        If NoSpace2=Copy(CommentLine,1,Length(NoSpace2)) Then
          Begin Delete(CommentLine,1,Length(NoSpace2)); ExtraSpace:=False End
        Else
        If NoSpace3=Copy(CommentLine,1,Length(NoSpace3)) Then
          Begin Delete(CommentLine,1,Length(NoSpace3)); ExtraSpace:=False End
        Else
        If Percent1=Copy(CommentLine,1,Length(Percent1)) Then
          Begin Delete(CommentLine,1,Length(Percent1)); Percent:=True End
        Else
        If Percent2=Copy(CommentLine,1,Length(Percent2)) Then
          Begin Delete(CommentLine,1,Length(Percent2)); Percent:=True End
        Else
        If Percent3=Copy(CommentLine,1,Length(Percent3)) Then
          Begin Delete(CommentLine,1,Length(Percent3)); Percent:=True End
        Else
        If NoPercent1=Copy(CommentLine,1,Length(NoPercent1)) Then
          Begin Delete(CommentLine,1,Length(NoPercent1)); Percent:=False End
        Else
        If NoPercent2=Copy(CommentLine,1,Length(NoPercent2)) Then
          Begin Delete(CommentLine,1,Length(NoPercent2)); Percent:=False End
        Else
        If NoPercent3=Copy(CommentLine,1,Length(NoPercent3)) Then
          Begin Delete(CommentLine,1,Length(NoPercent3)); Percent:=False End
        Else
        If EUC1=Copy(CommentLine,1,Length(EUC1)) Then
          Begin Delete(CommentLine,1,Length(EUC1)); EUC:=True End
        Else
        If NoEUC1=Copy(CommentLine,1,Length(NoEUC1)) Then
          Begin Delete(CommentLine,1,Length(NoEUC1)); EUC:=False End
        Else
        If NoEUC2=Copy(CommentLine,1,Length(NoEUC2)) Then
          Begin Delete(CommentLine,1,Length(NoEUC2)); EUC:=False End
        Else
        If Extended1=Copy(CommentLine,1,Length(Extended1)) Then
          Begin Delete(CommentLine,1,Length(Extended1)); Extended:=True End
        Else
        If Standard1=Copy(CommentLine,1,Length(Standard1)) Then
          Begin Delete(CommentLine,1,Length(Standard1)); Extended:=False End
        Else
        If LaTeX1=Copy(CommentLine,1,Length(LaTeX1)) Then
          Begin Delete(CommentLine,1,Length(LaTeX1)); LaTeX:=True End
        Else
        If TeX1=Copy(CommentLine,1,Length(TeX1)) Then
          Begin Delete(CommentLine,1,Length(TeX1)); LaTeX:=False End
        Else
        If TeX2=Copy(CommentLine,1,Length(TeX2)) Then
          Begin Delete(CommentLine,1,Length(TeX2)); LaTeX:=False End
        Else
        If One1=Copy(CommentLine,1,Length(One1)) Then
          Begin Delete(CommentLine,1,Length(One1)); Size:=1 End
        Else
        If Two1=Copy(CommentLine,1,Length(Two1)) Then
          Begin Delete(CommentLine,1,Length(Two1)); Size:=2 End
        Else
        If Three1=Copy(CommentLine,1,Length(Three1)) Then
          Begin Delete(CommentLine,1,Length(Three1)); Size:=3 End
        Else
        If Four1=Copy(CommentLine,1,Length(Four1)) Then
          Begin Delete(CommentLine,1,Length(Four1)); Size:=4 End
        Else
        If Five1=Copy(CommentLine,1,Length(Five1)) Then
          Begin Delete(CommentLine,1,Length(Five1)); Size:=5 End
        Else
        If Six1=Copy(CommentLine,1,Length(Six1)) Then
          Begin Delete(CommentLine,1,Length(Six1)); Size:=6 End
        Else
        If Seven1=Copy(CommentLine,1,Length(Seven1)) Then
          Begin Delete(CommentLine,1,Length(Seven1)); Size:=7 End
        Else
        If One2=Copy(CommentLine,1,Length(One2)) Then
          Begin Delete(CommentLine,1,Length(One2)); Size:=1 End
        Else
        If Two2=Copy(CommentLine,1,Length(Two2)) Then
          Begin Delete(CommentLine,1,Length(Two2)); Size:=2 End
        Else
        If Three2=Copy(CommentLine,1,Length(Three2)) Then
          Begin Delete(CommentLine,1,Length(Three2)); Size:=3 End
        Else
        If Four2=Copy(CommentLine,1,Length(Four2)) Then
          Begin Delete(CommentLine,1,Length(Four2)); Size:=4 End
        Else
        If Five2=Copy(CommentLine,1,Length(Five2)) Then
          Begin Delete(CommentLine,1,Length(Five2)); Size:=5 End
        Else
        If Six2=Copy(CommentLine,1,Length(Six2)) Then
          Begin Delete(CommentLine,1,Length(Six2)); Size:=6 End
        Else
        If Seven2=Copy(CommentLine,1,Length(Seven2)) Then
          Begin Delete(CommentLine,1,Length(Seven2)); Size:=7 End
        Else
        If One3=Copy(CommentLine,1,Length(One3)) Then
          Begin Delete(CommentLine,1,Length(One3)); Size:=1 End
        Else
        If Three3=Copy(CommentLine,1,Length(Three3)) Then
          Begin Delete(CommentLine,1,Length(Three3)); Size:=3 End
        Else
        If Four3=Copy(CommentLine,1,Length(Four3)) Then
          Begin Delete(CommentLine,1,Length(Four3)); Size:=4 End
        Else
        If Five3=Copy(CommentLine,1,Length(Five3)) Then
          Begin Delete(CommentLine,1,Length(Five3)); Size:=5 End
        Else
        If Six3=Copy(CommentLine,1,Length(Six3)) Then
          Begin Delete(CommentLine,1,Length(Six3)); Size:=6 End
        Else
        If Seven3=Copy(CommentLine,1,Length(Seven3)) Then
          Begin Delete(CommentLine,1,Length(Seven3)); Size:=7 End
        Else
          {Unknown run-time parameter}
          {Terminate prematurely current scan}
          CommentLine:='%'
        End;
      {Echo status if allowed}
      If Echo And (CommentLine<>'%') Then
        Begin
        Write(OutFile,'%');
        EchoParameters(OutFile,RunTime)
        End
      End
    Else
      {Unknown run-time parameter flag}
      {Terminate prematurely current scan}
      CommentLine:='%'
  Until Length(CommentLine)=1
  End
End;

Procedure LineBreak(Var OutFile:OutFileType; ExtraSpace:Boolean;
                    Var Scanning:ScanningType);
{The continuous chain of Bitmaps has just been interrupted by a line break}
{We know the next Roman character is equivalent to a space, i.e. not a letter}
{A \eeee may be inserted if the previous Bitmap was a .,!?}
{A \eee may be inserted if the previous Bitmap was a :; center dot )]'"}
{If glue inserted, make sure to leave a totally blank line as present before}
Begin
With Scanning Do
  Begin
  Immediate:=False;
  If Echo And ExtraSpace Then 
    If RomanMajorEOL Then Writeln(OutFile,'\eeee')
    Else
      If RomanMinorEOL Then Writeln(OutFile,'\eee')
  End
End;

Procedure RomanBreak(Var OutFile:OutFileType; ExtraSpace:Boolean;
                     Var Scanning:ScanningType);
{The continuous chain of Bitmaps has just been interrupted by a Roman}
{The next Roman character may be a letter so a \eee is possible}
{A \eeee may be inserted if the previous Bitmap was a .,!?}
{A \eee may be inserted if the previous Bitmap was a :; center dot )]'"}
{Curly brackets are used in \eee and \eeee when the next Roman is a letter}
Begin
With Scanning Do
  Begin
  Immediate:=False;
  If Echo And ExtraSpace Then
    If RomanMajorEOL Then
      If WasLetter Then Write(OutFile,'\eeee{}')
      Else Write(OutFile,'\eeee')
    Else
      If RomanMinorEOL Then
        If WasLetter Then Write(OutFile,'\eee{}')
        Else Write(OutFile,'\eee')
      Else
        If WasLetter And Not RomanOpening Then Write(OutFile,'\eee{}')
  End
End;

Procedure GotUNIX(Var OutFile:OutFileType; Var Scanning:ScanningType;
                  Var RunTime:RunTimeType);
{Handles UNIX EOL}
{May add glue after the previous Bitmap and before this Roman}
Begin
With Scanning,RunTime Do
  Begin
  If Immediate Then
    If First Then LineBreak(OutFile,ExtraSpace,Scanning)
    Else
      If Not Comment Then
        If Percent Then
          If Echo Then Write(OutFile,'%') 
          Else
        Else
          LineBreak(OutFile,ExtraSpace,Scanning);
  If Echo Then Writeln(OutFile);
  If Comment Then 
    If Not First Then PerformScan(CommentLine,RunTime,Echo,OutFile)
    Else
  Else
    WasLetter:=False;
  First:=True;
  Comment:=True;
  CommentLine:=''
  End
End;

Procedure GotDOS(Var OutFile:OutFileType; Var Scanning:ScanningType;
                 Var RunTime:RunTimeType; Var InFile:InFileType);
{Handles DOS EOL}
{May add glue after the previous Bitmap and before this Roman}
{An error only stops the current pass to help the user determine its cause}
Var Data2:Byte;
Begin
With Scanning Do
  Begin
  GotUNIX(OutFile,Scanning,RunTime);
  {Line Feed must follow immediately}
  If EOF(InFile) Then Done:=True
  Else
    Begin
    Read(InFile,Data2);
    If Data2<>$0A Then Done:=True
    End;
  If Done Then
    Begin
    Writeln('.');
    Write(Chr(7)+'Abnormal DOS end of line..')
    End
  End
End;

Procedure ValidateBitmap(Bitmap:BitmapRange);
{Prints a warning when an extended or an empty Bitmap is used}
Var Invalid:Boolean;
Begin
Invalid:=False;
If (109<=Bitmap) And (Bitmap<=119) Then Invalid:=True
Else
If (128<=Bitmap) And (Bitmap<=135) Then Invalid:=True
Else
If (143<=Bitmap) And (Bitmap<=153) Then Invalid:=True
Else
If (169<=Bitmap) And (Bitmap<=175) Then Invalid:=True
Else
If (184<=Bitmap) And (Bitmap<=203) Then Invalid:=True
Else
If (214<=Bitmap) And (Bitmap<=220) Then Invalid:=True
Else
If (247<=Bitmap) And (Bitmap<=252) Then Invalid:=True
Else
If (279<=Bitmap) And (Bitmap<=282) Then Invalid:=True
Else
If Bitmap=366 Then Invalid:=True
Else
If (463<=Bitmap) And (Bitmap<=470) Then Invalid:=True
Else
If (495<=Bitmap) And (Bitmap<=502) Then Invalid:=True
Else
If (527<=Bitmap) And (Bitmap<=564) Then Invalid:=True
Else
If (598<=Bitmap) And (Bitmap<=612) Then Invalid:=True
Else
If (646<=Bitmap) And (Bitmap<=658) Then Invalid:=True
Else
If (691<=Bitmap) And (Bitmap<=1410) Then Invalid:=True
Else
If (4376<=Bitmap) And (Bitmap<=4418) Then Invalid:=True;
If Invalid Then
  Begin
  Writeln('.');
  Write('Warning! The non-standard JIS ''83 Bitmap ',Bitmap,' encountered')
  End
End;

Procedure GotBitmap(Var OutFile:OutFileType; EUC,Extended:Boolean; 
                    Var InFile:InFileType; Var Scanning:ScanningType); 
{Handles Bitmap}
{An error only stops the current pass to help the user determine its cause}
{If desired, non-standard Bitmaps are pointed out in the first pass}
Var Data2:Byte;
Begin
With Scanning Do
  Begin
  If First Then
    {First character on line}
    Begin
    First:=False;
    Comment:=False
    End;
  If EOF(InFile) Then
    Begin
    Done:=True;
    Writeln('.');
    If EUC Then Write(Chr(7)+'Incomplete EUC character pair..')
    Else Write(Chr(7)+'Incomplete MS-kanji character pair..')
    End
  Else
    Begin
    Read(InFile,Data2);
    If EUC Then
      If ($A0<Data2) And (Data2<$FF) Then 
        Bitmap:=94*(Data1-$A1)+(Data2-$A1)+1
      Else
        Begin
        Done:=True;
        Writeln('.');
        Write(Chr(7)+'Invalid EUC character pair..')
        End
    Else
      If ( ($40<=Data2) And (Data2<=$7E) ) Or 
         ( ($80<=Data2) And (Data2<=$FC) )
      Then
        Begin
        If (Data1>=$E0) Then Bitmap:=1+188*(Data1-$C1)
        Else Bitmap:=1+188*(Data1-$81);
        If (Data2>=$80) Then Bitmap:=Bitmap+(Data2-$41)
        Else Bitmap:=Bitmap+(Data2-$40)
        End
      Else
        Begin
        Done:=True;
        Writeln('.');
        Write(Chr(7)+'Invalid MS-kanji character pair..')
        End;
    If Not Done Then
      {Bitmaps in comment skipped}
      If Comment Then
        Begin
        CommentLine:=CommentLine+Chr(Data1)+Chr(Data2);
        If Echo Then Write(OutFile,Chr(Data1)+Chr(Data2))
        End
      Else
        If (1<=Bitmap) And (Bitmap<=BitmapMax) Then 
          Begin
          Found:=True;
          {Point out non-standard Bitmaps in first pass}
          If Not Echo And Not Extended Then ValidateBitmap(Bitmap)
          End
        Else
          Begin
          Done:=True;
          Writeln('.');
          Write(Chr(7)+'Bitmap ',Bitmap,' does not exist..')
          End
    End
  End
End;

Procedure GotRoman(Var OutFile:OutFileType; ExtraSpace:Boolean;
                   Var Scanning:ScanningType);
{Handles roman}
{May add glue after the previous Bitmap and before this Roman}
Begin
With Scanning Do
  Begin
  If First Then
    {First character on line}
    Begin
    First:=False;
    If Chr(Data1)<>'%' Then Comment:=False
    End;
  If Comment Then CommentLine:=CommentLine+Chr(Data1)
  Else
    Begin
    {Determine if this roman is a letter or a number}
    WasLetter:=( ('A'<=UpCase(Chr(Data1))) And (UpCase(Chr(Data1))<='Z') ) Or
                      (  ('0'<=Chr(Data1)) And (Chr(Data1)<='9') );
    If Immediate Then RomanBreak(OutFile,ExtraSpace,Scanning)
    End;
  If Echo Then Write(OutFile,Chr(Data1))
  End
End;

Procedure GetBitmap(Var InFile:InFileType; Var OutFile:OutFileType; 
                    Var Scanning:ScanningType; Var RunTime:RunTimeType);
{Scans input file and stops when a Bitmap is met}
{An error only stops the current pass to help the user determine its cause}
{Accepts UNIX LF or DOS CR/LF as end of line indicator in input file}
{Updates JemTeX parameters with run-time parameters}
{Comment indicates the line is a comment line and does not break continuity}
{Immediate indicates the current Bitmap immediately followed previous Bitmap}
{If the next character encountered is Roman, glue may be inserted}
{If desired, will add % at Japanese end of lines to preserve continuity}
Begin
With Scanning,RunTime Do
  Begin
  {No Bitmap found initially}
  Found:=False;
  {Assume the next character is a Bitmap}
  WasLetter:=False; 
  Immediate:=True;
  {Some non-comment Bitmap was met before or it's the first call to GetBitmap}
  CommentLine:='';
  {Comment holds; it's the first call ever to GetBitmap; it's first character}
  {Comment fails; some non-comment Bitmap was met before; it isnt 1st character}
  First:=Comment;
  Repeat
    {Check if file just finished}
    If EOF(InFile) Then Done:=True
    Else
      {More file coming}
      Begin
      Read(InFile,Data1);
      If Data1=$0A Then GotUNIX(OutFile,Scanning,RunTime)
      Else
        If Data1=$0D Then GotDOS(OutFile,Scanning,RunTime,InFile)
        Else
          If EUC Then
            If ($A0<Data1) And (Data1<$FF) Then
              GotBitmap(OutFile,EUC,Extended,InFile,Scanning)
            Else
              GotRoman(OutFile,ExtraSpace,Scanning)
          Else
            If ( ($81<=Data1) And (Data1<=$9F) ) Or 
               ( ($E0<=Data1) And (Data1<=$EA) ) 
            Then
              GotBitmap(OutFile,EUC,Extended,InFile,Scanning)
            Else
              GotRoman(OutFile,ExtraSpace,Scanning)
      End
  Until Done Or Found
  End
End;

{---------------------------------- GetFont ----------------------------------}

Procedure GetFont(Var InFile:InFileType; Var Fonts:FontsType; 
                  Var InitialRunTime:RunTimeType);
{Finds the Japanese fonts needed}
Var 
  {Run time parameters}
  RunTime:RunTimeType;
  {Current font number}
  FontPtr:FontRange;
  SizePtr:SizeRange;
  {Scanning information}
  Scanning:ScanningType;
  {Dummy since no output in first pass}
  DummyOutFile:OutFileType;
Begin
RunTime:=InitialRunTime;
{No Japanese font needed so far}
For SizePtr:=1 To SizeMax Do 
  For FontPtr:=0 To FontMax Do
    Fonts[SizePtr,FontPtr]:=False;
With Scanning Do
  Begin
  {Not reached EOF yet}
  Done:=False;
  {No echo in first pass}
  Echo:=False;
  {Dummy since no output in first pass}
  Immediate:=False;
  WasLetter:=False;
  RomanMajorEOL:=False;
  RomanMinorEOL:=False;
  RomanOpening:=False;
  {Tell indirectly to GetBitmap that this is the first time it is called}
  Comment:=True;
  Repeat
    {Get the next Bitmap skipping over [La]TeX comments}
    GetBitmap(InFile,DummyOutFile,Scanning,RunTime);
    If Not Done Then Fonts[RunTime.Size,Bitmap Div 128]:=True
  Until Done
  End;
{Last state of LaTeX prevails for the second pass}
InitialRunTime.LaTeX:=RunTime.LaTeX
End;

{----------------------------------- Header ----------------------------------}

Procedure Header(Var OutFile:OutFileType; Var Fonts:FontsType; LaTeX:Boolean);
{Writes [La]TeX header}
{Fonts declared global for speed, even if never actually modified here}
Var 
  FontPtr:FontRange;
  SizePtr:SizeRange;
  C0,C1,C2:Char;
  Scale:Integer;
Begin
Writeln(OutFile,'\tracingstats=1');
For SizePtr:=1 To SizeMax Do
  Begin
  C0:=Chr( Ord('a')+SizePtr-1 );
  Case SizePtr Of
    1:Scale:=1000;
    2:Scale:=1095;
    3:Scale:=1200;
    4:Scale:=1440;
    5:Scale:=1728;
    6:Scale:=2074;
    7:Scale:=2488
    End;
  For FontPtr:=0 To FontMax Do
    If Fonts[SizePtr,FontPtr] Then
      Begin
      C1:=Chr( Ord('a')+(FontPtr Div 8) );
      C2:=Chr( Ord('a')+(FontPtr Mod 8) );
      If LaTeX Then
        Writeln(OutFile,'\newfont{\k'+C0+C1+C2+'}{kanji'+C1+C2+' scaled ',
                Scale,'}')
      Else
        Writeln(OutFile,'\font\k'+C0+C1+C2+'=kanji'+C1+C2+' scaled ',Scale)
    End
  End;
If LaTeX Then
  Begin
  Writeln(OutFile,'\newcommand{\kk}[2]{{#1\symbol{#2}}}');
  Writeln(OutFile,'\newcommand{\hh}{\discretionary{}{}{}}');
  Writeln(OutFile,'\newcommand{\ee}{\nobreak\hskip0pt plus.1em\relax}');
  Writeln(OutFile,'\newcommand{\eee}{\nobreak\hskip.3em plus.1em\relax}');
  Writeln(OutFile,'\newcommand{\eeee}{\nobreak\hskip.9em plus.1em minus.1em}')
  End
Else
  Begin
  Writeln(OutFile,'\def\kk#1#2{{#1\char#2}}');
  Writeln(OutFile,'\def\hh{\discretionary{}{}{}}');
  Writeln(OutFile,'\def\ee{\nobreak\hskip0pt plus.1em\relax}');
  Writeln(OutFile,'\def\eee{\nobreak\hskip.3em plus.1em\relax}');
  Writeln(OutFile,'\def\eeee{\nobreak\hskip.9em plus.1em minus.1em}')
  End;
Writeln(OutFile)
End;

{---------------------------------- Convert ----------------------------------}

Procedure BitmapType(Bitmap:BitmapRange; Var Punctuation:PunctuationType);
{Finds characteristics of current Bitmap}
Begin
With Punctuation Do
  Begin
  OldMajorEOL:=NewMajorEOL;
  OldMinorEOL:=NewMinorEOL;
  OldOpening:=NewOpening;
  OldClosing:=NewClosing;
  OldCenterDot:=NewCenterDot;
  OldJapanese:=NewJapanese;
  NewMajorEOL:=False;
  NewMinorEOL:=False;
  NewOpening:=False;
  NewClosing:=False;
  NewCenterDot:=False;
  NewJapanese:=False;
  {Full width .,!?}
  If (2<=Bitmap) And (Bitmap<=5) Then NewMajorEOL:=True
  Else
  If (Bitmap=9) Or (Bitmap=10) Then NewMajorEOL:=True
  Else
  {Half width .,!?}
  If (Bitmap=691) Or (Bitmap=720) Then NewMajorEOL:=True
  Else
  {Full width :;}
  If (Bitmap=7) Or (Bitmap=8) Then NewMinorEOL:=True
  Else
  {Half width :;}
  If (Bitmap=692) Or (Bitmap=693) Then NewMinorEOL:=True
  Else
  {Full width `"([< and other openings}
  If (38<=Bitmap) And (Bitmap<=58) And Not Odd(Bitmap) Then NewOpening:=True
  Else
  {Half width `"([< and other openings}
  If (696<=Bitmap)And(Bitmap<=716) And Not Odd(Bitmap) Then NewOpening:=True
  Else
  {Full width '")]> and other closings}
  If (39<=Bitmap) And (Bitmap<=59) And Odd(Bitmap) Then NewClosing:=True
  Else
  {Half width '")]> and other closings}
  If (697<=Bitmap) And (Bitmap<=717) And Odd(Bitmap) Then NewClosing:=True
  Else
  {Full width Japanese center dot}
  If (Bitmap=6) Then NewCenterDot:=True
  Else
  {Half width Japanese center dot}
  If (Bitmap=469) Then NewCenterDot:=True
  Else
  {Full width Hiragana}
  If (283<=Bitmap) And (Bitmap<=365) Then NewJapanese:=True
  Else
  {Full width Katakana}
  If (377<=Bitmap) And (Bitmap<=462) Then NewJapanese:=True
  Else
  {Full width Kanji level 1}
  If (1411<=Bitmap) And (Bitmap<=4375) Then NewJapanese:=True
  Else
  {Full width Kanji level 2}
  If (4419<=Bitmap) And (Bitmap<=7806) Then NewJapanese:=True
  Else
  {Script Hiragana}
  If (753<=Bitmap) And (Bitmap<=835) Then NewJapanese:=True
  Else
  {Script Katakana}
  If (847<=Bitmap) And (Bitmap<=932) Then NewJapanese:=True
  End
End;

Procedure Hyphenate(Var OutFile:OutFileType; Var Punctuation:PunctuationType);
{Adds hyphenation between consecutive Bitmaps}
Begin
With Punctuation Do
  {No hyphenation between two odd symbols}
  If OldJapanese Or NewJapanese Then
    {No hyphenation before some symbols}
    If Not NewMajorEOL And Not NewMinorEOL And Not NewCenterDot And 
       Not NewClosing
    Then   
      {No hyphenation after some symbols}
      If Not OldOpening Then Write(OutFile,'\hh')
End;

Procedure Glue(Var OutFile:OutFileType; Var Punctuation:PunctuationType;
               ExtraSpace:Boolean);
{Adds glue between consecutive Bitmaps}
Var GlueAdded:Boolean;
Begin
With Punctuation Do
  Begin
  GlueAdded:=False;
  If ExtraSpace Then
    Begin
    {Trying to add big glue}
    If OldMajorEOL Then
      {No big glue between identical symbols}
      If Not NewMajorEOL Then
        {No big glue before some symbols}
        If Not NewClosing Then
          Begin
          GlueAdded:=True;
          Write(OutFile,'\eeee')
          End;
    If Not GlueAdded Then
      {Trying to add medium glue based on old symbol}
      If OldMinorEOL Or OldCenterDot Or OldClosing Then
        {No medium glue before some symbols}
        If Not NewMajorEOL And Not NewMinorEOL And Not NewClosing Then
          Begin
          GlueAdded:=True;
          Write(OutFile,'\eee')
          End;
    If Not GlueAdded Then
      {Trying to add medium glue based on new symbol}
      If NewCenterDot Or NewOpening Then
        {No medium glue after some symbols}
        If Not OldOpening Then
          Begin
          GlueAdded:=True;
          Write(OutFile,'\eee')
          End
    End;
  {Always make sure to add some glue}
  If Not GlueAdded Then Write(OutFile,'\ee')
  End
End;

Procedure Convert(Var InFile:InFileType; Var OutFile:OutFileType;
                  Var RunTime:RunTimeType);
{Convert .JEM into .TeX by translating Bitmaps and adding hyphenation and glue}
Var 
  {Japanese punctuation information}
  Punctuation:PunctuationType;
  {Scanning information}
  Scanning:ScanningType;
  {Current font number}
  FontPtr:FontRange;
  C0,C1,C2:Char;
Begin
With Punctuation,Scanning,RunTime Do
  Begin
  {Not reached EOF yet}
  Done:=False;
  {Echo in second pass}
  Echo:=True;
  {Nothing done yet}
  Immediate:=False;
  WasLetter:=False;
  {Tell indirectly to GetBitmap that this is the first time it is called}
  Comment:=True;
  {Initial japanese punctuation information}
  NewMajorEOL:=False; NewMinorEOL:=False;
  NewOpening:=False; NewClosing:=False;
  NewCenterDot:=False; NewJapanese:=False;
  Repeat
    {Set up scanning information in case a roman letter follows immediately}
    RomanMajorEOL:=NewMajorEOL;
    RomanMinorEOL:=NewMinorEOL Or NewCenterDot Or NewClosing;
    RomanOpening:=NewOpening;
    {Get the next Bitmap skipping over [La]TeX comments}
    {May add glue between the old Bitmap and an hypothetical Roman}
    GetBitmap(InFile,OutFile,Scanning,RunTime);
    If Not Done Then
      Begin
      {Find what kind of Bitmap it is}
      BitmapType(Bitmap,Punctuation);
      If Immediate Then
        {Add hyphenation and glue between consecutive Bitmaps}
        Begin
        Hyphenate(OutFile,Punctuation);
        Glue(OutFile,Punctuation,ExtraSpace)
        End
      Else
        {Add glue after the old Roman and before this new Bitmap}
        If ExtraSpace Then
          If NewCenterDot Or NewOpening Then Write(OutFile,'\eee')
          Else 
            If WasLetter Then
              {No medium glue before some symbols}
              If Not NewMajorEOL And Not NewMinorEOL And Not NewClosing Then
                Write(OutFile,'\eee');
      {Write the Bitmap}
      C0:=Chr( Ord('a')+Size-1 );
      FontPtr:=Bitmap Div 128;
      C1:=Chr( Ord('a')+(FontPtr Div 8) );
      C2:=Chr( Ord('a')+(FontPtr Mod 8) );
      Write(OutFile,'\kk{\k'+C0+C1+C2+'}{',Bitmap Mod 128,'}')
      {The next character may be Roman, GetBitmap will handle the glue then}
      End
  Until Done
  End
End;

{------------------------------------ Main -----------------------------------}

Begin
Writeln;
Writeln('Japanese to [La]TeX Conversion Program.');   {To make Borland happy}
Writeln('Version 2.00 Copyright F. Jalbert 1991.');
Writeln;


GetParameters(RunTime);
Writeln;
Write('Opening Japanese file '+RunTime.FileName);
OpenFile(InFile,RunTime);
Writeln('.');
If RunTime.LaTeX Then Write('Creating LaTeX file '+RunTime.FileName+'.tex')
Else Write('Creating TeX file '+RunTime.FileName+'.tex');
Assign(OutFile,RunTime.FileName+'.tex');
Rewrite(OutFile);
Writeln('.');
Writeln;


Write('Scanning Japanese file for fonts');
GetFont(InFile,Fonts,RunTime);
Reset(InFile);
Writeln('.');
If RunTime.LaTeX Then Write('Writing LaTeX header')
Else Write('Writing TeX header');
Header(OutFile,Fonts,RunTime.LaTeX);
Writeln('.');
Write('Converting Japanese file');
Convert(InFile,OutFile,RunTime);
Writeln('.');
Writeln;


Write('Closing Japanese file '+RunTime.FileName+RunTime.Extension);
Close(InFile);
Writeln('.');
If RunTime.LaTeX Then Write('Closing LaTeX file '+RunTime.FileName+'.tex')
Else Write('Closing TeX file '+RunTime.FileName+'.tex');
Close(OutFile);
Writeln('.');
Writeln;


Writeln('Japanese to [La]TeX conversion completed.');
Writeln
End.
