Репозитории 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 |
Группа :: Система/Основа
Пакет: 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 §ion)
+{
+ 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 §ion);
+ 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