445a81dd27c016ee616534a74a66e4fdf6de36e9
[pandora-libraries.git] / minimenu / mmcustom_cats.c
1
2 #include <stdio.h>
3 #include <limits.h> /* for PATH_MAX */
4 #define __USE_GNU /* for strndup */
5 #include <string.h> /* for strdup */
6 #include <stdlib.h> /* getenv */
7
8 #include "pnd_container.h"
9 #include "pnd_conf.h"
10 #include "pnd_discovery.h"
11 #include "pnd_notify.h"
12 #include "pnd_dbusnotify.h"
13 #include "pnd_logger.h"
14
15 #include "mmenu.h"
16 #include "mmcustom_cats.h"
17
18 mmcustom_cat_t mmcustom_complete [ MMCUSTOM_CATS_MAX ];
19 unsigned int mmcustom_count = 0;
20
21 pnd_conf_handle g_custom_h = 0;
22
23 char *mmcustom_determine_path ( void ) {
24   char *home = getenv ( "HOME" );
25   static char path [ PATH_MAX ];
26   bzero ( path, PATH_MAX );
27
28   snprintf ( path, PATH_MAX - 1, "%s/%s", home ? home : ".", MMCUSTOM_CATS_PREF_FILENAME );
29
30   return ( path );
31 }
32
33 static unsigned char loaded = 0;
34 unsigned char mmcustom_setup ( void ) {
35
36   if ( ! loaded ) {
37     loaded = 1;
38
39     // inhale conf file
40     char *path = mmcustom_determine_path();
41
42     g_custom_h = pnd_conf_fetch_by_path ( path );
43
44     if ( ! g_custom_h ) {
45       pnd_log ( pndn_rem, "Custom category conf file %s not found; is okay.\n", path );
46       return ( 1 ); // file does not exist most likely
47     }
48
49     // find its head; if no head (empty file), bail
50     char *iter = pnd_box_get_head ( g_custom_h );
51
52     if ( ! iter ) {
53       pnd_log ( pndn_rem, "Custom category conf file %s is empty. Fine.\n", path );
54       return ( 1 );
55     }
56
57     // walk the conf, plucking out the values
58     while ( iter ) {
59       char *k = pnd_box_get_key ( iter );
60
61       // does this entry look like it is a custom category?
62       if ( strncmp ( k, MMCUSTOM_CATS_SECTION, strlen ( MMCUSTOM_CATS_SECTION ) ) == 0 ) {
63         // determine the actual category name part
64         k += ( strlen ( MMCUSTOM_CATS_SECTION ) + 1 );
65
66         mmcustom_complete [ mmcustom_count ].cat = strdup ( k );
67         if ( iter && strcmp ( iter, MMCUSTOM_CATS_NOCAT ) != 0 ) {
68           mmcustom_complete [ mmcustom_count ].parent_cat = strdup ( iter );
69         } else {
70           mmcustom_complete [ mmcustom_count ].parent_cat = NULL;
71         }
72
73         mmcustom_count += 1;
74
75       }
76
77       // next!
78       iter = pnd_box_get_next ( iter );
79
80     } // while
81
82     //pnd_log ( pndn_rem, "Found %u custom categories.\n", mmcustom_count );
83
84   } // loaded already?
85
86   return ( 1 );
87 }
88
89 void mmcustom_shutdown ( void ) {
90
91   bzero ( mmcustom_complete, sizeof(mmcustom_cat_t) * MMCUSTOM_CATS_MAX );
92   mmcustom_count = 0;
93   loaded = 0;
94
95   return;
96 }
97
98 unsigned char mmcustom_is_ready ( void ) {
99   return ( loaded );
100 }
101
102 unsigned char mmcustom_write ( char *fullpath /* if NULL, uses canonical location */ ) {
103
104   if ( ! fullpath ) {
105     fullpath = mmcustom_determine_path();
106   }
107
108   FILE *f = fopen ( fullpath, "w" );
109
110   if ( ! f ) {
111     return ( 0 );
112   }
113
114   int i;
115   for ( i = 0; i < mmcustom_count; i++ ) {
116     if ( mmcustom_complete [ i ].cat ) {
117       fprintf ( f, "%s.%s\t%s\n", MMCUSTOM_CATS_SECTION, mmcustom_complete [ i ].cat, mmcustom_complete [ i ].parent_cat ? mmcustom_complete [ i ].parent_cat : MMCUSTOM_CATS_NOCAT );
118     }
119   }
120
121   fclose ( f );
122
123   return ( 1 );
124 }
125
126 mmcustom_cat_t *mmcustom_query ( char *name, char *parentcatname ) {
127   int i;
128
129   // search for the cat/parent combination
130   for ( i = 0; i < mmcustom_count; i++ ) {
131     mmcustom_cat_t *p = &(mmcustom_complete [ i ]);
132
133     if ( strcasecmp ( p -> cat, name ) == 0 ) {
134
135       if ( parentcatname == NULL && p -> parent_cat == NULL ) {
136         return ( p );
137       } else if ( parentcatname && p -> parent_cat && strcasecmp ( p -> parent_cat, parentcatname ) == 0 ) {
138         return ( p );
139       }
140
141     }
142
143   } // for
144
145   return ( NULL );
146 }
147
148 mmcustom_cat_t *mmcustom_register ( char *catname, char *parentcatname ) {
149   mmcustom_complete [ mmcustom_count ].cat = strdup ( catname );
150   if ( parentcatname ) {
151     mmcustom_complete [ mmcustom_count ].parent_cat = strdup ( parentcatname );
152   }
153   mmcustom_count += 1;
154   return ( &(mmcustom_complete [ mmcustom_count - 1 ]) );
155 }
156
157 unsigned int mmcustom_count_subcats ( char *catname ) {
158   int i;
159   unsigned int counter = 0;
160
161   for ( i = 0; i < mmcustom_count; i++ ) {
162
163     if ( mmcustom_complete [ i ].parent_cat && strcasecmp ( mmcustom_complete [ i ].parent_cat, catname ) == 0 ) {
164       counter++;
165     }
166
167   }
168
169   return ( counter );
170 }
171
172 void mmcustom_unregister ( char *catname, char *parentcatname ) {
173   int i;
174   int parent_index = -1;
175
176   if ( parentcatname ) {
177     pnd_log ( pndn_warning, "Goal: Remove subcat %s of %s\n", catname, parentcatname );
178   } else {
179     pnd_log ( pndn_warning, "Goal: Remove parent cat %s and descendants\n", catname );
180   }
181
182   for ( i = 0; i < mmcustom_count; i++ ) {
183
184     // killing a parent cat, or just a subcat?
185     if ( parentcatname ) {
186
187       // killing a subcat, so match cat+subcat to kill
188       if ( mmcustom_complete [ i ].cat && strcmp ( mmcustom_complete [ i ].cat, catname ) == 0 &&
189            mmcustom_complete [ i ].parent_cat && strcasecmp ( mmcustom_complete [ i ].parent_cat, parentcatname ) == 0 )
190       {
191         pnd_log ( pndn_warning, "  Removing subcat: %s of %s\n", catname, parentcatname );
192         free ( mmcustom_complete [ i ].cat );
193         mmcustom_complete [ i ].cat = NULL;
194         break;
195       }
196
197     } else {
198
199       // killing a parent cat, so kill it, and any children of it
200       if ( mmcustom_complete [ i ].parent_cat == NULL &&
201            mmcustom_complete [ i ].cat &&
202            strcmp ( mmcustom_complete [ i ].cat, catname ) == 0 )
203       {
204         // flag the prent for future death (we need its name for now, since the caller is using it)
205         parent_index = i;
206       }
207       else if ( mmcustom_complete [ i ].cat &&
208                 mmcustom_complete [ i ].parent_cat &&
209                 strcmp ( mmcustom_complete [ i ].parent_cat, catname ) == 0 )
210       {
211         // kill children of it
212         pnd_log ( pndn_warning, "  Removing cascading subcat: %s of %s\n", mmcustom_complete [ i ].cat, mmcustom_complete [ i ].parent_cat );
213         free ( mmcustom_complete [ i ].cat );
214         mmcustom_complete [ i ].cat = NULL;
215       }
216
217     }
218
219   } // for
220
221   // kill the actual cat itself
222   if ( i >= 0 ) {
223     pnd_log ( pndn_warning, "  Removing cat: %s\n", catname );
224     free ( mmcustom_complete [ i ].cat );
225     mmcustom_complete [ i ].cat = NULL;
226   }
227
228   return;
229 }