diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2018-03-19 19:55:58 +0100 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2018-03-19 19:55:58 +0100 |
commit | d1a8285f818eb7e5c3d6a05709ea21a808490b8c (patch) | |
tree | 326578f0505cbed07cfe60de530022822dc237ac /app/bin/paths.c | |
parent | 16e9630b79f0a7a90c6cedb6781175bb8b337dc1 (diff) |
New upstream version 5.1.0upstream/5.1.0
Diffstat (limited to 'app/bin/paths.c')
-rw-r--r-- | app/bin/paths.c | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/app/bin/paths.c b/app/bin/paths.c new file mode 100644 index 0000000..cbd9b38 --- /dev/null +++ b/app/bin/paths.c @@ -0,0 +1,220 @@ +/** \file paths.c +* Path and file name handling functions. +*/ + +/* XTrkCad - Model Railroad CAD + * Copyright (C) 2017 Martin Fischer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <stdarg.h> + +#ifdef WINDOWS +#include <windows.h> +#endif + +#include <wlib.h> +#include <dynstring.h> +#include "track.h" +#include "common.h" +#include "utility.h" +#include "misc.h" +#include "i18n.h" +#include "uthash.h" +#include "paths.h" + +struct pathTable { + char type[ PATH_TYPE_SIZE]; /**< type of path */ + DynString path; /**< path */ + UT_hash_handle hh; /**< makes this structure hashable */ +}; + +static struct pathTable *paths; + +static void AddPath(const char *type, char*path); +static struct pathTable *FindPath(const char *type); + +#define PATHS_SECTION "paths" + +/** +* Find the path for a given type in the hash table +* +* \param type IN the searched type +* \param entry OUT the table entry +* \return +*/ + +static struct pathTable * +FindPath(const char *type) +{ + struct pathTable *entry; + HASH_FIND_STR(paths, type, entry); + return (entry); +} + +/** + * Add a path to the table. If it already exists, the value ist updated. + * + * \param type IN type of path + * \param path IN path + */ +static void +AddPath(const char *type, char*path) +{ + struct pathTable *tableEntry; + tableEntry = FindPath(type); + + if (tableEntry) { + DynStringClear(&(tableEntry->path)); + } else { + tableEntry = malloc(sizeof(struct pathTable)); + DynStringMalloc(&tableEntry->path, 16); + strcpy(tableEntry->type, type); + HASH_ADD_STR(paths, type, tableEntry); + } + + DynStringCatCStr(&(tableEntry->path), path); +} + +/** + * Update the current directory for a specific filetype. Get the directory part from the current file. + * XTrackCAD keeps seprate directories for different filetypes.(for trackplans, bitmaps and DXF files). + * The paths are stored in a hash table using the file type as the hash. + * + * \param pathType IN file type + * \param fileName IN fully qualified filename + * \return + * + */ + +void SetCurrentPath( + const char * pathType, + const char * fileName) +{ + char *path; + char *copy; + assert(fileName != NULL); + assert(pathType != NULL); + copy = strdup(fileName); + path = strrchr(copy, FILE_SEP_CHAR[0]); + + if (path) { + *path = '\0'; + AddPath(pathType, copy); + wPrefSetString(PATHS_SECTION, pathType, copy); + } + + free(copy); +} + +/** + * Get the current path for a given file type. Following options are searched: + * 1. the hash array + * 2. the preferences file for this type + * 3. the older general setting (for backwards compatibility) + * 4. the user's home directory as default + * Search is finished when one of the options returns a valid path + * + * \param IN pathType the type + * \return pointer to path of NULL if not existing + */ + +char *GetCurrentPath( + const char *pathType) +{ + struct pathTable *currentPath; + const char *path; + assert(pathType != NULL); + currentPath = FindPath(pathType); + + if (currentPath) { + return (DynStringToCStr(&(currentPath->path))); + } + + path = wPrefGetString(PATHS_SECTION, pathType); + + if (!path) { + path = wPrefGetString("file", "directory"); + } + + if (!path) { + path = wGetUserHomeDir(); + } + + AddPath(pathType, (char *)path); + return ((char *)path); +} + +/** +* Find the filename/extension piece in a fully qualified path +* +* \param path IN the full path +* \return pointer to the filename part +*/ + +char *FindFilename(char *path) +{ + char *name; + name = strrchr(path, FILE_SEP_CHAR[0]); + + if (name) { + name++; + } else { + name = path; + } + + return (name); +} + +/** +* Make a full path definition from directorys and filenames. The individual pieces are +* concatinated. Where necessary a path delimiter is added. A pointer to the resulting +* string is returned. This memory should be free'd when no longer needed. +* Windows: to construct an absolute path, a leading backslash has to be included after +* the drive delimiter ':' or at the beginning of the first directory name. +* +* \param str OUT pointer to the complete path +* \param ... IN one or more parts of the path, terminate with NULL +*/ + +void +MakeFullpath(char **str, ...) +{ + va_list valist; + const char *part; + char *separator = FILE_SEP_CHAR; + char lastchar = '\0'; + DynString path; + DynStringMalloc(&path, 0); + va_start(valist, str); + + while ((part = va_arg(valist, const char *))) { + if (part[0] !=separator[0] && lastchar && lastchar != separator[0] && + lastchar != ':') { + DynStringNCatCStr(&path, 1, separator); + } + + DynStringCatCStr(&path, part); + lastchar = part[strlen(part) - 1]; + } + + *str = strdup(DynStringToCStr(&path)); + DynStringFree(&path); + va_end(valist); +} |