source: trunk/third/gnome-core/panel/menu-rh.c @ 16298

Revision 16298, 8.7 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r16297, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * GNOME panel menu module. redhat menu reading code
3 * (C) 1998 The Free Software Foundation
4 *
5 * Author: George Lebl
6 */
7
8#include <config.h>
9#include <ctype.h>
10#include <stdio.h>
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <sys/wait.h>
14#include <dirent.h>
15#include <unistd.h>
16#include <string.h>
17#include <limits.h>
18#include <errno.h>
19#include <gnome.h>
20
21#include "panel-include.h"
22
23/*#define PANEL_DEBUG 1*/
24
25/*for AnotherLevel menus to trigger rereading on directory writes*/
26static time_t rhsysdir_mtime = 0;
27static time_t rhuserdir_mtime = 0;
28
29void
30rh_submenu_to_display(GtkWidget *menuw, GtkMenuItem *menuitem)
31{
32        struct stat s;
33        int r;
34        int do_read = FALSE;
35        char *userrh;
36        if(!panel_file_exists(REDHAT_MENUDIR))
37                return;
38        userrh = gnome_util_prepend_user_home(".wmconfig/");
39
40        stat(REDHAT_MENUDIR,&s);
41
42        if(rhsysdir_mtime != s.st_mtime)
43                do_read = TRUE;
44
45        r = stat(userrh,&s);
46        if((r == -1 && rhuserdir_mtime) ||
47           (r != -1 && rhuserdir_mtime != s.st_mtime))
48                do_read = TRUE;
49
50        g_free(userrh);
51
52        if(do_read)
53                create_rh_menu(FALSE);
54}
55
56enum { RH_MENU_ITEM,RH_MENU_GROUP };
57typedef struct _RHMenuItem RHMenuItem;
58struct _RHMenuItem {
59        int type;
60        char *name;
61        union {
62                struct {
63                        char *description;
64                        char *icon;
65                        char *mini_icon;
66                        char *exec;
67                } item;
68                GSList *items;
69        } u;
70};
71
72static void
73free_rh_item(RHMenuItem *rh)
74{
75        if(!rh) return;
76        g_free(rh->name);
77        if(rh->type == RH_MENU_ITEM) {
78                g_free(rh->u.item.description);
79                g_free(rh->u.item.icon);
80                g_free(rh->u.item.mini_icon);
81                g_free(rh->u.item.exec);
82        } else {
83                g_slist_foreach(rh->u.items,(GFunc)free_rh_item,NULL);
84                g_slist_free(rh->u.items);
85        }
86        g_free(rh);
87}
88
89/*most likely one of the ugliest functions in existence*/
90static char *
91read_word(char **p)
92{
93        char *buf;
94        char *w;
95        int quoted;
96        int len;
97        if(!p) return NULL;
98        if(!*p) return NULL;
99        while(*(*p) == ' ' || *(*p) == '\t') (*p)++;
100        if(!(*(*p))) return NULL;
101        quoted = FALSE;
102        for(w=*p,len=0;
103            *w && (quoted || (*w!=' ' && *w!='\t'));
104            w++) {
105                if(*w=='"')
106                        quoted = !quoted;
107                else
108                        len++;
109        }
110        buf = g_malloc(len+1);
111        quoted = FALSE;
112        for(w=buf;*(*p) && (quoted || (*(*p)!=' ' && *(*p)!='\t'));(*p)++) {
113                if(*(*p)=='"')
114                        quoted = !quoted;
115                else {
116                        *w++ = *(*p);
117                }
118        }
119        *w='\0';
120        return buf;
121}
122
123static int
124sort_rh(RHMenuItem *a, RHMenuItem *b)
125{
126        if(a->type > b->type) return -1;
127        else if(a->type < b->type) return 1;
128        return strcmp(a->name,b->name);
129}
130
131static GSList *
132insert_rh_into_tree(GSList *list,RHMenuItem *rh,GSList *group)
133{
134        GSList *li;
135        RHMenuItem *ri;
136        if(!group)
137                return g_slist_insert_sorted(list,rh,(GCompareFunc)sort_rh);
138        for(li=list;li!=NULL;li=g_slist_next(li)) {
139                ri = li->data;
140                if(ri->type == RH_MENU_GROUP &&
141                   strcmp(ri->name,(char *)group->data)==0) {
142                        ri->u.items = insert_rh_into_tree(ri->u.items, rh,
143                                                          group->next);
144                        break;
145                }
146        }
147        /*we inserted it already*/
148        if(li) return list;
149       
150        ri = g_new0(RHMenuItem,1);
151        ri->type = RH_MENU_GROUP;
152        ri->name = g_strdup(group->data);
153        ri->u.items = insert_rh_into_tree(ri->u.items, rh,
154                                          group->next);
155        return g_slist_insert_sorted(list,ri,(GCompareFunc)sort_rh);
156}
157
158static void
159kill_amp (char *str)
160{
161        int len;
162       
163        if (str == NULL)
164                return;
165
166        len = strlen (str);
167
168        if (len > 0 &&
169            str[len-1] == '&') {
170                str[len-1] = '\0';
171
172                if (len > 1 &&
173                    str[len-2] == ' ')
174                        str[len-2] = '\0';
175        }
176}
177
178static GSList *
179add_redhat_entry(GSList *list, char *file)
180{
181        FILE *fp;
182        char *p,*w;
183        char buf[256];
184        GSList *group = NULL;
185       
186        RHMenuItem *rh = NULL;
187       
188        fp = fopen(file,"r");
189        if(!fp) return list;
190       
191        rh = g_new0(RHMenuItem,1);
192        while(fgets(buf,256,fp)) {
193                p = strchr(buf,'\n');
194                if(p) *p='\0';
195                p = buf;
196                g_free(read_word(&p)); /*XXX:ignore??*/
197                w = read_word(&p);
198                if (!w) ;
199                else if(strcmp(w,"name")==0) {
200                        g_free(rh->name);
201                        rh->name = read_word(&p);
202                } else if(strcmp(w,"description")==0) {
203                        g_free(rh->u.item.description);
204                        rh->u.item.description = read_word(&p);
205                } else if(strcmp(w,"icon")==0) {
206                        char *s = read_word(&p);
207                        g_free(rh->u.item.icon);
208                        if(*s == '/') {
209                                if(panel_file_exists(s))
210                                        rh->u.item.icon = s;
211                                else {
212                                        g_free(s);
213                                        rh->u.item.icon = NULL;
214                                }
215                        } else {
216                                rh->u.item.icon = g_concat_dir_and_file("/usr/share/icons", s);
217                                if(!panel_file_exists(rh->u.item.icon)) {
218                                        g_free(rh->u.item.icon);
219                                        rh->u.item.icon = gnome_pixmap_file(s);
220                                }
221                                g_free(s);
222                        }
223                } else if(strcmp(w,"mini-icon")==0) {
224                        char *s = read_word(&p);
225                        g_free(rh->u.item.mini_icon);
226                        if(*s == '/') {
227                                if(panel_file_exists(s))
228                                        rh->u.item.mini_icon = s;
229                                else {
230                                        g_free(s);
231                                        rh->u.item.mini_icon = NULL;
232                                }
233                        } else {
234                                rh->u.item.mini_icon = g_concat_dir_and_file("/usr/share/icons/mini", s);
235                                if(!panel_file_exists(rh->u.item.mini_icon)) {
236                                        g_free(rh->u.item.mini_icon);
237                                        rh->u.item.mini_icon = gnome_pixmap_file(s);
238                                }
239                                g_free(s);
240                        }
241                } else if(strcmp(w,"exec")==0) {
242                        g_free(rh->u.item.exec);
243                        rh->u.item.exec = read_word(&p);
244                        kill_amp (rh->u.item.exec);
245                } else if(strcmp(w,"group")==0) {
246                        char *sc;
247                        char *s = read_word(&p);
248
249                        if(group) {
250                                g_slist_foreach(group,(GFunc)g_free,NULL);
251                                g_slist_free(group);
252                                group = NULL;
253                        }
254                        sc = strtok(s,"/");
255                        while(sc) {
256                                group = g_slist_append(group, g_strdup(sc));
257                                sc = strtok(NULL,"/");
258                        }
259                        g_free(s);
260                }
261                g_free(w);
262        }
263        fclose(fp);
264        if(!rh->name || !rh->u.item.exec) {
265                if(group) {
266                        g_slist_foreach(group,(GFunc)g_free,NULL);
267                        g_slist_free(group);
268                }
269                free_rh_item(rh);
270                return list;
271        }
272        list = insert_rh_into_tree(list,rh,group);
273        g_slist_foreach(group,(GFunc)g_free,NULL);
274        g_slist_free(group);
275        return list;
276}
277
278
279static void
280make_rh_submenu(char *dir, GSList *rhlist)
281{
282        GSList *li;
283        FILE *fp;
284        char *order_file;
285        order_file = g_concat_dir_and_file(dir,".order");
286        fp = fopen(order_file,"w");
287        g_free(order_file);
288        for(li = rhlist;li!=NULL;li = g_slist_next(li)) {
289                RHMenuItem *ri = li->data;
290                GnomeDesktopEntry dentry = {0};
291                dentry.name = ri->name;
292                if(ri->type == RH_MENU_GROUP) {
293                        char *p;
294                        char *s;
295                        s = g_strdup(ri->name);
296                        dentry.type = "Directory";
297                        while((p=strchr(s,' '))) *p='_';
298
299                        p = g_concat_dir_and_file(dir,s);
300                        g_free(s);
301                        if(fp) fprintf(fp,"%s\n",sure_string(g_basename(p)));
302                        mkdir(p,0755);
303                        dentry.location = g_concat_dir_and_file(p,".directory");
304                       
305                        make_rh_submenu(p,ri->u.items);
306                        /* free up the strings */
307                        g_free(p);
308                } else {
309                        char *p;
310                        char *s;
311                        s = g_strconcat(ri->name,".desktop",NULL);
312                        while((p=strchr(s,' '))) *p='_';
313
314                        dentry.type = "Application";
315                        dentry.comment = ri->u.item.description;
316                        dentry.icon = ri->u.item.icon?
317                                ri->u.item.icon:
318                                ri->u.item.mini_icon;
319                        gnome_config_make_vector(ri->u.item.exec,
320                                                 &dentry.exec_length,
321                                                 &dentry.exec);
322                        dentry.location = g_concat_dir_and_file(dir,s);
323                        if(fp) fprintf(fp,"%s\n",s);
324                        /* free up the location */
325                        g_free(s);
326                }
327                gnome_desktop_entry_save(&dentry);
328                if(dentry.exec) g_strfreev(dentry.exec);
329                g_free(dentry.location);
330        }
331        if(fp) fclose(fp);
332}
333
334
335void
336create_rh_menu(int dofork)
337{
338        char *userrh = gnome_util_prepend_user_home(".wmconfig");
339        char *rhdir = gnome_util_home_file("apps-redhat");
340        GSList *rhlist = NULL;
341        int i;
342        char *dirs[3] = {REDHAT_MENUDIR,NULL,NULL};
343        struct stat s;
344        g_return_if_fail(userrh!=NULL);
345        g_return_if_fail(rhdir!=NULL);
346       
347        dirs[1] = userrh;
348        rhsysdir_mtime = rhuserdir_mtime = 0;
349        if(stat(REDHAT_MENUDIR,&s)!=-1)
350                rhsysdir_mtime = s.st_mtime;
351        else if(stat(userrh,&s)!=-1)
352                rhuserdir_mtime = s.st_mtime;
353
354        /*slightly hackish, but since this thing eats up a lot of
355          ram, and it leaves nothing in memory that we need, we
356          just fork a process to do it unless we need the data
357          synchroniously*/
358        if(dofork) {
359                int i = fork();
360                if(i>0) {
361                        g_free (userrh);
362                        g_free (rhdir);
363                        wait(NULL);
364                        return;
365                /*if fork failed, no need to worry we'll just do it
366                  in this process*/
367                } else if(i<0) {
368                        dofork = FALSE;
369                } else {
370                        /*we're in a child, so fork once more and
371                          exit the parent to not leave any zombies
372                          around*/
373                        if(fork()>0) {
374                                _exit(0);
375                        }
376                }
377        }
378
379        remove_directory(rhdir,FALSE);
380
381        /*read redhat wmconfig files*/
382        for(i=0;dirs[i];i++) {
383                DIR *dir;
384                struct dirent *dent;
385
386                dir = opendir (dirs[i]);
387                if(!dir) continue;
388                while((dent = readdir (dir)) != NULL) {
389                        char *p;
390                        if(dent->d_name[0] == '.' &&
391                           (dent->d_name[1] == '\0' ||
392                            (dent->d_name[1] == '.' &&
393                             dent->d_name[2] == '\0')))
394                                continue;
395                        p = g_strconcat(dirs[i],"/",dent->d_name,NULL);
396                        rhlist = add_redhat_entry(rhlist,p);
397                        /* free the list. */
398                        g_free(p);
399                }
400                closedir(dir);
401        }
402        g_free(userrh);
403        mkdir(rhdir,0755);
404        if(rhlist) {
405                make_rh_submenu(rhdir,rhlist);
406
407                g_slist_foreach(rhlist,(GFunc)free_rh_item,NULL);
408                g_slist_free(rhlist);
409        }
410        g_free(rhdir);
411        if(dofork)
412                _exit(0);
413}
Note: See TracBrowser for help on using the repository browser.