Rebuilt mmenu 'category' internals so its much more pleasant to work with (internally)
authorskeezix <skeezix@flotsam-vm.(none)>
Wed, 26 Jan 2011 16:31:49 +0000 (11:31 -0500)
committerskeezix <skeezix@flotsam-vm.(none)>
Wed, 26 Jan 2011 16:31:49 +0000 (11:31 -0500)
minimenu/mmcat.c
minimenu/mmcat.h
minimenu/mmconf.c
minimenu/mmenu.c
minimenu/mmui.c

index 241d65a..3a72d46 100644 (file)
@@ -6,6 +6,7 @@
 #include <dirent.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <ctype.h>
 
 #include "pnd_conf.h"
 #include "pnd_logger.h"
 #include "mmcache.h"
 #include "mmcat.h"
 
-mm_category_t _categories [ MAX_CATS ];
-mm_category_t *g_categories = _categories;
-unsigned char g_categorycount = 0;
+// all categories known -- visible, hidden, subcats, whatever.
+pnd_box_handle m_categories = NULL;
+unsigned int m_categorycount = 0;
 
-mm_category_t _categories_invis [ MAX_CATS ];
-unsigned char _categories_inviscount = 0;
+// all categories being published right now -- a subset copied from m_categories
+mm_category_t *g_categories [ MAX_CATS ];
+unsigned char g_categorycount;
 
+// category mappings
 mm_catmap_t g_catmaps [ MAX_CATS ];
 unsigned char g_catmapcount = 0;
 
 extern pnd_conf_handle g_conf;
 
-unsigned char category_push ( char *catname, pnd_disco_t *app, pnd_conf_handle ovrh, char *fspath ) {
+void category_init ( void ) {
+  m_categories = pnd_box_new ( "Schrodinger's cat" );
+  return;
+}
+
+unsigned char category_push ( char *catname, pnd_disco_t *app, pnd_conf_handle ovrh, char *fspath, unsigned char visiblep ) {
   mm_category_t *c;
 
   // check category list; if found, append app to the end of it.
@@ -42,20 +50,25 @@ unsigned char category_push ( char *catname, pnd_disco_t *app, pnd_conf_handle o
   // find or create category
   //
 
-  if ( ( c = category_query ( catname ) ) ) {
+  if ( ( c = pnd_box_find_by_key ( m_categories, catname ) ) ) {
     // category was found..
   } else {
     // category wasn't found..
     //pnd_log ( PND_LOG_DEFAULT, "New category '%s'\n", catname );
-    g_categories [ g_categorycount ].catname = strdup ( catname );
-    g_categories [ g_categorycount ].refs = NULL;
-    c = &(g_categories [ g_categorycount ]);
+    c = pnd_box_allocinsert ( m_categories, catname, sizeof(mm_category_t) );
+    c -> catname = strdup ( catname );
+    if ( visiblep ) {
+      c -> catflags = CFNORMAL;
+    } else {
+      c -> catflags = CFHIDDEN;
+    }
+    c -> refs = NULL;
 
     if ( fspath ) {
-      g_categories [ g_categorycount ].fspath = strdup ( fspath );;
+      c -> fspath = strdup ( fspath );
     }
 
-    g_categorycount++;
+    m_categorycount++;
   }
 
   if ( ! app ) {
@@ -88,7 +101,7 @@ unsigned char category_push ( char *catname, pnd_disco_t *app, pnd_conf_handle o
     while ( iter ) {
 
       if ( iter -> ref -> title_en ) {
-       if ( cat_sort_score ( ar, iter ) < 0 ) {
+       if ( cat_sort_score ( c, ar, iter ) < 0 ) {
          // new guy is smaller than the current guy!
          break;
        }
@@ -125,26 +138,10 @@ unsigned char category_push ( char *catname, pnd_disco_t *app, pnd_conf_handle o
   return ( 1 );
 }
 
-mm_category_t *category_query ( char *catname ) {
-  unsigned char i;
-
-  for ( i = 0; i < g_categorycount; i++ ) {
-
-    if ( strcasecmp ( g_categories [ i ].catname, catname ) == 0 ) {
-      return ( &(g_categories [ i ]) );
-    }
-
-  }
-
-  return ( NULL );
-}
-
-int cat_sort_score ( mm_appref_t *s1, mm_appref_t *s2 ) {
-
-  extern unsigned char ui_category;
+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 ( g_categories [ ui_category ].fspath ) {
+  if ( cat -> fspath ) {
 
     if ( s1 == s2 ) {
       return ( 0 ); // equal
@@ -173,32 +170,41 @@ int cat_sort_score ( mm_appref_t *s1, mm_appref_t *s2 ) {
 }
 
 void category_dump ( void ) {
-  unsigned int i;
 
   // WHY AREN'T I SORTING ON INSERT?
 
   // dump
-  for ( i = 0; i < g_categorycount; i++ ) {
-    pnd_log ( PND_LOG_DEFAULT, "Category %u: '%s' * %u\n", i, g_categories [ i ].catname, g_categories [ i ].refcount );
-    mm_appref_t *ar = g_categories [ i ].refs;
+  mm_category_t *iter = pnd_box_get_head ( m_categories );
+  unsigned int counter = 0;
+
+  while ( iter ) {
+
+    pnd_log ( PND_LOG_DEFAULT, "Category %u: '%s' * %u\n", counter, iter -> catname, iter -> refcount );
+    mm_appref_t *ar = iter -> refs;
 
     while ( ar ) {
       pnd_log ( PND_LOG_DEFAULT, "  Appref %s\n", IFNULL(ar -> ref -> title_en,"No Name") );
       ar = ar -> next;
     }
 
-  } // for
+    iter = pnd_box_get_next ( iter );
+    counter++;
+  }
 
   return;
 }
 
-static void _category_freeall ( mm_category_t *p, unsigned int c ) {
-  unsigned int i;
+void category_freeall ( void ) {
+  mm_category_t *c, *cnext;
   mm_appref_t *iter, *next;
 
-  for ( i = 0; i < c; i++ ) {
+  c = pnd_box_get_head ( m_categories );
+
+  while ( c ) {
+    cnext = pnd_box_get_next ( c );
 
-    iter = p [ i ].refs;
+    // wipe 'em
+    iter = c -> refs;
 
     while ( iter ) {
       next = iter -> next;
@@ -206,30 +212,23 @@ static void _category_freeall ( mm_category_t *p, unsigned int c ) {
       iter = next;
     }
 
-    p [ i ].refs = NULL;
+    c -> refs = NULL;
 
-    if ( p [ i ].catname ) {
-      free ( p [ i ].catname );
-      p [ i ].catname = NULL;
+    if ( c -> catname ) {
+      free ( c -> catname );
+      c -> catname = NULL;
     }
 
-    if ( p [ i ].fspath ) {
-      free ( p [ i ].fspath );
-      p [ i ].fspath = NULL;
+    if ( c -> fspath ) {
+      free ( c -> fspath );
+      c -> fspath = NULL;
     }
 
-  } // for
-
-  return;
-}
-
-void category_freeall ( void ) {
-
-  _category_freeall ( g_categories, g_categorycount );
-  _category_freeall ( _categories_invis, _categories_inviscount );
+    pnd_box_delete_node ( m_categories, c );
 
-  g_categorycount = 0;
-  _categories_inviscount = 0;
+    // next
+    c = cnext;
+  }
 
   return;
 }
@@ -255,8 +254,8 @@ unsigned char category_map_setup ( void ) {
       {
        //pnd_log ( pndn_debug, "target(%s) from(%s)\n", k, buffer );
 
-       category_push ( k, NULL, 0, NULL /* fspath */ );
-       g_catmaps [ g_catmapcount ].target = category_query ( k );
+       category_push ( k, NULL, 0, NULL /* fspath */, 1 );
+       g_catmaps [ g_catmapcount ].target = pnd_box_find_by_key ( m_categories, k );
        g_catmaps [ g_catmapcount ].from = strdup ( buffer );
        g_catmapcount++;
 
@@ -285,7 +284,6 @@ mm_category_t *category_map_query ( char *cat ) {
 
 unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco_t *app, pnd_conf_handle ovrh, unsigned char visiblep ) {
   mm_category_t *cat;
-  unsigned char catcount = g_categorycount;
   char catnamebuffer [ 512 ] = "";
 
   if ( ! catname ) {
@@ -294,19 +292,10 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco
 
   //fprintf ( stderr, "meta push: '%s'\n", catname );
 
-  if ( ! visiblep ) {
-    //return ( 1 ); // fine, suppress it
-
-    // serious evidence this was a rushed program
-    g_categories = _categories_invis;
-    g_categorycount = _categories_inviscount;
-
-    // if invisible, and a parent category name is known, prepend it for ease of use
-    if ( parentcatname ) {
-      snprintf ( catnamebuffer, 500, "%s.%s", parentcatname, catname );
-      catname = catnamebuffer;
-    }
-
+  // if invisible, and a parent category name is known, prepend it for ease of use
+  if ( ! visiblep && parentcatname ) {
+    snprintf ( catnamebuffer, 500, "%s.%s", parentcatname, catname );
+    catname = catnamebuffer;
   }
 
   // do we honour cat mapping at all?
@@ -316,31 +305,26 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco
     cat = category_map_query ( catname );
 
     if ( cat ) {
-      category_push ( cat -> catname, app, ovrh, NULL /* fspath */ );
-      goto visibility_hack_cleanup;
+      category_push ( cat -> catname, app, ovrh, NULL /* fspath */, visiblep );
+      goto meta_done;
     }
 
     // not mapped.. but default?
     if ( pnd_conf_get_as_int_d ( g_conf, "categories.map_default_on", 0 ) ) {
       char *def = pnd_conf_get_as_char ( g_conf, "categories.map_default_cat" );
       if ( def ) {
-       category_push ( def, app, ovrh, NULL /* fspath */ );
-       goto visibility_hack_cleanup;
+       category_push ( def, app, ovrh, NULL /* fspath */, visiblep );
+       goto meta_done;
       }
     }
 
   } // cat map is desired?
 
   // not default, just do it
-  category_push ( catname, app, ovrh, NULL /* fspath */ );
+  category_push ( catname, app, ovrh, NULL /* fspath */, visiblep );
 
   // hack :(
- visibility_hack_cleanup:
-  if ( ! visiblep ) {
-    _categories_inviscount = g_categorycount;
-    g_categories = _categories;
-    g_categorycount = catcount;
-  }
+ meta_done:
 
   //fprintf ( stderr, "cat meta-push : vis[%30s,%d b] : tally; vis %d invis %d\n", catname, visiblep, g_categorycount, _categories_inviscount );
 
@@ -427,13 +411,13 @@ unsigned char category_fs_restock ( mm_category_t *cat ) {
 
        // found a directory or executable?
        if ( disco ) {
-         // register with this category
+         // register with current category
          disco -> unique_id = strdup ( uid );
          disco -> title_en = strdup ( de -> d_name );
          disco -> object_flags = PND_DISCO_GENERATED;
          disco -> object_path = strdup ( cat -> fspath );
          disco -> object_filename = strdup ( de -> d_name );
-         category_push ( cat -> catname, disco, 0, NULL /* fspath already set */ );
+         category_push ( cat -> catname, disco, 0 /* no ovr */, NULL /* fspath already set */, 1 /* visible */ );
          // if a override icon exists, cache it up
          cache_icon ( disco, pnd_conf_get_as_int_d ( g_conf, "grid.icon_max_width", 50 ),
                       pnd_conf_get_as_int_d ( g_conf, "grid.icon_max_height", 50 ) );
@@ -452,16 +436,116 @@ unsigned char category_fs_restock ( mm_category_t *cat ) {
 }
 
 static int catname_cmp ( const void *p1, const void *p2 ) {
-  mm_category_t *c1 = (mm_category_t*) p1;
-  mm_category_t *c2 = (mm_category_t*) p2;
-  return ( strcasecmp ( c1 -> catname, c2 -> catname ) );
+  //mm_category_t *c1 = (mm_category_t*) p1;
+  //mm_category_t *c2 = (mm_category_t*) p2;
+  mm_category_t *c1 = *( (mm_category_t**) p1 );
+  mm_category_t *c2 = *( (mm_category_t**) p2 );
+
+  if ( ( isalnum ( c1 -> catname [ 0 ] ) ) && ( ! isalnum ( c1 -> catname [ 1 ] ) ) ) {
+    return ( -1 );
+  } else if ( ( ! isalnum ( c1 -> catname [ 0 ] ) ) && ( isalnum ( c1 -> catname [ 1 ] ) ) ) {
+    return ( 1 );
+  } else if ( ( ! isalnum ( c1 -> catname [ 0 ] ) ) && ( ! isalnum ( c1 -> catname [ 1 ] ) ) ) {
+    return ( 0 );
+  }
+
+  int i = strcasecmp ( c1 -> catname, c2 -> catname );
+  //printf ( "cat name compare %p %s to %p %s = %d\n", p1, c1 -> catname, p2, c2 -> catname, i );
+
+  return ( i );
 }
 
 void category_sort ( void ) {
   // we probably don't want to sort tab categories, since the user may have specified an ordering
   // But we can sort invisi-cats, to make them easier to find, and ordered by parent category
 
+#if 0
   qsort ( _categories_invis, _categories_inviscount, sizeof(mm_category_t), catname_cmp );
+#endif
+
+#if 1
+  qsort ( g_categories, g_categorycount, sizeof(mm_category_t*), catname_cmp );
+#endif
 
   return;
 }
+
+void category_publish ( unsigned int filter_mask, char *param ) {
+  unsigned char interested;
+
+  // clear published categories
+  memset ( g_categories, '\0', sizeof(mm_category_t*) * MAX_CATS );
+  g_categorycount = 0;
+
+  // figure out the start
+  mm_category_t *iter = pnd_box_get_head ( m_categories );
+
+  // for each category we know...
+  while ( iter ) {
+
+    interested = 0;
+
+    // is this category desired?
+    if ( filter_mask == CFALL ) {
+      interested = 1;
+    } else if ( iter -> catflags == filter_mask ) {
+      interested = 1;
+    } // if
+
+    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++;
+    }
+
+    // next
+    iter = pnd_box_get_next ( iter );
+  }
+
+  // dump
+#if 0
+  unsigned int i;
+  for ( i = 0; i < g_categorycount; i++ ) {
+    printf ( "Unsorted cat %d %p: %s\n", i, &(g_categories [ i ]), g_categories [ i ] -> catname );
+  }
+#endif
+
+  // sort published categories
+  category_sort();
+
+  return;
+}
+
+unsigned int category_count ( unsigned int filter_mask ) {
+  mm_category_t *iter = pnd_box_get_head ( m_categories );
+  unsigned int count = 0;
+
+  // for each category we know...
+  while ( iter ) {
+
+    // is this category desired?
+    if ( iter -> catflags == filter_mask ) {
+      count++;
+    } // if
+
+    // next
+    iter = pnd_box_get_next ( iter );
+  }
+
+  return ( count );
+}
+
+int category_index ( char *catname ) {
+  unsigned char i;
+  for ( i = 0; i < g_categorycount; i++ ) {
+    if ( strcasecmp ( g_categories [ i ] -> catname, catname ) == 0 ) {
+      return ( i );
+    }
+  }
+  return ( -1 );
+}
index a1f8142..c886f2d 100644 (file)
@@ -2,6 +2,11 @@
 #ifndef h_mmcat_h
 #define h_mmcat_h
 
+/* code for storing/retrieving/messing with 'categories' (ie: tabs, more or less)
+ */
+
+// an appreg is a minimenu registered app, that in turn points to the libpnd disco-t entry, but also stores anything
+// minimenu specific about it.
 typedef struct _mm_appref_t {
   pnd_disco_t *ref;
   pnd_conf_handle ovrh;
@@ -9,26 +14,38 @@ typedef struct _mm_appref_t {
   struct _mm_appref_t *next;
 } mm_appref_t;
 
-typedef struct {
+// an actual category reference; points to a list of appref's and supplies a tabname, a filesystem mountpoint, etc.
+typedef struct _mm_category_t {
   char *catname;          // name of the category
+  unsigned int catflags;  // flags
+
   // current applications
   mm_appref_t *refs;      // apps (from g_active_apps) that are in this category
   unsigned int refcount;  // how many apps in this category
+
   // if a directory browser category, additional info is needed
   char *fspath;           // NULL if a pnd-category (not a filesystem category)
   pnd_box_handle disco;   // faux-applications generated from filesystem (so that refs can point to here)
+
 } mm_category_t;
 
-#define MAX_CATS 200
+// the flags available for the above mm_category_t.catflags
+#define CFNORMAL 1 // catflag
+#define CFHIDDEN 2 // catflag: 1, 2, 4,...
+#define CFSUBCAT 4 // catflag
+
+// how many cats can we handle?
+#define MAX_CATS 250
 
+// what do we call the "All" tab, if present
 #define CATEGORY_ALL "All"
 
 // try to populate as many cats as necessary
-unsigned char category_push ( char *catname, pnd_disco_t *app, pnd_conf_handle ovrh, char *fspath ); // catname is not pulled from app, so we can make them up on the fly (ie: "All");
-mm_category_t *category_query ( char *catname );
+void category_init ( void ); // set up; call first!
+unsigned char category_push ( char *catname, pnd_disco_t *app, pnd_conf_handle ovrh, char *fspath, unsigned char visiblep ); // catname is not pulled from app, so we can make them up on the fly (ie: "All");
 void category_dump ( void ); // sort the apprefs
 void category_freeall ( void );
-int cat_sort_score ( mm_appref_t *s1, mm_appref_t *s2 ); // like strcmp, but used to sort apps by title
+int cat_sort_score ( mm_category_t *cat, mm_appref_t *s1, mm_appref_t *s2 ); // like strcmp, but used to sort apps by title
 void category_sort ( void ); // for sorting categories
 
 // category mapping hack
@@ -44,4 +61,14 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco
 // filesystem browser
 unsigned char category_fs_restock ( mm_category_t *cat );
 
+// advertising to rest of the system
+//
+extern mm_category_t *g_categories [ MAX_CATS ];
+extern unsigned char g_categorycount;
+#define CFALL    0xFF // filter mask
+#define CFBYNAME 0xFE // filter mask; the name param is used to pick a single category to populate
+void category_publish ( unsigned int filter_mask, char *param ); // populates g_categories and g_categorycount; pass in CFNORMAL or CFHIDDEN or CFALL or whatever
+unsigned int category_count ( unsigned int filter_mask );
+int category_index ( char *catname ); // figure out index in g_categories of named cat
+
 #endif
index 0923a34..b25ec9c 100644 (file)
@@ -70,10 +70,6 @@ confitem_t pages[] = {
 extern pnd_conf_handle g_conf;
 extern SDL_Surface *sdl_realscreen;
 extern mm_imgcache_t g_imagecache [ IMG_TRUEMAX ];
-extern mm_category_t *g_categories;
-extern unsigned char g_categorycount;
-extern mm_category_t _categories_invis [ MAX_CATS ];
-extern unsigned char _categories_inviscount;
 extern pnd_box_handle g_active_apps;
 
 unsigned char conf_run_menu ( confitem_t *toplevel ) {
@@ -179,21 +175,21 @@ unsigned char conf_run_menu ( confitem_t *toplevel ) {
                if ( v ) {
                  unsigned char n = 0;
                  for ( n = 0; n < g_categorycount; n++ ) {
-                   if ( strcmp ( v, g_categories [ n ].catname ) == 0 ) {
+                   if ( strcmp ( v, g_categories [ n ] -> catname ) == 0 ) {
                      break;
                    }
                  }
                  if ( n < g_categorycount ) {
                    if ( left && n ) {
-                     pnd_conf_set_char ( g_conf, page [ sel ].key, g_categories [ n - 1 ].catname );
+                     pnd_conf_set_char ( g_conf, page [ sel ].key, g_categories [ n - 1 ] -> catname );
                    } else if ( ! left && n + 1 < g_categorycount ) {
-                     pnd_conf_set_char ( g_conf, page [ sel ].key, g_categories [ n + 1 ].catname );
+                     pnd_conf_set_char ( g_conf, page [ sel ].key, g_categories [ n + 1 ] -> catname );
                    }
                  } else {
-                   pnd_conf_set_char ( g_conf, page [ sel ].key, g_categories [ 0 ].catname );
+                   pnd_conf_set_char ( g_conf, page [ sel ].key, g_categories [ 0 ] -> catname );
                  }
                } else {
-                 pnd_conf_set_char ( g_conf, page [ sel ].key, g_categories [ 0 ].catname );
+                 pnd_conf_set_char ( g_conf, page [ sel ].key, g_categories [ 0 ] -> catname );
                }
              } // if category count
            }
@@ -564,60 +560,52 @@ unsigned char conf_prepare_page ( confitem_t *page ) {
 
       template -> text = ""; // so it won't get repopulated again later
 
-      typedef struct {
-       mm_category_t *cat;
-       unsigned char n;
-      } _foo;
-      _foo cats [ 2 ];
-      cats [ 0 ].cat = g_categories;
-      cats [ 0 ].n = g_categorycount;
-      cats [ 1 ].cat = _categories_invis;
-      cats [ 1 ].n = _categories_inviscount;
+      // switch categories being published
+      category_publish ( CFALL, NULL );
 
       // for each tab
-      unsigned int i, j;
-      for ( j = 0; j < 2; j++ ) {
-       mm_category_t *cc = cats [ j ].cat;
-       unsigned char cn = cats [ j ].n;
-       char catname [ 512 ];
-       char *actual_catname;
-
-       for ( i = 0;  i < cn; i++ ) {
-
-         // if this is an invisi-guy, it has parent-cat prepended; we want the real cat name.
-         strncpy ( catname, cc [ i ].catname, 500 );
-         if ( ( actual_catname = strchr ( catname, '.' ) ) ) {
-           actual_catname++; // skip the period
-         } else {
-           actual_catname = catname;
-         }
-         //fprintf ( stderr, "conf ui; got '%s' but showing '%s'\n", cc [ i ].catname, actual_catname );
+      unsigned int i;
+      char catname [ 512 ];
+      char *actual_catname;
 
-         if ( strncmp ( cc [ i ].catname, "All ", 4 ) == 0 ) {
-           // skip All tab, since it is generated, and managed by another config item
-           continue;
-         }
+      for ( i = 0;  i < g_categorycount; i++ ) {
 
-         p -> text = strndup ( actual_catname, 40 );
-         p -> desc = NULL;
-         p -> def = NULL;
+       // if this is an invisi-guy, it has parent-cat prepended; we want the real cat name.
+       strncpy ( catname, g_categories [ i ] -> catname, 500 );
 
-         sprintf ( buffer, "%s.%s", template -> key, actual_catname );
-         p -> key = strdup ( buffer );
-         p -> type = ct_boolean;
-         p -> newhead = NULL;
+       if ( ( actual_catname = strchr ( catname, '.' ) ) ) {
+         actual_catname++; // skip the period
+       } else {
+         actual_catname = catname;
+       }
+       //fprintf ( stderr, "conf ui; got '%s' but showing '%s'\n", cc [ i ].catname, actual_catname );
 
-         // create to positive if not existant
-         if ( ! pnd_conf_get_as_char ( g_conf, buffer ) ) {
-           pnd_conf_set_char ( g_conf, buffer, "1" );
-         }
+       if ( strncmp ( g_categories [ i ] -> catname, "All ", 4 ) == 0 ) {
+         // skip All tab, since it is generated, and managed by another config item
+         continue;
+       }
+
+       p -> text = strndup ( actual_catname, 40 );
+       p -> desc = NULL;
+       p -> def = NULL;
 
-         //fprintf ( stderr, "Created tabshow entry '%s'\n", cc [ i ].catname );
+       sprintf ( buffer, "%s.%s", template -> key, actual_catname );
+       p -> key = strdup ( buffer );
+       p -> type = ct_boolean;
+       p -> newhead = NULL;
 
-         p++;
+       // create to positive if not existant
+       if ( ! pnd_conf_get_as_char ( g_conf, buffer ) ) {
+         pnd_conf_set_char ( g_conf, buffer, "1" );
        }
 
-      }
+       //fprintf ( stderr, "Created tabshow entry '%s'\n", cc [ i ].catname );
+
+       p++;
+      } // for
+
+      // switch categories being published
+      category_publish ( CFNORMAL, NULL );
 
       break;
     }
index 0d427a9..0709a31 100644 (file)
@@ -355,9 +355,12 @@ int main ( int argc, char *argv[] ) {
     emit_and_quit ( MM_QUIT );
   }
 
+  // init categories
+  category_init();
+
   // create all cat
   if ( pnd_conf_get_as_int_d ( g_conf, "categories.do_all_cat", 1 ) ) {
-    category_push ( g_x11_present ? CATEGORY_ALL "    (X11)" : CATEGORY_ALL "   (No X11)", NULL /*app*/, 0, NULL /* fspath */ );
+    category_push ( g_x11_present ? CATEGORY_ALL "    (X11)" : CATEGORY_ALL "   (No X11)", NULL /*app*/, 0, NULL /* fspath */, 1 /* visible */ );
   }
 
   // set up category mappings
@@ -670,7 +673,7 @@ void applications_scan ( void ) {
        // push to All category
        // we do this first, so first category is always All
        if ( pnd_conf_get_as_int_d ( g_conf, "categories.do_all_cat", 1 ) ) {
-         category_push ( g_x11_present ? CATEGORY_ALL "    (X11)" : CATEGORY_ALL "   (No X11)", iter, ovrh, NULL /* fspath */ );
+         category_push ( g_x11_present ? CATEGORY_ALL "    (X11)" : CATEGORY_ALL "   (No X11)", iter, ovrh, NULL /* fspath */, 1 /* visible */ );
        } // all?
 
        // is this app suppressed? if not, show it in whatever categories the user is allowing
@@ -696,9 +699,6 @@ void applications_scan ( void ) {
     itercount++;
   } // while
 
-  // sort (some) categories
-  category_sort();
-
   // set up filesystem browser tabs
   if ( pnd_conf_get_as_int_d ( g_conf, "filesystem.do_browser", 0 ) ) {
     char *searchpath = pnd_conf_get_as_char ( g_conf, "filesystem.tab_searchpaths" );
@@ -715,7 +715,7 @@ void applications_scan ( void ) {
 
       // check if dir is empty; if so, skip it.
       if ( ! is_dir_empty ( buffer ) ) {
-       category_push ( tabname /* tab name */, NULL /* app */, 0 /* override */, buffer /* fspath */ );
+       category_push ( tabname /* tab name */, NULL /* app */, 0 /* override */, buffer /* fspath */, 1 /* visible */ );
       }
 
     }
@@ -726,6 +726,9 @@ void applications_scan ( void ) {
   // dump categories
   //category_dump();
 
+  // publish desired categories
+  category_publish ( CFNORMAL, NULL );
+
   // let deferred icon cache go now
   ui_post_scan();
 
index a43797a..ebfe706 100644 (file)
@@ -81,11 +81,6 @@ ui_context_t ui_display_context;        // display paramaters: see mmui_context.
 unsigned char ui_detail_hidden = 0;     // if >0, detail panel is hidden
 // FUTURE: If multiple panels can be shown/hidden, convert ui_detail_hidden to a bitmask
 
-extern mm_category_t *g_categories;
-extern unsigned char g_categorycount;
-extern mm_category_t _categories_invis [ MAX_CATS ];
-extern unsigned char _categories_inviscount;
-
 static SDL_Surface *ui_scale_image ( SDL_Surface *s, unsigned int maxwidth, int maxheight ); // height -1 means ignore
 static int ui_selected_index ( void );
 
@@ -344,15 +339,15 @@ void ui_render ( void ) {
   ui_context_t *c = &ui_display_context; // for convenience and shorthand
 
   // how many total rows do we need?
-  icon_rows = g_categories [ ui_category ].refcount / c -> col_max;
-  if ( g_categories [ ui_category ].refcount % c -> col_max > 0 ) {
+  icon_rows = g_categories [ ui_category ] -> refcount / c -> col_max;
+  if ( g_categories [ ui_category ] -> refcount % c -> col_max > 0 ) {
     icon_rows++;
   }
 
 #if 1
   // if no selected app yet, select the first one
   if ( ! ui_selected && pnd_conf_get_as_int_d ( g_conf, "minimenu.start_selected", 0 ) ) {
-    ui_selected = g_categories [ ui_category ].refs;
+    ui_selected = g_categories [ ui_category ] -> refs;
   }
 #endif
 
@@ -518,7 +513,7 @@ void ui_render ( void ) {
 
          // draw text
          SDL_Surface *rtext;
-         rtext = TTF_RenderText_Blended ( g_tab_font, g_categories [ col ].catname, c -> fontcolor );
+         rtext = TTF_RenderText_Blended ( g_tab_font, g_categories [ col ] -> catname, c -> fontcolor );
          src.x = 0;
          src.y = 0;
          src.w = rtext -> w < text_width ? rtext -> w : text_width;
@@ -646,9 +641,9 @@ void ui_render ( void ) {
       }
     }
 
-    if ( g_categories [ ui_category ].refs ) {
+    if ( g_categories [ ui_category ] -> refs ) {
 
-      appiter = g_categories [ ui_category ].refs;
+      appiter = g_categories [ ui_category ] -> refs;
       row = 0;
       displayrow = 0;
 
@@ -1343,8 +1338,8 @@ void ui_process_input ( unsigned char block_p ) {
        // many SDLK_keycodes map to ASCII ("a" is ascii(a)), so try to jump to a filename of that name, in this category?
        // and if already there, try to jump to next, maybe?
        // future: look for sequence typing? ie: user types 'm' then 'a', look for 'ma*' instead of 'm' then 'a' matching
-       if ( isalpha ( event.key.keysym.sym ) && g_categories [ ui_category ].refcount > 0 ) {
-         mm_appref_t *app = g_categories [ ui_category ].refs;
+       if ( isalpha ( event.key.keysym.sym ) && g_categories [ ui_category ] -> refcount > 0 ) {
+         mm_appref_t *app = g_categories [ ui_category ] -> refs;
 
          //fprintf ( stderr, "sel %s next %s\n", ui_selected -> ref -> title_en, ui_selected -> next -> ref -> title_en );
 
@@ -1447,12 +1442,12 @@ void ui_push_left ( unsigned char forcecoil ) {
       i--;
     }
 
-  } else if ( g_categories [ ui_category ].refs == ui_selected ) {
+  } else if ( g_categories [ ui_category ] -> refs == ui_selected ) {
     // can't go any more left, we're at the head
 
   } else {
     // figure out the previous item; yay for singly linked list :/
-    mm_appref_t *i = g_categories [ ui_category ].refs;
+    mm_appref_t *i = g_categories [ ui_category ] -> refs;
     while ( i ) {
       if ( i -> next == ui_selected ) {
        ui_selected = i;
@@ -1499,7 +1494,7 @@ void ui_push_right ( unsigned char forcecoil ) {
     }
 
   } else {
-    ui_selected = g_categories [ ui_category ].refs;
+    ui_selected = g_categories [ ui_category ] -> refs;
   }
 
   ui_set_selected ( ui_selected );
@@ -1525,7 +1520,7 @@ void ui_push_up ( void ) {
     unsigned int col = ui_determine_screen_col ( ui_selected );
 
     // go to end
-    ui_selected = g_categories [ ui_category ].refs;
+    ui_selected = g_categories [ ui_category ] -> refs;
     while ( ui_selected -> next ) {
       ui_selected = ui_selected -> next;
     }
@@ -1568,8 +1563,8 @@ void ui_push_down ( void ) {
     unsigned int row = ui_determine_row ( ui_selected );
 
     // max rows?
-    unsigned int icon_rows = g_categories [ ui_category ].refcount / col_max;
-    if ( g_categories [ ui_category ].refcount % col_max > 0 ) {
+    unsigned int icon_rows = g_categories [ ui_category ] -> refcount / col_max;
+    if ( g_categories [ ui_category ] -> refcount % col_max > 0 ) {
       icon_rows++;
     }
 
@@ -1580,7 +1575,7 @@ void ui_push_down ( void ) {
 
       unsigned char col = ui_determine_screen_col ( ui_selected );
 
-      ui_selected = g_categories [ ui_category ].refs;
+      ui_selected = g_categories [ ui_category ] -> refs;
 
       while ( col ) {
        ui_selected = ui_selected -> next;
@@ -1628,7 +1623,7 @@ void ui_push_exec ( void ) {
        char *c;
 
        // lop off last word; if the thing ends with /, lop that one, then the next word.
-       while ( ( c = strrchr ( g_categories [ ui_category].fspath, '/' ) ) ) {
+       while ( ( c = strrchr ( g_categories [ ui_category] -> fspath, '/' ) ) ) {
          *c = '\0'; // lop off the last hunk
          if ( *(c+1) != '\0' ) {
            break;
@@ -1636,27 +1631,26 @@ void ui_push_exec ( void ) {
        } // while
 
        // nothing left?
-       if ( g_categories [ ui_category].fspath [ 0 ] == '\0' ) {
-         strcpy ( g_categories [ ui_category].fspath, "/" );
+       if ( g_categories [ ui_category] -> fspath [ 0 ] == '\0' ) {
+         free ( g_categories [ ui_category] -> fspath );
+         g_categories [ ui_category] -> fspath = strdup ( "/" );
        }
 
       } else {
        // go down
-       char *temp = malloc ( strlen ( g_categories [ ui_category].fspath ) + strlen ( ui_selected -> ref -> title_en ) + 1 + 1 );
-       sprintf ( temp, "%s/%s", g_categories [ ui_category].fspath, ui_selected -> ref -> title_en );
-       free ( g_categories [ ui_category].fspath );
-       g_categories [ ui_category].fspath = temp;
-       //strcat ( g_categories [ ui_category].fspath, "/" );
-       //strcat ( g_categories [ ui_category].fspath, ui_selected -> ref -> title_en );
+       char *temp = malloc ( strlen ( g_categories [ ui_category] -> fspath ) + strlen ( ui_selected -> ref -> title_en ) + 1 + 1 );
+       sprintf ( temp, "%s/%s", g_categories [ ui_category] -> fspath, ui_selected -> ref -> title_en );
+       free ( g_categories [ ui_category] -> fspath );
+       g_categories [ ui_category] -> fspath = temp;
       }
 
-      pnd_log ( pndn_debug, "Cat %s is now in path %s\n", g_categories [ ui_category ].catname, g_categories [ ui_category ].fspath );
+      pnd_log ( pndn_debug, "Cat %s is now in path %s\n", g_categories [ ui_category ] -> catname, g_categories [ ui_category ]-> fspath );
 
       // forget the selection, nolonger applies
       ui_selected = NULL;
       ui_set_selected ( ui_selected );
       // rescan the dir
-      category_fs_restock ( &(g_categories [ ui_category ]) );
+      category_fs_restock ( g_categories [ ui_category ] );
       // redraw the grid
       render_mask |= CHANGED_SELECTION;
 
@@ -1695,7 +1689,7 @@ void ui_push_exec ( void ) {
        // popen test
        {
          char popenbuf [ FILENAME_MAX ];
-         snprintf ( popenbuf, FILENAME_MAX, "%s %s/%s", MIMETYPE_EXE, g_categories [ ui_category ].fspath, ui_selected -> ref -> title_en );
+         snprintf ( popenbuf, FILENAME_MAX, "%s %s/%s", MIMETYPE_EXE, g_categories [ ui_category ] -> fspath, ui_selected -> ref -> title_en );
 
          FILE *marceau;
          if ( ! ( marceau = popen ( popenbuf, "r" ) ) ) {
@@ -1738,17 +1732,17 @@ void ui_push_exec ( void ) {
 
        // full path to executable so we don't rely on implicit "./"
        char execbuf [ FILENAME_MAX ];
-       snprintf ( execbuf, FILENAME_MAX, "%s/%s", g_categories [ ui_category ].fspath, ui_selected -> ref -> title_en );
+       snprintf ( execbuf, FILENAME_MAX, "%s/%s", g_categories [ ui_category ] -> fspath, ui_selected -> ref -> title_en );
 
        // do it!
-       chdir ( g_categories [ ui_category ].fspath );
+       chdir ( g_categories [ ui_category ] -> fspath );
        exec_raw_binary ( execbuf /*ui_selected -> ref -> title_en*/ );
        chdir ( cwd );
 #else
        // DEPRECATED / NOT TESTED
        // get mmwrapper to run it
        char buffer [ PATH_MAX ];
-       sprintf ( buffer, "%s %s/%s\n", MM_RUN, g_categories [ ui_category ].fspath, ui_selected -> ref -> title_en );
+       sprintf ( buffer, "%s %s/%s\n", MM_RUN, g_categories [ ui_category ] -> fspath, ui_selected -> ref -> title_en );
        if ( pnd_conf_get_as_int_d ( g_conf, "minimenu.live_on_run", 0 ) == 0 ) {
          emit_and_quit ( buffer );
        } else {
@@ -1797,7 +1791,7 @@ void ui_push_ltrigger ( void ) {
 
   if ( ui_category > 0 ) {
     ui_category--;
-    category_fs_restock ( &(g_categories [ ui_category ]) );
+    category_fs_restock ( g_categories [ ui_category ] );
   } else {
     if ( pnd_conf_get_as_int_d ( g_conf, "tabs.wraparound", 0 ) > 0 ) {
       ui_category = g_categorycount - 1;
@@ -1805,7 +1799,7 @@ void ui_push_ltrigger ( void ) {
       if ( ui_category >= ( screen_width / tab_width ) ) {
        ui_catshift = ui_category - ( screen_width / tab_width ) + 1;
       }
-      category_fs_restock ( &(g_categories [ ui_category ]) );
+      category_fs_restock ( g_categories [ ui_category ] );
     }
   }
 
@@ -1839,12 +1833,12 @@ void ui_push_rtrigger ( void ) {
 
   if ( ui_category < ( g_categorycount - 1 ) ) {
     ui_category++;
-    category_fs_restock ( &(g_categories [ ui_category ]) );
+    category_fs_restock ( g_categories [ ui_category ] );
   } else {
     if ( pnd_conf_get_as_int_d ( g_conf, "tabs.wraparound", 0 ) > 0 ) {
       ui_category = 0;
       ui_catshift = 0;
-      category_fs_restock ( &(g_categories [ ui_category ]) );
+      category_fs_restock ( g_categories [ ui_category ] );
     }
   }
 
@@ -2050,7 +2044,7 @@ int ui_selected_index ( void ) {
     return ( -1 ); // no index
   }
 
-  mm_appref_t *r = g_categories [ ui_category ].refs;
+  mm_appref_t *r = g_categories [ ui_category ] -> refs;
   int counter = 0;
   while ( r ) {
     if ( r == ui_selected ) {
@@ -2257,7 +2251,7 @@ int ui_modal_single_menu ( char *argv[], unsigned int argc, char *title, char *f
 unsigned char ui_determine_row ( mm_appref_t *a ) {
   unsigned int row = 0;
 
-  mm_appref_t *i = g_categories [ ui_category ].refs;
+  mm_appref_t *i = g_categories [ ui_category ] -> refs;
   while ( i != a ) {
     i = i -> next;
     row++;
@@ -2274,7 +2268,7 @@ unsigned char ui_determine_screen_row ( mm_appref_t *a ) {
 unsigned char ui_determine_screen_col ( mm_appref_t *a ) {
   unsigned int col = 0;
 
-  mm_appref_t *i = g_categories [ ui_category ].refs;
+  mm_appref_t *i = g_categories [ ui_category ] -> refs;
   while ( i != a ) {
     i = i -> next;
     col++;
@@ -2435,7 +2429,7 @@ void ui_touch_act ( unsigned int x, unsigned int y ) {
        ui_category = t -> catnum;
        render_mask |= CHANGED_CATEGORY;
        // rescan the dir
-       category_fs_restock ( &(g_categories [ ui_category ]) );
+       category_fs_restock ( g_categories [ ui_category ] );
       }
 
       break;
@@ -2515,7 +2509,7 @@ void ui_post_scan ( void ) {
     // default behaviour will pick first cat (ie: usually All)
     unsigned int i;
     for ( i = 0; i < g_categorycount; i++ ) {
-      if ( strcasecmp ( g_categories [ i ].catname, dc ) == 0 ) {
+      if ( strcasecmp ( g_categories [ i ] -> catname, dc ) == 0 ) {
        ui_category = i;
        // ensure visibility
        unsigned int screen_width = ui_display_context.screen_width;
@@ -2533,6 +2527,12 @@ void ui_post_scan ( void ) {
 
   } // default cat
 
+  // if we're sent right to a dirbrowser tab, restock it now (normally we restock on entry)
+  if ( g_categories [ ui_category ] -> fspath ) {
+    printf ( "Restock on start: '%s'\n", g_categories [ ui_category ] -> fspath );
+    category_fs_restock ( g_categories [ ui_category ] );
+  }
+
   // redraw all
   render_mask |= CHANGED_EVERYTHING;
 
@@ -2894,40 +2894,43 @@ void ui_revealscreen ( void ) {
   unsigned int labelmax = 0;
   unsigned int i;
 
-  if ( ! _categories_inviscount ) {
+  if ( ! category_count ( CFHIDDEN ) ) {
     return; // nothing to do
   }
 
-  for ( i = 0; i < _categories_inviscount; i++ ) {
-    labels [ labelmax++ ] = _categories_invis [ i ].catname;
+  // switch to hidden categories
+  category_publish ( CFHIDDEN, NULL );
+
+  // build up labels to show in menu
+  for ( i = 0; i < g_categorycount; i++ ) {
+    labels [ labelmax++ ] = g_categories [ i ] -> catname;
   }
 
+  // show menu
   int sel = ui_modal_single_menu ( labels, labelmax, "Temporary Category Reveal",
                                   "Enter to select; other to return." );
 
+  // if selected, try to set this guy to visible
   if ( sel >= 0 ) {
 
-    if ( category_query ( _categories_invis [ sel ].catname ) ) {
-      // already present
-      return;
-    }
-
     // fix up category name, if its been hacked
-    if ( strchr ( _categories_invis [ sel ].catname, '.' ) ) {
-      char *t = _categories_invis [ sel ].catname;
-      _categories_invis [ sel ].catname = strdup ( strchr ( _categories_invis [ sel ].catname, '.' ) + 1 );
+    if ( strchr ( g_categories [ sel ] -> catname, '.' ) ) {
+      char *t = g_categories [ sel ] -> catname;
+      g_categories [ sel ] -> catname = strdup ( strchr ( g_categories [ sel ] -> catname, '.' ) + 1 );
       free ( t );
     }
-    // copy invisi-cat into live-cat
-    memmove ( &(g_categories [ g_categorycount ]), &(_categories_invis [ sel ]), sizeof(mm_category_t) );
-    g_categorycount++;
-    // move subsequent invisi-cats up, so the selected invisi-cat is nolonger existing in invisi-list at
-    // all (avoid double-free() later)
-    memmove ( &(_categories_invis [ sel ]), &(_categories_invis [ sel + 1 ]), sizeof(mm_category_t) * ( _categories_inviscount - sel - 1 ) );
-    _categories_inviscount--;
-
-    // switch to the new category
-    ui_category = g_categorycount - 1;
+
+    // reflag this guy to be visible
+    g_categories [ sel ] -> catflags = CFNORMAL;
+
+    // switch to the new category.. cache name.
+    char *switch_to_name = g_categories [ sel ] -> catname;
+
+    // republish categories
+    category_publish ( CFNORMAL, NULL );
+
+    // switch to the new category.. with the cached name!
+    ui_category = category_index ( switch_to_name );
 
     // ensure visibility
     unsigned int screen_width = ui_display_context.screen_width;