1 // -*- mode: c++; c-file-style: "linux"; c-basic-offset: 2; indent-tabs-mode: nil -*-
2 // Copyright (C) 2004-2015 Andrej Vodopivec <andrej.vodopivec@gmail.com>
3 // (C) 2015-2018 Gunter Königsmann <wxMaxima@physikbuch.de>
4 // (C) 2008-2009 Ziga Lenarcic <zigalenarcic@users.sourceforge.net>
5 // (C) 2011-2011 cw.ahbong <cw.ahbong@gmail.com>
6 // (C) 2012-2013 Doug Ilijev <doug.ilijev@gmail.com>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // SPDX-License-Identifier: GPL-2.0+
24
25
26 /*! \file
27 This file defines the class DirStructure
28
29 DirStructure informs about what directory is to be found where on the current system.
30 */
31
32 #include "Dirstructure.h"
33 #include <wx/filename.h>
34 #include <wx/dir.h>
35 #include "Version.h"
36
37 // This macro is used to mark the macports prefix, so that it can be easily patched
38 // The MacPorts port file for wxMaxima uses this, so don't remove this!
39 // Note: this is not done with a define passed through cmake because I didn't find a way
40 // to pass paths which need quoting through cmake.
41 #define OSX_MACPORTS_PREFIX "/opt/local"
42 // If set to 1, the macports path is put first into the search path (after app package paths).
43 // This could be done with a define but then it doesn't make sense to use a different method.
44 #define OSX_MACPORTS_PREFER 0
45
Dirstructure()46 Dirstructure::Dirstructure()
47 {
48 m_dirStructure = this;
49 m_helpDir = ResourcesDir();
50
51 // The path Gentoo hides the manual at
52 if(wxDirExists(m_helpDir + wxString::Format("/doc/wxmaxima-%s",GITVERSION)))
53 m_helpDir += wxString::Format("/doc/wxmaxima-%s",GITVERSION);
54 if(wxDirExists(m_helpDir + wxT("/doc/wxmaxima")))
55 m_helpDir += wxT("/doc/wxmaxima");
56
57 if(wxDirExists(m_helpDir + wxT("/html")))
58 m_helpDir += wxT("/html");
59
60 if(wxDirExists(m_helpDir + wxT("/info")))
61 m_helpDir += wxT("/info");
62
63 if(wxDirExists(m_helpDir + wxT("/help")))
64 m_helpDir += wxT("/help");
65
66 if(!wxGetEnv(wxT("MAXIMA_USERDIR"),&m_userConfDir))
67 m_userConfDir = wxGetHomeDir();
68 m_userConfDir += "/";
69
70 #ifndef __WXMSW__
71 m_userConfDir += wxT(".");
72 #endif
73
74 m_userConfDir += wxT("maxima");
75
76 if(!wxDirExists(m_userConfDir))
77 wxMkDir(m_userConfDir, wxS_DIR_DEFAULT);
78
79 m_userConfDir += "/";
80
81 }
82
ResourcesDir() const83 wxString Dirstructure::ResourcesDir() const
84 {
85 wxString exepath = wxStandardPaths::Get().GetExecutablePath();
86 if(!exepath.IsEmpty())
87 {
88 // Our resources dir is somewhere near to the dir the binary can be found.
89 wxFileName exe(exepath);
90
91 // We only need the drive and the directory part of the path to the binary
92 exe.ClearExt();
93 exe.SetName(wxEmptyString);
94
95 // If the binary is in a source or bin folder the resources dir is one level above
96 wxArrayString dirs = exe.GetDirs();
97 if((dirs.Last().Upper() == wxT("SRC")) || (dirs.Last().Upper() == wxT("BIN")))
98 {
99 exe.RemoveLastDir();
100 dirs = exe.GetDirs();
101 }
102
103 // If the binary is in the wxMaxima folder the resources dir is two levels above as we
104 // are in MacOS/wxmaxima
105 if((dirs.Last().Upper() == wxT("MACOS")))
106 exe.RemoveLastDir();
107
108 // If there is a Resources folder the resources are there
109 if(wxDirExists(exe.GetPath() + wxT("/Resources")))
110 exe.AppendDir("Resources");
111
112 // If there is a share folder the resources are there
113 if(wxDirExists(exe.GetPath() + wxT("/share")))
114 exe.AppendDir("share");
115
116
117 exepath = exe.GetPath();
118 }
119 else
120 {
121 exepath = CMAKE_INSTALL_PREFIX;
122 }
123 return exepath;
124 }
125
DataDir() const126 wxString Dirstructure::DataDir() const
127 {
128 wxString dir = ResourcesDir();
129 if(wxDirExists(dir + wxT("/data")))
130 dir += wxT("/data");
131 if(wxDirExists(dir + wxT("/wxMaxima")))
132 dir += wxT("/wxMaxima");
133
134 return dir;
135 }
136
ArtDir() const137 wxString Dirstructure::ArtDir() const
138 {
139 wxString dir = ResourcesDir();
140 if(wxDirExists(dir + wxT("/wxMaxima")))
141 dir += wxT("/wxMaxima");
142
143 if(wxDirExists(dir + wxT("/art")))
144 dir += wxT("/art");
145
146 return dir;
147 }
148
MaximaDefaultLocation()149 wxString Dirstructure::MaximaDefaultLocation()
150 {
151 wxString maximaLocation;
152 wxFileName exe = wxStandardPaths::Get().GetExecutablePath();
153 exe.MakeAbsolute();
154 wxFileName maxima;
155 #if defined __WXMSW__ || defined __WXOSX__
156 wxString notFound = _("Maxima not found as %s");
157 #endif
158 #if defined __WXMSW__
159 wxString exeDir = exe.GetPathWithSep();
160 maxima = exeDir + "../bin/maxima.bat";
161 maxima.MakeAbsolute();
162 if(wxFileExists(maximaLocation = maxima.GetFullPath()))
163 return maximaLocation;
164
165 wxLogMessage(wxString::Format(notFound,maximaLocation.utf8_str()));
166 maxima = exeDir + "maxima.bat";
167 maxima.MakeAbsolute();
168 if(wxFileExists(maximaLocation = maxima.GetFullPath()))
169 return maximaLocation;
170
171 wxLogMessage(wxString::Format(notFound,maximaLocation.utf8_str()));
172 maxima = exeDir + "bin/maxima.bat";
173 maxima.MakeAbsolute();
174 if(wxFileExists(maximaLocation = maxima.GetFullPath()))
175 return maximaLocation;
176
177 wxLogMessage(wxString::Format(notFound,maximaLocation.utf8_str()));
178 maxima = exeDir + "../maxima.bat";
179 maxima.MakeAbsolute();
180 if(wxFileExists(maximaLocation = maxima.GetFullPath()))
181 return maximaLocation;
182
183 wxLogMessage(wxString::Format(notFound,maximaLocation.utf8_str()));
184 maxima = exeDir + "maxima";
185 maxima.MakeAbsolute();
186 if(wxFileExists(maximaLocation = maxima.GetFullPath()))
187 return maximaLocation;
188
189 wxLogMessage(wxString::Format(notFound,maximaLocation.utf8_str()));
190 maxima = exeDir + "bin/maxima";
191 maxima.MakeAbsolute();
192 if(wxFileExists(maximaLocation = maxima.GetFullPath()))
193 return maximaLocation;
194
195 wxLogMessage(wxString::Format(notFound,maximaLocation.utf8_str()));
196 maxima = exeDir + "../maxima";
197 maxima.MakeAbsolute();
198 if(wxFileExists(maximaLocation = maxima.GetFullPath()))
199 return maximaLocation;
200
201 wxLogMessage(wxString::Format(notFound,maximaLocation.utf8_str()));
202 maxima = exeDir + "../bin/maxima";
203 maxima.MakeAbsolute();
204 if(wxFileExists(maximaLocation = maxima.GetFullPath()))
205 return maximaLocation;
206
207 wxLogMessage(wxString::Format(notFound,maximaLocation.utf8_str()));
208 #elif defined __WXOSX__
209 wxString exeDir = exe.GetPathWithSep();
210 maximaLocation = "/Applications/Maxima.app";
211 if (wxFileExists(maximaLocation))
212 return maximaLocation;
213
214 wxLogMessage(wxString::Format(notFound,maximaLocation.utf8_str()));
215 maximaLocation = "/Applications/maxima.app";
216 if (wxFileExists(maximaLocation))
217 return maximaLocation;
218
219 // The Macports path (if it is prefered over homebrew)
220 #if OSX_MACPORTS_PREFER
221 wxLogMessage(wxString::Format(notFound,maximaLocation.utf8_str()));
222 maximaLocation = OSX_MACPORTS_PREFIX "/bin/maxima";
223 if (wxFileExists(maximaLocation))
224 return maximaLocation;
225 #endif
226
227 // The homebrew path
228 wxLogMessage(wxString::Format(notFound,maximaLocation.utf8_str()));
229 maximaLocation = "/usr/local/bin/maxima";
230 if (wxFileExists(maximaLocation))
231 return maximaLocation;
232
233 // The Macports path (if it is not prefered over homebrew)
234 #if !OSX_MACPORTS_PREFER
235 wxLogMessage(wxString::Format(notFound,maximaLocation.utf8_str()));
236 maximaLocation = OSX_MACPORTS_PREFIX "/bin/maxima";
237 if (wxFileExists(maximaLocation))
238 return maximaLocation;
239 #endif
240
241 wxLogMessage(wxString::Format(notFound,maximaLocation.utf8_str()));
242 maximaLocation = "/usr/bin/maxima";
243 if (wxFileExists(maximaLocation))
244 return maximaLocation;
245
246 wxLogMessage(wxString::Format(notFound,maximaLocation.utf8_str()));
247 maxima = exeDir + "maxima";
248 maxima.MakeAbsolute();
249 if(wxFileExists(maximaLocation = maxima.GetFullPath()))
250 return maximaLocation;
251
252 wxLogMessage(wxString::Format(notFound,maximaLocation.utf8_str()));
253 #endif
254 return wxT("maxima");
255 }
256
GnuplotDefaultLocation(wxString pathguess)257 wxString Dirstructure::GnuplotDefaultLocation(wxString pathguess)
258 {
259 wxString gnuplot_binary;
260
261 if(wxFileName(pathguess).IsAbsolute())
262 gnuplot_binary = pathguess;
263 else
264 {
265 wxPathList pathlist;
266
267 // Add paths relative to the path of the wxMaxima executable
268 pathlist.Add(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath());
269 pathlist.Add(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath()+"/../");
270 pathlist.Add(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath()+"/../gnuplot");
271 pathlist.Add(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath()+"/../gnuplot/bin");
272
273 // Add paths from the PATH environment variable
274 pathlist.AddEnvList(wxT("PATH"));
275
276 // Add OSX specific paths
277 #ifdef __WXOSX__
278 // MacPorts:
279 // The MacPorts default binary path /opt/local/bin/ is not in the PATH for applications.
280 // It is added to .profile, but this is only used by shells.
281 // => Add the default MacPorts binary path /opt/local/bin/ to our search path list.
282 //
283 // Homebrew:
284 // Homebrew installs binaries in /usr/local/bin, which is in the PATH by default.
285 //
286 // Application packages including gnuplot:
287 // The above wxMaxima executable relative logic should work
288 //
289 // If gnuplot is somewhere else (e.g. non default MacPort or Homebrew path), the command
290 // gnuplot_command:"/opt/local/bin/gnuplot"$
291 // must be added manually to ~/.maxima/wxmaxima-init.mac
292 // This should be documented for the installer packages, e.g. as MacPorts "notes" field.
293 pathlist.Add(OSX_MACPORTS_PREFIX "/bin");
294 #endif
295
296 // Find executable "gnuplot" in our list of paths
297 gnuplot_binary = pathlist.FindAbsoluteValidPath(pathguess);
298 // If not successful, Find executable "gnuplot.exe" in our list of paths
299 if(gnuplot_binary == wxEmptyString)
300 gnuplot_binary = pathlist.FindAbsoluteValidPath(pathguess + wxT(".exe"));
301 // If not successful, use the original command (better than empty for error messages)
302 if(gnuplot_binary == wxEmptyString)
303 {
304 wxLogMessage(_("Gnuplot not found, using the default: ") + pathguess);
305 gnuplot_binary = pathguess;
306 }
307 else
308 {
309 wxLogMessage(_("Gnuplot found at: ") + gnuplot_binary);
310 }
311 }
312
313 return gnuplot_binary;
314 }
315
UserAutocompleteFile()316 wxString Dirstructure::UserAutocompleteFile()
317 {
318 wxString newFileName = UserConfDir() + wxT("wxmaxima.ac");
319 if(!wxFileExists(newFileName))
320 {
321 wxString potentialOldFile = UserConfDir() + wxT(".wxmaxima.ac");
322 if(wxFileExists(potentialOldFile))
323 wxRenameFile(potentialOldFile, newFileName);
324 potentialOldFile = UserConfDir() + wxT(".wxmax.ac");
325 if(wxFileExists(potentialOldFile))
326 wxRenameFile(potentialOldFile, newFileName);
327 }
328 return newFileName;
329 }
330
331 Dirstructure *Dirstructure::m_dirStructure;
332