1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: 4; c-basic-offset: 4 -*- */
3 /* cdemenu-desktop--method.c
5 Author: Stephen Browne <stephen.browne@sun.com>
7 Copyright (C) 2002 Sun Microsystems, Inc.
9 The Gnome Library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
14 The Gnome Library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
19 You should have received a copy of the GNU Library General Public
20 License along with the Gnome Library; see the file COPYING.LIB. If not,
21 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.
30 #include <sys/types.h>
42 #include <libgnomevfs/gnome-vfs-mime.h>
44 #include <libgnomevfs/gnome-vfs-module.h>
45 #include <libgnomevfs/gnome-vfs-method.h>
46 #include <libgnomevfs/gnome-vfs-utils.h>
47 #include <libgnomevfs/gnome-vfs-ops.h>
48 #include <libgnomevfs/gnome-vfs-module-shared.h>
49 #include <libgnomevfs/gnome-vfs-i18n.h>
52 #define CDE_ICON_NAME_CACHE "/.gnome/g-cdeiconnames"
54 static GSList *cdemenufiles;
56 typedef struct _DtFile DtFile;
63 static GnomeVFSMethod *parent_method = NULL;
66 find_title_for_menu (gchar *name)
75 for (filename = cdemenufiles; filename !=NULL; filename=filename->next){
76 file = fopen((gchar*)filename->data,"r");
77 while (fgets(line,LINESIZE,file) != NULL){
78 if (strstr(line,"f.menu") && strstr(line, name)) {
79 tmp = strstr (line, "f.menu");
81 title = strdup (line);
94 open_and_find_pointer_to_menu(gchar *name)
98 FILE *filesave = NULL, *file = NULL;
100 gboolean found = FALSE;
102 for (filename = cdemenufiles; filename !=NULL; filename=filename->next){
104 file = fopen((gchar*)filename->data,"r");
105 while (fgets(line,LINESIZE,file) != NULL){
106 if (strstr(line,"Menu") == line) {
109 temp = (strtok(line," "));
112 temp = (strtok(line,"\t"));
115 temp = g_strstrip(temp);
116 if (temp && !(strcmp(temp,name))) {
118 position = ftell (file);
121 temp = (strtok (NULL," "));
123 temp = (strtok (NULL,"\t"));
128 fseek (file, position, SEEK_SET);
129 if (filesave !=NULL) fclose(filesave);
131 if (!strcmp(name, "DtRootMenu")) break;
141 expand_env_vars(char *s)
143 char **tokens, **token;
147 tokens = g_strsplit(s,"/",30);
148 for (token = tokens; *token !=NULL; token++) {
153 tmp2 = tmp+(strlen(tmp))-1; *tmp2='\0';
155 tmp3 = g_getenv(tmp);
156 if (!tmp3 && strstr(tmp, "LC_CTYPE"))
157 /* It's not always the case $LC_CTYPE or $LANG is set */
158 tmp3 = (char*)setlocale(LC_CTYPE, NULL);
160 /* don't do g_strdup (s?s1:s2) as that doesn't work with
161 certain gcc 2.96 versions */
162 *token = tmp3 ? g_strdup(tmp3) : g_strdup("");
165 expanded = g_strjoinv("/", tokens);
170 /* This function is only used to make the default CDE menu look nice */
172 get_icon_for_menu (char *name)
174 /* Translate exactly the same in CDE's sys.dtwmrc file of the locale */
175 if (!strcmp(name, _("Applications")))
176 return ("/usr/dt/appconfig/icons/C/Dtapps.m.pm");
177 /* Translate exactly the same in CDE's sys.dtwmrc file of the locale */
178 if (!strcmp(name, _("Cards")))
179 return ("/usr/dt/appconfig/icons/C/SDtCard.m.pm");
180 /* Translate exactly the same in CDE's sys.dtwmrc file of the locale */
181 if (!strcmp(name, _("Files")))
182 return ("/usr/dt/appconfig/icons/C/Dtdata.m.pm");
183 /* Translate exactly the same in CDE's sys.dtwmrc file of the locale */
184 if (!strcmp(name, _("Folders")))
185 return ("/usr/dt/appconfig/icons/C/DtdirB.m.pm");
186 /* Translate exactly the same in CDE's sys.dtwmrc file of the locale */
187 if (!strcmp(name, _("Help")))
188 return ("/usr/dt/appconfig/icons/C/Dthelp.m.pm");
189 /* Translate exactly the same in CDE's sys.dtwmrc file of the locale */
190 if (!strcmp(name, _("Hosts")))
191 return ("/usr/dt/appconfig/icons/C/Dtterm.m.pm");
192 /* Translate exactly the same in CDE's sys.dtwmrc file of the locale */
193 if (!strcmp(name, _("Links")))
194 return ("/usr/dt/appconfig/icons/C/SDturlweb.m.pm");
195 /* Translate exactly the same in CDE's sys.dtwmrc file of the locale */
196 if (!strcmp(name, _("Mail")))
197 return ("/usr/dt/appconfig/icons/C/Dtmail.m.pm");
198 /* Translate exactly the same in CDE's sys.dtwmrc file of the locale */
199 if (!strcmp(name, _("Tools")))
200 return ("/usr/dt/appconfig/icons/C/SDtGears.m.pm");
201 /* Translate exactly the same in CDE's sys.dtwmrc file of the locale */
202 if (!strcmp(name, _("Windows")))
203 return ("/usr/dt/appconfig/icons/C/DtDtwm.m.pm");
208 get_icon_for_action(char *action)
210 gchar line[LINESIZE];
212 char **dir, *expandeddir, *fullpath=NULL;
214 char *icon_name_cache_path;
216 char *iconsearchpath[] = {"/usr/dt/appconfig/icons/$LC_CTYPE",
217 "/etc/dt/appconfig/icons/$LC_CTYPE",
219 "/usr/dt/appconfig/icons/C", NULL};
221 /*if action has arg strip the arg*/
222 if ((tmp=strchr(action,'\"'))) {*tmp='\0'; tmp=NULL;}
224 /*Return NULL icon if icon DB does not exist*/
225 icon_name_cache_path = g_strconcat (g_get_home_dir (), CDE_ICON_NAME_CACHE, NULL);
226 file = fopen(icon_name_cache_path,"r");
227 g_free(icon_name_cache_path);
228 if (!file) return NULL;
230 while (fgets(line,LINESIZE,file) != NULL){
231 if (strstr(line,action)){
232 if (fgets(line,LINESIZE,file) != NULL) {
233 if (strstr(line,"ICON")){
234 tmp = strchr(line,':');
235 if (tmp == NULL) return NULL;
237 tmp = g_strstrip(tmp);
238 for (dir = iconsearchpath; *dir != NULL; dir++) {
239 expandeddir = expand_env_vars(*dir);
240 fullpath = g_strdup_printf("%s/%s.m.pm",
242 if (g_file_test(fullpath,G_FILE_TEST_EXISTS)){
247 fullpath = g_strdup_printf("%s/%s.s.pm",
249 if (g_file_test(fullpath,G_FILE_TEST_EXISTS)){
252 } else g_free (fullpath);
265 get_title (gchar *line)
268 tmp = strchr (line, '\"');
270 tmp = g_strstrip (line);
274 tmp2 = strchr (tmp, '\"');
275 if(tmp2) *tmp2 = '\0';
277 return (g_strdup (tmp));
280 static GnomeVFSResult
281 do_open (GnomeVFSMethod *method,
282 GnomeVFSMethodHandle **method_handle,
284 GnomeVFSOpenMode mode,
285 GnomeVFSContext *context)
288 gchar *tmp, *tmp2, *end;
290 gchar line[LINESIZE];
291 gchar *name, *title, *exec=NULL, *icon=NULL;
292 gchar *menuname = g_path_get_basename(g_path_get_dirname(uri->text));
293 DtFile *dtfile = g_new0(DtFile, 1);
295 *method_handle = (GnomeVFSMethodHandle *)dtfile;
297 if (strcmp(menuname,"/") == 0) menuname = "DtRootMenu";
298 unescaped = gnome_vfs_unescape_string (menuname, NULL);
300 name = gnome_vfs_unescape_string (g_path_get_basename(uri->text), NULL);
301 /* Strip off the .desktop if this is a .desktop file */
302 tmp = strstr(name,".desktop"); if (tmp) *tmp='\0'; tmp=NULL;
304 file = open_and_find_pointer_to_menu (unescaped);
309 return GNOME_VFS_ERROR_NOT_FOUND;
312 if (strcmp(name,".directory") == 0) {
313 char *utf8_name = NULL;
315 if (!strcmp (unescaped, "DtRootMenu"))
316 title = g_strdup_printf ("\"%s\"",unescaped);
317 else title = find_title_for_menu (unescaped);
319 tmp = get_title (title);
321 utf8_name = g_locale_to_utf8 (tmp, -1,
324 /* fallback to avoid crash */
325 if (utf8_name == NULL)
326 utf8_name = g_strdup (tmp);
328 dtfile->contents = g_strdup_printf
331 /* Note that we include the utf-8
332 * translated name without a language
333 * specifier, but that's OK, it will
340 get_icon_for_menu(utf8_name));
346 while (fgets(line,LINESIZE,file) != NULL){
347 if (line[0] == '#') continue;
348 else if (line[0] == '}') break;
349 else if (strstr(line,name)){
350 if((tmp = strstr(line,"f.action")) != NULL){
351 char *utf8_name = NULL;
354 end = strchr(tmp,'\n');
356 exec=g_strdup_printf("dtaction %s",tmp);
357 icon=get_icon_for_action(tmp);
358 if (!icon) icon=g_strdup("NONE");
360 utf8_name = g_locale_to_utf8 (name, -1,
364 /* fallback to avoid crash */
365 if (utf8_name == NULL)
366 utf8_name = g_strdup (name);
368 dtfile->contents= g_strdup_printf
371 /* Note that we include the
372 * utf-8 translated name
374 * specifier, but that's
375 * OK, it will work */
381 "Type=Application\n",
386 } else if ((tmp = strstr(line,"f.exec"))!=NULL){
387 char *utf8_name = NULL;
390 tmp = g_strstrip(tmp);
391 /* strip off quotes */
392 if (*tmp == '\"') tmp++;
393 end = tmp+(strlen(tmp))-1;
394 if (*end == '\"') *end = '\0';
396 utf8_name = g_locale_to_utf8 (name, -1,
400 /* fallback to avoid crash */
401 if (utf8_name == NULL)
402 utf8_name = g_strdup (name);
404 dtfile->contents= g_strdup_printf
407 /* Note that we include the
408 * utf-8 translated name
410 * specifier, but that's
411 * OK, it will work */
417 "Type=Application\n",
427 dtfile->current=dtfile->contents;
434 static GnomeVFSResult
435 do_close (GnomeVFSMethod *method,
436 GnomeVFSMethodHandle *method_handle,
437 GnomeVFSContext *context)
440 DtFile *dtfile = (DtFile*)method_handle;
442 g_free(dtfile->contents);
447 static GnomeVFSResult
448 do_read (GnomeVFSMethod *method,
449 GnomeVFSMethodHandle *method_handle,
451 GnomeVFSFileSize num_bytes,
452 GnomeVFSFileSize *bytes_read,
453 GnomeVFSContext *context)
456 DtFile *dtfile = (DtFile *)method_handle;
457 if (dtfile->current == NULL) return GNOME_VFS_ERROR_EOF;
459 bytes = snprintf(buffer, num_bytes, "%s",dtfile->current);
460 if (bytes == -1 ) dtfile->current+=num_bytes;
461 else dtfile->current=NULL;
463 *bytes_read=(GnomeVFSFileSize)bytes;
468 static GnomeVFSResult
469 do_open_directory (GnomeVFSMethod *method,
470 GnomeVFSMethodHandle **method_handle,
472 GnomeVFSFileInfoOptions options,
473 GnomeVFSContext *context)
477 gchar *menuname = g_path_get_basename(uri->text);
478 if (strcmp(menuname,"/") == 0) menuname = "DtRootMenu";
480 unescaped = gnome_vfs_unescape_string (menuname, NULL);
482 file = open_and_find_pointer_to_menu(unescaped);
484 *method_handle = (GnomeVFSMethodHandle *)file;
488 return file ? GNOME_VFS_OK : GNOME_VFS_ERROR_NOT_FOUND;
491 static GnomeVFSResult
492 do_close_directory (GnomeVFSMethod *method,
493 GnomeVFSMethodHandle *method_handle,
494 GnomeVFSContext *context)
496 fclose((FILE *)method_handle);
501 static GnomeVFSResult
502 do_read_directory (GnomeVFSMethod *method,
503 GnomeVFSMethodHandle *method_handle,
504 GnomeVFSFileInfo *file_info,
505 GnomeVFSContext *context)
507 gchar line[LINESIZE];
508 gchar *tmp, *tmp2,*escaped_str;
509 FILE *file = (FILE *)method_handle;
510 /*static int sep=0;*/
512 file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_TYPE;
514 while (fgets(line,LINESIZE,file) != NULL){
515 if (line[0] == '#') continue;
516 else if (line[0] == '}') return GNOME_VFS_ERROR_EOF;
517 else if (strstr(line,"f.action") && (strstr(line,"ExitSession")
518 || strstr(line,"LockDisplay")
519 || strstr(line,"AddItemToMenu")
520 || strstr(line,"CustomizeWorkspaceMenu")
521 || strstr(line,"UpdateWorkspaceMenu"))) {
522 file_info->name = g_strdup("bogus.desktop");
523 file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
526 else if (strstr(line,"f.action") || strstr(line,"f.exec")) {
527 tmp2 = strstr (line, "f.");
530 tmp = get_title (line);
531 escaped_str = gnome_vfs_escape_string (tmp);
532 file_info->name = g_strdup_printf("%s.desktop",escaped_str);
533 file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
534 g_free (escaped_str);
539 else if (strstr(line,"f.separator")) {
540 file_info->name = g_strdup_printf("separator%d.desktop",
542 file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
543 sep++; if (sep>10) sep = 0;
547 else if (strstr(line,"f.menu")) {
548 tmp = strstr(line,"f.menu");
550 tmp = g_strstrip(tmp);
551 file_info->name = gnome_vfs_escape_string (tmp);
552 file_info->type = GNOME_VFS_FILE_TYPE_DIRECTORY;
560 static GnomeVFSResult
561 do_get_file_info (GnomeVFSMethod *method,
563 GnomeVFSFileInfo *file_info,
564 GnomeVFSFileInfoOptions options,
565 GnomeVFSContext *context)
567 GnomeVFSURI *file_uri;
568 GnomeVFSResult result;
572 /* FIXME: This isnt right at all but it satisfies gnome-vfs for now */
573 s = gnome_vfs_get_uri_from_local_path(cdemenufiles->data);
574 file_uri = gnome_vfs_uri_new(s);
577 result = (* parent_method->get_file_info) (parent_method,
582 gnome_vfs_uri_unref (file_uri);
588 do_is_local (GnomeVFSMethod *method,
589 const GnomeVFSURI *uri)
591 /* FIXME: This isn't always true, some cde menu files are remote */
595 /* gnome-vfs bureaucracy */
596 static GnomeVFSMethod method = {
597 sizeof (GnomeVFSMethod),
605 NULL, /* truncate handle */
610 NULL, /* file info from handle */
612 NULL, /* make directory */
613 NULL, /* remove directory */
617 NULL, /* set file info */
619 NULL, /* find directory */
620 NULL /* symbolic link */
624 find_all_included_files(gchar *filename)
627 gchar line[LINESIZE];
628 gchar *tmp, *expanded;
629 file = fopen(filename,"r");
630 while (fgets(line,LINESIZE,file) != NULL){
631 if (g_ascii_strncasecmp(line, "Include",7) == 0) {
632 while (fgets(line,LINESIZE,file) !=NULL){
633 if (line[0] == '#') continue;
634 if (line[0] == '{') continue;
635 else if (line[0] == '}') break;
636 tmp = g_strstrip(line);
637 if (tmp[0] == '\0') continue;
638 expanded = expand_env_vars(tmp);
639 if (g_file_test(expanded,G_FILE_TEST_EXISTS)){
640 cdemenufiles = g_slist_append(cdemenufiles,
642 find_all_included_files(expanded);
652 create_cde_icon_name_cache (void)
654 /* fork the dttypes command to create the icon name cache */
657 char *icon_name_cache_path;
659 if ((t = fork ()) < 0) {
660 g_error ("Unable to fork.");
662 /* On a Solaris box, waitpid() fails with an interrupted system call.
663 Hence, loop till it succeeds. Avoids zombies
665 while ((waitpid (t,NULL,0) == -1) && errno == EINTR);
667 icon_name_cache_path = g_strconcat (g_get_home_dir (), CDE_ICON_NAME_CACHE, NULL);
668 old_mask = umask(033);
669 fd = open (icon_name_cache_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
671 fchmod (fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
672 g_free(icon_name_cache_path);
674 execl("/usr/dt/bin/dttypes", "dttypes", "-w", "fld_name", "ICON",
675 "-l", "fld_name", "ICON", NULL);
680 vfs_module_init (const char *method_name,
685 char *icon_name_cache_path;
687 parent_method = gnome_vfs_method_get ("file");
689 if (parent_method == NULL) {
690 g_error ("Could not find 'file' method for gnome-vfs");
694 /* find the right cde menu file to start with */
696 files[0] = expand_env_vars("$HOME/.dt/$LC_CTYPE/dtwmrc");
697 files[1] = expand_env_vars("$HOME/.dt/dtwmrc");
698 files[2] = expand_env_vars("/etc/dt/config/$LC_CTYPE/sys.dtwmrc");
699 files[3] = g_strdup("/etc/dt/config/sys.dtwmrc");
700 files[4] = expand_env_vars("/usr/dt/config/$LC_CTYPE/sys.dtwmrc");
701 files[5] = g_strdup("/usr/dt/config/sys.dtwmrc");
702 files[6] = g_strdup("/usr/dt/config/C/sys.dtwmrc");
705 if (g_file_test(files[i],G_FILE_TEST_EXISTS)){
706 cdemenufiles = g_slist_append(cdemenufiles,
711 for (i=0;i<7;i++) g_free(files[i]);
713 /* if didnt find any menu start file then we are fecked */
714 if (cdemenufiles == NULL) return NULL;
716 /* from that file find a list of all included files */
717 find_all_included_files(cdemenufiles->data);
719 /*create the icon name cache if it does not exist*/
720 icon_name_cache_path = g_strconcat (g_get_home_dir (), CDE_ICON_NAME_CACHE, NULL);
721 if (!g_file_test(icon_name_cache_path, G_FILE_TEST_EXISTS))
722 create_cde_icon_name_cache();
724 g_free(icon_name_cache_path);
729 vfs_module_shutdown (GnomeVFSMethod *method)
731 /* free up any stuff in here */
733 g_slist_foreach(cdemenufiles, (GFunc)g_free, NULL);
734 g_slist_free(cdemenufiles);