[PATCH] XDG base directory support (history and wxt)

"Jun. T" <[email protected]>
Newsgroups gmane.comp.graphics.gnuplot.devel
Message-ID <[email protected]>
I'm not a fan of XDG basedir, but moving only ~/.gnuplot to XDG
directory may be a kind of "half done".

Attached is a possible patch for moving ~/{.gnuplot_history,.gnuplot-wxt}
to XDG directories (it seems qtterminal.conf is already taken care of).
A few points to discuss:

[1] Where to save the history?
There were three possibilities $XDG_{CONFIG,DATA,CACHE}_HOME, and probably
DATA directory is most widely used for history (but I'm not sure).
But to make the situation still more complicated, they added one more
directory $XDG_STATE_HOME recently. It seems this directory is most
suitable for history, but it is new and very few programs are using it yet,
and I'm rather suspicious of whether many programs that are already using
DATA (or CACHE?) directory for history will modify their code.
(and XDG may add more basedirs to make it further complicated...)

In the attached patch I use the STATE directory,
but I have no objection to using other directories.

Since only one file (the history file) is saved in the directory, I think
we can save it directly under XDG ( ~/.local/state/gnuplot_history)
instead of saving it as ~/.local/state/gnuplot/history.

[2] Migration
With the patch, gnuplot will continue to use traditional config or history
files in ~/ if they exist (as it does for the main config file ~/.gnuplot).
Users must move the traditional files to XDG dirs (or remove ~/.gnuplot-wxt
and ~/.gnuplot_history) manually if they want to migrate.

We could make gnuplot to force move traditional ones to XDG directories, but
I rather hesitate to do this.

[3] wxWidgets
They added a function (wxStandardPaths::FileLayout()) for supporting XDG
basedir in wxWidgets 3.1.1.
https://docs.wxwidgets.org/3.1.5/classwx_standard_paths.html
But even if FileLayout is set to FileLayout_XDG, it seems I still need to set
the full pathname of the config flie manually in wxFileConfig constructor to
make it saved in $XDG_CONFIG_HOME/gnuplot/ (i.e., not directly under
$XDG_CONFIG_HOME/). So I didn't use wxStandardPaths but used xdg_get_var() in
xdg.c and manually set the full pathname of the config file.

Good thing of this is it works with older wxWidgets (3.1.x is a kind of
development release).

I'm not familiar with wxWidgets. If there are anyone who knows wxWidgets better
please feel free to improve the patch.

[4] Documents
Are there any documents that need be updated?

_______________________________________________
gnuplot-beta mailing list
[email protected]
Membership management via: https://lists.sourceforge.net/lists/listinfo/gnuplot-beta
xdg.patch (application/octet-stream, 5 KB)
diff --git a/src/gp_hist.h b/src/gp_hist.h
index 1a938a609..dc6b3d616 100644
--- a/src/gp_hist.h
+++ b/src/gp_hist.h
@@ -75,7 +75,7 @@ extern int history_base;
 void using_history(void);
 void clear_history(void);
 void add_history(char *line);
-void read_history(char *);
+int read_history(char *);
 int write_history(char *);
 int where_history(void);
 int history_set_pos(int offset);
diff --git a/src/history.c b/src/history.c
index 109018116..0c9999e5c 100644
--- a/src/history.c
+++ b/src/history.c
@@ -88,10 +88,10 @@ write_history(char *filename)
 
 /* routine to read history entries from a file
  */
-void
+int
 read_history(char *filename)
 {
-    gp_read_history(filename);
+    return gp_read_history(filename);
 }
 
 
diff --git a/src/plot.c b/src/plot.c
index 66fdb6e45..c6ad9be20 100644
--- a/src/plot.c
+++ b/src/plot.c
@@ -495,7 +495,29 @@ main(int argc_orig, char **argv)
 	    expanded_history_filename = gp_strdup(GNUPLOT_HISTORY_FILE);
 	    gp_expand_tilde(&expanded_history_filename);
 #endif
-	    read_history(expanded_history_filename);
+	    if (read_history(expanded_history_filename)) {
+#ifdef USE_XDG_BASEDIR
+		/* ~/.gnuplot_history not exists.
+		 * Use state_dir/gnuplot_history only if state_dir/ exists
+		 * or can be created. Otherwise, do not modify
+		 * expanded_histofy_filename so that write_history() will
+		 * create ~/.gnuplot_history */
+		/* XXX should we use state_dir/gnuplot/history? */
+		char *state_dir = xdg_get_var(kXDGStateHome);
+		struct stat sb;
+		if ((!stat(state_dir, &sb) && S_ISDIR(sb.st_mode))
+				|| !mkdir(state_dir, 00700)) {
+		    const char *file_name = "gnuplot_history";
+		    size_t len = strlen(state_dir) + strlen(file_name) + 1;
+		    free(expanded_history_filename);
+		    expanded_history_filename = gp_alloc(len, "history");
+		    strcpy(expanded_history_filename, state_dir);
+		    PATH_CONCAT(expanded_history_filename, file_name);
+		    read_history(expanded_history_filename);
+		}
+		free(state_dir);
+#endif /* USE_XDG_BASEDIR */
+	    }
 
 	    /*
 	     * It is safe to ignore the return values of 'atexit()' and
diff --git a/src/wxterminal/wxt_gui.cpp b/src/wxterminal/wxt_gui.cpp
index 7e59ee655..45166944e 100644
--- a/src/wxterminal/wxt_gui.cpp
+++ b/src/wxterminal/wxt_gui.cpp
@@ -120,6 +120,7 @@
 #include <wx/printdlg.h>
 
 extern "C" {
+#include "xdg.h"
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
@@ -327,13 +328,36 @@ bool wxtApp::OnInit()
 	/* application and vendor name are used by wxConfig to construct the name
 	 * of the config file/registry key and must be set before the first call
 	 * to Get() */
-	SetVendorName(wxT("gnuplot"));
-	SetAppName(wxT("gnuplot-wxt"));
-	wxConfigBase *pConfig = wxConfigBase::Get();
+	const wxString vendorName(wxT("gnuplot"));
+	const wxString appName(wxT("gnuplot-wxt"));
+	SetVendorName(vendorName);
+	SetAppName(appName);
+
+#ifdef USE_XDG_BASEDIR
+	if (!wxFileConfig::GetLocalFile(appName).Exists()) {
+		// Traditional config file (~/.gnuplot-wxt) does not exist.
+		// We will use $XDG_CONFIG_HOME/gnuplot/gnuplot-wxt.conf only if
+		// $XDG_CONFIG_HOME/gnuplot/ exists or can be created. This
+		// requires at least $XDG_CONFIG_HOME/ should already exist.
+		bool useXDG = true;
+		char *configHome = xdg_get_var(kXDGConfigHome);
+		wxString configDir = wxString(configHome) + "/" + vendorName;
+		free(configHome);
+		if (!wxDirExists(configDir)) {
+			// configDir (~/.config/gnuplot) not exists; try to create it
+			wxLogNull nolog;	// do not show error dialog
+			useXDG = wxMkdir(configDir, 00700);
+		}
+		if (useXDG) {
+			wxString configFile = configDir + "/" + appName + ".conf";
+			wxConfig::Set(new wxFileConfig(vendorName, appName, configFile));
+		}
+	}
+#endif
 	/* this will force writing back of the defaults for all values
 	 * if they're not present in the config - this can give the user an idea
 	 * of all possible settings */
-	pConfig->SetRecordDefaults();
+	wxConfig::Get()->SetRecordDefaults();
 
 	FPRINTF((stderr, "OnInit finished\n"));
 
diff --git a/src/xdg.c b/src/xdg.c
index e6652d329..6e1ad85cf 100644
--- a/src/xdg.c
+++ b/src/xdg.c
@@ -13,6 +13,7 @@
 static const char *xdg_env_vars[] = {
     [kXDGConfigHome] = "XDG_CONFIG_HOME",
     [kXDGDataHome] = "XDG_DATA_HOME",
+    [kXDGStateHome] = "XDG_STATE_HOME",
     [kXDGCacheHome] = "XDG_CACHE_HOME",
     [kXDGRuntimeDir] = "XDG_RUNTIME_DIR",
     [kXDGConfigDirs] = "XDG_CONFIG_DIRS",
@@ -25,6 +26,7 @@ static const char *xdg_env_vars[] = {
 static const char *const xdg_defaults[] = {
     [kXDGConfigHome] = "~/.config",
     [kXDGDataHome] = "~/.local/share",
+    [kXDGStateHome] = "~/.local/state",
     [kXDGCacheHome] = "~/.cache",
     [kXDGRuntimeDir] = "",
     [kXDGConfigDirs] = "/etc/xdg/",
diff --git a/src/xdg.h b/src/xdg.h
index cab5e1415..de43f8fe6 100644
--- a/src/xdg.h
+++ b/src/xdg.h
@@ -10,6 +10,7 @@ typedef enum {
   kXDGNone = -1,
   kXDGConfigHome,  /* XDG_CONFIG_HOME */
   kXDGDataHome,    /* XDG_DATA_HOME */
+  kXDGStateHome,   /* XDG_STATE_HOME */
   kXDGCacheHome,   /* XDG_CACHE_HOME */
   kXDGRuntimeDir,  /* XDG_RUNTIME_DIR */
   kXDGConfigDirs,  /* XDG_CONFIG_DIRS */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.