Dear all,

I hope this is the final patch as the subject suggests. Attached is my
previous Again-Updated PATCH ;-) plus

1. change mode from string to enum
2. add Enrico's cygwin support
3. remove checkViewerEntries completely under windows (configure.py).

It has been test by Enrico and me. With this patch, viewers under
windows are handled automatically. Appropriate menu items under view
will be shown for formats that are "openable" under windows.

I would suggest that we remove the format panel in the preference
dialog under windows.

OK to apply?
Bo
Index: src/graph.C
===================================================================
--- src/graph.C	(revision 13766)
+++ src/graph.C	(working copy)
@@ -78,7 +78,7 @@
 		Q_.pop();
 		Format const & format = formats.get(i);
 		if (!only_viewable || !format.viewer().empty() ||
-		    format.isChildFormat())
+		    format.isAutoViewable() || format.isChildFormat())
 			result.push_back(i);
 
 		vector<int>::const_iterator cit =
Index: src/format.C
===================================================================
--- src/format.C	(revision 13766)
+++ src/format.C	(working copy)
@@ -35,6 +35,10 @@
 using lyx::support::quoteName;
 using lyx::support::subst;
 using lyx::support::Systemcall;
+using lyx::support::VIEW;
+using lyx::support::EDIT;
+using lyx::support::canAutoOpenFile;
+using lyx::support::autoOpenFile;
 
 using std::string;
 using std::distance;
@@ -87,7 +91,9 @@
 Format::Format(string const & n, string const & e, string const & p,
 	       string const & s, string const & v, string const & ed)
 	: name_(n), extension_(e), prettyname_(p), shortcut_(s), viewer_(v), editor_(ed)
-{}
+{
+	autoViewable_ = canAutoOpenFile(e, VIEW);
+}
 
 
 bool Format::dummy() const
@@ -224,12 +230,14 @@
 	    format->isChildFormat())
 		format = getFormat(format->parentFormat());
 	if (!format || format->viewer().empty()) {
-// I believe this is the wrong place to show alerts, it should be done by
-// the caller (this should be "utility" code)
-		Alert::error(_("Cannot view file"),
-			bformat(_("No information for viewing %1$s"),
-				prettyName(format_name)));
-		return false;
+		if (!autoOpenFile(filename, VIEW)) {
+			// I believe this is the wrong place to show alerts, it should be done by
+			// the caller (this should be "utility" code)
+			Alert::error(_("Cannot view file"),
+			     _("No default viewer for viewing ") + filename);
+			return false;
+		}
+		return true;
 	}
 
 	string command = libScriptSearch(format->viewer());
@@ -280,12 +288,14 @@
 	    format->isChildFormat())
 		format = getFormat(format->parentFormat());
 	if (!format || format->editor().empty()) {
-// I believe this is the wrong place to show alerts, it should be done by
-// the caller (this should be "utility" code)
-		Alert::error(_("Cannot edit file"),
-			bformat(_("No information for editing %1$s"),
-				prettyName(format_name)));
-		return false;
+		if (!autoOpenFile(filename, EDIT)) {
+			// I believe this is the wrong place to show alerts, it should be done by
+			// the caller (this should be "utility" code)
+			Alert::error(_("Cannot edit file"),
+				_("No default editor for editing " + filename));
+			return false;
+		}
+		return true;
 	}
 
 	string command = format->editor();
Index: src/support/os.h
===================================================================
--- src/support/os.h	(revision 13766)
+++ src/support/os.h	(working copy)
@@ -80,6 +80,23 @@
  */
 void cygwin_path_fix(bool use_cygwin_paths);
 
+#if defined(__CYGWIN__) || defined(__CYGWIN32__)
+enum PathStyle {
+	posix,
+	windows
+};
+
+/// Converts a path to a target style.
+std::string convert_path(std::string const & p, PathStyle const & target);
+
+/// Converts a path list to a target style.
+std::string convert_path_list(std::string const & p, PathStyle const & target);
+
+/// Copy cygwin environment variables to the Windows environment
+/// if they're not already there.
+void setup_windows_environment(void);
+#endif
+
 } // namespace os
 } // namespace support
 } // namespace lyx
Index: src/support/filetools.C
===================================================================
--- src/support/filetools.C	(revision 13766)
+++ src/support/filetools.C	(working copy)
@@ -51,6 +51,12 @@
 #include <fstream>
 #include <sstream>
 
+#if defined(_WIN32) || defined(__CYGWIN__)
+# include <windef.h>
+# include <shellapi.h>	
+# include <shlwapi.h>
+#endif
+
 #ifndef CXX_GLOBAL_CSTD
 using std::fgetc;
 using std::isalnum;
@@ -1225,5 +1231,59 @@
 	return cmp;
 }
 
+
+bool canAutoOpenFile(string const & ext, auto_open_mode const mode)
+{
+#if defined(_WIN32) || defined(__CYGWIN__)
+	DWORD bufSize = MAX_PATH + 100;
+	TCHAR buf[MAX_PATH + 100];
+	// reference: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc
+	//                 /platform/shell/reference/shlwapi/registry/assocquerystring.asp
+	HRESULT res;
+	if (mode == VIEW)
+		res = AssocQueryString(0, ASSOCSTR_EXECUTABLE,
+			ext.c_str(), "open", buf, &bufSize);
+	else
+		res = AssocQueryString(0, ASSOCSTR_EXECUTABLE,
+			ext.c_str(), "edit", buf, &bufSize);
+	// if an application is found, test if it exists
+	return res == S_OK && fs::exists(buf);
+#else
+	// currently, no default viewer is tried for non-windows system
+	// support for KDE/Gnome/Macintosh may be added later
+	return false;
+#endif
+}
+
+
+bool autoOpenFile(string const & filename, auto_open_mode const mode)
+{
+#if defined(_WIN32) || defined(__CYGWIN__)
+	lyxerr[Debug::FILES] << "Auto open file: " << filename << std::endl;
+
+	// reference: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc
+	//                 /platform/shell/reference/functions/shellexecute.asp
+# ifdef __CYGWIN__
+	string const converted_path =
+		os::convert_path(filename, os::PathStyle(os::windows));
+	char const * const win_path = converted_path.c_str();
+	// Need to sync the Windows environment
+	os::setup_windows_environment();
+# else
+	char const * const win_path = filename.c_str();
+# endif
+	if (mode == VIEW) 
+		return reinterpret_cast<int>(ShellExecute(NULL, "open", 
+			win_path, NULL, NULL, 1)) > 32;
+	else
+		return reinterpret_cast<int>(ShellExecute(NULL, "edit", 
+			win_path, NULL, NULL, 1)) > 32;
+#else
+	// currently, no default viewer is tried for non-windows system
+	// support for KDE/Gnome/Macintosh may be added later
+	return false;
+#endif
+}
+
 } //namespace support
 } // namespace lyx
Index: src/support/os_cygwin.C
===================================================================
--- src/support/os_cygwin.C	(revision 13766)
+++ src/support/os_cygwin.C	(working copy)
@@ -86,13 +86,9 @@
 		(!contains(p, '\\') && (p.length() <= 1 || p[1] == ':'));
 }
 
+} // namespace anon
 
-enum PathStyle {
-    posix,
-    windows
-};
 
-
 string convert_path(string const & p, PathStyle const & target)
 {
 	char path_buf[PATH_MAX];
@@ -139,9 +135,7 @@
 	return subst(p, '\\', '/');
 }
 
-} // namespace anon
 
-
 string external_path(string const & p)
 {
 	return convert_path(p, cygwin_path_fix_ ? PathStyle(windows)
@@ -199,6 +193,49 @@
 }
 
 
+// Copy cygwin environment variables to the Windows environment
+// if they're not already there.
+void setup_windows_environment(void)
+{
+	char **envp = environ;
+	char curval[2];
+	string var;
+	string val;
+	bool temp_seen = false;
+
+	while (envp && *envp) {
+		val = split(*envp++, var, '=');
+
+		if (var == "TEMP")
+			temp_seen = true;
+		
+		if (GetEnvironmentVariable(var.c_str(), curval, 2) == 0
+				&& GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
+			/* Convert to Windows style where necessary */
+			if (var == "PATH" || var == "LD_LIBRARY_PATH") {
+				string const winpathlist =
+				    convert_path_list(val, PathStyle(windows));
+				if (!winpathlist.empty()) {
+					SetEnvironmentVariable(var.c_str(),
+						winpathlist.c_str());
+				}
+			} else if (var == "HOME" || var == "TMPDIR" ||
+					var == "TMP" || var == "TEMP") {
+				string const winpath =
+					convert_path(val, PathStyle(windows));
+				SetEnvironmentVariable(var.c_str(), winpath.c_str());
+			} else {
+				SetEnvironmentVariable(var.c_str(), val.c_str());
+			}
+		}
+	}
+	if (!temp_seen) {
+		string const winpath = convert_path("/tmp", PathStyle(windows));
+		SetEnvironmentVariable("TEMP", winpath.c_str());
+	}
+}
+
+
 // returns a string suitable to be passed to popen when
 // reading a pipe
 char const * popen_read_mode()
Index: src/support/filetools.h
===================================================================
--- src/support/filetools.h	(revision 13766)
+++ src/support/filetools.h	(working copy)
@@ -266,6 +266,25 @@
 
 cmd_ret const runCommand(std::string const & cmd);
 
+enum auto_open_mode {
+	VIEW,
+	EDIT
+};
+
+/** Check whether or not a file can be viewed by a default viewer 
+ *  \param extension (without leading .)
+ *  \mode can be opened in VIEW or EDIT mode
+ *  \returns whether or not the format can be viewed
+ */
+bool canAutoOpenFile(std::string const & ext, auto_open_mode const mode=VIEW);
+
+/** view a file, with given command and parameter.
+ *  \param filename
+ *  \param mode open in VIEW or EDIT mode
+ *  \returns whether or not the file is viewed (or edited) successfully.
+ */
+bool autoOpenFile(std::string const & filename, auto_open_mode const mode=VIEW);
+
 } // namespace support
 } // namespace lyx
 
Index: src/support/Makefile.am
===================================================================
--- src/support/Makefile.am	(revision 13766)
+++ src/support/Makefile.am	(working copy)
@@ -9,6 +9,8 @@
 
 noinst_LTLIBRARIES = libsupport.la
 
+libsupport_la_LIBADD = $(LIBSHLWAPI)
+
 BUILT_SOURCES = $(PCH_FILE) package.C
 
 AM_CPPFLAGS += $(PCH_FLAGS) -I$(srcdir)/.. $(BOOST_INCLUDES)
Index: src/format.h
===================================================================
--- src/format.h	(revision 13766)
+++ src/format.h	(working copy)
@@ -49,6 +49,10 @@
 		return viewer_;
 	}
 	///
+	bool const isAutoViewable() const {
+		return autoViewable_;
+	}
+	///
 	void setViewer(std::string const & v) {
 		viewer_ = v;
 	}
@@ -67,6 +71,8 @@
 	///
 	std::string viewer_;
 	///
+	bool autoViewable_;
+	///
 	std::string editor_;
 };
 
Index: lib/configure.py
===================================================================
--- lib/configure.py	(revision 13766)
+++ lib/configure.py	(working copy)
@@ -671,7 +671,9 @@
 ''')
   # check latex
   LATEX = checkLatex()
-  checkFormatEntries()
+  # viewers under windows are handled automatically
+  if os.name != 'nt' and sys.platform != 'cygwin':
+    checkFormatEntries()
   checkConverterEntries()
   (chk_linuxdoc, bool_linuxdoc, linuxdoc_cmd) = checkLinuxDoc()
   (chk_docbook, bool_docbook, docbook_cmd) = checkDocBook()
Index: config/cygwin.m4
===================================================================
--- config/cygwin.m4	(revision 13766)
+++ config/cygwin.m4	(working copy)
@@ -22,4 +22,10 @@
     done
     ;;
   esac
+
+  case $host_os in
+  cygwin* | mingw* )
+    AC_SUBST(LIBSHLWAPI, [-lshlwapi])
+    ;;
+  esac
 ])

Reply via email to