// http://standards.freedesktop.org/menu-spec/latest/apa.html
//
-char *freedesktop_approved_cats[] = {
- "AudioVideo",
- "Audio",
- "Video",
- "Development",
- "Education",
- "Game",
- "Graphics",
- "Network",
- "Office",
- "Settings",
- "System",
- "Utility",
- "Building",
- "Debugger",
- "IDE",
- "GUIDesigner",
- "Profiling",
- "RevisionControl",
- "Translation",
- "Calendar",
- "ContactManagement",
- "Database",
- "Dictionary",
- "Chart",
- "Email",
- "Finance",
- "FlowChart",
- "PDA",
- "ProjectManagement",
- "Presentation",
- "Spreadsheet",
- "WordProcessor",
- "2DGraphics",
- "VectorGraphics",
- "RasterGraphics",
- "3DGraphics",
- "Scanning",
- "OCR",
- "Photography",
- "Publishing",
- "Viewer",
- "TextTools",
- "DesktopSettings",
- "HardwareSettings",
- "Printing",
- "PackageManager",
- "Dialup",
- "InstantMessaging",
- "Chat",
- "IRCClient",
- "FileTransfer",
- "HamRadio",
- "News",
- "P2P",
- "RemoteAccess",
- "Telephony",
- "TelephonyTools",
- "VideoConference",
- "WebBrowser",
- "WebDevelopment",
- "Midi",
- "Mixer",
- "Sequencer",
- "Tuner",
- "TV",
- "AudioVideoEditing",
- "Player",
- "Recorder",
- "DiscBurning",
- "ActionGame",
- "AdventureGame",
- "ArcadeGame",
- "BoardGame",
- "BlocksGame",
- "CardGame",
- "KidsGame",
- "LogicGame",
- "RolePlaying",
- "Simulation",
- "SportsGame",
- "StrategyGame",
- "Art",
- "Construction",
- "Music",
- "Languages",
- "Science",
- "ArtificialIntelligence",
- "Astronomy",
- "Biology",
- "Chemistry",
- "ComputerScience",
- "DataVisualization",
- "Economy",
- "Electricity",
- "Geography",
- "Geology",
- "Geoscience",
- "History",
- "ImageProcessing",
- "Literature",
- "Math",
- "NumericalAnalysis",
- "MedicalSoftware",
- "Physics",
- "Robotics",
- "Sports",
- "ParallelComputing",
- "Amusement",
- "Archiving",
- "Compression",
- "Electronics",
- "Emulator",
- "Engineering",
- "FileTools",
- "FileManager",
- "TerminalEmulator",
- "Filesystem",
- "Monitor",
- "Security",
- "Accessibility",
- "Calculator",
- "Clock",
- "TextEditor",
- "Documentation",
- "Core",
- "KDE",
- "GNOME",
- "GTK",
- "Qt",
- "Motif",
- "Java",
- "ConsoleOnly",
- "Screensaver",
- "TrayIcon",
- "Applet",
- "Shell",
- NULL
+freedesktop_cat_t freedesktop_complete[] = {
+
+ // HACK
+ { BADCATNAME, NULL, "Lazy PXML dev is lazy." },
+ // HACK
+
+ { "AudioVideo", NULL, "A multimedia (audio/video) application" },
+ { "Audio", NULL, "An audio application" },
+ { "Video", NULL, "A video application" },
+ { "Development", NULL, "An application for development" },
+ { "Education", NULL, "Educational software" },
+ { "Game", NULL, "A game" },
+ { "Graphics", NULL, "Graphical application" },
+ { "Network", NULL, "Network application such as a web browser" },
+ { "Office", NULL, "An office type application" },
+ { "Settings", NULL, "Settings applications" },
+ { "System", NULL, "System application" },
+ { "Utility", NULL, "Small utility application" },
+
+ { "Building", "Development", "A tool to build applications " },
+ { "Debugger", "Development", "A tool to debug applications" },
+ { "IDE", "Development", "IDE application " },
+ { "GUIDesigner", "Development", "A GUI designer application " },
+ { "Profiling", "Development", "A profiling tool " },
+ { "RevisionControl", "Development", "Applications like cvs or subversion " },
+ { "Translation", "Development", "A translation tool " },
+ { "Calendar", "Office", "Calendar application " },
+ { "ContactManagement", "Office", "E.g. an address book " },
+ { "Database", "Office", "Application to manage a database " },
+ { "Dictionary", "Office", "A dictionary " },
+ { "Chart", "Office", "Chart application" },
+ { "Email", "Office", "Email application" },
+ { "Finance", "Office", "Application to manage your finance " },
+ { "FlowChart", "Office", "A flowchart application " },
+ { "PDA", "Office", "Tool to manage your PDA " },
+ { "ProjectManagement", "Office", "Project management application " },
+ { "Presentation", "Office", "Presentation software " },
+ { "Spreadsheet", "Office", "A spreadsheet " },
+ { "WordProcessor", "Office", "A word processor " },
+ { "2DGraphics", "Graphics", "2D based graphical application " },
+ { "VectorGraphics", "Graphics", "Vector based graphical application " },
+ { "RasterGraphics", "Graphics", "Raster based graphical application " },
+ { "3DGraphics", "Graphics", "3D based graphical application " },
+ { "Scanning", "Graphics", "Tool to scan a file/text " },
+ { "OCR", "Graphics", "Optical character recognition application " },
+ { "Photography", "Graphics", "Camera tools, etc. " },
+ { "Publishing", "Graphics", "Desktop Publishing applications and Color Management tools " },
+ { "Viewer", "Graphics", "Tool to view e.g. a graphic or pdf file " },
+ { "TextTools", "Utility", "A text tool utiliy " },
+ { "DesktopSettings", "Settings", "Configuration tool for the GUI " },
+ { "HardwareSettings", "Settings", "A tool to manage hardware components, like sound cards, video cards or printers " },
+ { "Printing", "Settings", "A tool to manage printers " },
+ { "PackageManager", "Settings", "A package manager application " },
+ { "Dialup", "Network", "A dial-up program " },
+ { "InstantMessaging", "Network", "An instant messaging client " },
+ { "Chat", "Network", "A chat client" },
+ { "IRCClient", "Network", "An IRC client" },
+ { "FileTransfer", "Network", "Tools like FTP or P2P programs " },
+ { "HamRadio", "Network", "HAM radio software " },
+ { "News", "Network", "A news reader or a news ticker " },
+ { "P2P", "Network", "A P2P program " },
+ { "RemoteAccess", "Network", "A tool to remotely manage your PC " },
+ { "Telephony", "Network", "Telephony via PC " },
+ { "TelephonyTools", "Utility", "Telephony tools, to dial a number, manage PBX, ... " },
+ { "VideoConference", "Network", "Video Conference software " },
+ { "WebBrowser", "Network", "A web browser " },
+ { "WebDevelopment", "Network", "A tool for web developers " },
+ { "Midi", "AudioVideo", "An app related to MIDI " },
+ { "Mixer", "AudioVideo", "Just a mixer " },
+ { "Sequencer", "AudioVideo", "A sequencer " },
+ { "Tuner", "AudioVideo", "A tuner " },
+ { "TV", "AudioVideo", "A TV application" },
+ { "AudioVideoEditing", "Audio", "Application to edit audio/video files " },
+ { "Player", "Audio", "Application to play audio/video files " },
+ { "Recorder", "Audio", "Application to record audio/video files " },
+ { "DiscBurning", "AudioVideo", "Application to burn a disc " },
+ { "ActionGame", "Game", "An action game " },
+ { "AdventureGame", "Game", "Adventure style game" },
+ { "ArcadeGame", "Game", "Arcade style game" },
+ { "BoardGame", "Game", "A board game" },
+ { "BlocksGame", "Game", "Falling blocks game" },
+ { "CardGame", "Game", "A card game " },
+ { "KidsGame", "Game", "A game for kids" },
+ { "LogicGame", "Game", "Logic games like puzzles, etc " },
+ { "RolePlaying", "Game", "A role playing game " },
+ { "Simulation", "Game", "A simulation game " },
+ { "SportsGame", "Game", "A sports game " },
+ { "StrategyGame", "Game", "A strategy game " },
+ { "Art", "Education", "Software to teach arts " },
+ { "Construction", "Education", NULL },
+ { "Music", "Audio", "Musical software" },
+ { "Languages", "Education", "Software to learn foreign languages " },
+ { "Science", "Education", "Scientific software " },
+ { "ArtificialIntelligence", "Education", "Artificial Intelligence software " },
+ { "Astronomy", "Education", "Astronomy software " },
+ { "Biology", "Education", "Biology software " },
+ { "Chemistry", "Education", "Chemistry software " },
+ { "ComputerScience", "Education", "ComputerSience software " },
+ { "DataVisualization", "Education", "Data visualization software " },
+ { "Economy", "Education", "Economy software " },
+ { "Electricity", "Education", "Electricity software" },
+ { "Geography", "Education", "Geography software" },
+ { "Geology", "Education", "Geology software" },
+ { "Geoscience", "Education", "Geoscience software" },
+ { "History", "Education", "History software" },
+ { "ImageProcessing", "Education", "Image Processing software " },
+ { "Literature", "Education", "Literature software " },
+ { "Math", "Education", "Math software " },
+ { "NumericalAnalysis", "Education", "Numerical analysis software " },
+ { "MedicalSoftware", "Education", "Medical software " },
+ { "Physics", "Education", "Physics software " },
+ { "Robotics", "Education", "Robotics software " },
+ { "Sports", "Education", "Sports software " },
+ { "ParallelComputing", "Education", "Parallel computing software " },
+ { "Amusement", NULL, "A simple amusement " },
+ { "Archiving", "Utility", "A tool to archive/backup data " },
+ { "Compression", "Utility", "A tool to manage compressed data/archives " },
+ { "Electronics", NULL, "Electronics software, e.g. a circuit designer" },
+ { "Emulator", "Game", "Emulator of another platform, such as a DOS emulator " },
+ { "Engineering", NULL, "Engineering software, e.g. CAD programs " },
+ { "FileTools", "Utility", "A file tool utility " },
+ { "FileManager", "System", "A file manager " },
+ { "TerminalEmulator", "System", "A terminal emulator application " },
+ { "Filesystem", "System", "A file system tool " },
+ { "Monitor", "System", "Monitor application/applet that monitors some resource or activity " },
+ { "Security", "System", "A security tool " },
+ { "Accessibility", "System", "Accessibility " },
+ { "Calculator", "Utility", "A calculator " },
+ { "Clock", "Utility", "A clock application/applet " },
+ { "TextEditor", "Utility", "A text editor " },
+ { "Documentation", NULL, "Help or documentation " },
+ { "Core", NULL, "Important application, core to the desktop such as a file manager or a help browser " },
+ { "KDE", "QT", "Application based on KDE libraries " },
+ { "GNOME", "GTK", "Application based on GNOME libraries " },
+ { "GTK", NULL, "Application based on GTK+ libraries" },
+ { "Qt", NULL, "Application based on Qt libraries" },
+ { "Motif", NULL, "Application based on Motif libraries" },
+ { "Java", NULL, "Application based on Java GUI libraries, such as AWT or Swing" },
+ { "ConsoleOnly", NULL, "Application that only works inside a terminal (text-based or command line application)" },
+ { NULL, NULL, NULL }
};
-unsigned char freedesktop_check_cat ( char *name ) {
- char **p = freedesktop_approved_cats;
+freedesktop_cat_t *freedesktop_category_query ( char *name ) {
+ freedesktop_cat_t *p = freedesktop_complete;
- while ( *p ) {
+ while ( p -> cat ) {
- if ( strcasecmp ( *p, name ) == 0 ) {
- return ( 1 );
+ if ( strcasecmp ( p -> cat, name ) == 0 ) {
+ return ( p );
}
p++;
}
- return ( 0 );
+ return ( NULL );
}
#if 0
int main ( void ) {
- printf ( "check Applet (should be 1) -> %d\n", freedesktop_check_cat ( "Applet" ) );
- printf ( "check Education (should be 1) -> %d\n", freedesktop_check_cat ( "Education" ) );
- printf ( "check Mofo (should be 0) -> %d\n", freedesktop_check_cat ( "Mofo" ) );
+ printf ( "check Applet (should be 1) -> %d\n", freedesktop_category_query ( "Applet" ) );
+ printf ( "check Education (should be 1) -> %d\n", freedesktop_category_query ( "Education" ) );
+ printf ( "check Mofo (should be 0) -> %d\n", freedesktop_category_query ( "Mofo" ) );
return ( 0 );
}
// are we in a directory browser, or looking at pnd-files?
if ( cat -> fspath ) {
+ // directory browser mode
if ( s1 == s2 ) {
return ( 0 ); // equal
}
+ // pnd tab
+ //
+
+ // if this is comparing subcat folder to subcat folder, or pnd to pnd, or pnd to subcat folder?
+ unsigned char s1sub = 0;
+ unsigned char s2sub = 0;
+ if ( s1 -> ref -> object_type == pnd_object_type_directory ) {
+ s1sub = 1;
+ }
+ if ( s2 -> ref -> object_type == pnd_object_type_directory ) {
+ s2sub = 1;
+ }
+
+ if ( ( s1sub ) && ( s2sub ) ) {
+ return ( strcasecmp ( s1 -> ref -> title_en, s2 -> ref -> title_en ) );
+ } else if ( ( s1sub ) && ( ! s2sub ) ) {
+ return ( -1 );
+ } else if ( ( ! s1sub ) && ( s2sub ) ) {
+ return ( 1 );
+ } else if ( ( ! s1sub ) && ( ! s2sub ) ) {
+ return ( strcasecmp ( s1 -> ref -> title_en, s2 -> ref -> title_en ) );
+ }
+
return ( strcasecmp ( s1 -> ref -> title_en, s2 -> ref -> title_en ) );
}
char catnamebuffer [ 512 ] = "";
#endif
+ //fprintf ( stderr, "meta push: '%s'\n", catname );
+
if ( ! catname ) {
return ( 1 ); // fine, just nada
}
- //fprintf ( stderr, "meta push: '%s'\n", catname );
+ // we don't screw with "All" category that mmenu.c generates on the fly
+ if ( strncmp ( catname, "All ", 4 ) == 0 ) {
+ goto category_done_audit;
+ }
+
+ // category cleansing; lets..
+ // - ensure we only let good freedesktop categories through
+ // - we fix case.. no more UtIliTy (a good cat, studlycaps)
+ // - no more good cats but swapped ancestry; Utility as child of something?
+ // - if bogus, we just ship it off to BAD_CAT
+
+ unsigned char cat_is_clean = 1;
+ freedesktop_cat_t *fdcat = NULL, *fdpcat = NULL;
+ fdcat = freedesktop_category_query ( catname );
+ if ( parentcatname ) {
+ fdpcat = freedesktop_category_query ( parentcatname );
+ }
+
+ // ensure requested cat is good
+ if ( ! fdcat ) {
+ // requested cat is bad, send it to Other
+ cat_is_clean = 0;
+ printf ( "PXML Fail %s: Cat request %s (parent %s) -> bad cat\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
+
+ // do the Other substitution right away, so remaining code has something to look at in fdcat
+ fdcat = freedesktop_category_query ( BADCATNAME );
+ catname = fdcat -> cat;
+ fdpcat = NULL;
+ parentcatname = NULL;
+
+ } else {
+ // use canonicle entry, so our Case is now correct!
+ catname = fdcat -> cat;
+ }
+
+ // ensure parent is good, if specified
+ if ( parentcatname ) {
+ if ( ! fdpcat ) {
+ // requested cat is bad, send it to Other
+ cat_is_clean = 0;
+ printf ( "PXML Fail %s: Cat request %s (parent %s) -> parent bad cat\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
+ // fix immediately so code doesn't explode
+ parentcatname = NULL;
+ } else {
+ // use canonicle entry, so our Case is now correct!
+ parentcatname = fdpcat -> cat;
+ }
+ }
+
+ // ensure ancestry is good
+ // - if cat request is for child, ensure its a child
+ // - if parent specified, ensure its a parent
+ // - if child specified, ensure its parent is the right parent(?!)
+ //
+ if ( parentcatname ) {
+ // implies catname request is for child, with parent parentcatname
+
+ if ( fdcat -> parent_cat == NULL ) {
+ // but wait, catname is actually a parent cat...
+ cat_is_clean = 0;
+ printf ( "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be child, but FD says its a parent\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
+ }
+ if ( fdpcat -> parent_cat ) {
+ // but wait, parent cat is actually a subcat!
+ cat_is_clean = 0;
+ printf ( "PXML Fail %s: Cat request %s (parent %s) -> parent cat, FD says its a child\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
+ }
+
+ } else {
+ // implies request is for a parent cat - itself has no parent
+
+ if ( fdcat -> parent_cat ) {
+ // but wait, cat actually has a parent!
+ cat_is_clean = 0;
+ printf ( "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be parent, FD says its a child\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
+ }
+
+ }
+
+ // ensure that if this is a child cat, its parent is the right parent
+ if ( parentcatname ) {
+ if ( ( ! fdcat -> parent_cat ) ||
+ ( ! fdpcat ) )
+ {
+ // child cat points to a different parent than requested parent!
+ cat_is_clean = 0;
+ printf ( "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be child of a cat which FD says is the wrong parent (1)\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
+ } else if ( strcasecmp ( fdcat -> parent_cat, fdpcat -> cat ) != 0 ) {
+ // child cat points to a different parent than requested parent!
+ cat_is_clean = 0;
+ printf ( "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be child of a cat which FD says is the wrong parent (2)\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" );
+ }
+ }
+
+ // did testing fail? if so, bump to Other!
+ //
+ if ( ! cat_is_clean ) {
+ // set Other visibility
+ visiblep = cat_is_visible ( g_conf, BADCATNAME );
+ // fix cat request
+ fdcat = freedesktop_category_query ( BADCATNAME );
+ catname = fdcat -> cat;
+ // nullify parent cat request (if any)
+ fdpcat = NULL;
+ parentcatname = NULL;
+ } else {
+ //printf ( "PXML Category Pass: Cat request %s (parent %s)\n", catname, parentcatname ? parentcatname : "n/a" );
+ }
// push bad categories into Other (if we're not targeting All right now)
- if ( pnd_conf_get_as_int_d ( g_conf, "categories.good_cats_only", 1 ) ) {
+#if 0
+ if ( 1 /*pnd_conf_get_as_int_d ( g_conf, "categories.good_cats_only", 1 )*/ ) {
// don't audit All
if ( strncmp ( catname, "All ", 4 ) != 0 ) {
} // not All
} // good cats only?
+#endif
+
+ category_done_audit:
// if invisible, and a parent category name is known, prepend it for ease of use
#if 0 // prepending
} // cat map is desired?
+ // is app already in the target cat? (ie: its being pushed twice due to cat mapping or Other'ing or something..)
+ if ( app ) {
+ if ( category_contains_app ( catname, app -> unique_id ) ) {
+ printf ( "App Fail: app (%s %s) is already in cat %s\n", app -> title_en ? app -> title_en : "no name?", app -> unique_id, catname );
+ return ( 1 ); // success, already there!
+ }
+ }
+
// not default, just do it
category_push ( catname, parentcatname /* parent cat */, app, ovrh, NULL /* fspath */, visiblep );
return ( -1 );
}
+
+unsigned char category_contains_app ( char *catname, char *unique_id ) {
+
+ mm_category_t *c = pnd_box_find_by_key ( m_categories, catname );
+
+ if ( ! c ) {
+ return ( 0 ); // wtf?
+ }
+
+ if ( ! c -> refs ) {
+ return ( 0 ); // no apps at all
+ }
+
+ mm_appref_t *iter = c -> refs;
+
+ while ( iter ) {
+
+ if ( strcmp ( iter -> ref -> unique_id, unique_id ) == 0 ) {
+ return ( 1 );
+ }
+
+ iter = iter -> next;
+ }
+
+ return ( 0 );
+}