]> git.lyx.org Git - lyx.git/blob - lib/scripts/clean_dvi.py
Replace the deprecated os.popen3 with the subprocess module.
[lyx.git] / lib / scripts / clean_dvi.py
1 #! /usr/bin/env python
2
3 '''
4 file clean_dvi.py
5 This file is part of LyX, the document processor.
6 Licence details can be found in the file COPYING
7 or at http://www.lyx.org/about/licence.php
8
9 author Angus Leeming
10 Full author contact details are available in the file CREDITS
11 or at http://www.lyx.org/about/credits.php
12
13 Usage:
14     python clean_dvi.py infile.dvi outfile.dvi
15
16 clean_dvi modifies the input .dvi file so that
17 dvips and yap (a dvi viewer on Windows) can find
18 any embedded PostScript files whose names are protected
19 with "-quotes.
20
21 It works by:
22 1 translating the machine readable .dvi file to human
23   readable .dtl form,
24 2 manipulating any references to external files
25 3 translating the .dtl file back to .dvi format.
26
27 It requires dv2dt and dt2dv from the DTL dviware package
28 http://www.ctan.org/tex-archive/dviware/dtl/
29 '''
30
31 import os, re, subprocess, sys
32
33 def usage(prog_name):
34     return 'Usage: %s in.dvi out.dvi\n' \
35            % os.path.basename(prog_name)
36
37
38 def warning(message):
39     sys.stderr.write(message + '\n')
40
41
42 def error(message):
43     sys.stderr.write(message + '\n')
44     sys.exit(1)
45
46
47 def manipulated_dtl(data):
48     psfile_re = re.compile(r'(special1 +)([0-9]+)( +\'PSfile=")(.*)(" llx=.*)')
49
50     lines = data.split('\n')
51     for i in range(len(lines)):
52         line = lines[i]
53         match = psfile_re.match(line)
54         if match != None:
55             file = match.group(4)
56             filelen = len(file)
57             file = file.replace('"', '')
58             # Don't forget to update the length of the string too...
59             strlen = int(match.group(2)) - (filelen - len(file))
60
61             lines[i] = '%s%d%s%s%s' \
62                        % ( match.group(1), strlen, match.group(3),
63                            file, match.group(5) )
64
65     return '\n'.join(lines)
66
67
68 def main(argv):
69     # First establish that the expected information has
70     # been input on the command line and whether the
71     # required executables exist.
72     if len(argv) != 3:
73         error(usage(argv[0]))
74
75     infile  = argv[1]
76     outfile = argv[2]
77
78     if not os.path.exists(infile):
79         error('Unable to read "%s"\n' % infile)
80
81     # Convert the input .dvi file to .dtl format.
82     if os.name == 'nt':
83         unix = False
84     else:
85         unix = True
86     dv2dt_call = 'dv2dt "%s"' % infile
87     dv2dt_pipe = subprocess.Popen(dv2dt_call, universal_newlines=True, \
88         stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, \
89         shell=unix, close_fds=unix)
90     (dv2dt_stdin, dv2dt_stdout, dv2dt_stderr) = \
91         (dv2dt_pipe.stdin, dv2dt_pipe.stdout, dv2dt_pipe.stderr)
92
93     dv2dt_stdin.close()
94     dv2dt_data   = dv2dt_stdout.read()
95     dv2dt_status = dv2dt_stdout.close()
96
97     if dv2dt_status != None or len(dv2dt_data) == 0:
98         dv2dt_err = dv2dt_stderr.read()
99         error("Failed: %s\n%s\n" % ( dv2dt_call, dv2dt_err) )
100
101     # Manipulate the .dtl file.
102     dtl_data = manipulated_dtl(dv2dt_data)
103     if dtl_data == None:
104         error("Failed to manipulate the dtl file")
105
106     # Convert this .dtl file back to .dvi format.
107     dt2dv_call = 'dt2dv -si "%s"' % outfile
108     dt2dv_stdin = os.popen(dt2dv_call, 'w')
109     dt2dv_stdin.write(dtl_data)
110
111
112 if __name__ == "__main__":
113     main(sys.argv)