{$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.