Path: utzoo!mnetor!tmsoft!torsqnt!news-server.csri.toronto.edu!cs.utexas.edu!uunet!munnari.oz.au!yoyo.aarnet.edu.au!sirius.ucs.adelaide.edu.au!f.adelaide.edu.au!cthomas From: cthomas@f.adelaide.edu.au Newsgroups: comp.text.tex Subject: MSWORD --> LaTeX Translator source code Message-ID: <1991Feb18.220648.1@f.adelaide.edu.au> Date: 18 Feb 91 12:36:48 GMT Sender: news@ucs.adelaide.edu.au Organization: University of Adelaide Lines: 528 Nntp-Posting-Host: f.adelaide.edu.au Hi Netters, I had so many requests for my MSWORD-->LaTeX program that I have decided to post it on the network. This barebones program will compile under Turbo Pascal V5.0 I must acknowledge that some of the screen formatting routines were taken from Jamson & Nameroff (1986) Turbo Pascal Programmer's Library Osbourne McGraw-Hill. USE ---- COMPILE the Pascal Code and run the .exe file. The program will prompt for a MSWORD print file name and an output file name for the translated file. Translation will begin. The program has limited error checking but should not overwrite existing files and will inform of common DOS errors (eg file not found). PREPARE WORD files by: 1. setting margins to zero and page width to say 7 inches. Using left justified text also simplifies things. 2. Use print options to select a printer driver such as an Epson FX80 or LQ800 3. Print the document to a file eg. example.txt and use this as the source file for the translation program. THE TRANSLATION PROGRAM works by interpreting Epson compatible printer codes and translating a limited set of these to appropriate LaTeX code. This approach is limited and cannot easily be used to interprete undelined text; tables etc also present dificulties. But I do have some MSWORD macros to help format basic LaTeX tables. The present version will cope with: IBM PC Hi-Ascii characters Special LaTeX characters such as \ % { } etc. Math characters such as + - Italicized text Bolded text Superscripts and Subscripts Small caps format Characters bolded and to be printed in Epson Large type will be interpreted as \section{text} The program can be easily expanded to cope with more complex procedures. If someone does, can they please send me a copy. I started an interactive version of the program to allow insertion of special commands around any bolded text since I thought bolding was widely used to denote some sought of heading. I never got the chance to complete it because my department put in a 3COM PC network with all the printing aids I needed (I still use Latex for my manuals!!). FINALLY I take no responsibility for any problems you might have AND I reserve the right to the basic concept on which the program is based; I believe this approach has not been previously reported. If you distribute the code, please distribute it with my name and address Dr Connor J Thomas Department of Microbiology and Immunology University of Adelaide GPO Box 498 Adelaide 5001 South Australia Email: cthomas@f.adelaide.edu.au CUT HERE --------------------------------------------------------------------------- program translate_latex (input, output); uses crt, dos, turbo3; const linefeed = ^J; carriagereturn = ^M; escape = ^[; emptystring = ^@; ctrl_A = ^A; space = ' '; si = ^O; {Condensed print command} so = ^N; {Enlarged print command} DC2 = ^R; {Cancel condensed print} DC4 = ^T; {Cancel enlarged print} type textfil = text; filespec = string[13]; string79 = string[79]; greek = set of 224..234; {IBM PC Hi ASCII Characters} var inputfile, outputfile : textfil; filename : string79; ch : char; testio : integer; success, needsource, flag_bold : boolean; {---------------------------------------------------------------------------} procedure clean_window (x1, y1, x2, y2: integer); begin window (x1, y1, x2, y2); clrscr; window (1, 1, 80, 25); end; {---------------------------------------------------------------------------} procedure Set_Video (attribute: integer); var blinking, {number to add for blinking} bold : integer; {number to add for bold} begin blinking := (attribute and 4) * 4; { set blinking color based on MSB} if (attribute and 1) = 1 then {set reverse video} begin bold := (attribute and 2) * 7; TextColor (1 + blinking + bold); TextBackground (3); end else {set normal video colors} begin bold := (attribute and 2) * 5 div 2; TextColor (7 + blinking + bold); TextBackground (0); end; end; {---------------------------------------------------------------------------} procedure put_string (out_string: string79; line, col, attrib: integer); begin set_video (attrib); GotoXY (col, line); write (out_string); set_video (0); end; {---------------------------------------------------------------------------} procedure put_centered_string (out_string: string79; line, attrib: integer); begin put_string (out_string, line, 40 - length (out_string) div 2, attrib); end; {---------------------------------------------------------------------------} procedure put_prompt (out_string: string79; line, col: integer); begin GotoXY (col, line); Clreol; put_string (out_string, line, col, 3); end; {---------------------------------------------------------------------------} procedure get_string (var in_string: string79; line, col, attrib, str_length: integer); const bell = 7; back_space =8; carriage_return = 13; escape = 27; right_arrow = 77; var oldstr : string79; in_char : char; I : integer; begin oldstr := in_string; put_string (in_string, line, col, attrib); for I := length (in_string) to str_length - 1 do put_string (' ', line, col + I, attrib); GotoXY (col, line); read (kbd, in_char); if ord (in_char) <> carriage_return then in_string := ''; while ord (in_char) <> carriage_return do begin if ord (in_char) = back_space then begin if length (in_string) > 0 then begin in_string[0] := chr(length (in_string) - 1); write (chr(back_space)); write (' '); write (chr(back_space)); end; end else if ord(in_char) = escape then begin read (kbd, in_char); if ord (in_char) = right_arrow then begin if length (oldstr) > length (in_string) then begin in_string[0] := chr(length (in_string) + 1); in_char := oldstr[ord(in_string[0])]; in_string[ord(in_string[0])] := in_char; write (in_char); end end else write (chr(bell)); end else if length (in_string) < str_length then begin in_string[0] := chr(length (in_string) + 1); in_string[ord(in_string[0])] := in_char; write (in_char); end else write (chr(bell)); read (kbd, in_char); end; put_string (in_string, line, col, attrib); for I := length (in_string) to str_length - 1 do put_string (' ', line, col + I, 0); end; {---------------------------------------------------------------------------} procedure get_prompted_string (var in_string: string79; inattr, str_length: integer; strdesc: string79; descline, desccol: integer; prompt: string79; prline, prcol: integer); {sample call: get_prompted_string (NAME, 1 ,30, 'Student Name: ', 10, 2, 'Enter students'' full name.', 24, 2); } begin put_string (strdesc, descline, desccol, 2); put_prompt (prompt, prline, prcol); get_string (In_string, descline, desccol + length (strdesc), inattr, str_length); put_string (strdesc, descline, desccol, 0); end; {---------------------------------------------------------------------------} procedure read_char; begin read(inputfile,ch) end; {---------------------------------------------------------------------------} procedure ask_latex_command(ch: char); var latex_command: string79; begin latex_command := ''; clean_window (1, 13, 80, 25); put_string ('Help! I don''t know LaTex for ', 15, 2, 2); put_string (ch, 15, 31, 3); get_prompted_string (latex_command, 1, 50, 'Enter LaTex equivalent: ', 17, 2, 'Enter Latex command as well as queried character', 24, 2); write(outputfile, latex_command); clean_window (1, 13, 80, 25); put_centered_string ('Please wait: I''m still translating ', 18, 2); end; {---------------------------------------------------------------------------} procedure super_or_sub; {Process Super- and Subscripts} begin read_char; case ch of '0', emptystring : write (outputfile, '$^{'); '1', ctrl_A : write (outputfile, '$_{'); end; {* case *} end; {---------------------------------------------------------------------------} procedure h_tab; {This filters out printer htab codes} begin read_char; read_char; write(outputfile, space); end; {---------------------------------------------------------------------------} procedure ESC_rubbish; {All printer codes not translated} begin if ch = 'K' then begin read_char; read_char end else read_char end; {---------------------------------------------------------------------------} procedure escape_char; {Escape precedes a lot of printer codes} begin read_char; case ch of '4': write(outputfile,'{\it '); {request italics} '5': write(outputfile,'\/}'); {end italics} 'E': write(outputfile,'{\bf '); {select bold face} 'F': write(outputfile,'}'); {close braces} 'g': write(outputfile,'{\sc '); {request small caps} 'p', 'C', 'J', 'K': ESC_rubbish; {unwanted esc code} 'T': write(outputfile,'}$'); {request math mode} 'S': super_or_sub; {request super/subscript} '$': h_tab; {remove horizontal tab} end; (* case *) end; {---------------------------------------------------------------------------} procedure greek_char; begin case ord(ch) of 224: write(outputfile, '$\alpha$'); 225: write(outputfile, '$\beta$'); 226: write(outputfile, '$\gamma$'); 227: write(outputfile, '$\pi$'); 228: write(outputfile, '$\Sigma$'); 229: write(outputfile, '$\sigma$'); 230: write(outputfile, '$\mu$'); 231: write(outputfile, '$\tau$'); 232: write(outputfile, '$\Phi$'); 233: write(outputfile, '$\theta'); 244: write(outputfile, '$\Omega'); 235: write(outputfile, '$\delta'); end; {case} end; {---------------------------------------------------------------------------} procedure large_print; {if text is in Large size convert to \section} begin {Happens when receive a SO code from printer output} flag_bold := false; read_char; if ch = escape then begin read_char; if ch = 'E' then begin flag_bold := true; write(outputfile, '\section{') end else write(outputfile, '{\large '); end else write(outputfile, '{\large ',ch); end; {Printer drivers add printer codes in a nested fashion. For example, if you} {use word to bold text then change to enlarged print, then the printer codes} {are nested in that order eg. ctrl-N Esc E bold large text Esc F ctrl-T. } {---------------------------------------------------------------------------} procedure title; begin put_centered_string ('MICROSOFT WORD TO LATEX CONVERSION', 3, 3); put_centered_string ('Connor J. Thomas, February 1991', 5, 8); put_centered_string ('Department of Microbiology and Immunology', 6, 8); put_centered_string ('University of Adelaide, GPO Box 498, Adelaide', 7, 8); gotoXY (1, 8); end; {---------------------------------------------------------------------------} procedure err_message; var ch : char; begin put_string ('Error in file access: ', 14, 2, 4); case testio of $1 : put_string ('Filename does not exist! ', 16, 2, 2); $2 : put_string ('File not found! ',16, 2, 2); $F0 : put_string ('Disk write error occurred! ', 16, 2, 2); $F1 : put_string ('Disk is full! ', 16, 2, 2); $FF : put_string ('File has dissappeared! Replace disk! ', 16, 2, 2); else put_string ('Some problem with these files has occurred! ', 16, 2, 2); end; (* case *) put_string ('Correct Fault and press any key to continue ', 18, 2, 3); put_string ('or press , to quit now ', 19, 2, 3); read(kbd, ch); if ch in ['Q','q'] then halt; if needsource then clean_window (1, 6, 80, 25) else clean_window (1, 12, 80, 25); end; {---------------------------------------------------------------------------} procedure open_files; begin needsource := true; repeat filename := ''; if needsource then get_prompted_string (filename, 1, 13, 'MS Word Print Filename: ', 10, 2, 'Enter Filename with Extension', 24, 2) else get_prompted_string (filename, 1, 13, 'Latex Filename: ', 12, 2, 'Enter Filename with .tex Extension', 24, 2); writeln; {$I-} if needsource then begin assign(inputfile,filename); reset(inputfile); testio := ioresult; success := (testio = 0); end else begin assign(outputfile,filename); reset(outputfile); testio := ioresult; success := (testio > 0); if success then begin assign (outputfile, filename); rewrite (outputfile); end; end; {$I+} if not success then begin err_message; end else if needsource then begin needsource := false; success := false; end; until success; end; {---------------------------------------------------------------------------} procedure read_data; begin ch := ' '; while not eof(inputfile) do begin read_char; if (ord(ch) in [32..127]) then case ch of '#','$','&','%': write(outputfile,'\',ch); {Special Latex chars} '_','{','}': write(outputfile,'\',ch); '>','<','+','=': write(outputfile,'$',ch,'$'); {Treat as Math} else write(outputfile,ch); end; (* case *) if (ord(ch) < 32) then case ch of carriagereturn, linefeed: write(outputfile,ch); escape: escape_char; si: write(outputfile, '{\small '); so: large_print; { \large or \section ? } DC2: write(outputfile, '}'); DC4: begin if not flag_bold then write(outputfile, '}'); { Don't add brace if text was bold } end; end; (* case *) if (ord(ch) > 127) then if (ord(ch) in [224..235]) then greek_char else ask_latex_command(ch); end; (* while *) end; {procedure} {---------------------------------------------------------------------------} procedure close_files; begin close(outputfile); close(inputfile); end; {---------------------------------------------------------------------------} { MAIN } {---------------------------------------------------------------------------} begin clrscr; title; repeat open_files; clean_window (1, 13, 80, 25); put_centered_string ('Please wait: I''m busy translating', 18, 2); read_data; close_files; clean_window (1, 8, 80, 25); put_centered_string ('File has been translated!!', 10, 2); put_centered_string ('Press Q or q to quit now,', 12, 2); put_centered_string ('or press any other key to translate another file', 14, 2); read (kbd, ch); clean_window (1, 6, 80, 25); until ch in ['Q','q']; clean_window (1, 6, 80, 25); put_centered_string ('Goodbye!!', 12, 2); gotoxy (1, 24); end.