1 // -*- C++ -*- 2 /** 3 * \file filetools.h 4 * This file is part of LyX, the document processor. 5 * Licence details can be found in the file COPYING. 6 * 7 * \author Lars Gullik Bjønnes 8 * 9 * Full author contact details are available in file CREDITS. 10 */ 11 12 #ifndef LYX_FILETOOL_H 13 #define LYX_FILETOOL_H 14 15 #include "support/docstring.h" 16 17 #include <utility> 18 #include <string> 19 #include <set> 20 21 namespace lyx { 22 namespace support { 23 24 class FileName; 25 26 /// Record used temp file names 27 static std::set<std::string> tmp_names_; 28 29 /// Get a temporary file name. 30 /** 31 * The actual temp file (QTemporaryFile object) is immediately 32 * destroyed after the name has been generated, so a new file 33 * has to be created manually from the name. 34 * This is needed if the temp file has to be manually removed 35 * (e.g., when temp files are used as conversion target, and the initial 36 * file only serves as a placeholder), since QTemporaryFile objects 37 * cannot be manually removed at least on Windows (they are always 38 * kept open internally even after close()). 39 * In order to avoid race conditions due to duplicate names, we record 40 * all used temp file names. 41 * If you don't have to remove the temp file manually, use TempFile instead! 42 */ 43 FileName const tempFileName(std::string const &); 44 45 /// Remove and unregister a temporary file. 46 void removeTempFile(FileName const &); 47 48 /** Creates the global LyX temp dir. 49 \p deflt can be an existing directory name. In this case a new directory 50 inside \p deflt is created. If \p deflt does not exist yet, \p deflt is 51 created and used as the temporary directory. 52 \return the tmp dir name or string() if something went wrong. 53 */ 54 FileName const createLyXTmpDir(FileName const & deflt); 55 56 #if 0 57 // FIXME unused. Should this be deleted or resurrected? 58 /** Find file by searching several directories. 59 Uses a string of paths separated by ";"s to find a file to open. 60 Can't cope with pathnames with a ';' in them. Returns full path to file. 61 If path entry begins with $$LyX/, use system_lyxdir. 62 If path entry begins with $$User/, use user_lyxdir. 63 Example: "$$User/doc;$$LyX/doc". 64 */ 65 FileName const fileOpenSearch(std::string const & path, 66 std::string const & name, 67 std::string const & ext = std::string()); 68 #endif 69 70 /// How to search files 71 enum search_mode { 72 /// The file must exist (return an empty file name otherwise) 73 must_exist, 74 /// Only do file name expansion, return the complete name even if 75 /// the file does not exist 76 may_not_exist, 77 /// The (image) file may be present with hi-dpi resolution - 78 /// the lookup checks for a file named "image" + "@2x" + ".ext" first. 79 /// If found it will return e.g. "image@2x.png" instead of "image.png". 80 /// Otherwise it will work as must_exist. 81 check_hidpi 82 }; 83 84 /** Returns the real name of file name in directory path, with optional 85 extension ext. 86 The file is searched in the given path (unless it is an absolute 87 file name), first directly, and then with extension .ext (if given). 88 */ 89 FileName const fileSearch(std::string const & path, 90 std::string const & name, 91 std::string const & ext = std::string(), 92 search_mode mode = must_exist); 93 94 /// 95 bool isLyXFileName(std::string const & filename); 96 97 /// 98 bool isSGMLFileName(std::string const & filename); 99 100 /// check for characters in filenames not allowed by LaTeX 101 bool isValidLaTeXFileName(std::string const & filename); 102 103 /** check for characters in filenames that might lead to 104 problems when manually compiling the LaTeX export of LyX 105 and opening the result with some older DVI-viewers 106 */ 107 bool isValidDVIFileName(std::string const & filename); 108 109 /// check whether the file has binary contents 110 bool isBinaryFile(FileName const & filename); 111 112 /** Returns the path of a library data file. 113 Search the file name.ext in the subdirectory dir of 114 -# user_lyxdir 115 -# build_lyxdir (if not empty) 116 -# system_lyxdir 117 The third parameter `ext' is optional. 118 */ 119 FileName const libFileSearch(std::string const & dir, 120 std::string const & name, 121 std::string const & ext = std::string(), 122 search_mode mode = must_exist); 123 124 /** Same as libFileSearch(), but tries first to find an 125 internationalized version of the file by prepending $LANG_ to the 126 name 127 */ 128 FileName const 129 i18nLibFileSearch(std::string const & dir, 130 std::string const & name, 131 std::string const & ext = std::string()); 132 133 /** Same as libFileSearch(), but tries first to find a preferred 134 version of the file by appending the icon set name to the dir 135 */ 136 FileName const 137 imageLibFileSearch(std::string & dir, std::string const & name, 138 std::string const & ext = std::string(), 139 search_mode mode = must_exist); 140 141 /// How to quote a filename 142 enum quote_style { 143 /** Quote for the (OS dependant) shell. This is needed for command 144 line arguments of subprocesses. */ 145 quote_shell, 146 /** Quote a file name for the (OS dependant) shell. This is needed 147 for file names as command line arguments of subprocesses. */ 148 quote_shell_filename, 149 /** Quote for python. Use this if you want to store a filename in a 150 python script. Example: \code 151 os << "infile = " << quoteName(filename) << '\\n'; 152 \endcode This uses double quotes, so that you can also use this 153 to quote filenames as part of a string if the string is quoted 154 with single quotes. */ 155 quote_python 156 }; 157 158 /** Takes a command such as "python $$s/scripts/convertDefault.py file.in file.out" 159 * and replaces "$$s/" with the path to the LyX support directory containing 160 * this script. If the script is not found, "$$s/" is removed. Executing the 161 * command will still fail, but the error message will make some sort of 162 * sense ;-) 163 */ 164 std::string const commandPrep(std::string const & command); 165 166 enum latex_path_extension { 167 PROTECT_EXTENSION, 168 EXCLUDE_EXTENSION 169 }; 170 171 enum latex_path_dots { 172 LEAVE_DOTS, 173 ESCAPE_DOTS 174 }; 175 176 /** @param path a file path in internal_path format. Ie, directories 177 * are indicated by '/', not by '\'. 178 * 179 * Manipulates @c path into a form suitable for inclusion in a LaTeX 180 * document. 181 * If @c path contains LaTeX special characters, these are escaped. 182 * Eg, '~' -> '\\string~' 183 * If @c path contains spaces, then the returned path is enclosed in 184 * "-quotes. This last fix will lead to successful compiliation of the 185 * LaTeX file only if a sufficiently modern LaTeX compiler is used. 186 * If @c ext == EXCLUDE_EXTENSION the extension is left outside the quotes. 187 * This is needed for pdfeTeX, Version 3.141592-1.21a-2.2 (Web2C 7.5.4) 188 * (format=pdflatex 2005.4.11) in combination with 189 * pdftex.def 2002/06/19 v0.03k graphics/color for pdftex: 190 * It does not recognize the file extension if it is inside the quotes. 191 * If @c dots == ESCAPE_DOTS dots in the filename are replaced by 192 * "\\lyxdot ". This is needed for the \\includegraphics command if the 193 * automatic format selection is used. 194 */ 195 std::string const latex_path(std::string const & path, 196 latex_path_extension extension = PROTECT_EXTENSION, 197 latex_path_dots dots = LEAVE_DOTS); 198 199 /// Substitutes active latex characters with underscores in filename 200 FileName const makeLatexName(FileName const & file); 201 202 /** Put the name in quotes suitable for the current shell or python, 203 depending on \p style. */ 204 std::string const quoteName(std::string const & file, quote_style style = quote_shell); 205 206 /// Add a filename to a path. Any path from filename is stripped first. 207 std::string const addName(std::string const & path, std::string const & fname); 208 209 /// Append sub-directory(ies) to path in an intelligent way 210 std::string const addPath(std::string const & path, std::string const & path2); 211 212 /** Change extension of oldname to extension. 213 If oldname does not have an extension, it is appended. 214 If the extension is empty, any extension is removed from the name. 215 */ 216 std::string const 217 changeExtension(std::string const & oldname, std::string const & extension); 218 219 /// Remove the extension from \p name 220 std::string const removeExtension(std::string const & name); 221 222 /** Add the extension \p ext to \p name. 223 Use this instead of changeExtension if you know that \p name is without 224 extension, because changeExtension would wrongly interpret \p name if it 225 contains a dot. 226 */ 227 std::string const 228 addExtension(std::string const & name, std::string const & extension); 229 230 /// Return the extension of the file (not including the .) 231 std::string const getExtension(std::string const & name); 232 233 /** \return the name that LyX will give to the unzipped file \p zipped_file 234 if the second argument of unzipFile() is empty. 235 */ 236 std::string const unzippedFileName(std::string const & zipped_file); 237 238 /** Unzip \p zipped_file. 239 The unzipped file is named \p unzipped_file if \p unzipped_file is not 240 empty, and unzippedFileName(\p zipped_file) otherwise. 241 Will overwrite an already existing unzipped file without warning. 242 */ 243 FileName const unzipFile(FileName const & zipped_file, 244 std::string const & unzipped_file = std::string()); 245 246 /** Convert relative path into absolute path based on a basepath. 247 If relpath is absolute, just use that. 248 If basepath doesn't exist use CWD. 249 */ 250 FileName const makeAbsPath(std::string const & RelPath = std::string(), 251 std::string const & BasePath = std::string()); 252 253 /** Creates a nice compact path for displaying. The parameter 254 threshold, if given, specifies the maximal length of the path. 255 */ 256 docstring const 257 makeDisplayPath(std::string const & path, unsigned int threshold = 1000); 258 259 /** Makes relative path out of absolute path. 260 If it is deeper than basepath, 261 it's easy. If basepath and abspath share something (they are all deeper 262 than some directory), it'll be rendered using ..'s. If they are completely 263 different, then the absolute path will be used as relative path 264 WARNING: the absolute path and base path must really be absolute paths!!! 265 */ 266 docstring const 267 makeRelPath(docstring const & abspath, docstring const & basepath); 268 269 /// Strip filename from path name 270 std::string const onlyPath(std::string const & fname); 271 272 /// Strips path from filename 273 std::string const onlyFileName(std::string const & fname); 274 275 /** Check and Replace Environmentvariables ${NAME} in Path. 276 Replaces all occurrences of these, if they are found in the 277 environment. 278 Variables are defined by Var := '${' [a-zA-Z_][a-zA-Z_0-9]* '}' 279 */ 280 std::string const replaceEnvironmentPath(std::string const & path); 281 282 /** 283 Return a string to be used as a prefix to a command for setting the 284 environment of the TeX engine with respect to the paths \p path and \p lpath. 285 */ 286 std::string latexEnvCmdPrefix(std::string const &path, std::string const & lpath); 287 288 /** Replace all references to a current directory (a lonely '.' or 289 the prefix "./") in \c pathlist with \c path. Also prefixes 290 all non-absolute paths with \c path. 291 */ 292 std::string const replaceCurdirPath(std::string const & path, std::string const & pathlist); 293 294 /** Set \c link to the path \c file points to as a symbolic link. 295 \return true if successful. 296 */ 297 bool readLink(FileName const & file, FileName & link); 298 299 /** 300 * Search a TeX file in all locations the latex compiler would search it, 301 * with the help of kpsewhich. 302 * The current working directory must be set correctly, so that relative 303 * names work. 304 * \param fil The filename to search 305 * \param format The file format as used by kpsewhich, e.g. "bib", "bst" etc. 306 */ 307 FileName const findtexfile(std::string const & fil, 308 std::string const & format, 309 bool const onlykpse = false); 310 311 /** \param file1, file2 the two files to be compared. Must have absolute paths. 312 * \returns 1 if \c file1 has a more recent timestamp than \c file2, 313 * 0 if their timestamps are the same, 314 * -1 if \c file2 has a more recent timestamp than \c file1. 315 * If one of the files does not exist, the return value indicates the file 316 * which does exist. Eg, if \c file1 exists but \c file2 does not, return 1. 317 */ 318 int compare_timestamps(FileName const & file1, FileName const & file2); 319 320 /// \param lfuns: true if we're converting lfuns, false if prefs 321 bool prefs2prefs(FileName const & filename, FileName const & tempfile, 322 bool lfuns); 323 324 /// Does file \p file need to be updated by configure.py? 325 bool configFileNeedsUpdate(std::string const & file); 326 327 typedef std::pair<int, std::string> cmd_ret; 328 329 cmd_ret const runCommand(std::string const & cmd); 330 331 int fileLock(const char * lock_file); 332 void fileUnlock(int fd, const char * lock_file); 333 334 } // namespace support 335 } // namespace lyx 336 337 338 339 #endif 340