1
// --------------------------------------------------------------------
2
// The Ipe document, with PDF support
3
// --------------------------------------------------------------------
6
This file is part of the extensible drawing editor Ipe.
7
Copyright (C) 1993-2004 Otfried Cheong
9
Ipe is free software; you can redistribute it and/or modify it
10
under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2 of the License, or
12
(at your option) any later version.
14
As a special exception, you have permission to link Ipe with the
15
CGAL library and distribute executables, as long as you follow the
16
requirements of the Gnu General Public License in regard to all of
17
the software in the executable aside from CGAL.
19
Ipe is distributed in the hope that it will be useful, but WITHOUT
20
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
22
License for more details.
24
You should have received a copy of the GNU General Public License
25
along with Ipe; if not, you can find it at
26
"http://www.gnu.org/copyleft/gpl.html", or write to the Free
27
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
41
#include <qtextstream.h>
43
// --------------------------------------------------------------------
46
\brief Support for loading/saving/running Latex on IpeDocument.
48
This class supports running pdflatex to generate the PDF output for
49
text objects, and adds I/O using QFile's to IpeDocument.
51
All members of the class are static.
55
IpeDocument *IpeModel::New(const QString &fname, int &reason)
59
if (!f.open(IO_ReadOnly))
61
XmlQSource source(&f);
62
IpeDocument::TFormat format = IpeDocument::FileFormat(source);
64
IpeDocument *self = IpeDocument::New(source, format, reason);
69
bool IpeModel::Save(const IpeDocument *doc, const QString &fname,
70
IpeString creator, IpeDocument::TFormat format,
74
if (!f.open(IO_WriteOnly))
76
IpeQStream stream(&f);
77
bool result = doc->Save(stream, creator, format, flags,
78
IpePreferences::Static()->iCompressLevel);
83
bool IpeModel::AddStyleSheet(IpeDocument *doc, const QString &fname)
86
if (!file.open(IO_ReadOnly))
88
XmlQSource source(&file);
89
bool result = doc->AddStyleSheet(source);
94
// --------------------------------------------------------------------
97
/*! Prepend \a styleDirs to Latex include path. */
98
int IpeModel::RunLatex(IpeDocument *doc, bool needLatex,
99
const QStringList &styleDirs, QString &texLog)
101
IpePreferences *prefs = IpePreferences::Static();
102
texLog = QString::null;
105
for (IpeDocument::iterator it = doc->begin(); it != doc->end(); ++it)
106
count += converter.ScanPage(*it);
109
// First we need a temporary directory
110
QDir temp = QDir(prefs->iLatexDir);
112
// create Pdflatex directory if it doesn't exist
113
QDir().mkdir(temp.absPath());
117
QString texFile = temp.filePath("text.tex");
118
QString pdfFile = temp.filePath("text.pdf");
119
QString logFile = temp.filePath("text.log");
120
QFile::remove(logFile);
123
if(!file.open(IO_WriteOnly))
125
IpeQStream stream(&file);
126
int err = converter.CreateLatexSource(stream, doc->Properties().iPreamble,
131
return ErrWritingSource;
132
if (err == 0 && !needLatex)
133
return ErrAlreadyHaveForm;
134
// Latex source has been prepared correctly
136
// set up TEXINPUTS (but special handling for MikTeX below)
137
QCString ti = "TEXINPUTS=";
139
if (styleDirs.count() > 0) {
141
for (uint i = 0; i < styleDirs.count(); ++i)
142
ti.append((styleDirs[i] + ":").local8Bit());
144
if (!prefs->iTexInputs.empty()) {
146
ti.append(prefs->iTexInputs.CString());
149
putenv(qstrdup(ti.data()));
152
QString s = temp.filePath("runlatex.bat");
154
f.open(IO_WriteOnly);
155
QTextStream batFile(&f);
156
QString dirPath = QDir::convertSeparators(temp.path());
157
if (dirPath.length() > 2 && dirPath[1] == ':')
158
batFile << dirPath.left(2) << "\r\n";
159
batFile << "cd \"" << dirPath << "\"\r\n";
160
batFile << "\"" << prefs->iPdfLatex << "\"";
161
if (prefs->iMikTeX) {
162
for (uint i = 0; i < styleDirs.count(); ++i) {
163
batFile << " -include-directory=\""
164
<< QDir::convertSeparators(styleDirs[i]) << "\"";
167
batFile << " text.tex\r\n";
169
s = "call \"" + QDir::convertSeparators(s) + "\"";
170
system(s.local8Bit());
172
QCString s = "cd " + QFile::encodeName(temp.path()) + "; " +
173
QFile::encodeName(prefs->iPdfLatex) + " text.tex";
176
// Check log file for Pdflatex version and errors
178
if (!log.open(IO_ReadOnly))
180
texLog = QString(log.readAll());
182
if (texLog.left(14) != "This is pdfTeX" &&
183
texLog.left(15) != "This is pdfeTeX")
185
prefs->iMikTeX = (texLog.left(80).find("MikTeX") >= 0);
186
int i = texLog.find('-');
189
QString version = texLog.mid(i+1, 30);
190
ipeDebug("pdfTeX version %s", version.latin1());
191
if (version[0] == '1' && '0' <= version[1] && version[1] <= '3')
192
return ErrOldPdfLatex;
193
if (version.left(2) == "14" && version.left(3) < "14f")
194
return ErrOldPdfLatex;
196
if (texLog.find("\n!") >= 0)
200
if (!pdfF.open(IO_ReadOnly))
202
XmlQSource source(&pdfF);
203
if (converter.ReadPdf(source) && converter.UpdateTextObjects()) {
204
doc->SetFontPool(converter.TakeFontPool());
205
ipeDebug("Pdflatex run completed successfully");
208
return ErrLatexOutput;
211
// --------------------------------------------------------------------