menu-fentry.c 17 KB
Newer Older
1 2
/*
 * GNOME panel menu module.
3 4
 * (C) 1997, 1998, 1999, 2000 The Free Software Foundation
 * Copyright 2000 Eazel, Inc.
5 6 7 8 9 10 11 12
 *
 * Authors: Miguel de Icaza
 *          Federico Mena
 */

#include <config.h>
#include <ctype.h>
#include <stdio.h>
Asbjørn Pettersen's avatar
Asbjørn Pettersen committed
13
#include <sys/types.h>
14 15 16 17 18 19 20
#include <sys/stat.h>
#include <sys/wait.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
21

Mark McLoughlin's avatar
Mark McLoughlin committed
22
#include <libgnome/libgnome.h>
23

24 25 26 27 28 29
#include <libgnomevfs/gnome-vfs-mime-utils.h>
#include <libgnomevfs/gnome-vfs-uri.h>
#include <libgnomevfs/gnome-vfs-ops.h>
#include <libgnomevfs/gnome-vfs-directory.h>
#include <libgnomevfs/gnome-vfs-utils.h>

Mark McLoughlin's avatar
Mark McLoughlin committed
30
#include "menu-fentry.h"
31
#include "quick-desktop-reader.h"
Mark McLoughlin's avatar
Mark McLoughlin committed
32 33

#include "panel-util.h"
34
#include "panel-config-global.h"
Mark McLoughlin's avatar
Mark McLoughlin committed
35
#include "session.h"
36

37
#undef MENU_FENTRY_DEBUG
38

39 40 41
/* the minimum number of seconds between stats of files */
#define STAT_EVERY 3

42 43
static GSList *dir_list = NULL;

44 45
extern GlobalConfig global_config;

46
static GSList *
47 48 49 50 51
prepend_mfile (GSList *list,
	       const char *name,
	       gboolean verified,
	       time_t mtime,
	       gboolean is_dir)
52 53 54 55 56
{
	MFile *mfile = g_new0 (MFile, 1);

	mfile->name = g_strdup (name);
	mfile->verified = verified;
57 58
	mfile->mtime = mtime;
	mfile->is_dir = is_dir;
59 60 61 62 63

	return g_slist_prepend (list, mfile);
}

static MFile *
64
find_mfile (GSList *list, const char *string)
65 66 67 68 69 70 71 72 73
{
	GSList *li;

	g_return_val_if_fail (string != NULL, NULL);

	for (li = list; li != NULL; li = li->next) {
		MFile *mfile = li->data;

		if (mfile->name != NULL &&
74
		    strcmp (mfile->name, string) == 0)
75 76 77 78 79 80 81
			return mfile;
	}

	return NULL;
}


82
/*reads in the sort order and makes a list*/
83
static GSList *
84
get_presorted_from (const char *dir_uri)
85
{
86 87 88
	char *uri, *sort_order, *p;
	GSList *list = NULL;
	QuickDesktopItem *qitem;
89
	
90 91 92 93
	uri = g_build_path ("/", dir_uri, ".directory", NULL);
	qitem = quick_desktop_item_load_uri (uri,
					     NULL /* expected_type */,
					     FALSE /* run_tryexec */);
94

95
	g_free (uri);
96

97 98
	if (qitem == NULL)
		return NULL;
99

100 101 102
	/* steal sort_order, we're gonna mangle it */
	sort_order = qitem->sort_order;
	qitem->sort_order = NULL;
103

104
	quick_desktop_item_destroy (qitem);
105

106
	if (sort_order == NULL)
107 108
		return NULL;

109 110 111 112 113 114 115 116 117 118 119
	p = strtok (sort_order, ";");
	while (p != NULL) {
		list = prepend_mfile (list,
				      p /* name */,
				      FALSE /* verified */,
				      0 /* mtime */,
				      /* We don't know if it's
				       * a directory */
				      FALSE /* is_dir */);

		p = strtok (NULL, ";");
120 121
	}

122 123 124
	g_free (sort_order);

	return list;
125 126 127
}

static GSList *
128
read_directory (GSList *list, const char *menuuri)
129
{
130 131 132 133 134 135 136 137
	GnomeVFSDirectoryHandle *handle = NULL;

	if (gnome_vfs_directory_open (&handle, menuuri,
				      GNOME_VFS_FILE_INFO_DEFAULT)
	    == GNOME_VFS_OK) {
		GnomeVFSFileInfo *info = gnome_vfs_file_info_new ();
		while (gnome_vfs_directory_read_next (handle, info)
		       == GNOME_VFS_OK) {
138 139
			MFile *mfile;

140 141
			if (info->name[0] == '.') {
				gnome_vfs_file_info_clear (info);
142
				continue;
143
			}
144

145 146 147 148 149 150 151 152 153 154 155 156
			mfile = find_mfile (list, info->name);

			/* FIXME: what if there is no mtime in the info? */

			if (mfile == NULL) {
				list = prepend_mfile (list,
						      info->name,
						      TRUE /* verified */,
						      info->mtime,
						      (info->type == GNOME_VFS_FILE_TYPE_DIRECTORY));
			/* if we've already found it in the presorted,
			 * just verify it */
157
			} else {
158 159 160
				mfile->verified = TRUE;
				mfile->mtime = info->mtime;
				mfile->is_dir = (info->type == GNOME_VFS_FILE_TYPE_DIRECTORY);
161 162
			}

163
			gnome_vfs_file_info_clear (info);
164 165
		}

166 167
		gnome_vfs_file_info_unref (info);
		gnome_vfs_directory_close (handle);
168 169 170 171 172
	}

	return list;
}

173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
void
free_mfile (MFile *mfile)
{
	if (mfile != NULL) {
		g_free (mfile->name);
		mfile->name = NULL;

		g_free (mfile);
	}
}

void
free_mfile_list (GSList *list)
{
	GSList *li;
	for (li = list; li != NULL; li = li->next) {
		free_mfile (li->data);
		li->data = NULL;
	}
	g_slist_free (list);
}

195
GSList *
196
get_mfiles_from_menudir (const char *menuuri)
197 198 199
{
	GSList *list = NULL;

200 201
	list = get_presorted_from (menuuri);
	list = read_directory (list, menuuri);
202

203
	return g_slist_reverse (list);
204 205
}

206
static char *
207
get_applet_goad_id_from_ditem(QuickDesktopItem *ii)
208
{
209
#ifdef MENU_FENTRY_DEBUG
210
  printf ("GET THAT GOAD OUT OF HERE...menu-fentry.c get_applet_gaod_id_from_ditem\n");
211
#endif
212 213
  return NULL;
  /*
214
	int i;
215
	int constantlen = strlen ("--activate-goad-server");
216

217
	g_return_val_if_fail (ii != NULL, NULL);
218

219 220
	if (ii->exec == NULL ||
	    ii->type == NULL)
221
		return NULL;
222
	
223 224
	if (strcmp (ii->type, "PanelApplet") == 0) {
		return g_strjoinv (" ", ii->exec);
225
	} else {
226 227
		if (ii->exec[0] == NULL)
			return NULL;
228 229 230
		//this is here as a horrible hack since that's the way it
		//  used to work, but now one should make the .desktop type
		//  PanelApplet
231 232 233 234
		for(i=1;ii->exec[i];i++) {
			if(strncmp("--activate-goad-server",
				   ii->exec[i],constantlen)==0) {
				if(strlen(ii->exec[i])>constantlen)
235
					return g_strdup(&ii->exec[i][constantlen+1]);
236
				else
237
					return g_strdup(ii->exec[i+1]);
238
			}
239 240
		}
	}
241
	return NULL;
242
*/
243 244 245
}

static void
246
fr_free (FileRec *fr, gboolean free_fr)
247
{
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
	if (fr == NULL)
		return;

	g_free (fr->name);
	fr->name = NULL;
	g_free (fr->fullname);
	fr->fullname = NULL;
	g_free (fr->comment);
	fr->comment = NULL;
	g_free (fr->icon);
	fr->icon = NULL;
	g_free (fr->goad_id);
	fr->goad_id = NULL;
	g_free (fr->tryexec_path);
	fr->tryexec_path = NULL;

	if (fr->parent != NULL &&
	    free_fr)
		fr->parent->recs = g_slist_remove (fr->parent->recs, fr);
	fr->parent = NULL;

	if (fr->type == FILE_REC_DIR) {
270 271
		DirRec *dr = (DirRec *)fr;
		GSList *li;
272 273 274 275 276 277 278 279 280 281

		for (li = dr->mfl; li != NULL; li = li->next) {
			MenuFinfo *mf = li->data;
			li->data = NULL;
			mf->fr = NULL;
		}
		g_slist_free (dr->mfl);
		dr->mfl = NULL;

		for (li = dr->recs; li != NULL; li = li->next) {
282
			FileRec *ffr = li->data;
283
			li->data = NULL;
284
			ffr->parent = NULL;
285
			fr_free (ffr, TRUE);
286
		}
287
		g_slist_free (dr->recs);
288 289 290 291 292 293 294
		dr->recs = NULL;

		if (dr->tryexecs != NULL) {
			g_slist_foreach (dr->tryexecs, (GFunc) g_free, NULL);
			g_slist_free (dr->tryexecs);
			dr->tryexecs = NULL;
		}
295
		dir_list = g_slist_remove (dir_list, fr);
296
	}
297 298

	if (free_fr) {
299
		g_free (fr);
300
	} else  {
301 302 303
		int type = fr->type;
		if (fr->type == FILE_REC_DIR)
			memset (fr, 0, sizeof(DirRec));
304
		else
305 306 307 308
			memset (fr, 0, sizeof(FileRec));
		/* we must reset the type so that we don't crash
		 * if we call fr_free on this again */
		fr->type = type;
309 310 311 312
	}
}

static void
313
fr_fill_dir (FileRec *fr, int sublevels)
314 315 316
{
	GSList *flist;
	DirRec *dr = (DirRec *)fr;
317
	time_t curtime = time (NULL);
318
	
319 320 321
	g_return_if_fail (dr->recs == NULL);
	g_return_if_fail (fr != NULL);
	g_return_if_fail (fr->name != NULL);
322

323
	flist = get_mfiles_from_menudir (fr->name);
324
	while (flist != NULL) {
325 326
		MFile *mfile = flist->data;
		char *name;
327 328
		GSList *tmp = flist;
		flist = flist->next;
329
		g_slist_free_1 (tmp);
330

331
		if ( ! mfile->verified) {
332 333 334 335
			free_mfile (mfile);
			continue;
		}

336
#ifdef MENU_FENTRY_DEBUG
337 338
		g_print ("fr->name = \"%s\" , mfile->name = \"%s\"\n",
			 fr->name, mfile->name);
339
#endif
340 341

		name = g_build_path ("/", fr->name, mfile->name, NULL);
342

343 344 345 346 347
		if (mfile->is_dir) {
			FileRec *ffr = fr_read_dir (NULL, name, mfile->mtime,
						     sublevels - 1);
			if (ffr != NULL) {
				dr->recs = g_slist_prepend (dr->recs, ffr);
348
			}
349
		} else {
350
			QuickDesktopItem *qitem;
351
			char *tryexec_path;
352
			if ( ! is_ext2 (mfile->name, ".desktop", ".kdelnk")) {
353
				g_free (name);
354
				free_mfile (mfile);
355
#ifdef MENU_FENTRY_DEBUG
356
				g_print ("BAD EXTENSION\n");
357
#endif
358 359 360
				continue;
			}

361 362
			tryexec_path = NULL;

363 364 365 366 367 368 369 370 371 372 373
			qitem = quick_desktop_item_load_uri (name /* uri */,
							     NULL /* expected_type */,
							     FALSE /* run_tryexec */);
			if (qitem != NULL &&
			    qitem->tryexec != NULL) {
				tryexec_path = g_find_program_in_path (qitem->tryexec);
				if (tryexec_path == NULL) {
					dr->tryexecs = g_slist_prepend (dr->tryexecs,
									g_strdup (qitem->tryexec));
					quick_desktop_item_destroy (qitem);
					qitem = NULL;
374 375
				}
			}
376

377
			if (qitem != NULL) {
378
				FileRec *ffr = g_new0 (FileRec, 1);
379 380
				if (qitem->type != NULL &&
				    g_ascii_strcasecmp (qitem->type, "separator") == 0)
381 382 383
					ffr->type = FILE_REC_SEP;
				else
					ffr->type = FILE_REC_FILE;
384
				ffr->name = name;
385 386
				name = NULL;
				ffr->mtime = mfile->mtime;
387 388
				ffr->last_stat = curtime;
				ffr->parent = dr;
389 390 391 392 393 394
				ffr->icon = qitem->icon;
				qitem->icon = NULL;
				ffr->fullname = qitem->name;
				qitem->name = NULL;
				ffr->comment = qitem->comment;
				qitem->comment = NULL;
395
				ffr->tryexec_path = tryexec_path;
396 397

				/* FIXME: we don't need this shit I don't think */
398
				ffr->goad_id =
399
					get_applet_goad_id_from_ditem (qitem);
400

401
				quick_desktop_item_destroy (qitem);
402

403
				dr->recs = g_slist_prepend (dr->recs, ffr);
404 405 406
			} 
#ifdef MENU_FENTRY_DEBUG
			else {
407
				g_print ("NO QITEM\n");
408
			}
409
#endif
410
		}
411 412
		g_free (name);
		free_mfile (mfile);
413
	}
414
	dr->recs = g_slist_reverse (dr->recs);
415 416 417
}

FileRec *
418
fr_read_dir (DirRec *dr, const char *muri, time_t mtime, int sublevels)
419
{
420
	char *furi;
421
	FileRec *fr;
422
	time_t curtime = time (NULL);
423
	GnomeVFSFileInfo *info;
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
424
	
425 426
	g_return_val_if_fail (muri != NULL, NULL);

427
#ifdef MENU_FENTRY_DEBUG
428 429
	g_print ("fr_read_dir (..., \"%s\", %ld, %d)\n",
		 muri, (long)mtime, sublevels);
430
#endif
431

432
	info = gnome_vfs_file_info_new ();
433 434

	/*this will zero all fields*/
435
	if (dr == NULL) {
436
		dr = g_new0 (DirRec, 1);
437
		dr->force_reread = FALSE;
438 439 440 441
		/* this must be set otherwise we may messup on
		   fr_free */
		dr->frec.type = FILE_REC_DIR;
	}
442 443
	fr = (FileRec *)dr;

444
	if (fr->last_stat < curtime-STAT_EVERY) {
445 446 447 448 449
		if (mtime <= 0) {
			if (gnome_vfs_get_file_info
			    (muri, info, GNOME_VFS_FILE_INFO_DEFAULT)
			    != GNOME_VFS_OK) {
				gnome_vfs_file_info_unref (info);
450
				fr_free (fr, TRUE);
451 452 453
				return NULL;
			}

454 455
			/* FIXME: what if there is no mtime in the info? */
			fr->mtime = info->mtime;
456
		} else {
457
			fr->mtime = mtime;
458 459
		}

460 461 462 463
		fr->last_stat = curtime;
	}

	fr->type = FILE_REC_DIR;
464
	g_free (fr->name);
465
	fr->name = g_strdup (muri);
466

467 468 469 470 471
	gnome_vfs_file_info_clear (info);

	/* FIXME: we've already read this when reading the sort_order,
	 * so damnit we should just use that copy, oh well */
	furi = g_build_path ("/", muri, ".directory", NULL);
472
	if (dr->ditemlast_stat >= curtime-STAT_EVERY ||
473 474 475
	    gnome_vfs_get_file_info (furi, info,
				     GNOME_VFS_FILE_INFO_DEFAULT)
	    == GNOME_VFS_OK) {
476
		QuickDesktopItem *qitem;
477 478 479
		qitem = quick_desktop_item_load_uri (furi /* uri */,
						     NULL /* expected_type */,
						     TRUE /* run_tryexec */);
480
		if (qitem != NULL) {
481
			g_free (fr->icon);
482
			fr->icon = g_strdup (qitem->icon);
483
			g_free (fr->fullname);
484
			fr->fullname = g_strdup (qitem->name);
485
			g_free (fr->comment);
486 487
			fr->comment = g_strdup (qitem->comment);
			quick_desktop_item_destroy (qitem);
488
		} else {
489
			g_free (fr->icon);
490
			fr->icon = NULL;
491
			g_free (fr->fullname);
492
			fr->fullname = NULL;
493
			g_free (fr->comment);
Jacob Berkman's avatar
Jacob Berkman committed
494
			fr->comment = NULL;
495 496
		}
		/*if we statted*/
497
		if (info->mtime != 0)
498
			dr->ditemlast_stat = curtime;
499
		dr->ditemmtime = info->mtime;
500
	}
501
	g_free (furi);
502
	
503 504 505
	/* add if missing from list of directories */
	if (g_slist_find (dir_list, fr) == NULL)
		dir_list = g_slist_prepend (dir_list, fr);
506 507 508
	
	/*if this is a fake structure, so we don't actually look into
	  the directory*/
509 510
	if (sublevels > 0)
		fr_fill_dir (fr, sublevels);
511

512 513
	gnome_vfs_file_info_unref (info);

514 515 516 517 518
	return fr;
}


FileRec *
519
fr_replace (FileRec *fr)
520
{
521
	char *name = fr->name;
522 523
	DirRec *par = fr->parent;
	
524
	g_assert (fr->type == FILE_REC_DIR);
525

526
	/* null these so they don't get freed */
527 528
	fr->parent = NULL;
	fr->name = NULL;
529 530 531 532 533 534 535

	/* don't free the actual structure */
	fr_free (fr, FALSE);

	/* sanity */
	fr->type = FILE_REC_DIR;

536
	fr = fr_read_dir ((DirRec *)fr, name, 0, 1);
537
	if (fr != NULL)
538
		fr->parent = par;
539 540
	g_free (name);

541 542 543 544 545
	return fr;
}


FileRec *
546
fr_check_and_reread (FileRec *fr)
547 548 549
{
	DirRec *dr = (DirRec *)fr;
	FileRec *ret = fr;
550
	time_t curtime;
551
	GnomeVFSFileInfo *info;
552

553 554
	g_return_val_if_fail (fr != NULL, fr);
	g_return_val_if_fail (fr->type == FILE_REC_DIR, fr);
555

556 557
	info = gnome_vfs_file_info_new ();

558 559
	if (dr->recs == NULL) {
		fr_fill_dir (fr, 1);
560
	} else {
561 562
		gboolean reread = FALSE;
		gboolean any_change = FALSE;
563
		GSList *li;
564

565 566 567
		if ( ! global_config.menu_check)
			return ret;

568 569 570 571
		if (dr->force_reread)
			reread = TRUE;
		dr->force_reread = FALSE;

572 573 574
		/* recheck tryexecs */
		for (li = dr->tryexecs; ! reread && li != NULL; li = li->next) {
			char *tryexec = li->data;
575
			char *p = g_find_program_in_path  (tryexec);
576 577 578 579 580 581 582

			if (p != NULL) {
				reread = TRUE;
				g_free (p);
			}
		}

583 584
		curtime = time (NULL);

585
		if ( ! reread &&
586 587 588 589 590
		    fr->last_stat < curtime - STAT_EVERY) {
			if (gnome_vfs_get_file_info
			    (fr->name, info, GNOME_VFS_FILE_INFO_DEFAULT)
			    != GNOME_VFS_OK) {
				gnome_vfs_file_info_unref (info);
591
				fr_free (fr, TRUE);
592 593
				return NULL;
			}
594

595 596
			if (info->mtime != fr->mtime)
				reread = TRUE;
597
		}
598 599 600 601

		for (li = dr->recs;
		     ! reread && li != NULL;
		     li = li->next) {
602 603
			FileRec *ffr = li->data;
			DirRec *ddr;
604
			GnomeVFSResult result;
605 606 607 608 609 610
			char *p;
			struct stat s;

			switch(ffr->type) {
			case FILE_REC_DIR:
				ddr = (DirRec *)ffr;
611 612 613 614
				p = g_build_path ("/",
						  ffr->name,
						  ".directory",
						  NULL);
615
				if (ddr->ditemlast_stat >= curtime-STAT_EVERY) {
616
					g_free (p);
617
					break;
618
				}
619
				dr->ditemlast_stat = curtime;
620 621 622 623 624
				gnome_vfs_file_info_clear (info);
				if (gnome_vfs_get_file_info
				    (p, info, GNOME_VFS_FILE_INFO_DEFAULT)
				    != GNOME_VFS_OK) {
					gnome_vfs_file_info_clear (info);
625
					/* perhaps the directory is gone */
626 627 628 629 630
					if (gnome_vfs_get_file_info
					    (ffr->name, info,
					     GNOME_VFS_FILE_INFO_DEFAULT)
					    != GNOME_VFS_OK) {
						g_free (p);
631 632 633 634 635
						reread = TRUE;
						break;
					}
					/* if not, we're just now missing a
					 * desktop file */
636 637
					if (dr->ditemmtime > 0) {
						g_free (ffr->icon);
638
						ffr->icon = NULL;
639
						g_free (ffr->fullname);
640
						ffr->fullname = NULL;
641
						g_free (ffr->comment);
Jacob Berkman's avatar
Jacob Berkman committed
642
						ffr->comment = NULL;
643
						ddr->ditemmtime = 0;
644 645
						any_change = TRUE;
					}
646
					dr->ditemlast_stat = 0;
647
					g_free (p);
648 649
					break;
				}
650
				if (ddr->ditemmtime != info->mtime) {
651 652 653 654
					QuickDesktopItem *qitem;
					qitem = quick_desktop_item_load_file (p /* file */,
									      NULL /* expected_type */,
									      TRUE /* run_tryexec */);
655 656 657 658
					if (qitem != NULL) {
						g_free (ffr->icon);
						ffr->icon = g_strdup (qitem->icon);
						g_free (ffr->fullname);
659
						ffr->fullname = g_strdup (qitem->name);
660
						g_free (ffr->comment);
661 662
						ffr->comment = g_strdup (qitem->comment);
						quick_desktop_item_destroy (qitem);
663
					} else {
664
						g_free (ffr->icon);
665
						ffr->icon = NULL;
666
						g_free (ffr->fullname);
667
						ffr->fullname = NULL;
668
						g_free (ffr->comment);
Jacob Berkman's avatar
Jacob Berkman committed
669
						ffr->comment = NULL;
670
					}
671
					ddr->ditemmtime = info->mtime;
672 673 674 675 676
					any_change = TRUE;
				}
				g_free(p);
				break;
			case FILE_REC_FILE:
677
				if (ffr->last_stat >= curtime-STAT_EVERY)
678
					break;
679 680 681 682
				gnome_vfs_file_info_clear (info);
				if (gnome_vfs_get_file_info
				    (ffr->name, info, GNOME_VFS_FILE_INFO_DEFAULT)
				    != GNOME_VFS_OK) {
683 684 685
					reread = TRUE;
					break;
				}
686
				ffr->last_stat = curtime;
687
				if (ffr->mtime != info->mtime) {
688 689 690 691 692
					QuickDesktopItem *qitem;
					qitem = quick_desktop_item_load_file (ffr->name /* file */,
									      NULL /* expected_type */,
									      TRUE /* run_tryexec */);
					if (qitem != NULL) {
693
						g_free (ffr->icon);
694
						ffr->icon = g_strdup (qitem->icon);
695 696

						g_free (ffr->fullname);
697
						ffr->fullname = g_strdup (qitem->name);
698 699

						g_free (ffr->comment);
700
						ffr->comment = g_strdup (qitem->comment);
701

702
						quick_desktop_item_destroy (qitem);
703 704 705 706 707 708 709
					} else {
						reread = TRUE;
						break;
					}
					ffr->mtime = s.st_mtime;
					any_change = TRUE;
				}
710
				if (ffr->tryexec_path != NULL &&
711 712
				    ! g_file_test (ffr->tryexec_path,
						   G_FILE_TEST_EXISTS)) {
713 714
					reread = TRUE;
				}
715 716
				break;
			case FILE_REC_EXTRA:
717
				if (ffr->last_stat >= curtime-STAT_EVERY)
718
					break;
719 720 721 722 723 724 725
				gnome_vfs_file_info_clear (info);
				result = gnome_vfs_get_file_info
				    (ffr->name,
				     info,
				     GNOME_VFS_FILE_INFO_DEFAULT);
				if((result != GNOME_VFS_OK && ffr->mtime > 0) ||
				   (result == GNOME_VFS_OK && ffr->mtime != info->mtime))
726
					reread = TRUE;
727
				ffr->last_stat = curtime;
728 729 730
				break;
			}
		}
731 732 733 734

		if (reread) {
			ret = fr_replace (fr);
		} else if (any_change) {
735
			GSList *li;
736
			for (li = dr->mfl; li != NULL; li = li->next) {
737 738 739 740 741
				MenuFinfo *mf = li->data;
				li->data = NULL;
				mf->fr = NULL;
			}
			g_slist_free (dr->mfl);
742 743 744 745 746 747 748
			dr->mfl = NULL;
		}
	}
	return ret;
}

FileRec *
749
fr_get_dir (const char *mdir)
750 751
{
	GSList *li;
752 753
	g_return_val_if_fail (mdir!=NULL, NULL);

754
	for(li = dir_list; li != NULL; li = li->next) {
755
		FileRec *fr = li->data;
756 757
		g_assert(fr != NULL);
		g_assert(fr->name != NULL);
758 759
		if (strcmp (fr->name, mdir) == 0)
			return fr_check_and_reread (fr);
760
	}
761
	return fr_read_dir (NULL, mdir, 0, 1);
762
}
763

764 765 766 767 768 769 770
/* Get all directories we have in memory */
GSList*
fr_get_all_dirs (void)
{
  return dir_list;
}

771
void
772
fr_force_reread (void)
773 774 775 776
{
	GSList *li;
	for(li = dir_list; li != NULL; li = li->next) {
		DirRec *dr = li->data;
777
		g_assert (dr != NULL);
778 779 780 781

		dr->force_reread = TRUE;
	}
}