Imported Upstream version 1.8.15
[platform/upstream/doxygen.git] / src / msc.cpp
1 /******************************************************************************
2  *
3  * 
4  *
5  * Copyright (C) 1997-2015 by Dimitri van Heesch.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation under the terms of the GNU General Public License is hereby 
9  * granted. No representations are made about the suitability of this software 
10  * for any purpose. It is provided "as is" without express or implied warranty.
11  * See the GNU General Public License for more details.
12  *
13  * Documents produced by Doxygen are derivative works derived from the
14  * input used in their production; they are not affected by this license.
15  *
16  */
17
18 #include "msc.h"
19 #include "portable.h"
20 #include "config.h"
21 #include "message.h"
22 #include "docparser.h"
23 #include "doxygen.h"
24 #include "index.h"
25 #include "util.h"
26 #include "ftextstream.h"
27
28 #include <qdir.h>
29
30 static const int maxCmdLine = 40960;
31
32 static bool convertMapFile(FTextStream &t,const char *mapName,const QCString relPath,
33                            const QCString &context)
34 {
35   QFile f(mapName);
36   if (!f.open(IO_ReadOnly))
37   {
38     err("failed to open map file %s for inclusion in the docs!\n"
39         "If you installed Graphviz/dot after a previous failing run, \n"
40         "try deleting the output directory and rerun doxygen.\n",mapName);
41     return FALSE;
42   }
43   const int maxLineLen=1024;
44   char buf[maxLineLen];
45   char url[maxLineLen];
46   char ref[maxLineLen];
47   int x1,y1,x2,y2;
48   while (!f.atEnd())
49   {
50     bool isRef = FALSE;
51     int numBytes = f.readLine(buf,maxLineLen);
52     buf[numBytes-1]='\0';
53     //printf("ReadLine `%s'\n",buf);
54     if (qstrncmp(buf,"rect",4)==0)
55     {
56       // obtain the url and the coordinates in the order used by graphviz-1.5
57       sscanf(buf,"rect %s %d,%d %d,%d",url,&x1,&y1,&x2,&y2);
58
59       if (qstrcmp(url,"\\ref")==0 || qstrcmp(url,"@ref")==0)
60       {
61         isRef = TRUE;
62         sscanf(buf,"rect %s %s %d,%d %d,%d",ref,url,&x1,&y1,&x2,&y2);
63       }
64
65       // sanity checks
66       if (y2<y1) { int temp=y2; y2=y1; y1=temp; }
67       if (x2<x1) { int temp=x2; x2=x1; x1=temp; }
68
69       t << "<area href=\"";
70
71       if ( isRef )
72       {
73         // handle doxygen \ref tag URL reference
74         DocRef *df = new DocRef( (DocNode*) 0, url, context );
75         t << externalRef(relPath,df->ref(),TRUE);
76         if (!df->file().isEmpty()) t << df->file() << Doxygen::htmlFileExtension;
77         if (!df->anchor().isEmpty()) t << "#" << df->anchor();
78         delete df;
79       }
80       else
81       {
82         t << url;
83       }
84       t << "\" shape=\"rect\" coords=\""
85         << x1 << "," << y1 << "," << x2 << "," << y2 << "\""
86         << " alt=\"\"/>" << endl;
87     }
88   }
89
90   return TRUE;
91 }
92
93 void writeMscGraphFromFile(const char *inFile,const char *outDir,
94                            const char *outFile,MscOutputFormat format)
95 {
96   QCString absOutFile = outDir;
97   absOutFile+=portable_pathSeparator();
98   absOutFile+=outFile;
99
100   // chdir to the output dir, so dot can find the font file.
101   QCString oldDir = QDir::currentDirPath().utf8();
102   // go to the html output directory (i.e. path)
103   QDir::setCurrent(outDir);
104   //printf("Going to dir %s\n",QDir::currentDirPath().data());
105   QCString mscExe = Config_getString(MSCGEN_PATH)+"mscgen"+portable_commandExtension();
106   QCString mscArgs;
107   QCString imgName = outFile;
108   switch (format)
109   {
110     case MSC_BITMAP:
111       mscArgs+="-T png";
112       imgName+=".png";
113       break;
114     case MSC_EPS:
115       mscArgs+="-T eps";
116       imgName+=".eps";
117       break;
118     case MSC_SVG:
119       mscArgs+="-T svg";
120       imgName+=".svg";
121       break;
122     default:
123       goto error; // I am not very fond of goto statements, but when in Rome...
124   }
125   mscArgs+=" -i \"";
126   mscArgs+=inFile;
127  
128   mscArgs+="\" -o \"";
129   mscArgs+=imgName+"\"";
130   int exitCode;
131 //  printf("*** running: %s %s outDir:%s %s\n",mscExe.data(),mscArgs.data(),outDir,outFile);
132   portable_sysTimerStart();
133   if ((exitCode=portable_system(mscExe,mscArgs,FALSE))!=0)
134   {
135     portable_sysTimerStop();
136     goto error;
137   }
138   portable_sysTimerStop();
139   if ( (format==MSC_EPS) && (Config_getBool(USE_PDFLATEX)) )
140   {
141     QCString epstopdfArgs(maxCmdLine);
142     epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
143                          outFile,outFile);
144     portable_sysTimerStart();
145     if (portable_system("epstopdf",epstopdfArgs)!=0)
146     {
147       err("Problems running epstopdf. Check your TeX installation!\n");
148     }
149     portable_sysTimerStop();
150   }
151
152   Doxygen::indexList->addImageFile(imgName);
153
154 error:
155   QDir::setCurrent(oldDir);
156 }
157
158 QCString getMscImageMapFromFile(const QCString& inFile, const QCString& outDir,
159                                 const QCString& relPath,const QCString& context)
160 {
161   QCString outFile = inFile + ".map";
162
163
164   //printf("*** running:getMscImageMapFromFile \n");
165   // chdir to the output dir, so dot can find the font file.
166   QCString oldDir = QDir::currentDirPath().utf8();
167   // go to the html output directory (i.e. path)
168   QDir::setCurrent(outDir);
169   //printf("Going to dir %s\n",QDir::currentDirPath().data());
170
171   QCString mscExe = Config_getString(MSCGEN_PATH)+"mscgen"+portable_commandExtension();
172   QCString mscArgs = "-T ismap -i \"";
173   mscArgs+=inFile;
174   mscArgs+="\" -o \"";
175   mscArgs+=outFile + "\"";
176
177   int exitCode;
178   portable_sysTimerStart();
179   if ((exitCode=portable_system(mscExe,mscArgs,FALSE))!=0)
180   {
181     portable_sysTimerStop();
182     QDir::setCurrent(oldDir);
183     return "";
184   }
185   portable_sysTimerStop();
186   
187   QGString result;
188   FTextStream tmpout(&result);
189   convertMapFile(tmpout, outFile, relPath, context);
190   QDir().remove(outFile);
191
192   QDir::setCurrent(oldDir);
193   return result.data();
194 }
195
196 void writeMscImageMapFromFile(FTextStream &t,const QCString &inFile,
197                               const QCString &outDir,
198                               const QCString &relPath,
199                               const QCString &baseName,
200                               const QCString &context,
201                               MscOutputFormat format
202                             )
203 {
204   QCString mapName = baseName+".map";
205   t << "<img src=\"" << relPath << baseName << ".";
206   switch (format)
207   {
208     case MSC_BITMAP:
209       t << "png";
210       break;
211     case MSC_EPS:
212       t << "eps";
213       break;
214     case MSC_SVG:
215       t << "svg";
216       break;
217     default:
218       t << "unknown";
219   }
220   QCString imap = getMscImageMapFromFile(inFile,outDir,relPath,context);
221   if (!imap.isEmpty())
222   {
223     t << "\" alt=\""
224       << baseName << "\" border=\"0\" usemap=\"#" << mapName << "\"/>" << endl;
225     t << "<map name=\"" << mapName << "\" id=\"" << mapName << "\">" << imap << "</map>" << endl;
226   }
227   else
228   {
229     t << "\" alt=\"" << baseName << "\" border=\"0\"/>" << endl;
230   }
231 }
232