--- menu-2.1.25/update-menus/common.h~ 2005-08-07 21:54:54 +0400 +++ menu-2.1.25/update-menus/common.h 2005-08-07 21:55:38 +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_KDE "/usr/share/applications/kde/" +#define XDGMENUS_GNOME "/usr/share/applications/gnome/" #define MENUMETHODS "/etc/menu-methods/" #define USERMETHODS ".menu-methods/" --- menu-2.1.25/update-menus/update-menus.h~ 2005-08-07 21:52:18 +0400 +++ menu-2.1.25/update-menus/update-menus.h 2005-08-07 21:52:28 +0400 @@ -122,6 +122,7 @@ public: typedef enum { report_quiet, report_normal, report_verbose, report_debug} verbosity_type; parsestream::eol_type compat; std::vector menufilesdir; + std::vector desktopfilesdir; std::string menumethod; bool usedefaultmenufilesdirs; bool onlyoutput_to_stdout; --- menu-2.1.25/update-menus/update-menus.cc~ 2005-07-24 15:39:26 +0400 +++ menu-2.1.25/update-menus/update-menus.cc 2005-09-11 20:59:10 +0400 @@ -57,6 +57,7 @@ static const char * home_dir; set installed_packages; set menufiles_processed; +set desktopfiles_processed; int total_menuentries; int verbose=0; @@ -463,6 +464,234 @@ 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 &menudata) +{ + FILE *desktop_file = fopen(filename.c_str(), "r"); + if (desktop_file == NULL) return 0; + + char firstline[MAX_LINE]; + if (fgets(firstline, MAX_LINE, desktop_file) == NULL) + { + pclose(desktop_file); + return 0; + } + if (strcmp(firstline, "[Desktop Entry]\n") != 0) + { + 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]; + fgets(tmp, MAX_LINE, desktop_file); + 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' ) + 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) ); + std::list ctglist; + for(std::string::iterator it = categories.begin(); it != categories.end(); ++it) + { + std::string ctg; + + while( it != categories.end() && *it != ';' ) + { + ctg += *it; + ++it; + } + if( it == categories.end() ) --it; + + if( ctg.size() > 0 ) + ctglist.push_front(ctg); + } + for(std::list::iterator it = ctglist.begin(); it != ctglist.end(); ++it) + { + if( *it != "X-KDE-More" ) + { + menu_line += " section=\""+*it+"\""; + have_section = true; + break; + } + } + } + } + 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) + { + menu_line += " icon=\""+line.substr(5, sz-5)+"\""; + } + } + 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 && xdg_command + if(sz > 5) + { + menu_line += " xdg_command=\""+line.substr(5, sz-5)+"\""; + int sps_pos = line.find(' '); + if( sps_pos > 5 ) + menu_line += " command=\""+line.substr(5, sps_pos-5)+"\""; + else + menu_line += " command=\""+line.substr(5, sz-5)+"\""; + } + } + else if( line.compare(0, 12, "GenericName=") == 0 ) + { + if(sz > 12) + { + menu_line += " xdg_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, 9, "Encoding=") != 0 ) + { + // fill xdg_extra + 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 xdg_filename + { + int slash_pos = shortfilename.rfind("/"); + if( slash_pos >= 0 ) + menu_line += " xdg_filename=\""+shortfilename.substr(slash_pos+1, shortfilename.size()-slash_pos-1)+"\""; + else + menu_line += " xdg_filename=\""+shortfilename+"\""; + } + + // add xdg_extra + if( d_extra.size() > 0 ) + menu_line += " xdg_extra=\""+d_extra+"\""; + + menudata.push_back(string("!F ") + filename + '\n'); + menudata.push_back(menu_line + '\n'); +// cerr << __FUNCTION__ << " add " << filename << std::endl; + + pclose(desktop_file); + return 1; +} + /** Read a menufile and create one (or more) menu entries for it. * * Returns the number of menu entries read. */ @@ -591,6 +820,47 @@ void read_menufilesdir(vector &m } } +/** Read a XDG directory full of desktop files */ +void read_desktopfilesdir(vector &menudata) +{ + int menuentries = 0; + for(vector::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 != "README") && (name != "core") && (name[0] != '.') && + (name.find(".bak") == string::npos) && + (name[name.length()-1] != '~')) + + if (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 */ void run_menumethod(string methodname, const vector &menudata) { @@ -1037,7 +1307,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::const_iterator i = menudata.begin(); i != menudata.end(); ++i)