Logo Search packages:      
Sourcecode: wallpaper-tray version File versions  Download package

wp_tray_util.c

// WP_TRAY_UTIL.C //////////////////////////////////////////////////////
//
// Author:                    E^rthW( )rm 2003
// Last Mod:                  Friday, September 05 2003
// About:                     Utilities for directory recursion
//                                  and regular expression checks etc
// License:             GPL

// includes ////////////////////////////////////////////////////////////
//
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <regex.h>
#include <unistd.h>
#include <dirent.h>
#include <time.h>
#include <errno.h>
#include <gtk/gtk.h>
#include <string.h>
#include <gconf/gconf-client.h>
#include "../include/wp_tray_util.h"

// globals /////////////////////////////////////////////////////////////
//
gboolean                                  b_check_file;
int                                             (*f_wp_stat)(const char *, struct stat *);

// f_is_image //////////////////////////////////////////////////////////
//
// regular expression check for 'valid' image
#define     f_is_image(sz_file)           (b_check_file ? f_reg_exp_match(sz_file, ".jpg|.jpeg|.png|.gif|.bmp|.tiff") : 1)

// f_count_dir_entries /////////////////////////////////////////////////
//
// pass in the path to the a search directory and a pointer to a
// zeroed integer to count regular files
gint
f_count_dir_entries                       (gchar *sz_dir, gint *p_dir_count)
{
      DIR                                 * dir;                  // pointers needed for functions to iterating directory entries
      struct dirent                       * entry;
      struct stat                         statinfo;         // struct needed for determining info about an entry with stat()
      
      // open the directory 
      if((dir = opendir(sz_dir)) == NULL)
      {
            //fprintf(stderr, "f_count_dir_entries: could not open directory %s\n", sz_dir);
            return *p_dir_count;
      }
      
      // change working dir to be able to read file information 
      if(chdir(sz_dir) == -1)
      {
            //printf("f_count_dir_entries: could not change to directory %s\n", sz_dir);
            return *p_dir_count;
      }// end if 
            
      while((entry = readdir(dir)) != NULL)
      {
            // get info for dir entry
            if(f_wp_stat(entry->d_name, &statinfo) == -1)
                  printf("f_count_dir_entries: could not stat file or directory %s\n", entry->d_name);
            
            // count entries
            *p_dir_count += S_ISREG(statinfo.st_mode) && f_is_image(entry->d_name);
            
            // recurse into any sub directories
            if(S_ISDIR(statinfo.st_mode) && strncmp(".", entry->d_name, 1) != 0)
            {
                  f_count_dir_entries(entry->d_name, p_dir_count);
            }// end if
      }// end while
      
      // oops, mem leakage without this ya wanker!
      closedir(dir);
      
      // put working dir back 
      if(chdir("..") == -1)
      {
            //printf("f_count_dir_entries: could not change to directory ..\n");
            return *p_dir_count;
      }// end if 
      
      return (*p_dir_count);
}// end f_count_dir_entries

// f_get_dir_entry ////////////////////////////////////////////////
//
// get the name of the file entry given a directory to search
// and the numerical index of the file entry
gchar *
f_get_dir_entry                           (gchar *sz_dir, gint *p_dir_trgt, gchar **sz_dir_trgt)
{
      DIR                                 * dir;                  // pointers needed for functions to iterating directory entries
      struct dirent                       * entry;
      struct stat                         statinfo;         // struct needed for determining info about an entry with stat()
      
      // open the directory 
      if((dir = opendir(sz_dir)) == NULL)
      {
            //fprintf(stderr, "f_get_dir_entry: could not open directory %s\n", sz_dir);
            return *sz_dir_trgt;
      }
      
      // change working dir to be able to read file information 
      if(chdir(sz_dir) == -1)
      {
            //printf("f_get_dir_entry: could not change to directory %s\n", sz_dir);
            return *sz_dir_trgt;
      }// end if 
      
      while((entry = readdir(dir)) != NULL && *p_dir_trgt > 0)
      {
            // get info for dir entry
            if(f_wp_stat(entry->d_name, &statinfo) == -1)
                  printf("f_get_dir_entry: could not stat file or directory %s\n", entry->d_name);
                  
            // count entries
            *p_dir_trgt -= S_ISREG(statinfo.st_mode) && f_is_image(entry->d_name);
            
            // found the target yet?
            if(*p_dir_trgt == 0)
            {
                  // malloc a new string
                  *sz_dir_trgt = (gchar *)malloc(100);
                  
                  getcwd(*sz_dir_trgt, 100);

                  // copy the target string
                  strncat(*sz_dir_trgt, "/", 100);
                  strncat(*sz_dir_trgt, entry->d_name, 100);
            }// end if

            // recurse into any sub directories
            if(S_ISDIR(statinfo.st_mode) && strncmp(".", entry->d_name, 1) != 0)
            {
                  f_get_dir_entry(entry->d_name, p_dir_trgt, sz_dir_trgt);
            }// end if
      }// end while
      
      // put working dir back 
      chdir("..");
      
      // oops, mem leakage without this ya wanker!
      closedir(dir);
      
      // might be a handy return value
      return *sz_dir_trgt;
}// end f_get_dir_entry

// f_reg_exp_match ////////////////////////////////////////////////
//
// match a string to a regular expression
gboolean
f_reg_exp_match                           (const gchar *string, const gchar *pattern)
{
      gint                                status;
      regex_t                             re;
      
      // reg_exp into form suitable for regexec searches
      if(regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE) != 0)
      {
            // report error
      return FALSE;
      }// end if 
      
      // make the comparison
      status = regexec(&re, string, (size_t) 0, NULL, 0);
      
      // free the regcomp result 
      regfree(&re);
      
      // make status check
      if(status != 0)
      {
            // report error
            return FALSE;
      }// end if 
   
      // all is well
      return TRUE;
}// end f_reg_exp_match

// f_get_dir_regex_match_list //////////////////////////////////////////
//
// return a list of the directory entries matching a regular expression
GList *
f_get_dir_regex_match_list          (gchar *sz_dir, const gchar *sz_regex, GList **ls_result)
{
      DIR                                 * dir;                  // pointers needed for functions to iterating directory entries
      struct dirent                       * entry;
      struct stat                         statinfo;         // struct needed for determining info about an entry with stat()
      
      // open the directory 
      if((dir = opendir(sz_dir)) == NULL)
      {
            fprintf(stderr, "f_get_dir_regex_match_list: could not open directory %s\n", sz_dir);
      }// end if 
      
      // change working dir to be able to read file information 
      chdir(sz_dir);
      
      while((entry = readdir(dir)) != NULL)
      {
            // get info for dir entry
            stat(entry->d_name, &statinfo);
            
            // file entry?
            if(S_ISREG(statinfo.st_mode))
            {
                  // compare file name to the query 
                  if(f_reg_exp_match(entry->d_name, sz_regex))
                  {
                        // malloc a new string
                        gchar *sz_result = (gchar *)malloc(100);
                        
                        // build the result string
                        getcwd(sz_result, 100);
                        strncat(sz_result, "/", 100);
                        strncat(sz_result, entry->d_name, 100);
                        
                        // add the entry to the return list
                        *ls_result = g_list_append(*ls_result, sz_result);
                  }// end if 
            }// end if 

            // recurse into any sub directories
            if(S_ISDIR(statinfo.st_mode) && strncmp(".", entry->d_name, 1) != 0)
            {
                  f_get_dir_regex_match_list(entry->d_name, sz_regex, ls_result);
            }// end if
      }// end while
      
      // put working dir back 
      chdir("..");
      
      // might be a handy return value
      return *ls_result;
}// end f_get_dir_regex_match_list

// f_set_rand_wallpaper ////////////////////////////////////////////////
//
// select a wallpaper at random from the current dir list
gboolean
f_set_rand_wallpaper                (GtkWidget *button, gpointer user_data)
{
      int                                 n_dir_count;
      gchar                                     * sz_randfile;
      GSList                                    * ls_wp_dir, * ls_wp_dir_iter;
      GConfClient                         * p_client;
      GtkWidget                           * p_dialog;
      gboolean                            b_error;
      
      // essential setup shonk
      p_client    = gconf_client_get_default();
      n_dir_count = 0;
      sz_randfile = NULL;
      b_error           = FALSE;
      
      // get directory list
      ls_wp_dir = gconf_client_get_list(p_client, "/apps/wp_tray/dir_list", GCONF_VALUE_STRING, NULL);
      
      // we checking as we iterate?
      b_check_file      = gconf_client_get_bool(p_client, "/apps/wp_tray/b_img_check", NULL);
      
      // we following symlinks?
      if(gconf_client_get_bool(p_client, "/apps/wp_tray/b_follow_links", NULL))
            f_wp_stat = stat;
      else
            f_wp_stat = lstat;
      
      // count pixmaps in the directory list
      for(ls_wp_dir_iter = ls_wp_dir; ls_wp_dir_iter != NULL; ls_wp_dir_iter = g_slist_next(ls_wp_dir_iter))
      {
            gchar                   * sz_dir;
            
            // get data
            sz_dir = (gchar *)ls_wp_dir_iter->data;
            
            // count entries
            f_count_dir_entries(sz_dir, &n_dir_count);
            
            // warn about dodgy directories if needed
            if(n_dir_count == ERROR_DIR_NOT_FOUND)
            {
                  p_dialog =  gtk_message_dialog_new(NULL,
                                                   GTK_DIALOG_MODAL,
                                                 GTK_MESSAGE_WARNING,
                                                   GTK_BUTTONS_OK,
                                                   "The directory %s has been moved or no longer exists, please correct this or update your configuration.",
                                                                     sz_dir);
                  
                  gtk_dialog_run(GTK_DIALOG (p_dialog));
                  gtk_widget_destroy(p_dialog);
                  
                  b_error = TRUE;
            }// end if 
            if(n_dir_count == ERROR_DIR_NO_ACCESS)
            {
                  p_dialog =  gtk_message_dialog_new(NULL,
                                                   GTK_DIALOG_MODAL,
                                                 GTK_MESSAGE_WARNING,
                                                   GTK_BUTTONS_OK,
                                                   "The directory %s or one of its sub-directories is inaccessable to Wallpaper Tray, please correct this or update your configuration.",
                                                                     sz_dir);
                  
                  gtk_dialog_run(GTK_DIALOG (p_dialog));
                  gtk_widget_destroy(p_dialog);
                  
                  b_error = TRUE;
            }// end if 
      }// end for
      
      if(b_error == TRUE)
            return FALSE;
      
      // bomb out if there were no files found
      if(n_dir_count == 0)
      {
            p_dialog =  gtk_message_dialog_new(NULL,
                                             GTK_DIALOG_MODAL,
                                                 GTK_MESSAGE_WARNING,
                                                   GTK_BUTTONS_OK,
                                             "No wallpapers were found, please update your configuration to include at least one valid directory, or add some wallpapers to your existing directory.");
            
            gtk_dialog_run(GTK_DIALOG (p_dialog));
            gtk_widget_destroy(p_dialog);
            
            return FALSE;
      }// end if 
      
      // get random image index
      srand(time(NULL));
      n_dir_count = rand()%n_dir_count;
      
      // set iterator to list begining
      ls_wp_dir_iter = ls_wp_dir;
      
      // otherwise following loop will be b0rked
      n_dir_count ++;
      
      // loop to find image at index number
      while(n_dir_count)
      {
            gchar                   * sz_dir;
            
            // get data
            sz_dir = (gchar *)ls_wp_dir_iter->data;
            
            // try to get filename at index
            f_get_dir_entry(sz_dir, &n_dir_count, &sz_randfile);
            
            // next directory
            ls_wp_dir_iter = g_slist_next(ls_wp_dir_iter);
            
            // free list data ...
            g_free(sz_dir);
      }// end while
      
      // kill the directory list
      g_slist_free(ls_wp_dir);
      
      // set the string to the new wp     
      gconf_client_set_string(p_client, "/desktop/gnome/background/picture_filename",
                                    sz_randfile, NULL);
      
      // house work ....
      g_object_unref(G_OBJECT(p_client));
      free(sz_randfile);
      
      return 1;
}// end f_set_rand_wallpaper

Generated by  Doxygen 1.6.0   Back to index