Logo Search packages:      
Sourcecode: danpei version File versions  Download package

thumbnail_table.c

/*
 * Danpei -- a GTK+ based Image Viewer
 * Copyright (C) 2001-2003 Shinji Moiino
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
/* thumbnail_table.c */

#include <errno.h>
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <gdk/gdkx.h>

#include "config.h"
#include "dialog.h"
#include "image_cache.h"
#include "intl.h"
#include "statusbar.h"
#include "thumbnail.h"
#include "thumbnail_table.h"
#include "utils.h"
#include "version.h"
#include "viewer.h"

/* Static variables declaration. */
static SortOrder qsort_flag;

/* Static functions declaration. */
static gint     thumbnail_table_resize        (gpointer       );

static gint     thumbnail_table_get_file_list (gchar*       ,
                                               FormatSwitch*,
                                               FileList**     );

static gboolean thumbnail_table_decide_format (gchar*       ,
                                               gchar*       ,
                                               gint           );

static void     thumbnail_table_free_filelist (FileList*      );

static int      thumbnail_table_qsort_func    (const void*  ,
                                               const void*    );

static gint     thumbanail_table_calc_columns (TopLevel*      );

/* Function definitions. */
/*
 * @thumbnail_table_init_structure
 *
 *  Intialize the ThumbnailTable structure object specified by
 *  the argument.
 *
 */
void thumbnail_table_init_structure(ThumbnailTable *thumb_table) {
  thumb_table->scrolled_window     = NULL;
  thumb_table->table               = NULL;
  thumb_table->dir_name            = NULL;
  thumb_table->file_num            = -1;
  thumb_table->start_pos           = -1;
  thumb_table->end_pos             = -1;
  thumb_table->total_size          =  0;
  thumb_table->selected_thumbnails =  0;
  thumb_table->top_thumbnail       = NULL;
  thumb_table->end_thumbnail       = NULL;

  return;
}

/*
 * @thumbnail_table_destroy_structure
 *
 *  Destroy the ThumbnailTable structure object specified by
 *  the argument.
 *
 */
void thumbnail_table_destroy_structure(ThumbnailTable *thumb_table) {
  if (thumb_table->dir_name != NULL) {
    free(thumb_table->dir_name);
    thumb_table->dir_name = NULL;
  }
  thumb_table->file_num            = -1;
  thumb_table->start_pos           = -1;
  thumb_table->end_pos             = -1;
  thumb_table->total_size          =  0;
  thumb_table->selected_thumbnails =  0;
  thumbnail_free_structure_list(thumb_table->top_thumbnail);

  thumb_table->top_thumbnail = NULL;
  thumb_table->end_thumbnail = NULL;

  return;
}

/*
 * @thumbnail_table_create
 *
 *  Create a new Thumbnail table. 
 *
 */
void thumbnail_table_create(TopLevel *tp         ,
                            gchar    *dir_name   ,
                            gboolean display_page  ) {

  gint      wkgint1, wkgint2, wkgint3;
  FileList  *filelist1, *filelist2;
  Thumbnail *thumb1, *thumb2;
  gchar     *wk_num;
  gchar     file_size[32];

  /* Initialize the local variables. */
  wkgint1   = wkgint2   = wkgint3 = 0;
  filelist1 = filelist2 = NULL;
  thumb1    = thumb2    = NULL;
  wk_num    = NULL;

  if (tp->thumbnail_table.dir_name != NULL) {
    free(tp->thumbnail_table.dir_name);
  }

  tp->thumbnail_table.dir_name = strdup(dir_name);
  if (tp->thumbnail_table.dir_name == NULL) {
    /* Out of memory. */
    fprintf(stderr, "danpei: Out of memory.\n");
    fprintf(stderr, "        thumbnail_table.c: error -- 01.\n");
    gtk_exit(-1);
  }
  statusbar_put_message(&(tp->statusbar1), tp->thumbnail_table.dir_name);

  qsort_flag = tp->current_sort_order;
  tp->thumbnail_table.file_num = 
      thumbnail_table_get_file_list(dir_name, 
                                    &(tp->current_format), &filelist1);
  tp->thumbnail_table.start_pos     = tp->thumbnail_table.end_pos       = -1;
  tp->thumbnail_table.top_thumbnail = tp->thumbnail_table.end_thumbnail = NULL;

  filelist2 = filelist1;
  for (wkgint1 = 0; wkgint1 < tp->thumbnail_table.file_num; wkgint1++) {
    thumb1 = (Thumbnail*)malloc(sizeof(Thumbnail));
    if (thumb1 == NULL) {
      /* Out of memory. */
      fprintf(stderr, "danpei: Out of memory.\n");
      fprintf(stderr, "        thumbnail_table.c: error -- 02.\n");
      gtk_exit(-1);
    }
    else {
      thumbnail_init(thumb1);
    }

    thumb1->path     = strdup(dir_name);
    thumb1->filename = strdup(filelist2->filename);
    if ((thumb1->path == NULL) || (thumb1->filename == NULL)) {
      /* Out of memory. */
      fprintf(stderr, "danpei: Out of memory.\n");
      fprintf(stderr, "        thumbnail_table.c: error -- 03.\n");
      gtk_exit(-1);
    }
    thumb1->ctime = filelist2->ctime;
    thumb1->atime = filelist2->atime;
    thumb1->mtime = filelist2->mtime;
    thumb1->size  = filelist2->size;
    tp->thumbnail_table.total_size += thumb1->size;

    if (tp->thumbnail_table.top_thumbnail == NULL) {
      tp->thumbnail_table.top_thumbnail = thumb2 = thumb1;
      thumb1->prev = NULL;
      thumb1->next = NULL;
    }
    else {
      thumb2->next = thumb1;
      thumb1->prev = thumb2;
      thumb1->next = NULL;
      thumb2       = thumb1;
    }
    if (filelist2->next != NULL) { filelist2 = filelist2->next; }
  }

  /* Show the total size of image files. */
  utils_gint_to_gchar(tp->thumbnail_table.total_size, 9, TRUE, &wk_num);
  wkgint2 = strlen(wk_num);
  wkgint3 = 1;
  strcpy(file_size, "                              ");
  /* Insert cannma to total size. ex) 123456 -> 123,456 */
  for (wkgint1 = 0; wkgint1 < wkgint2; wkgint1++) {
    if (((wkgint2 - wkgint1 == 3) && (wkgint2 > 3)) ||
        ((wkgint2 - wkgint1 == 6) && (wkgint2 > 6))    ) {
      file_size[wkgint3] = ',';
      wkgint3++;
    }
    file_size[wkgint3] = wk_num[wkgint1];
    wkgint3++;
  }
  file_size[wkgint3] = '\0';
  free(wk_num);
  strcat(file_size, " bytes used");
  statusbar_put_message(&(tp->statusbar2), file_size);

  tp->thumbnail_table.end_thumbnail = thumb1;
  thumbnail_table_free_filelist(filelist1);

  /* Create the GtkTable widget etc. */
  if (display_page == TRUE) {
    tp->thumbnail_table.selected_thumbnails = 0;
    thumbnail_table_display_next_page(tp);
  }

  /* Set the sensitivity of toolbar etc. */
  toplevel_set_menu_sensitive(tp, STATUS_NO_SELECTED);

  return; 
}

/*
 * @thumbnail_table_reload_all
 *
 *  Remove all cache files about current directory, and re-create
 *  thumbnails and cache files.
 *
 */
void thumbnail_table_reload_all(TopLevel *tp, gboolean is_all) {
  Thumbnail *thumb;
  gchar     *pixmap_name;

  thumb = tp->thumbnail_table.top_thumbnail;

  /* Remove cache files. */
  while (thumb != NULL) {
    if (((is_all == TRUE )                             )  ||
        ((is_all == FALSE) && (thumb->selected == TRUE))     ) {
      if ((thumb->path != NULL) && (thumb->filename != NULL)) {
        pixmap_name = (gchar*)malloc(sizeof(gchar) * 
                                     (strlen(thumb->path)     +
                                      strlen("/")             +
                                      strlen(thumb->filename) + 1));
        if (pixmap_name == NULL) {
          /* Out of memory. */
          fprintf(stderr, "danpei: Out of memory.\n");
          fprintf(stderr, "        thumbnail_table.c: error -- 04.\n");
          gtk_exit(-1);
        }
        else {
          sprintf(pixmap_name, "%s/%s", thumb->path, thumb->filename);
        }
        image_cache_delete(&(tp->cache), pixmap_name);
        free(pixmap_name);
      }
    }
    thumb = thumb->next;
  }

  thumbnail_table_refresh(tp);

  return;
}

/*
 * @thumbnail_table_refresh
 *
 *  Re-create thumbnails using cache files.
 *
 */
void thumbnail_table_refresh(TopLevel *tp) {
  gchar        *dir_name;
  gint         start_pos, end_pos;

  if (tp->thumbnail_table.dir_name == NULL) { return; }

  dir_name = strdup(tp->thumbnail_table.dir_name);
  if (dir_name == NULL) {
    /* Out of memory. */
    fprintf(stderr, "danpei: Out of memory.\n");
    fprintf(stderr, "        thumbnail_table.c: error -- 05.\n");
    gtk_exit(-1);
  }
  else {
    tp->app_status = STATUS_TABLE_REFRESH;
    start_pos = tp->thumbnail_table.start_pos;
    end_pos   = tp->thumbnail_table.end_pos;

    thumbnail_table_destroy_structure(&(tp->thumbnail_table));
    if ((tp->viewer).alive == TRUE) {
      gtk_widget_destroy((tp->viewer).window);
    }
    thumbnail_table_create(tp, dir_name, FALSE);
    thumbnail_table_set_position_after_refresh(tp, start_pos, end_pos);

    if ((tp->thumbnail_table.start_pos < 0) ||
        (tp->thumbnail_table.end_pos   < 0)    ) {
      thumbnail_table_display_next_page(tp);
    }
    else {
      thumbnail_table_display_current_page(tp, -1, -1);
    }

    free(dir_name);
  }

  tp->app_status = STATUS_NONE;

  return;
}

/*
 * @thumbnail_table_set_position_after_refresh
 *
 *  After refreshing thumbnails, set the new start_pos and end_pos.
 *
 */
void thumbnail_table_set_position_after_refresh(TopLevel *tp           ,
                                                gint     prev_start_pos,
                                                gint     prev_end_pos    ) {
  if (prev_start_pos > tp->thumbnail_table.file_num - 1) {
    tp->thumbnail_table.start_pos = -1;
    tp->thumbnail_table.end_pos   = -1;
  }
  else {
    if ((tp->thumbnail_table.file_num > 0) && (prev_start_pos < 0)) {
      tp->thumbnail_table.start_pos = 0;
    }
    else {
      tp->thumbnail_table.start_pos = prev_start_pos;
    }
    if (tp->thumbnail_table.file_num > prev_end_pos) {
      if (tp->thumbnail_table.start_pos + tp->app_option.max_num > 
                               tp->thumbnail_table.file_num - 1) {
        tp->thumbnail_table.end_pos = tp->thumbnail_table.file_num - 1;
      }
      else {
        tp->thumbnail_table.end_pos = prev_start_pos + 
                                           tp->app_option.max_num - 1;
      }
    }
    else {
      tp->thumbnail_table.end_pos = tp->thumbnail_table.file_num - 1;
      if (tp->thumbnail_table.file_num < tp->app_option.max_num + 1) {
        tp->thumbnail_table.start_pos = 0;
      }
      else {
        tp->thumbnail_table.start_pos = 
            tp->thumbnail_table.end_pos - tp->app_option.max_num + 1;
      }
    }
  }

  return;
}

/*
 * @thumbnail_table_display_prev_page
 *
 *  Display the previous page of the thumnails.
 *
 */
void thumbnail_table_display_prev_page(TopLevel *tp) {
  gint prev_start_pos, prev_end_pos;

  if (tp->thumbnail_table.start_pos == 0) {
    /* Set the arguments for thumbnail_table_display_current_page() */
    prev_start_pos = tp->thumbnail_table.start_pos;
    prev_end_pos   = tp->thumbnail_table.end_pos;
  }
  else {
    /* Set the arguments for thumbnail_table_display_current_page() */
    prev_start_pos = prev_end_pos = -1;

    /* Calcurate the start_pos and end_pos. */
    if ((tp->thumbnail_table.start_pos < 0) || 
        (tp->thumbnail_table.end_pos   < 0)    ) {
      /* First call */
      if (tp->thumbnail_table.file_num < tp->app_option.max_num) {
        tp->thumbnail_table.start_pos = 0;
        tp->thumbnail_table.end_pos   = tp->thumbnail_table.file_num - 1;
      }
      else {
        tp->thumbnail_table.start_pos = 0;
        tp->thumbnail_table.end_pos   = tp->app_option.max_num - 1;
      }
    }
    else {
      if (tp->thumbnail_table.start_pos - tp->app_option.max_num >= 0) {
        /* The number of the rest files is over the max_num. */
        tp->thumbnail_table.end_pos    = tp->thumbnail_table.start_pos - 1;
        tp->thumbnail_table.start_pos  = tp->thumbnail_table.end_pos - 
                                             tp->app_option.max_num  + 1;
      }
      else {
        tp->thumbnail_table.start_pos  = 0;
        if (tp->thumbnail_table.file_num < tp->app_option.max_num)
          tp->thumbnail_table.end_pos  = tp->thumbnail_table.file_num - 1;
        else
          tp->thumbnail_table.end_pos  = tp->app_option.max_num - 1;
      }
    }
  }

  tp->app_status = STATUS_TABLE_PREV;
  thumbnail_table_display_current_page(tp, prev_start_pos, prev_end_pos);
  tp->app_status = STATUS_NONE;

  return;
}

/*
 * @thumbnail_table_display_next_page
 *
 *  Display the next page of the thumnails.
 *
 */
void thumbnail_table_display_next_page(TopLevel *tp) {
  gint prev_start_pos, prev_end_pos;

  if (tp->thumbnail_table.end_pos == tp->thumbnail_table.file_num - 1) {
    /* Set the arguments for thumbnail_table_display_current_page() */
    prev_start_pos = tp->thumbnail_table.start_pos;
    prev_end_pos   = tp->thumbnail_table.end_pos;
  }
  else {
    /* Set the arguments for thumbnail_table_display_current_page() */
    prev_start_pos = prev_end_pos = -1;

    /* Calcurate the start_pos and end_pos. */
    if ((tp->thumbnail_table.start_pos < 0) || 
        (tp->thumbnail_table.end_pos   < 0)    ) {
      /* First call */
      if (tp->thumbnail_table.file_num < tp->app_option.max_num) {
        tp->thumbnail_table.start_pos = 0;
        tp->thumbnail_table.end_pos   = tp->thumbnail_table.file_num - 1;
      }
      else {
        tp->thumbnail_table.start_pos = 0;
        tp->thumbnail_table.end_pos   = tp->app_option.max_num - 1;
      }
    }
    else {
      if (tp->thumbnail_table.file_num - tp->thumbnail_table.end_pos > 
                                              tp->app_option.max_num   ) {
        /* The number of the rest files is over the max_num. */
        tp->thumbnail_table.start_pos  = tp->thumbnail_table.end_pos + 1;
        tp->thumbnail_table.end_pos   += tp->app_option.max_num;
      }
      else {
        tp->thumbnail_table.start_pos  = tp->thumbnail_table.file_num - 
                                         tp->app_option.max_num;
        tp->thumbnail_table.end_pos    = tp->thumbnail_table.file_num - 1;
      }
    }
  }

  tp->app_status = STATUS_TABLE_NEXT;
  thumbnail_table_display_current_page(tp, prev_start_pos, prev_end_pos);
  tp->app_status = STATUS_NONE;

  return;
}

/*
 * @thumbnail_table_display_current_page
 *
 *  o Set the start position and  file count at the toolbar.
 *  o Display the thumnails from the start_pos to the end_pos.
 *
 *  -- the arguments 'prev_*_pos' are used by the check which
 *     new thumbnail table should be created or not.
 *
 */
void thumbnail_table_display_current_page(TopLevel *tp           ,
                                          gint     prev_start_pos,
                                          gint     prev_end_pos    ) {
  Thumbnail *wk_thumb, *wk_thumb1, *wk_thumb2;
  gint      wkgint,wkgint2;
  guint     cells, rows, columns;
  gint      left_attach, top_attach;
  gchar     *num_pt, wk_str[10];
  gchar     *progressbar_msg1[] = { "     "                              ,
                                    N_("  Creating thumbnails now ...  "),
                                    N_("  Wait for a minute.           "),
                                    "     "                              ,
                                    ""                                     };
  gchar     *progressbar_msg2[] = { "     "                              ,
                                    N_("  Refresh now ...  ")            ,
                                    "     "                              ,
                                    ""                                     };

  /* Initialize the local variables. */
  wk_thumb    = wk_thumb1  = wk_thumb2  = NULL;
  cells       = rows       = columns    = 0;
  left_attach = top_attach = 0;

  /* Destroy the current table. */
  if (tp->thumbnail_table.table != NULL) {
    if (GTK_IS_WIDGET(tp->thumbnail_table.table) == TRUE) {
      gtk_widget_destroy(tp->thumbnail_table.table);
      tp->thumbnail_table.table = NULL;
      thumbnail_count_selected_thumbnails(
                      tp, (-1) * tp->thumbnail_table.selected_thumbnails);
    }
    wk_thumb = tp->thumbnail_table.top_thumbnail;
    while (wk_thumb != NULL) {
      wk_thumb->selected = FALSE;
      wk_thumb = wk_thumb->next;
    }
  }

  /* Put the numbers. */
  if ((tp->thumbnail_table.start_pos < 0) ||
      (tp->thumbnail_table.end_pos   < 0)   ) {
    /* No thumbnails. */
    gtk_entry_set_text(GTK_ENTRY(tp->tb_entry), "0");
    gtk_label_set_text(GTK_LABEL(tp->tb_label), "/ 0");
    gtk_widget_set_sensitive(tp->tb_entry, FALSE);
    gtk_widget_set_sensitive(tp->tb_label, FALSE);
    toplevel_set_menu_sensitive(
         tp, STATUS_NO_THUMBNAIL | STATUS_NO_PREV | STATUS_NO_NEXT |
             STATUS_NO_SELECTED);
    return;
  }
  else {
    utils_gint_to_gchar(tp->thumbnail_table.start_pos + 1, 5, 
                        TRUE, &num_pt);
    gtk_entry_set_text(GTK_ENTRY(tp->tb_entry), num_pt);
    free(num_pt);
    if (tp->thumbnail_table.start_pos < 1) {
      if (tp->thumbnail_table.end_pos > tp->thumbnail_table.file_num - 2) {
        toplevel_set_menu_sensitive(tp, STATUS_THUMBNAIL | 
                                        STATUS_NO_PREV   |
                                        STATUS_NO_NEXT      );
      }
      else {
        toplevel_set_menu_sensitive(tp, STATUS_THUMBNAIL | 
                                        STATUS_NO_PREV   |
                                        STATUS_NEXT        );
      }
    }
    else {
      if (tp->thumbnail_table.end_pos > tp->thumbnail_table.file_num - 2) {
        toplevel_set_menu_sensitive(tp, STATUS_THUMBNAIL | 
                                        STATUS_PREV   |
                                        STATUS_NO_NEXT      );
      }
      else {
        toplevel_set_menu_sensitive(tp, STATUS_THUMBNAIL | 
                                        STATUS_PREV   |
                                        STATUS_NEXT        );
      }
    }
    utils_gint_to_gchar(tp->thumbnail_table.file_num, 5, TRUE, &num_pt);
    sprintf(wk_str, "/ %s", num_pt);
    gtk_label_set_text(GTK_LABEL(tp->tb_label), wk_str);
    gtk_widget_set_sensitive(tp->tb_entry, TRUE);
    gtk_widget_set_sensitive(tp->tb_label, TRUE);
    free(num_pt);
  }
  
  /* Check the start_pos and end_pos. */
  if ((tp->thumbnail_table.start_pos == prev_start_pos)   &&
      (tp->thumbnail_table.end_pos   == prev_end_pos          )) {
    return;
  }

  /* Calcurate the position of the list of the Thumbnail structure 
   * objects. 
   */
  wk_thumb = tp->thumbnail_table.top_thumbnail;
  for (wkgint = 0; wkgint < tp->thumbnail_table.start_pos; wkgint++) {
    wk_thumb = wk_thumb->next;
  }

  /* Save the wk_thumb for using after. */
  wk_thumb1 = wk_thumb;

  /* Create the thumbnails as widget. */
  wkgint2 = tp->thumbnail_table.end_pos - tp->thumbnail_table.start_pos + 1;

  /* Create the progress bar dialog. */
  tp->progressbar_dialog.window = GTK_WINDOW(tp->window);
  if (tp->app_status == STATUS_TABLE_REFRESH) {
    dialog_progressbar_dialog_create(progressbar_msg2,
                                     &(tp->progressbar_dialog));
  }
  else {
    dialog_progressbar_dialog_create(progressbar_msg1,
                                     &(tp->progressbar_dialog));
  }

  /* Create the thumbnails. */
  for (wkgint = 0; wkgint < wkgint2; wkgint++) {
    if (tp->progressbar_dialog.is_cancel == TRUE) {
      tp->thumbnail_table.end_pos = 
                          tp->thumbnail_table.start_pos + wkgint - 1;
      dialog_progressbar_dialog_destroy(&(tp->progressbar_dialog));
      break;
    }
    dialog_progressbar_dialog_update(&(tp->progressbar_dialog),
                                     wkgint, wkgint2);
    thumbnail_create(wk_thumb, tp);
    wk_thumb = wk_thumb->next; 
  }

  dialog_progressbar_dialog_destroy(&(tp->progressbar_dialog));

  /* Display the created thumbnails. */
  cells = tp->thumbnail_table.end_pos - tp->thumbnail_table.start_pos + 1;
  columns = thumbanail_table_calc_columns(tp);
  tp->columns = columns;

  rows = (cells / columns) + 1; 
  if ((columns * (rows - 1)) == cells) { rows--; }

  tp->thumbnail_table.table = gtk_table_new(rows, columns, TRUE);
  if (tp->thumbnail_table.table == NULL) {
    /* Out of memory. */
    fprintf(stderr, "danpei: Out of memory.\n");
    fprintf(stderr, "        thumbnail_table.c: error -- 06.\n");
    gtk_exit(-1);
  }
  else {
    gtk_container_add(GTK_CONTAINER(tp->thumbnail_table.ev_box), 
                      tp->thumbnail_table.table                  );
    gtk_widget_show(tp->thumbnail_table.table);
  }

  wk_thumb = wk_thumb1;
  for (wkgint = 0; wkgint < cells ; wkgint++) {
    left_attach = wkgint % columns;
    top_attach  = wkgint / columns;
    gtk_table_attach(GTK_TABLE(tp->thumbnail_table.table), 
                     wk_thumb->ev_box,
                     left_attach     , left_attach + 1, 
                     top_attach      , top_attach  + 1, 
                     0, 0, 4, 4); 
                    /* GTK_FILL | GTK_EXPAND, 
                       GTK_FILL | GTK_EXPAND, 1, 1); */
    wk_thumb = wk_thumb->next;
  }

  return;
}

/*
 * Delete this line because configure_event will be emitted only when
 * the window is moved.
 * -- It seems that configure_event will not be emitted when the window 
 *    is resized.
 */
/*
 * @thumbnail_table_cb_configure
 *
 */
/*
void thumbnail_table_cb_configure(GtkWidget         *widget,       
                                  GdkEventConfigure *ev    , 
                                  gpointer          data     ) {
  TopLevel *tp;

  tp = (TopLevel*)data;

  if (tp->columns == 0) { return; }
  if (tp->columns == thumbanail_table_calc_columns(tp)) { return; }

  gtk_idle_add_priority(GTK_PRIORITY_RESIZE, thumbnail_table_resize, tp);
  
  return;
}
*/


/* Static function definitions. */
/*
 * @thumbnail_table_resize
 *
 */
static gint thumbnail_table_resize(gpointer data) {
  TopLevel *tp;

  tp = (TopLevel*)data;
  
  thumbnail_table_display_current_page(tp, -1, -1);

  return 0;
}

/*
 * @thumbnail_table_get_file_list
 *
 *  Acquire the files which applicable to an specified format from 
 *  the specified directory and list-ize them.
 *  Also, this function returns the number of files.
 *
 */
static gint thumbnail_table_get_file_list(gchar        *dir_name ,
                                          FormatSwitch *format   ,
                                          FileList     **filelist  ) {
  DIR           *dirp;
  struct dirent *ent;
  struct stat   stat_buf;
  gchar         *full_path, *ext;
  FileList      *wk_fl1, *wk_fl2;
  gint          file_num, max_length, wk_length;
  void          *qsort_wk1, *qsort_wk2;

  /* Initialize the local variables. */
  ent        = NULL;
  full_path  = ext       = NULL;
  file_num   = 0;
  max_length = wk_length = 0;
  *filelist  = wk_fl1    = wk_fl2 = NULL;
  qsort_wk1  = qsort_wk2 = NULL;

  if ((dirp = opendir(dir_name)) == NULL) { return 0; }

  while((ent = readdir(dirp)) != NULL) {
    if((strcmp(ent->d_name, ".")  != 0) &&
       (strcmp(ent->d_name, "..") != 0)     ) {
      full_path = (gchar*)malloc(sizeof(gchar) * 
                                 (strlen(dir_name)    +
                                  strlen("/")         +
                                  strlen(ent->d_name) + 1));
      if (full_path == NULL) {
        /* Out of memory. */
        fprintf(stderr, "danpei: Out of memory.\n");
        fprintf(stderr, "        thumbnail_table.c: error -- 07.\n");
        gtk_exit(-1);
      }

      sprintf(full_path, "%s/%s", dir_name, ent->d_name);

      if (stat(full_path, &stat_buf) == 0) {
        if (S_ISREG(stat_buf.st_mode)) {
          /* Get the extension to decide the format. */
          ext = ent->d_name;
          if ((ext = strrchr(ext, '.')) != NULL) { ext++; }

          if(thumbnail_table_decide_format(full_path,
                                           ext, 
                                           format->jpg_on * TYPE_JPG +
                                           format->bmp_on * TYPE_BMP +
                                           format->png_on * TYPE_PNG +
                                           format->xpm_on * TYPE_XPM +
                                           format->xbm_on * TYPE_XBM +
                                           format->tif_on * TYPE_TIF +
                                           format->gif_on * TYPE_GIF +
                                           format->pcx_on * TYPE_PCX   )
                                                                == TRUE) {
            /* Count up the file_num to use the sorting after. */
            file_num++;

            /* Get filename length and set maximum length to use for 
             * sorting after. 
             */
            wk_length = (sizeof(time_t) * 4                       ) +
                        (sizeof(size_t) * 1                       ) +
                        (sizeof(gchar)  * (strlen(ent->d_name) + 1)   );
            if (max_length < wk_length) {
              max_length = wk_length;
            }

            wk_fl2 = (FileList*)malloc(sizeof(FileList));
            if (wk_fl2 == NULL) {
              /* Out of Memory. */
              fprintf(stderr, "danpei: Out of memory.\n");
              fprintf(stderr, "        thumbnail_table.c: error -- 08.\n");
              gtk_exit(-1);
            }
            wk_fl2->ctime    = stat_buf.st_ctime;
            wk_fl2->atime    = stat_buf.st_atime;
            wk_fl2->mtime    = stat_buf.st_mtime;
            switch(qsort_flag) {
              case SORT_CTIME_A:
                wk_fl2->key_time = wk_fl2->ctime;
                break;
              case SORT_ATIME_A:
                wk_fl2->key_time = wk_fl2->atime;
                break;
              case SORT_MTIME_A:
                wk_fl2->key_time = wk_fl2->mtime;
                break;
              default:
                wk_fl2->key_time = wk_fl2->mtime;
                break;
            }
            wk_fl2->size     = stat_buf.st_size;
            wk_fl2->filename = strdup(ent->d_name);
            if (wk_fl2->filename == NULL) {
              /* Out of Memory. */
              fprintf(stderr, "danpei: Out of memory.\n");
              fprintf(stderr, "        thumbnail_table.c: error -- 09.\n");
              gtk_exit(-1);
            }

            if (wk_fl1 == NULL) {
              *filelist= wk_fl1 = wk_fl2;
              wk_fl2->next = NULL;
            }
            else {
              wk_fl1->next = wk_fl2;
              wk_fl2->next = NULL;
              wk_fl1       = wk_fl2;
            }
          }
        }
      }
      free(full_path);
    }
  }
  closedir(dirp);

  /* If required, performe the sorting by the file name. */

  if (*filelist == NULL) { return 0; }

  /* Allocate the memory for qsort(). */
  qsort_wk1 = malloc(max_length * file_num);
  if (qsort_wk1 == NULL) {
    /* Out of memory. */
    fprintf(stderr, "danpei: Out of memory.\n");
    fprintf(stderr, "        thumbnail_table.c: error -- 10.\n");
    gtk_exit(-1);
  }

  wk_fl1 = *filelist;
  qsort_wk2 = qsort_wk1;
  while(wk_fl1 != NULL) {
    *((time_t*)(qsort_wk2))                          = wk_fl1->ctime;
    *((time_t*)((qsort_wk2 + (sizeof(time_t) * 1)))) = wk_fl1->atime;
    *((time_t*)((qsort_wk2 + (sizeof(time_t) * 2)))) = wk_fl1->mtime;
    *((time_t*)((qsort_wk2 + (sizeof(time_t) * 3)))) = wk_fl1->mtime;
    *((time_t*)((qsort_wk2 + (sizeof(time_t) * 4)))) = wk_fl1->size;
    strcpy((gchar*)((qsort_wk2 + ((sizeof(time_t) * 4) + sizeof(size_t)))),
           wk_fl1->filename);
    wk_fl1 = wk_fl1->next;
    qsort_wk2 += max_length;
  }

  qsort(qsort_wk1, file_num, max_length, thumbnail_table_qsort_func);
    
  wk_fl1 = *filelist;
  qsort_wk2 = qsort_wk1;
  while(wk_fl1 != NULL) {
    if (wk_fl1->filename != NULL) { free(wk_fl1->filename); }
    wk_fl1->ctime    = *((time_t*)(qsort_wk2));
    wk_fl1->atime    = *((time_t*)((qsort_wk2 + (sizeof(time_t) * 1))));
    wk_fl1->mtime    = *((time_t*)((qsort_wk2 + (sizeof(time_t) * 2))));
    wk_fl1->key_time = *((time_t*)((qsort_wk2 + (sizeof(time_t) * 3))));
    wk_fl1->size     = *((time_t*)((qsort_wk2 + (sizeof(time_t) * 4))));
    wk_fl1->filename = strdup((gchar*)((qsort_wk2 +
                                         ((sizeof(time_t) * 4) + 
                                           sizeof(size_t)    )   )));
    if (wk_fl1->filename == NULL) {
      /* Out of memory. */
      fprintf(stderr, "danpei: Out of memory.\n");
      fprintf(stderr, "        thumbnail_table.c: error -- 11.\n");
      gtk_exit(-1);
    }
    wk_fl1 = wk_fl1->next;
    qsort_wk2 += max_length;
  }

  free(qsort_wk1);

  return file_num; 
}

/* 
 * @thumbnail_table_decide_format
 *
 *  Return TRUE if the filename is corresponds to the format which 
 *  specified by the argument 'format'.
 *
 */
static gboolean thumbnail_table_decide_format (gchar *filename ,
                                               gchar *extension,
                                               gint  format     ) {
  int fd, result;
  char buf[64];

  fd = open(filename, O_RDONLY, S_IROTH | S_IRGRP | S_IRUSR);
  if (fd == -1) { return FALSE; }

  result = read(fd, buf, 64); close(fd);
  if (result == -1) { return FALSE; }

  /* JPEG */
  if ((format & (gint)TYPE_JPG) != 0) {
    if ((buf[0] == (char)0xff) && (buf[1] == (char)0xd8) &&
        (buf[2] == (char)0xff)                              )
      return TRUE;
    else {
      if (extension != NULL) {
        if (((strcmp(extension, "jpeg") == 0) || 
             (strcmp(extension, "JPEG") == 0) ||
             (strcmp(extension, "jpg" ) == 0) || 
             (strcmp(extension, "JPG" ) == 0))   ) { return TRUE; }
      }
    }
  }
  
  /* BMP */
  if ((format & (gint)TYPE_BMP) != 0) {
    if ((buf[0] == 'B') && (buf[1] == 'M'))
      return TRUE;
    else {
      if (extension != NULL) {
        if (((strcmp(extension, "bmp") == 0) || 
             (strcmp(extension, "BMP") == 0))   ) { return TRUE; }
      }
    }
  }

  /* PNG */
  if ((format & (gint)TYPE_PNG) != 0) {
    if ((buf[0] == (char)0x89) && (buf[1] == (char)0x50) &&
        (buf[2] == (char)0x4e) && (buf[3] == (char)0x47) &&
        (buf[4] == (char)0x0d) && (buf[5] == (char)0x0a) &&
        (buf[6] == (char)0x1a) && (buf[7] == (char)0x0a)    )
      return TRUE;
    else {
      if (extension != NULL) {
        if (((strcmp(extension, "png") == 0) || 
             (strcmp(extension, "PNG") == 0))   ) { return TRUE; }
      }
    }
  }

  /* XPM */
  if ((format & (gint)TYPE_XPM) != 0) {
    if ((buf[0] == '/') && (buf[1] == '*') && (buf[2] == ' ') &&
        (buf[3] == 'X') && (buf[4] == 'P') && (buf[5] == 'M') &&
        (buf[6] == ' ') && (buf[7] == '*') && (buf[8] == '/')    ) 
      return TRUE; 
    else {
      if (extension != NULL) {
        if (((strcmp(extension, "xpm") == 0) || 
             (strcmp(extension, "XPM") == 0))  ) { return TRUE; }
      }
    }
  }

  /* XBM */
  if ((format & (gint)TYPE_XBM) != 0) {
    if (extension != NULL) {
      if ((strcmp(extension, "xbm") == 0) || 
          (strcmp(extension, "XBM") == 0)    ) { return TRUE; }
    }
  }

  /* TIFF */
  if ((format & (gint)TYPE_TIF) != 0) {
    if (((buf[0] == 'I') && (buf[1] == 'I'))  ||
        ((buf[0] == 'M') && (buf[1] == 'M'))     ) { return TRUE; }
    else {
      if (extension != NULL) {
        if ((strcmp(extension, "tiff") == 0) || 
            (strcmp(extension, "TIFF") == 0) ||
            (strcmp(extension, "tif" ) == 0) || 
            (strcmp(extension, "TIF" ) == 0)    ) { return TRUE; }
      }
    }
  }

  /* GIF */
  if ((format & (gint)TYPE_GIF) != 0) {
    if ((buf[0] == 'G') && (buf[1] == 'I') &&
        (buf[2] == 'F') && (buf[3] == '8')     ) { return TRUE; }
    else {
      if (extension != NULL) {
        if ((strcmp(extension, "gif") == 0) || 
            (strcmp(extension, "GIF") == 0)    ) { return TRUE; }
      }
    }
  }

  /* PCX */
  if ((format & (gint)TYPE_PCX) != 0) {
    if ((buf[0] == (char)0x0a) && (buf[2] == (char)0x01))
    { 
      return TRUE; 
    }
    else {
      if (extension != NULL) {
        if ((strcmp(extension, "pcx") == 0) || 
            (strcmp(extension, "PCX") == 0)    ) { return TRUE; }
      }
    }
  }

  return FALSE;
}

/*
 * @thumbnail_table_free_filelist
 *
 *  Free the FileList structure objects specified by the argument. 
 *
 */
static void thumbnail_table_free_filelist(FileList *top) {
  FileList *wk_fl1, *wk_fl2;

  wk_fl1 = top;

  while (wk_fl1 != NULL) {
    wk_fl2 = wk_fl1->next;
    if (wk_fl1->filename != NULL) { free(wk_fl1->filename); }
    free(wk_fl1);
    wk_fl1 = wk_fl2;
  }

  return;
}

/* 
 * @thumbnail_table_qsort_func
 *
 *  Function for qsort().
 *
 */
static int thumbnail_table_qsort_func(const void *var1,
                                      const void *var2 ) {
  int      ret_val;

  /* Initialize the local variables. */
  ret_val = 0;

  if ((qsort_flag == SORT_FILE_NAME_A) ||
      (qsort_flag == SORT_FILE_NAME_D)    ) {
    ret_val =
       strcmp((gchar*)((var1 + ((sizeof(time_t) * 4) + sizeof(size_t)))), 
              (gchar*)((var2 + ((sizeof(time_t) * 4) + sizeof(size_t)))) ); 
    if (ret_val == 0) {
      ret_val = *((time_t*)((var1 + (sizeof(time_t) * 3)))) -
                *((time_t*)((var2 + (sizeof(time_t) * 3))));
    }
  }
  else {
    ret_val = *((time_t*)((var1 + (sizeof(time_t) * 3)))) -
              *((time_t*)((var2 + (sizeof(time_t) * 3))));
    if (ret_val == 0) {
      ret_val =
         strcmp((gchar*)((var1 + ((sizeof(time_t) * 4) + sizeof(size_t)))), 
                (gchar*)((var2 + ((sizeof(time_t) * 4) + sizeof(size_t)))) );
    }
  }

  if (qsort_flag < SORT_FILE_NAME_D) {
    return ret_val;
  }
  else {
    return ret_val * -1;
  }
}

/*
 * @thumbanail_table_calc_columns
 *
 */
static gint thumbanail_table_calc_columns(TopLevel *tp) {
  gint columns;

  switch (tp->current_icon_size) {
    case ICON_SMALL :
      columns = tp->thumbnail_table.scrolled_window->allocation.width / 
                                               (tp->current_icon_size + 16);
      break;
    case ICON_LARGE :
      columns = tp->thumbnail_table.scrolled_window->allocation.width / 
                                               (tp->current_icon_size + 16);
      break;
    case ICON_MIDDLE:
    default:
      columns = tp->thumbnail_table.scrolled_window->allocation.width / 
                                               (tp->current_icon_size + 8);
      break;
  }
  if (columns < 1) { return 1;} else { return columns; }
}


Generated by  Doxygen 1.6.0   Back to index