Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37048244
en ru br
Репозитории ALT
S:2.1.41-alt23
5.1: 2.1.41-alt9
4.1: 2.1.41-alt3.M41.1
4.0: 2.1.35-alt5
3.0: 2.1.25-alt3
+backports:2.1.29-alt4.0.M30
www.altlinux.org/Changes

Группа :: Система/Основа
Пакет: menu

 Главная   Изменения   Спек   Патчи   Sources   Загрузить   Gear   Bugs and FR  Repocop 

Патч: menu-2.1.35-alt-xdginput.patch
Скачать


diff -u'Nrpk~' menu-2.1.35~/update-menus/common.h menu-2.1.35/update-menus/common.h
--- menu-2.1.35~/update-menus/common.h	2007-08-29 14:52:41 +0400
+++ menu-2.1.35/update-menus/common.h	2007-08-29 14:53:10 +0400
@@ -32,6 +32,9 @@ const int MAX_LINE = 10240;
 #define PACKAGEMENUS    "/usr/share/menu/"
 #define MENUMENUS       "/usr/share/menu/default/"
 #define USERMENUS       ".menu/"
+#define XDGMENUS       "/usr/share/applications/"
+#define XDGMENUS_GNOME       "/usr/share/applications/gnome/"
+#define XDGMENUS_KDE       "/usr/share/applications/kde/"
 
 #define MENUMETHODS     "/etc/menu-methods/"
 #define USERMETHODS     ".menu-methods/"
diff -u'Nrpk~' menu-2.1.35~/update-menus/Makefile.am menu-2.1.35/update-menus/Makefile.am
--- menu-2.1.35~/update-menus/Makefile.am	2004-01-29 12:34:09 +0300
+++ menu-2.1.35/update-menus/Makefile.am	2007-08-29 14:53:10 +0400
@@ -5,4 +5,6 @@ update_menus_SOURCES = update-menus.cc u
 		       parsestream.cc parsestream.h \
                        exceptions.h \
                        common.h \
+                       xdg_categories_translator.cc \
+                       xdg_categories_translator.h \
                        compose.hpp
diff -u'Nrpk~' menu-2.1.35~/update-menus/update-menus.cc menu-2.1.35/update-menus/update-menus.cc
--- menu-2.1.35~/update-menus/update-menus.cc	2007-08-29 14:52:41 +0400
+++ menu-2.1.35/update-menus/update-menus.cc	2007-07-30 18:49:48 +0400
@@ -45,6 +45,7 @@
 #include "config.h"
 #include "update-menus.h"
 #include "stringtoolbox.h"
+#include "xdg_categories_translator.h"
 
 using std::set;
 using std::vector;
@@ -58,6 +59,8 @@ static const char * home_dir;
 
 set<string> installed_packages;
 set<string> menufiles_processed;
+set<string> desktopfiles_processed;
+XdgCtgTranslator xdg_ctg_trans;
 int total_menuentries;
 
 int verbose=0;
@@ -178,6 +181,7 @@ void menuentry::check_req_tags(const std
         throw missing_tag(filename, *i);
   }
 
+  data["categories"] = xdg_ctg_trans.translate_section((data.find(SECTION_VAR))->second);
 }
 
 /** Parse a menuentry from a parsestream */
@@ -468,6 +472,269 @@ void read_pkginfo()
   pclose(status);
 }
 
+/** Read a XDG desktopfile and create one menu entry for it.
+ *
+ * Returns 0 or 1 of menu entries read. */
+int read_desktopfile(const string &filename, const string &shortfilename,
+                  vector<string> &menudata)
+{
+  FILE *desktop_file = fopen(filename.c_str(), "r");
+  if (desktop_file == NULL)  return 0;
+
+      {
+        // lookup Desktop Entry
+        bool desktop_entry_found = false;
+        char firstline[MAX_LINE];
+        while (!feof(desktop_file))
+        {
+	    if (fgets(firstline, MAX_LINE, desktop_file) == NULL)
+	    {
+		pclose(desktop_file);
+		return 0;
+	    }
+	    if (strcmp(firstline, "[Desktop Entry]\n") == 0)
+	    {
+		desktop_entry_found = true;
+		break;
+	    }
+        }
+	if (!desktop_entry_found)
+	{
+	    pclose(desktop_file);
+	    return 0;
+	}
+      }
+//      cerr << __FUNCTION__ << " read " << filename << std::endl;
+
+      bool have_section = false;
+      bool have_title = false;
+      std::string d_onlyshowin;
+      std::string d_terminal;
+      std::string d_extra;
+      std::string menu_line;
+
+      // create menu entry start
+      menu_line += "package=\"local.xdg_desktop_files\" xdg_desktopfile=\"true\"";
+//      int n_line = 2;
+      while (!feof(desktop_file))
+      {
+        std::string line;
+        char tmp[MAX_LINE];
+        if( !fgets(tmp, MAX_LINE, desktop_file) ) continue;
+	int len = strlen(tmp);
+
+	// ignore empty lines
+	if ( len <= 1) continue;
+
+	// quote
+	for(int i=0; i < MAX_LINE; i++)
+	{
+	  if( tmp[i] == '\"' )
+	    line += "\\\"";
+	  else if( tmp[i] == '\n' || tmp[i] == '\0' )
+	    break;
+	  else
+	    line += tmp[i];
+	}
+
+//	if( tmp[len-1] == '\n' )
+//	    line = std::string(tmp, 0, len-1);
+//	else
+//	    line = tmp;
+//	cerr << " line " << n_line++ << ":" << line << std::endl;
+	
+	int sz = line.size();
+
+	if( line.compare(0, 5, "Name=") == 0 )
+	{
+	  // take title
+//	  cerr << __FUNCTION__ << " take title" << std::endl;
+	  if(sz > 5)
+	  {
+	    menu_line += " title=\""+line.substr(5, sz-5)+"\"";
+	    have_title = true;
+	  }
+	}
+	else if( line.compare(0, 11, "Categories=") == 0 )
+	{
+	  // take section
+//	  cerr << __FUNCTION__ << " take section" << std::endl;
+	  if(sz > 11)
+	  {
+	    std::string categories( line.substr(11, sz-11) );
+	    if( categories.size() > 0 )
+	    {
+		std::string section = xdg_ctg_trans.translate(categories);
+		if( section.size() > 0 )
+		{
+		    menu_line += " section=\""+section+"\"";
+		    have_section = true;
+		}
+	    }
+	  }
+	}
+	else if( line.compare(0, 8, "Comment=") == 0 )
+	{
+	  // take longtitle
+	  if(sz > 8)
+	  {
+	    menu_line += " longtitle=\""+line.substr(8, sz-8)+"\"";
+	  }
+	}
+	else if( line.compare(0, 5, "Icon=") == 0 )
+	{
+	  // take icon
+	  if(sz > 5)
+	  {
+	    string icon = line.substr(5, sz-5);
+	    int icon_sz = sz-5;
+	    if( icon_sz > 4
+		&& icon.substr(icon_sz-4,1) != "." )
+	    {
+		icon += ".png";
+	    }
+	    else if( icon_sz > 0 && icon_sz <= 4 )
+	    {
+		icon += ".png";
+	    }
+	    menu_line += " icon=\""+icon+"\"";
+	  }
+	}
+	else if( line.compare(0, 9, "MimeType=") == 0 )
+	{
+	  // take mimetypes
+	  // FIXME? replace ; by ,
+	  if(sz > 9)
+	  {
+	    menu_line += " mimetypes=\""+line.substr(9, sz-9)+"\"";
+	  }
+	}
+	else if( line.compare(0, 5, "Exec=") == 0 )
+	{
+	  // take command && extra_command
+	  if(sz > 5)
+	  {
+	    menu_line += " extra_command=\""+line.substr(5, sz-5)+"\"";
+	    // cleanup for command
+	    int sps_pos = line.find(' ');
+	    int cur_pos = line.find('%');
+	    if( cur_pos > 5 && sps_pos >= 5)
+	    {
+		cur_pos = line.rfind(' ', cur_pos - 1);
+		if( cur_pos > 5 )
+		{
+		    sps_pos = cur_pos;
+		    cur_pos = line.rfind(' ', cur_pos - 1);
+		    if( cur_pos > 5 && line[cur_pos+1] == '-' )
+			sps_pos = cur_pos;
+		}
+	    }
+	    else
+		sps_pos = sz - 1;
+	    while( line[sps_pos] == ' ' )
+		sps_pos--;
+	    menu_line += " command=\""+line.substr(5, sps_pos+1-5)+"\"";
+	  }
+	}
+	else if( line.compare(0, 12, "GenericName=") == 0 )
+	{
+	  if(sz > 12)
+	  {
+	    menu_line += " genericname=\""+line.substr(12, sz-12)+"\"";
+	  }
+	}
+	else if( line.compare(0, 9, "Terminal=") == 0 )
+	{
+	  // fill d_terminal
+	  if(sz > 9)
+	  {
+	    d_terminal = line.substr(9, sz-9);
+	  }
+	}
+	else if( line.compare(0, 11, "OnlyShowIn=") == 0 )
+	{
+	  // fill d_onlyshowin
+	  if(sz > 11)
+	  {
+	    int start = sz - 3;
+	    int end = sz - 1 ;
+	    while( line[start] != ';' && line[start] != '=' && start >= 0 )
+		start--;
+	    start++;
+	    end = start;
+	    while( line[end] != ';' && line[end] != '\n' && end < sz )
+		end++;
+	    std::string onlyshowin(line.substr(start, end-start));
+	    d_onlyshowin = onlyshowin;
+	  }
+	}
+	else if( line.compare(0, 5, "Name[") == 0
+		|| line.compare(0, 8, "Comment[") == 0
+		|| line.compare(0, 12, "GenericName[") == 0 )
+	{
+	    xdg_ctg_trans.addI18n(line);
+	}
+	else if(line == "NoDisplay=true")
+	{
+	    pclose(desktop_file);
+	    return 0;
+	}
+	else if( line.compare(0, 9, "Encoding=") != 0
+		&& line.compare(0, 5, "Type=") != 0 )
+	{
+		// fill extra_opt
+		d_extra += line+"\\n";
+	}
+      }
+//      cerr << __FUNCTION__ << " end while" << std::endl;
+
+      // skip wrong entries
+      if ( !have_section || !have_title )
+      {
+//	cerr << __FUNCTION__ << " !have_section || !have_title " << filename << std::endl;
+        pclose(desktop_file);
+        return 0;
+      }
+
+      // take needs
+      if( d_terminal.size() > 0 || d_onlyshowin.size() > 0 )
+      {
+	if( d_terminal == "1" || d_terminal == "true" )
+	  menu_line += " needs=\"text\"";
+	else if( d_onlyshowin.size() > 0 )
+	  menu_line += " needs=\""+d_onlyshowin+"\"";
+	else
+	  menu_line += " needs=\"X11\"";
+      }
+      else
+	menu_line += " needs=\"X11\"";
+
+      // take extra_filename
+      {
+	int slash_pos = shortfilename.rfind("/");
+	if( slash_pos < 0 )
+	    slash_pos = 0;
+	else
+	    slash_pos += 1;
+	int dot_pos = shortfilename.rfind(".");
+	if( dot_pos <= slash_pos )
+	    dot_pos = shortfilename.size()-1;
+	menu_line += " extra_filename=\""+shortfilename.substr(slash_pos, dot_pos)+"\"";
+      }
+
+      // add extra_opt
+      if( d_extra.size() > 0 )
+        menu_line += " extra_opt=\""+d_extra+"\"";
+
+//      cerr << __FUNCTION__ << " add " << filename << std::endl;
+      menudata.push_back(string("!F ") + filename + '\n');
+
+      menudata.push_back(menu_line + '\n');
+
+      pclose(desktop_file);
+      return 1;
+}
+
 /** Read a menufile and create one (or more) menu entries for it.
  *
  * Returns the number of menu entries read. */
@@ -596,6 +863,45 @@ void read_menufilesdir(vector<string> &m
   }
 }
 
+/** Read a XDG directory full of desktop files */
+void read_desktopfilesdir(vector<string> &menudata)
+{
+  int menuentries = 0;
+  for(vector<string>::const_iterator method_i = config.desktopfilesdir.begin();
+      method_i != config.desktopfilesdir.end();
+      ++method_i)
+  {
+    string dirname = *method_i;
+    config.report(String::compose(_("Reading menu-entry files in %1."), dirname),
+        configinfo::report_verbose);
+    try {
+      struct dirent *entry;
+      DIR *dir = open_dir_check(dirname);
+      while((entry = readdir(dir)))
+      {
+        string name = entry->d_name;
+        if (name.find(".desktop") == name.length()-8 &&
+    	    desktopfiles_processed.find(name) == desktopfiles_processed.end())
+	{
+              desktopfiles_processed.insert(name);
+              name = dirname+name;
+              struct stat st;
+              int r = stat(name.c_str(),&st);
+              try {
+                if ((!r) && (S_ISREG(st.st_mode)||S_ISLNK(st.st_mode)) && (st.st_size < 30720))
+                    menuentries += read_desktopfile(name,entry->d_name, menudata);
+              }
+              catch (endofline p) {
+                cerr << String::compose(_("Error reading %1.\n"), name);
+              }
+        }
+      }
+    } catch (dir_error_read p) { }
+    total_menuentries += menuentries;
+    config.report(String::compose(_("%1 menu entries found (%2 total)."), menuentries, total_menuentries), configinfo::report_verbose);
+  }
+}
+
 /** Run a menu-method with --remove*/
 void run_menumethod_remove(string methodname)
 {
@@ -1092,7 +1398,12 @@ int main (int argc, char **argv)
       config.menufilesdir.push_back(MENUMENUS);
     }
 
+    config.desktopfilesdir.push_back(XDGMENUS);
+    config.desktopfilesdir.push_back(XDGMENUS_KDE);
+    //config.desktopfilesdir.push_back(XDGMENUS_GNOME);
+
     read_menufilesdir(menudata);
+    read_desktopfilesdir(menudata);
 
     if (config.onlyoutput_to_stdout) {
         for(vector<string>::const_iterator i = menudata.begin(); i != menudata.end(); ++i)
diff -u'Nrpk~' menu-2.1.35~/update-menus/update-menus.h menu-2.1.35/update-menus/update-menus.h
--- menu-2.1.35~/update-menus/update-menus.h	2007-06-06 13:39:41 +0400
+++ menu-2.1.35/update-menus/update-menus.h	2007-08-29 14:53:10 +0400
@@ -122,6 +122,7 @@ public:
   typedef enum { report_quiet, report_normal, report_verbose, report_debug} verbosity_type;
   parsestream::eol_type compat;
   std::vector<std::string> menufilesdir;
+  std::vector<std::string> desktopfilesdir;
   std::string menumethod;
   bool usedefaultmenufilesdirs;
   bool onlyoutput_to_stdout;
diff -u'Nrpk~' menu-2.1.35~/update-menus/xdg_categories_translator.cc menu-2.1.35/update-menus/xdg_categories_translator.cc
--- menu-2.1.35~/update-menus/xdg_categories_translator.cc	1970-01-01 03:00:00 +0300
+++ menu-2.1.35/update-menus/xdg_categories_translator.cc	2007-07-20 20:54:13 +0400
@@ -0,0 +1,179 @@
+
+#include <sys/types.h>
+#include <pwd.h>
+
+#include <cstring>
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+
+#include "common.h"
+#include "xdg_categories_translator.h"
+
+XdgCtgTranslator::XdgCtgTranslator()
+{
+    load(MENUMETHODS"/translate_xdg_categories");
+    load(MENUMETHODS"/translate_menu_sections", true);
+}
+
+XdgCtgTranslator::~XdgCtgTranslator(){}
+
+void XdgCtgTranslator::load(const std::string &translation_file, bool is_sections)
+{
+    FILE *transfile = fopen(translation_file.c_str(), "r");
+    if(!transfile) return;
+    while(!feof(transfile))
+    {
+	char tmp[MAX_LINE];
+	std::string line;
+	struct XdgCtgCondition condition;
+
+	if( !fgets(tmp, MAX_LINE, transfile) ) continue;
+	if( tmp[0] == '#' )
+	    continue;
+	int len = strlen(tmp);
+	if( len < 5 )
+	    continue;
+	if( tmp[len-1] == '\n' )
+	    line = std::string(tmp, 0, len-1);
+	else
+	    line = tmp;
+
+	// take section name
+	int eq_pos = line.find('=');
+	if( eq_pos < 2 )
+	    continue;
+	condition.section = std::string(line, 0, eq_pos);
+	line = std::string(line, eq_pos+1, line.size()-eq_pos-1);
+	//std::cerr << "section<" << condition.section << "> line<" << line << ">" << std::endl;
+
+	if(is_sections)
+	{
+	    section_to_category_map[condition.section] = line;
+	}
+	else
+	{
+	    // take conditions
+	    std::list<std::string> condlist = split(line, ';');
+	    for(std::list<std::string>::iterator it = condlist.begin(); it != condlist.end(); ++it)
+	    {
+		std::string subcondition = *it;
+		if( subcondition[0] == '!' )
+		{
+		    condition.conflicts.push_back(subcondition.substr(1, subcondition.size()-1));
+		    //std::cerr << "  conflict<" << subcondition.substr(1, subcondition.size()-1) << ">" << std::endl;
+		}
+		else
+		{
+		    condition.requires.push_back(subcondition);
+		    //std::cerr << "  require<" << subcondition << ">" << std::endl;
+		}
+	    }
+	    // add condition to list
+	    if( condition.requires.size() > 0 || condition.conflicts.size() > 0 )
+	    {
+		conditions.push_back(condition);
+	    }
+	}
+    }
+}
+
+std::string XdgCtgTranslator::translate(const std::string &categories)
+{
+    std::string section;
+    std::list<std::string> ctglist = split(categories, ';');
+    for(std::list<XdgCtgCondition>::iterator cond_it = conditions.begin(); cond_it != conditions.end(); ++cond_it)
+    {
+	XdgCtgCondition cond = *cond_it;
+//	find conflicts
+	unsigned int conflicts_found = 0;
+	for(std::list<std::string>::iterator ctg_it = ctglist.begin(); ctg_it != ctglist.end(); ++ctg_it)
+        {
+	    std::string category = *ctg_it;
+	    for(std::list<std::string>::iterator conflict_it = cond.conflicts.begin();
+		conflict_it != cond.conflicts.end(); ++conflict_it)
+	    {
+		if( category == *conflict_it )
+		{
+		    conflicts_found++;
+		    break;
+		}
+	    }
+	}
+//	find requires
+	unsigned int requires_found = 0;
+	for(std::list<std::string>::iterator ctg_it = ctglist.begin(); ctg_it != ctglist.end(); ++ctg_it)
+        {
+	    std::string category = *ctg_it;
+	    for(std::list<std::string>::iterator require_it = cond.requires.begin();
+		require_it != cond.requires.end(); ++require_it)
+	    {
+		if( category == *require_it )
+		{
+		    requires_found++;
+		    break;
+		}
+	    }
+	}
+	if( cond.requires.size() == requires_found && cond.conflicts.size() == conflicts_found )
+	{
+	    section = cond.section;
+	    break;
+	}
+    }
+    return section;
+}
+
+std::string XdgCtgTranslator::translate_section(const std::string &section)
+{
+    std::string categories = section_to_category_map[section];
+    if( categories.size() <= 0 )
+    {
+	categories = "UnknownCategory;";
+    }
+    return categories;
+}
+
+std::list<std::string> XdgCtgTranslator::split(std::string textline, const char separator)
+{
+    std::list<std::string> newlist;
+    for(std::string::iterator it = textline.begin(); it != textline.end(); ++it)
+    {
+	std::string substring;
+	while( it != textline.end() && *it != separator )
+	{
+	    substring += *it;
+	    ++it;
+	}
+	if( it == textline.end() ) --it;
+	if( substring.size() > 0 )
+	    newlist.push_back(substring);
+    }
+    return newlist;
+}
+
+void XdgCtgTranslator::saveI18n()
+{
+    const char* home_dir;
+    struct passwd *pwentry = getpwuid(getuid());
+    if (pwentry != NULL)
+	home_dir = pwentry->pw_dir;
+    else
+	home_dir = getenv("HOME");
+
+    std::ofstream i18n_file((std::string(home_dir)+"/.menu-updates.i18n").c_str(), std::ios::trunc);
+
+	for(std::map<std::string, std::map<std::string,std::string> >::iterator it = i18n.begin(); it != i18n.end(); ++it)
+	{
+	    std::string lng = (*it).first;
+	    std::map<std::string, std::string> lng_strings = (*it).second;
+	    for(std::map<std::string, std::string>::iterator it2 = lng_strings.begin(); it2 != lng_strings.end(); ++it2)
+	    {
+		i18n_file << lng << "|" << ((*it2).first).size() << "|" << (*it2).first << (*it2).second << std::endl;
+	    }
+	}
+}
+
+void XdgCtgTranslator::addI18n(const std::string &str)
+{
+}
diff -u'Nrpk~' menu-2.1.35~/update-menus/xdg_categories_translator.h menu-2.1.35/update-menus/xdg_categories_translator.h
--- menu-2.1.35~/update-menus/xdg_categories_translator.h	1970-01-01 03:00:00 +0300
+++ menu-2.1.35/update-menus/xdg_categories_translator.h	2007-07-20 20:52:58 +0400
@@ -0,0 +1,35 @@
+#ifndef __XDG_CATEGORIES_TRANSLATOR_H
+#define __XDG_CATEGORIES_TRANSLATOR_H
+
+#include <string>
+#include <list>
+#include <map>
+
+struct XdgCtgCondition
+{
+    std::string section;
+    std::list<std::string> requires;
+    std::list<std::string> conflicts;
+};
+
+class XdgCtgTranslator
+{
+public:
+    XdgCtgTranslator();
+    ~XdgCtgTranslator();
+
+    std::string translate(const std::string &categories);
+    std::string translate_section(const std::string &section);
+    void addI18n(const std::string&);
+    void saveI18n();
+    static std::list<std::string> split(std::string textline, const char separator);
+
+private:
+    std::list<XdgCtgCondition> conditions;
+    std::map<std::string,std::string> section_to_category_map;
+    std::map<std::string, std::map<std::string,std::string> > i18n;
+    
+    void load(const std::string &translation_file, bool is_sections = false);
+};
+
+#endif
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin