Logo Search packages:      
Sourcecode: rapidsvn version File versions  Download package

verblist.cpp

/*
 * ====================================================================
 * Copyright (c) 2002-2009 The RapidSvn Group.  All rights reserved.
 *
 * 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 3 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 (in the file GPL.txt.  
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://rapidsvn.tigris.org/.
 * ====================================================================
 */
/*
 * VerbList - Windows implementation
 */

// stl
#include "svncpp/vector_wrapper.hpp"

// wx
#include "wx/wx.h"
#include "wx/filename.h"

#ifdef __WXMSW__
#include "wx/msw/registry.h"
#include <windows.h>
#endif

// app
#include "verblist.hpp"


#ifndef __WXMSW__
/**********************************************************************
 * NON WINDOWS IMPLEMENTATION OF VerbList
 *********************************************************************/

00049 VerbList::VerbList()
{
}


00054 VerbList::~VerbList()
{
}


void
00060 VerbList::InitFromDocument(const wxString & documentPath, bool isAFolder)
{}


size_t
00065 VerbList::GetCount() const
{
  return 0;
}


const wxString &
00072 VerbList::GetName(size_t index) const
{
  static const wxString empty(wxT(""));
  return empty;
}


void
00080 VerbList::Launch(size_t index) const
{
}



#else
/**********************************************************************
 * WINDOWS IMPLEMENTATION OF VerbList
 *********************************************************************/


/**
 * This class stores one verb
 */
struct Verb
{
  typedef std::vector<Verb> LIST;
  bool m_uses_dde;
  wxString m_name;
  wxString m_command;
  wxString m_dde_command;
  wxString m_dde_app;
  wxString m_dde_topic;

  Verb();

  virtual ~ Verb() {};

  /**
   * Read verb information from the given verb of the given key in the
   * registry
   *
   * If the registry entry is bad, this may result in a verb with only a
   * name (no commands), but that'll still be usable in some contexts.
   *
   * @retval false if error has happened
   */
  bool
  ReadFromRegistry(const wxRegKey & base, const wxString & verb_name);


  /**
   * Lauch the verb on the given document
   */
  void Launch(const wxString & document_path) const;
};


/**
 * Private data members of VerbList
 */
struct VerbList::Data
{
  wxFileName document_path;
  wxString document_type_name;
  Verb::LIST verb_list;
};


//*********************************************************************

Verb::Verb() : m_uses_dde(false)
{
}

bool
Verb::ReadFromRegistry(const wxRegKey & base, const wxString & verb_name)
{
  // Store descriptive verb name
  m_name = verb_name;

  wxString command_key_name(verb_name + wxT("\\command"));

  // Read command key
  if (!base.HasSubKey(command_key_name))
    return false;

  wxRegKey command_key(base, command_key_name);

  command_key.QueryValue(NULL, m_command);

  // Attempt to read ddeexec key
  m_dde_command = wxT("");
  m_dde_topic = wxT("");
  m_dde_app = wxT("");

  const wxString dde_command_key_name(verb_name + wxT("\\ddeexec"));
  m_uses_dde = base.HasSubKey(dde_command_key_name);
  if (m_uses_dde)
  {
    wxRegKey dde_command_key(base, dde_command_key_name);;
    if (dde_command_key.HasValue(NULL))
      dde_command_key.QueryValue(NULL, m_dde_command);

    const wxString dde_topic_name(wxT("Topic"));
    if (dde_command_key.HasSubKey(dde_topic_name))
    {
      wxRegKey dde_topic_key(dde_command_key, dde_topic_name);
      if (dde_topic_key.HasValue(NULL))
        dde_topic_key.QueryValue(NULL, m_dde_topic);
    }

    const wxString dde_application_name(wxT("Application"));
    if (dde_command_key.HasSubKey(dde_application_name))
    {
      wxRegKey dde_app_key(dde_command_key, dde_application_name);
      if (dde_app_key.HasValue(NULL))
        dde_app_key.QueryValue(NULL, m_dde_app);
    }
  }

  return true;
}

void
Verb::Launch(const wxString  & document_path) const
{
  ShellExecute(NULL, m_name.c_str(),
               document_path.c_str(), NULL, NULL, SW_SHOWNORMAL);
  // TODO: error handling
}

/****************************************************************************/

VerbList::VerbList()
{
  m = new Data;
}

VerbList::~VerbList()
{
  delete m;
}

void
VerbList::InitFromDocument(const wxString & document_path, bool isAFolder)
{

  // Algorithm:
  // look up extension:          HKEY_CLASSES_ROOT\.ext
  // find ProgID of extension:   HKEY_CLASSES_ROOT\.ext\(Standard) = progid
  // find name of file type:     HKEY_CLASSES_ROOT\progid\(Standard) = file type name
  // find verbs:                 HKEY_CLASSES_ROOT\progid\shell\verb1
  // find command for each verb: HKEY_CLASSES_ROOT\progid\shell\verb1\command\(Standard) = command path
  //
  // Expand wildcards in command: "%1" and %1, and %SystemRoot% and other
  // environment variables.

  m->document_path = document_path;

  // Make sure list is empty
  m->verb_list.clear();


  wxString progid_key_name;

  // Get progid of extension
  wxRegKey regKeyHKCR; // (wxRegKey::HKCR, wxEmptyString);

  if (isAFolder)
    progid_key_name = wxT("Folder");
  else
  {
    // Find document extension
    if (!m->document_path.HasExt())
      // Nothing to go on; we cannot provide an editor
      return;

    wxString extension_key_name(wxT(".") + m->document_path.GetExt());
    if (!regKeyHKCR.HasSubKey(extension_key_name))
      return;

    wxRegKey ext_key(regKeyHKCR, extension_key_name);
    if (!ext_key.HasValue(NULL))
      return;

    ext_key.QueryValue(NULL, progid_key_name);
  }

  // Get information on progid (name, verbs)
  if (!regKeyHKCR.HasSubKey(progid_key_name))
    return;

  wxRegKey progid_key(regKeyHKCR, progid_key_name);

  // Get long name of progid (ignored if not found)
  if (progid_key.HasValue(NULL))
    progid_key.QueryValue(NULL, m->document_type_name);

  // Get verbs of progid
  const wxString progid_shell(wxT("shell"));
  if (!progid_key.HasSubKey(progid_shell))
    return;

  wxRegKey verb_base_key(progid_key, progid_shell);

  // Get name of default verb (ignored if not found)

  wxString default_verb_name(wxT(""));
  if (verb_base_key.HasValue(NULL))
    verb_base_key.QueryValue(NULL, default_verb_name);

  wxString verb_key_name;
  long index;
  bool ok = verb_base_key.GetFirstKey(verb_key_name, index);

  while (ok)
  {
    Verb verb;
    if (verb.ReadFromRegistry(verb_base_key, verb_key_name))
    {
      // Place first if default
      if (verb_key_name == default_verb_name)
        m->verb_list.insert(m->verb_list.begin(), verb);
      else
        m->verb_list.push_back(verb);
    }

    // select next key
    ok = verb_base_key.GetNextKey(verb_key_name, index);
  }
}

size_t
VerbList::GetCount() const
{
  return m->verb_list.size();
}

const wxString &
VerbList::GetName(size_t index) const
{
  return m->verb_list[index].m_name;
}

void
VerbList::Launch(size_t index) const
{
  m->verb_list[index].Launch(m->document_path.GetFullPath());
}


#endif

/* -----------------------------------------------------------------
 * local variables:
 * eval: (load-file "../rapidsvn-dev.el")
 * end:
 */

Generated by  Doxygen 1.6.0   Back to index