On Sun, Apr 30, 2006 at 10:20:27PM -0500, Bo Peng wrote:

> >
> > I am returning your patch with a small enhancement to the cygwin part.
> 
> Not  a problem. I will apply your modifications as well.

I have changed again the cygwin part. After thinking about it I moved
the code syncing the cygwin and windows environment to os::init,
where IMO it belongs.

Please find attached the updated patch.

-- 
Enrico
Index: src/graph.C
===================================================================
--- src/graph.C (revision 13787)
+++ src/graph.C (working copy)
@@ -77,8 +77,9 @@ Graph::getReachable(int from, bool only_
                int const i = Q_.front();
                Q_.pop();
                Format const & format = formats.get(i);
-               if (!only_viewable || !format.viewer().empty() ||
-                   format.isChildFormat())
+               if (!only_viewable || format.isChildFormat() ||
+                 (!format.viewer().empty() && 
+                         (format.viewer() != "auto" || 
format.isAutoViewable())))
                        result.push_back(i);
 
                vector<int>::const_iterator cit =
Index: src/format.C
===================================================================
--- src/format.C        (revision 13787)
+++ src/format.C        (working copy)
@@ -24,6 +24,8 @@
 #include "support/path.h"
 #include "support/systemcall.h"
 
+#include <boost/filesystem/operations.hpp>
+
 using lyx::support::bformat;
 using lyx::support::compare_ascii_no_case;
 using lyx::support::contains;
@@ -35,10 +37,16 @@ using lyx::support::Path;
 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;
 
+namespace fs = boost::filesystem;
+
 extern LyXServerSocket * lyxsocket;
 
 namespace {
@@ -87,7 +95,9 @@ bool operator<(Format const & a, Format 
 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
@@ -216,8 +226,12 @@ void Formats::setViewer(string const & n
 bool Formats::view(Buffer const & buffer, string const & filename,
                   string const & format_name) const
 {
-       if (filename.empty())
+       if (filename.empty() || !fs::exists(filename)) {
+               Alert::error(_("Cannot view file"),
+                       bformat(_("File does not exist: %1$s"),
+                               filename));
                return false;
+       }
 
        Format const * format = getFormat(format_name);
        if (format && format->viewer().empty() &&
@@ -231,6 +245,17 @@ bool Formats::view(Buffer const & buffer
                                prettyName(format_name)));
                return false;
        }
+       // viewer is 'auto'
+       if (format->viewer() == "auto") {
+               if (autoOpenFile(filename, VIEW))
+                       return true;
+               else {
+                       Alert::error(_("Cannot view file"),
+                               bformat(_("Auto-view file %1$s failed"),
+                                       filename));
+                       return false;
+               }
+       }
 
        string command = libScriptSearch(format->viewer());
 
@@ -272,8 +297,12 @@ bool Formats::view(Buffer const & buffer
 bool Formats::edit(Buffer const & buffer, string const & filename,
                         string const & format_name) const
 {
-       if (filename.empty())
+       if (filename.empty() || !fs::exists(filename)) {
+               Alert::error(_("Cannot edit file"),
+                       bformat(_("File does not exist: %1$s"),
+                               filename));
                return false;
+       }
 
        Format const * format = getFormat(format_name);
        if (format && format->editor().empty() &&
@@ -286,6 +315,17 @@ bool Formats::edit(Buffer const & buffer
                        bformat(_("No information for editing %1$s"),
                                prettyName(format_name)));
                return false;
+       }
+       // editor is 'auto'
+       if (format->editor() == "auto") {
+               if (autoOpenFile(filename, EDIT))
+                       return true;
+               else {
+                       Alert::error(_("Cannot edit file"),
+                               bformat(_("Auto-edit file %1$s failed"),
+                                       filename));
+                       return false;
+               }
        }
 
        string command = format->editor();
Index: src/support/os.h
===================================================================
--- src/support/os.h    (revision 13787)
+++ src/support/os.h    (working copy)
@@ -80,6 +80,19 @@ char path_separator();
  */
 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);
+#endif
+
 } // namespace os
 } // namespace support
 } // namespace lyx
Index: src/support/filetools.C
===================================================================
--- src/support/filetools.C     (revision 13787)
+++ 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;
@@ -1223,6 +1229,63 @@ int compare_timestamps(string const & fi
        }
 
        return cmp;
+}
+
+
+bool canAutoOpenFile(string const & ext, auto_open_mode const mode)
+{
+#if defined(_WIN32) || defined(__CYGWIN__)
+       if (ext == "")
+               return false;
+       
+       string full_ext = ext;
+       // if the extension is passed without leading dot
+       if (full_ext[0] != '.')
+               full_ext = "." + ext;
+
+       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
+       if (mode == VIEW)
+               return S_OK == AssocQueryString(0, ASSOCSTR_EXECUTABLE,
+                       full_ext.c_str(), "open", buf, &bufSize);
+       else
+               return S_OK == AssocQueryString(0, ASSOCSTR_EXECUTABLE,
+                       full_ext.c_str(), "edit", buf, &bufSize);
+#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();
+# 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
Index: src/support/os_cygwin.C
===================================================================
--- src/support/os_cygwin.C     (revision 13787)
+++ src/support/os_cygwin.C     (working copy)
@@ -35,7 +35,47 @@ namespace support {
 namespace os {
 
 void os::init(int, char *[])
-{}
+{
+       // Copy cygwin environment variables to the Windows environment
+       // if they're not already there.
+
+       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());
+       }
+}
 
 
 string current_root()
@@ -86,11 +126,7 @@ bool is_windows_path(string const & p)
                (!contains(p, '\\') && (p.length() <= 1 || p[1] == ':'));
 }
 
-
-enum PathStyle {
-    posix,
-    windows
-};
+} // namespace anon
 
 
 string convert_path(string const & p, PathStyle const & target)
@@ -138,8 +174,6 @@ string convert_path_list(string const & 
 
        return subst(p, '\\', '/');
 }
-
-} // namespace anon
 
 
 string external_path(string const & p)
Index: src/support/filetools.h
===================================================================
--- src/support/filetools.h     (revision 13787)
+++ src/support/filetools.h     (working copy)
@@ -266,6 +266,25 @@ typedef std::pair<int, std::string> cmd_
 
 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 13787)
+++ src/support/Makefile.am     (working copy)
@@ -9,6 +9,8 @@ EXTRA_DIST = package.C.in pch.h \
 
 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 13787)
+++ src/format.h        (working copy)
@@ -49,6 +49,10 @@ public:
                return viewer_;
        }
        ///
+       bool const isAutoViewable() const {
+               return autoViewable_;
+       }
+       ///
        void setViewer(std::string const & v) {
                viewer_ = v;
        }
@@ -66,6 +70,8 @@ private:
        std::string shortcut_;
        ///
        std::string viewer_;
+       ///
+       bool autoViewable_;
        ///
        std::string editor_;
 };
Index: lib/configure.py
===================================================================
--- lib/configure.py    (revision 13787)
+++ lib/configure.py    (working copy)
@@ -108,7 +108,7 @@ def checkCygwinPath(srcdir):
 
 
 ## Searching some useful programs
-def checkProg(description, progs, rc_entry = [], path = [] ):
+def checkProg(description, progs, rc_entry = [], path = [], searchProg = True):
   '''
     This function will search a program in $PATH plus given path
     If found, return directory and program name (not the options).
@@ -119,21 +119,32 @@ def checkProg(description, progs, rc_ent
       for searching but the whole string is used to replace
       %% for a rc_entry. So, feel free to add '$$i' etc for programs.
 
-    path: additional path
+    path: additional pathes
 
-    rc_entry: entry to outfile, can be emtpy, one pattern (%% for chosen
-       prog or 'none'), or one for each prog and 'none'.
-
-    NOTE: if you do not want 'none' entry to be added to the RC file,
-      specify an entry for each prog and use '' for 'none' entry.
-
-    FIXME: under windows, we should check registry instead of $PATH
+    rc_entry: entry to outfile, can be
+      1. emtpy: no rc entry will be added
+      2. one pattern: %% will be replaced by the first found program,
+         or 'none' is no program is found.
+      3. several patterns for each prog and 'none'. This is used 
+         when different programs have different usages. If you do not 
+         want 'none' entry to be added to the RC file, you can specify 
+         an entry for each prog and use '' for the 'none' entry.
+
+    searchProg: whether or not search given programs. If searchProg == False,
+      1. rc_entry[0] will be used, with %% replaced by 'auto'
+      2. ['', 'auto'] will be returned.
+      This is currently used under windows.
   '''
   # one rc entry for each progs plus none entry
   if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
     print "rc entry should have one item or item for each prog and none."
     sys.exit(2)
   print 'checking for ' + description + '...'
+  if not searchProg:
+    print '+checking for "auto"...  yes'
+    if len(rc_entry) > 0:
+      addToRC(rc_entry[0].replace('%%', 'auto'))
+    return ['', 'auto']
   ## print '(' + ','.join(progs) + ')',
   for idx in range(len(progs)):
     # ac_prog may have options, ac_word is the command name
@@ -186,22 +197,26 @@ def checkLatex():
   return ''
 
 
-def checkFormatEntries():  
+def checkFormatEntries(check = True):  
   ''' Check all formats (\Format entries) '''
   checkProg('a Tgif viewer and editor', ['tgif'],
-    rc_entry = [ r'\Format tgif       obj     Tgif                   "" "%%"   
"%%"'])
+    rc_entry = [ r'\Format tgif       obj     Tgif                   "" "%%"   
"%%"'],
+    searchProg = check)
   #
   checkProg('a FIG viewer and editor', ['xfig'],
-    rc_entry = [ r'\Format fig        fig     FIG                    "" "%%"   
"%%"'] )
+    rc_entry = [ r'\Format fig        fig     FIG                    "" "%%"   
"%%"'],
+    searchProg = check)
   #
   checkProg('a Grace viewer and editor', ['xmgrace'],
-    rc_entry = [ r'\Format agr        agr     Grace                  "" "%%"   
"%%"'] )
+    rc_entry = [ r'\Format agr        agr     Grace                  "" "%%"   
"%%"'],
+    searchProg = check)
   #
   checkProg('a FEN viewer and editor', ['xboard -lpf $$i -mode EditPosition'],
-    rc_entry = [ r'\Format fen        fen     FEN                    "" "%%"   
"%%"' ])
+    rc_entry = [ r'\Format fen        fen     FEN                    "" "%%"   
"%%"'],
+    searchProg = check)
   #
-  path, iv = checkProg('a raster image viewer', ['xv', 'kview', 'gimp'])
-  path, ie = checkProg('a raster image editor', ['gimp'])
+  path, iv = checkProg('a raster image viewer', ['xv', 'kview', 'gimp'], 
searchProg = check)
+  path, ie = checkProg('a raster image editor', ['gimp'], searchProg = check)
   addToRC(r'''\Format bmp        bmp     BMP                    "" "%s"        
"%s"
 \Format gif        gif     GIF                    "" "%s"      "%s"
 \Format jpg        jpg     JPEG                   "" "%s"      "%s"
@@ -227,25 +242,30 @@ def checkFormatEntries():  
 \Format linuxdoc   sgml    LinuxDoc               x  ""        "%%"
 \Format pdflatex   tex    "LaTeX (pdflatex)"      "" ""        "%%"
 \Format text       txt    "Plain text"            a  ""        "%%"
-\Format textparagraph txt "Plain text (paragraphs)"    "" ""   "%%"''' ])
+\Format textparagraph txt "Plain text (paragraphs)"    "" ""   "%%"''' ],
+    searchProg = check)
   #
   #checkProg('a Postscript interpreter', ['gs'],
   #  rc_entry = [ r'\ps_command "%%"' ])
   checkProg('a Postscript previewer', ['gsview32', 'gv', 'ghostview -swap', 
'kghostview'],
     rc_entry = [ r'''\Format eps        eps     EPS                    "" "%%" 
""
-\Format ps         ps      Postscript             t  "%%"      ""''' ])
+\Format ps         ps      Postscript             t  "%%"      ""''' ],
+    searchProg = check)
   #
   checkProg('a PDF previewer', ['acrobat', 'acrord32', 'gsview32', \
     'acroread', 'gv', 'ghostview', 'xpdf', 'kpdf', 'kghostview'],
     rc_entry = [ r'''\Format pdf        pdf    "PDF (ps2pdf)"          P  "%%" 
""
 \Format pdf2       pdf    "PDF (pdflatex)"        F  "%%"      ""
-\Format pdf3       pdf    "PDF (dvipdfm)"         m  "%%"      ""''' ])
+\Format pdf3       pdf    "PDF (dvipdfm)"         m  "%%"      ""'''],
+    searchProg = check)
   #
   checkProg('a DVI previewer', ['xdvi', 'windvi', 'yap', 'kdvi'],
-    rc_entry = [ r'\Format dvi        dvi     DVI                    D  "%%"   
""' ])
+    rc_entry = [ r'\Format dvi        dvi     DVI                    D  "%%"   
""' ],
+    searchProg = check)
   #
   checkProg('a HTML previewer', ['mozilla file://$$p$$i', 'netscape'],
-    rc_entry = [ r'\Format html       html    HTML                   H  "%%"   
""' ])
+    rc_entry = [ r'\Format html       html    HTML                   H  "%%"   
""' ],
+    searchProg = check)
   #
   # entried that do not need checkProg
   addToRC(r'''\Format date       ""     "date command"          "" ""  ""
@@ -273,7 +293,7 @@ def checkConverterEntries():
       Use PATH to avoid any problems with paths-with-spaces.
   '''
   path_orig = os.environ["PATH"]
-  os.environ["PATH"] = os.path.join('..','src','tex2lyx') + \
+  os.environ["PATH"] = os.path.join('..', 'src', 'tex2lyx') + \
     os.pathsep + path_orig
 
   checkProg('a LaTeX -> LyX converter', ['tex2lyx -f $$i $$o', \
@@ -671,7 +691,8 @@ Options:
 ''')
   # check latex
   LATEX = checkLatex()
-  checkFormatEntries()
+  # viewers under windows are handled automatically
+  checkFormatEntries(os.name != 'nt' and sys.platform != 'cygwin')
   checkConverterEntries()
   (chk_linuxdoc, bool_linuxdoc, linuxdoc_cmd) = checkLinuxDoc()
   (chk_docbook, bool_docbook, docbook_cmd) = checkDocBook()
Index: config/cygwin.m4
===================================================================
--- config/cygwin.m4    (revision 13787)
+++ config/cygwin.m4    (working copy)
@@ -22,4 +22,10 @@ AC_DEFUN([CHECK_WITH_CYGWIN],
     done
     ;;
   esac
+
+  case $host_os in
+  cygwin* | mingw* )
+    AC_SUBST(LIBSHLWAPI, [-lshlwapi])
+    ;;
+  esac
 ])

Reply via email to