X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=minimenu%2Fmmcat.c;h=2bf84e63f9835afbc226c336beb05d0595d38d91;hb=a3c9bde945629115d1cea9bf807f5e5bec4e2223;hp=e96aa2370c70e957fdbb24c581c78c7b2257bfd5;hpb=dfdfc979e18d84804e0fff5d87bc6c2c1a875e66;p=pandora-libraries.git diff --git a/minimenu/mmcat.c b/minimenu/mmcat.c index e96aa23..2bf84e6 100644 --- a/minimenu/mmcat.c +++ b/minimenu/mmcat.c @@ -39,6 +39,12 @@ void category_init ( void ) { return; } +static char *_normalize ( char *catname, char *parentcatname ) { + static char buffer [ 101 ]; + snprintf ( buffer, 100, "%s*%s", catname, parentcatname ? parentcatname : "NoParent" ); + return ( buffer ); +} + unsigned char category_push ( char *catname, char *parentcatname, pnd_disco_t *app, pnd_conf_handle ovrh, char *fspath, unsigned char visiblep ) { mm_category_t *c; @@ -51,12 +57,12 @@ unsigned char category_push ( char *catname, char *parentcatname, pnd_disco_t *a // find or create category // - if ( ( c = pnd_box_find_by_key ( m_categories, catname ) ) ) { + if ( ( c = pnd_box_find_by_key ( m_categories, _normalize ( catname, parentcatname ) ) ) ) { // category was found.. } else { // category wasn't found.. //pnd_log ( PND_LOG_DEFAULT, "New category '%s'\n", catname ); - c = pnd_box_allocinsert ( m_categories, catname, sizeof(mm_category_t) ); + c = pnd_box_allocinsert ( m_categories, _normalize ( catname, parentcatname ), sizeof(mm_category_t) ); c -> catname = strdup ( catname ); if ( parentcatname ) { c -> parent_catname = strdup ( parentcatname ); @@ -154,6 +160,7 @@ int cat_sort_score ( mm_category_t *cat, mm_appref_t *s1, mm_appref_t *s2 ) { // are we in a directory browser, or looking at pnd-files? if ( cat -> fspath ) { + // directory browser mode if ( s1 == s2 ) { return ( 0 ); // equal @@ -178,6 +185,29 @@ int cat_sort_score ( mm_category_t *cat, mm_appref_t *s1, mm_appref_t *s2 ) { } + // 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 ) ); } @@ -267,7 +297,7 @@ unsigned char category_map_setup ( void ) { //pnd_log ( pndn_debug, "target(%s) from(%s)\n", k, buffer ); category_push ( k, NULL /* parent cat */, NULL, 0, NULL /* fspath */, 1 ); - g_catmaps [ g_catmapcount ].target = pnd_box_find_by_key ( m_categories, k ); + g_catmaps [ g_catmapcount ].target = pnd_box_find_by_key ( m_categories, _normalize ( k, NULL /* TBD: hack, not sure if this is right default value */ ) ); g_catmaps [ g_catmapcount ].from = strdup ( buffer ); g_catmapcount++; @@ -294,18 +324,135 @@ mm_category_t *category_map_query ( char *cat ) { return ( NULL ); } -unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco_t *app, pnd_conf_handle ovrh, unsigned char visiblep ) { +unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco_t *app, pnd_conf_handle ovrh, unsigned char visiblep, unsigned char parentp ) { mm_category_t *cat; +#if 0 // prepending 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; + } + + // check if category came from an ovr-file; if so, we implicitly trust it instead of enforcing rules + if ( app -> object_flags & ( PND_DISCO_CUSTOM1 | PND_DISCO_CUSTOM2 ) ) { + 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, parentcatname ); + if ( parentcatname ) { + fdpcat = freedesktop_category_query ( parentcatname, NULL ); + } + + // 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, NULL ); + 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, NULL ); + 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 ) { @@ -340,12 +487,22 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco } // 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 if ( ! visiblep && parentcatname ) { snprintf ( catnamebuffer, 500, "%s.%s", parentcatname, catname ); catname = catnamebuffer; } +#endif + + // if this is a subcat push, and its requesting special 'no subcat', then just ditch it + if ( parentcatname && strcmp ( catname, "NoSubcategory" ) == 0 ) { + return ( 1 ); + } // do we honour cat mapping at all? if ( pnd_conf_get_as_int_d ( g_conf, "categories.map_on", 0 ) ) { @@ -369,12 +526,36 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco } // 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, parentcatname, 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! + } + } + + // are we not putting apps into parent cat, when subcat is present? if so.. + // if the cat we're looking at now is the main (or main alt-cat), and we also have a subcat, then ditch it. + // so, is the cat we're looking at right now the apps main (or main alt) cat? + if ( parentp ) { + // and does this app have sub/altsub cats? + if ( app -> main_category1 || app -> main_category2 || app -> alt_category1 || app -> alt_category2 ) { + // and we're only desiring the subcat version of the app? + if ( pnd_conf_get_as_int_d ( g_conf, "tabs.subcat_to_parent", 1 ) == 0 ) { + // create the parent category, since we need to be able to place a folder here maybe + category_push ( catname, parentcatname /* parent cat */, NULL /* app */, NULL /* ovrh */, NULL /* fspath */, visiblep ); + // bail + return ( 1 ); + } // subcat to parent? + } // app has subcat? + } // tab we're looking at now is the main tab? + // not default, just do it category_push ( catname, parentcatname /* parent cat */, app, ovrh, NULL /* fspath */, visiblep ); // if subcats as folders, then lets just make up a dummy app that pretends to be a folder, // and stuff it into the parent cat - if ( parentcatname && pnd_conf_get_as_int_d ( g_conf, "tabs.subcat_as_folders", 1 ) ) { + if ( parentcatname && pnd_conf_get_as_int_d ( g_conf, "tabs.subcat_as_folders", 1 ) && cat_is_visible ( g_conf, catname ) ) { // it is implicit that since we're talking parentcat, its already been created in a previous call // therefore, we need to.. @@ -384,7 +565,7 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco // iv) create the dummy app folder by pushing the disco into the apprefs as normal // v) create a dummy '..' for going back up, in the child - mm_category_t *pcat = pnd_box_find_by_key ( m_categories, parentcatname ); + mm_category_t *pcat = pnd_box_find_by_key ( m_categories, _normalize ( parentcatname, NULL ) ); if ( ! pcat -> disco ) { pcat -> disco = pnd_box_new ( pcat -> catname ); @@ -400,7 +581,7 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco disco = pnd_box_allocinsert ( pcat -> disco, catname, sizeof(pnd_disco_t) ); if ( disco ) { - // create the subcat faux-disco entry, and register into parent cat + // create the subcat faux-disco entry, and register into parent cat .. if its visible char uid [ 30 ]; sprintf ( uid, "%p", catname ); @@ -412,7 +593,7 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco } disco -> object_flags = PND_DISCO_GENERATED; disco -> object_type = pnd_object_type_directory; // suggest to Grid that its a dir - disco -> object_path = strdup ( catname ); + disco -> object_path = strdup ( _normalize ( catname, parentcatname ) ); category_push ( parentcatname, NULL /* parent cat */, disco, 0 /*ovrh*/, NULL /* fspath */, 1 /* visible */ ); @@ -507,6 +688,8 @@ unsigned char category_fs_restock ( mm_category_t *cat ) { case DT_DIR: if ( strcmp ( de -> d_name, "." ) == 0 ) { // ignore ".", but ".." is fine + } else if ( strcmp ( de -> d_name, ".." ) == 0 && strcmp ( cat -> fspath, "/" ) == 0 ) { + // ignore ".." only if we're at the true root } else { disco = pnd_box_allocinsert ( cat -> disco, uid, sizeof(pnd_disco_t) ); disco -> object_type = pnd_object_type_directory; // suggest to Grid that its a dir @@ -600,19 +783,32 @@ void category_publish ( unsigned int filter_mask, char *param ) { if ( filter_mask == CFALL ) { interested = 1; } else if ( filter_mask == CFBYNAME ) { - if ( strcasecmp ( iter -> catname, param ) == 0 ) { + char *foo = strchr ( param, '*' ) + 1; + if ( strncasecmp ( iter -> catname, param, strlen ( iter -> catname ) ) == 0 && + strcasecmp ( iter -> parent_catname, foo ) == 0 ) + { interested = 1; } } else if ( iter -> catflags == filter_mask ) { interested = 1; } // if + // desired tab? if ( interested ) { - // set us up the bomb; notice that we're just duplicating the pointers, not making - // any new data here; none of this should ever be free'd! - g_categories [ g_categorycount ] = iter; - g_categorycount++; - } + + // lets only publish tabs that actually have an app in them .. just in case we've + // pruned out all the apps (sent them to Other or are suppressing apps in parent cats or + // something) at some point. + if ( iter -> fspath || iter -> refs ) { + + // set us up the bomb; notice that we're just duplicating the pointers, not making + // any new data here; none of this should ever be free'd! + g_categories [ g_categorycount ] = iter; + g_categorycount++; + + } // has apps? + + } // interested? // next iter = pnd_box_get_next ( iter ); @@ -664,3 +860,29 @@ int category_index ( char *catname ) { return ( -1 ); } + +unsigned char category_contains_app ( char *catname, char *parentcatname, char *unique_id ) { + + mm_category_t *c = pnd_box_find_by_key ( m_categories, _normalize ( catname, parentcatname ) ); + + 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 ); +}