From be165578ea43b42e3f94321a4772b9ad25d3307f Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 8 Feb 2009 02:52:43 +0000 Subject: [PATCH] - Added GTK+-based clipboard support for Linux. - Fixed: Most Linux filesystems do not fill in d_type for scandir(), so we cannot rely on it to detect directories. - Added NicePath() function to perform shell-style ~ substitution on path names. - Changed the default screenshot directory on Unix to ~/.zdoom/screenshots/. - Added -shotdir command line option to temporarily override the screenshot_dir cvar. SVN r1413 (trunk) --- docs/rh-log.txt | 10 +++++ src/c_cmds.cpp | 51 ++++++++++++---------- src/cmdlib.cpp | 102 ++++++++++++++++++++++++++++++++++++++----- src/cmdlib.h | 1 + src/d_main.cpp | 20 +++------ src/m_misc.cpp | 32 +++++++++----- src/sdl/i_system.cpp | 52 +++++++++++++++++----- 7 files changed, 199 insertions(+), 69 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 12d9f1934e..4bc567f1ae 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,13 @@ +February 7, 2009 +- Added GTK+-based clipboard support for Linux. +- Fixed: Most Linux filesystems do not fill in d_type for scandir(), so we + cannot rely on it to detect directories. +- Added NicePath() function to perform shell-style ~ substitution on path + names. +- Changed the default screenshot directory on Unix to ~/.zdoom/screenshots/. +- Added -shotdir command line option to temporarily override the + screenshot_dir cvar. + February 7, 2009 (Changes by Graf Zahl) - Fixed: G_SerializeLevel must use the TEXMAN_ReturnFirst flag for getting the sky textures so that it still works when the first texture in a TEXTURE1 diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index a65541deff..b557b3ebbb 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -505,7 +505,7 @@ CCMD (error_fatal) CCMD (dir) { - FString dir; + FString dir, path; char curdir[256]; const char *match; findstate_t c_file; @@ -517,38 +517,45 @@ CCMD (dir) return; } - if (argv.argc() == 1 || chdir (argv[1])) + if (argv.argc() > 1) { - match = argv.argc() == 1 ? "./*" : argv[1]; - - dir = ExtractFilePath (match); - if (dir[0] != '\0') + path = NicePath(argv[1]); + if (chdir(path)) { - match += dir.Len(); + match = path; + dir = ExtractFilePath(path); + if (dir[0] != '\0') + { + match += dir.Len(); + } + else + { + dir = "./"; + } + if (match[0] == '\0') + { + match = "*"; + } + if (chdir (dir)) + { + Printf ("%s not found\n", dir.GetChars()); + return; + } } else - { - dir = "./"; - } - if (match[0] == '\0') { match = "*"; - } - - if (chdir (dir)) - { - Printf ("%s not found\n", dir.GetChars()); - return; + dir = path; } } else { match = "*"; - dir = argv[1]; - if (dir[dir.Len()-1] != '/') - { - dir += '/'; - } + dir = curdir; + } + if (dir[dir.Len()-1] != '/') + { + dir += '/'; } if ( (file = I_FindFirst (match, &c_file)) == ((void *)(-1))) diff --git a/src/cmdlib.cpp b/src/cmdlib.cpp index d255723eed..717ee4aba6 100644 --- a/src/cmdlib.cpp +++ b/src/cmdlib.cpp @@ -2,6 +2,10 @@ #ifdef _WIN32 #include +#else +#include +#include +#include #endif #include "doomtype.h" #include "cmdlib.h" @@ -345,25 +349,20 @@ const char *myasctime () /* CreatePath: creates a directory including all levels necessary */ /* */ /************************************************************************/ +#ifdef _WIN32 void DoCreatePath(const char * fn) { -#ifdef _WIN32 -char drive[_MAX_DRIVE]; -#endif -char path[PATH_MAX]; -char p[PATH_MAX]; -int i; + char drive[_MAX_DRIVE]; + char path[PATH_MAX]; + char p[PATH_MAX]; + int i; -#ifdef _WIN32 _splitpath(fn,drive,path,NULL,NULL); _makepath(p,drive,path,NULL,NULL); i=(int)strlen(p); if (p[i-1]=='/' || p[i-1]=='\\') p[i-1]=0; if (*path) DoCreatePath(p); _mkdir(p); -#else - // FIXME: write me -#endif } void CreatePath(const char * fn) @@ -378,6 +377,36 @@ void CreatePath(const char * fn) } else DoCreatePath(fn); } +#else +void CreatePath(const char *fn) +{ + char *copy, *p; + + if (fn[0] == '/' && fn[1] == '\0') + { + return; + } + p = copy = strdup(fn); + do + { + p = strchr(p + 1, '/'); + if (p != NULL) + { + *p = '\0'; + } + printf("%s\n", copy); + if (mkdir(copy, 0755) == -1) + { // failed + return; + } + if (p != NULL) + { + *p = '/'; + } + } while (p); + free(copy); +} +#endif // [RH] Replaces the escape sequences in a string with actual escaped characters. // This operation is done in-place. The result is the new length of the string. @@ -626,3 +655,56 @@ FString ExpandEnvVars(const char *searchpathstring) return out; } +//========================================================================== +// +// NicePath +// +// Handles paths with leading ~ characters on Unix as well as environment +// variable substitution. On Windows, this is identical to ExpandEnvVars. +// +//========================================================================== + +FString NicePath(const char *path) +{ +#ifdef _WIN32 + return ExpandEnvVars(path); +#else + if (path == NULL || *path == '\0') + { + return FString(""); + } + if (*path != '~') + { + return ExpandEnvVars(path); + } + + passwd *pwstruct; + const char *slash; + + if (path[1] == '/' || path[1] == '\0') + { // Get my home directory + pwstruct = getpwuid(getuid()); + slash = path + 1; + } + else + { // Get somebody else's home directory + slash = strchr(path, '/'); + if (slash == NULL) + { + slash = path + strlen(path); + } + FString who(path, slash - path); + pwstruct = getpwnam(who); + } + if (pwstruct == NULL) + { + return ExpandEnvVars(path); + } + FString where(pwstruct->pw_dir); + if (*slash != '\0') + { + where += ExpandEnvVars(slash); + } + return where; +#endif +} diff --git a/src/cmdlib.h b/src/cmdlib.h index 2447285207..538329e7aa 100644 --- a/src/cmdlib.h +++ b/src/cmdlib.h @@ -57,5 +57,6 @@ FString strbin1 (const char *start); void CreatePath(const char * fn); FString ExpandEnvVars(const char *searchpathstring); +FString NicePath(const char *path); #endif diff --git a/src/d_main.cpp b/src/d_main.cpp index 8c87e1c95f..2fe6785747 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2263,20 +2263,12 @@ void D_DoomMain (void) #endif file += "skins"; D_AddDirectory (file); - - const char *home = getenv ("HOME"); - if (home) - { - file = home; - if (home[strlen(home) - 1] != '/') - { - file += '/'; - } - file += ".zdoom/skins"; - D_AddDirectory (file); - } - - + +#ifdef unix + file = NicePath("~/" GAME_DIR "/skins"); + D_AddDirectory (file); +#endif + // Add common (global) wads D_AddConfigWads ("Global.Autoload"); diff --git a/src/m_misc.cpp b/src/m_misc.cpp index a7ef11e30a..2011c7d70a 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -301,19 +301,17 @@ static long ParseCommandLine (const char *args, int *argc, char **argv) #ifdef unix FString GetUserFile (const char *file, bool nodir) { - char *home = getenv ("HOME"); - if (home == NULL || *home == '\0') - I_FatalError ("Please set your HOME environment variable"); + FString path; - FString path = home; - if (path[path.Len()-1] != '/') - path += nodir ? "/" : "/"GAME_DIR; - else if (!nodir) - path += GAME_DIR; - - if (!nodir) + if (nodir) + { + path = NicePath("~/"); + } + else { struct stat info; + + path = NicePath("~/" GAME_DIR "/"); if (stat (path, &info) == -1) { if (mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR) == -1) @@ -330,7 +328,6 @@ FString GetUserFile (const char *file, bool nodir) } } } - path += '/'; path += file; return path; } @@ -649,10 +646,20 @@ void M_ScreenShot (const char *filename) else #endif { - int dirlen = (int)strlen (screenshot_dir); + int dirlen; + autoname = Args->CheckValue("-shotdir"); + if (autoname == NULL) + { + autoname = screenshot_dir; + } + dirlen = strlen(autoname); if (dirlen == 0) { +#ifdef unix + autoname = "~/.zdoom/screenshots/"; +#else autoname = progdir; +#endif } else if (dirlen > 0) { @@ -663,6 +670,7 @@ void M_ScreenShot (const char *filename) } } } + autoname = NicePath(autoname); if (!FindFreeName (autoname, writepcx ? "pcx" : "png")) { Printf ("M_ScreenShot: Delete some screenshots\n"); diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 680890b99e..cf2c2d4036 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #ifndef NO_GTK #include #include @@ -509,11 +510,7 @@ bool I_WriteIniFailed () static const char *pattern; -#ifdef OSF1 -static int matchfile (struct dirent *ent) -#else static int matchfile (const struct dirent *ent) -#endif { return fnmatch (pattern, ent->d_name, FNM_NOESCAPE) == 0; } @@ -568,21 +565,54 @@ int I_FindClose (void *handle) int I_FindAttr (findstate_t *fileinfo) { - struct dirent *ent = fileinfo->namelist[fileinfo->current]; + dirent *ent = fileinfo->namelist[fileinfo->current]; + struct stat buf; -#ifdef OSF1 - return 0; // I don't know how to detect dirs under OSF/1 -#else - return (ent->d_type == DT_DIR) ? FA_DIREC : 0; -#endif + if (stat(ent->d_name, &buf) == 0) + { + return S_ISDIR(buf.st_mode) ? FA_DIREC : 0; + } + return 0; } -// No clipboard support for Linux +// Clipboard support requires GTK+ +// TODO: GTK+ uses UTF-8. We don't, so some conversions would be appropriate. void I_PutInClipboard (const char *str) { +#ifndef NO_GTK + if (GtkAvailable) + { + GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); + if (clipboard != NULL) + { + gtk_clipboard_set_text(clipboard, str, -1); + } + clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); + if (clipboard != NULL) + { + gtk_clipboard_set_text(clipboard, str, -1); + } + } +#endif } char *I_GetFromClipboard () { +#ifndef NO_GTK + if (GtkAvailable) + { + GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); + if (clipboard != NULL) + { + gchar *text = gtk_clipboard_wait_for_text(clipboard); + if (text != NULL) + { + char *copy = copystring(text); + g_free(text); + return copy; + } + } + } +#endif return NULL; }