aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Alex Bennee <alex@bennee.com>2010-07-14 16:03:56 +0100
committerGravatar Alex Bennee <alex@bennee.com>2010-07-14 16:03:56 +0100
commita3e202820fd12e3c368c9ed2446740e9b1d16fd7 (patch)
treecf5b62c17350cd172c301146c8cba4dae01a2110 /src
parent26b8e06374c71e42be86694f5d5c4ee920ae4d26 (diff)
EasyTag 2.1.5
Diffstat (limited to 'src')
-rwxr-xr-x[-rw-r--r--]src/Makefile.am0
-rwxr-xr-x[-rw-r--r--]src/Makefile.mingw0
-rwxr-xr-x[-rw-r--r--]src/about.c0
-rwxr-xr-x[-rw-r--r--]src/base64.c0
-rwxr-xr-x[-rw-r--r--]src/base64.h0
-rw-r--r--src/browser.c66
-rwxr-xr-x[-rw-r--r--]src/cddb.c0
-rw-r--r--[-rwxr-xr-x]src/easytag.c123
-rw-r--r--src/et_core.c11
-rwxr-xr-x[-rw-r--r--]src/et_core.h0
-rwxr-xr-x[-rw-r--r--]src/flac_header.c0
-rw-r--r--src/flac_tag.c74
-rwxr-xr-x[-rw-r--r--]src/id3_tag.c0
-rw-r--r--src/id3v24_tag.c42
-rwxr-xr-x[-rw-r--r--]src/libapetag/apetaglib.c0
-rwxr-xr-x[-rw-r--r--]src/libmpg123/mpg123.c0
-rwxr-xr-xsrc/log.c3
-rwxr-xr-x[-rw-r--r--]src/misc.c0
-rwxr-xr-x[-rw-r--r--]src/mp4_tag.c7
-rwxr-xr-x[-rw-r--r--]src/ogg_tag.c0
-rw-r--r--src/picture.c2
-rwxr-xr-x[-rw-r--r--]src/picture.h0
-rw-r--r--[-rwxr-xr-x]src/prefs.c111
-rw-r--r--src/scan.c441
-rw-r--r--[-rwxr-xr-x]src/setting.c2
-rw-r--r--[-rwxr-xr-x]src/setting.h1
26 files changed, 640 insertions, 243 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 5e9961d..5e9961d 100644..100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
diff --git a/src/Makefile.mingw b/src/Makefile.mingw
index dd86f83..dd86f83 100644..100755
--- a/src/Makefile.mingw
+++ b/src/Makefile.mingw
diff --git a/src/about.c b/src/about.c
index 3b19a68..3b19a68 100644..100755
--- a/src/about.c
+++ b/src/about.c
diff --git a/src/base64.c b/src/base64.c
index 496f697..496f697 100644..100755
--- a/src/base64.c
+++ b/src/base64.c
diff --git a/src/base64.h b/src/base64.h
index f0ddea4..f0ddea4 100644..100755
--- a/src/base64.h
+++ b/src/base64.h
diff --git a/src/browser.c b/src/browser.c
index 7aa56f0..69a7dfe 100644
--- a/src/browser.c
+++ b/src/browser.c
@@ -61,7 +61,8 @@
/* Pixmaps */
#include "../pixmaps/opened_folder.xpm"
#include "../pixmaps/closed_folder.xpm"
-#include "../pixmaps/closed_folder_locked.xpm"
+#include "../pixmaps/closed_folder_readonly.xpm"
+#include "../pixmaps/closed_folder_unreadable.xpm"
#ifdef WIN32
#include "../pixmaps/ram_disk.xpm"
#endif
@@ -73,8 +74,9 @@
****************/
// Pixmaps
-static GdkPixbuf *opened_folder_pixmap = NULL, *closed_folder_pixmap, *closed_folder_locked_pixmap;
+static GdkPixbuf *opened_folder_pixmap = NULL, *closed_folder_pixmap, *closed_folder_readonly_pixmap, *closed_folder_unreadable_pixmap;
#ifdef WIN32
+// Pixmap used for Win32 only
static GdkPixbuf *harddrive_pixmap, *removable_pixmap, *cdrom_pixmap, *network_pixmap, *ramdisk_pixmap;
#endif
@@ -175,7 +177,7 @@ static gboolean check_for_subdir (gchar *path);
GtkTreePath *Find_Child_Node(GtkTreeIter *parent, gchar *searchtext);
-gboolean Check_For_Access_Permission (gchar *path);
+GdkPixbuf *Pixmap_From_Directory_Permission (gchar *path);
static void expand_cb (GtkWidget *tree, GtkTreeIter *iter, GtkTreePath *path, gpointer data);
static void collapse_cb (GtkWidget *tree, GtkTreeIter *iter, GtkTreePath *treePath, gpointer data);
@@ -1743,6 +1745,7 @@ void Browser_List_Refresh_Sort (void)
/*
* Intelligently sort the file list based on the current sorting method
+ * see also 'ET_Sort_File_List'
*/
gint Browser_List_Sort_Func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data)
{
@@ -2695,9 +2698,17 @@ static gboolean check_for_subdir (gchar *path)
{
while( (dirent=readdir(dir)) )
{
- // We don't read the directories '.' and '..', but may read hidden directories like '.mydir'
- if ( (g_ascii_strcasecmp (dirent->d_name,"..") != 0)
- && ( (g_ascii_strncasecmp(dirent->d_name,".", 1) != 0) || (BROWSE_HIDDEN_DIR && strlen(dirent->d_name) > 1)) )
+ // We don't read the directories '.' and '..', but may read hidden directories
+ // like '.mydir' (note that '..mydir' or '...mydir' aren't hidden directories)
+ // See also the rule into 'expand_cb' function
+ if ((g_ascii_strcasecmp(dirent->d_name,".") != 0)
+ && (g_ascii_strcasecmp(dirent->d_name,"..") != 0)
+ // Display hidden directories is needed, or keep only the not hidden directories
+ && (BROWSE_HIDDEN_DIR
+ || !( (g_ascii_strncasecmp(dirent->d_name,".", 1) == 0)
+ && (strlen(dirent->d_name) > 1)
+ && (g_ascii_strncasecmp(dirent->d_name+1,".", 1) != 0) ))
+ )
{
#ifdef WIN32
// On win32 : stat("/path/to/dir") succeed, while stat("/path/to/dir/") fails
@@ -2714,7 +2725,7 @@ static gboolean check_for_subdir (gchar *path)
g_free(npath);
- if(S_ISDIR(statbuf.st_mode))
+ if (S_ISDIR(statbuf.st_mode))
{
closedir(dir);
return TRUE;
@@ -2727,21 +2738,22 @@ static gboolean check_for_subdir (gchar *path)
}
/*
- * Check if you have access permissions for directory path. Returns 1 if ok, else 0.
+ * Check if you have permissions for directory path (autorized?, readonly? unreadable?).
+ * Returns the right pixmap.
*/
-gboolean Check_For_Access_Permission (gchar *path)
+GdkPixbuf *Pixmap_From_Directory_Permission (gchar *path)
{
DIR *dir;
if( (dir=opendir(path)) == NULL )
{
if (errno == EACCES)
- return FALSE;
+ return closed_folder_unreadable_pixmap;
} else
{
closedir(dir);
}
- return TRUE;
+ return closed_folder_pixmap;
}
@@ -2809,10 +2821,18 @@ static void expand_cb (GtkWidget *tree, GtkTreeIter *iter, GtkTreePath *gtreePat
path = g_strconcat(parentPath, dirent->d_name, NULL);
stat(path, &statbuf);
- // We don't read the directories '.' and '..', but may read hidden directories like '.mydir'
+ // We don't read the directories '.' and '..', but may read hidden directories
+ // like '.mydir' (note that '..mydir' or '...mydir' aren't hidden directories)
+ // See also the rule into 'check_for_subdir' function
if (S_ISDIR(statbuf.st_mode)
- && ( (g_ascii_strcasecmp (dirent->d_name,"..") != 0)
- && ((g_ascii_strncasecmp(dirent->d_name,".", 1) != 0) || (BROWSE_HIDDEN_DIR && strlen(dirent->d_name) > 1)) ) )
+ && (g_ascii_strcasecmp(dirent->d_name,".") != 0)
+ && (g_ascii_strcasecmp(dirent->d_name,"..") != 0)
+ // Display hidden directories is needed, or keep only the not hidden directories
+ && (BROWSE_HIDDEN_DIR
+ || !( (g_ascii_strncasecmp(dirent->d_name,".", 1) == 0)
+ && (strlen(dirent->d_name) > 1)
+ && (g_ascii_strncasecmp(dirent->d_name+1,".", 1) != 0) ))
+ )
{
if (path[strlen(path)-1]!=G_DIR_SEPARATOR)
@@ -2833,11 +2853,8 @@ static void expand_cb (GtkWidget *tree, GtkTreeIter *iter, GtkTreePath *gtreePat
else
has_subdir = FALSE;
- /* Select pixmap for accessible/unaccessible directory */
- if (Check_For_Access_Permission(path))
- pixbuf = closed_folder_pixmap;
- else
- pixbuf = closed_folder_locked_pixmap;
+ // Select pixmap according permissions for the directory
+ pixbuf = Pixmap_From_Directory_Permission(path);
gtk_tree_store_append(directoryTreeModel, &currentIter, iter);
gtk_tree_store_set(directoryTreeModel, &currentIter,
@@ -2909,13 +2926,13 @@ static void collapse_cb (GtkWidget *tree, GtkTreeIter *iter, GtkTreePath *treePa
// update the icon of the node to closed folder :-)
gtk_tree_store_set(directoryTreeModel, iter,
TREE_COLUMN_SCANNED, FALSE,
- TREE_COLUMN_PIXBUF, closed_folder_pixmap, -1);
+ TREE_COLUMN_PIXBUF, closed_folder_pixmap, -1);
}
#else
// update the icon of the node to closed folder :-)
gtk_tree_store_set(directoryTreeModel, iter,
TREE_COLUMN_SCANNED, FALSE,
- TREE_COLUMN_PIXBUF, closed_folder_pixmap, -1);
+ TREE_COLUMN_PIXBUF, closed_folder_pixmap, -1);
#endif
// insert dummy node
@@ -3004,9 +3021,10 @@ GtkWidget *Create_Browser_Items (GtkWidget *parent)
/* Create pixmaps */
if(!opened_folder_pixmap)
{
- opened_folder_pixmap = gdk_pixbuf_new_from_xpm_data(opened_folder_xpm);
- closed_folder_pixmap = gdk_pixbuf_new_from_xpm_data(closed_folder_xpm);
- closed_folder_locked_pixmap = gdk_pixbuf_new_from_xpm_data(closed_folder_locked_xpm);
+ opened_folder_pixmap = gdk_pixbuf_new_from_xpm_data(opened_folder_xpm);
+ closed_folder_pixmap = gdk_pixbuf_new_from_xpm_data(closed_folder_xpm);
+ closed_folder_readonly_pixmap = gdk_pixbuf_new_from_xpm_data(closed_folder_readonly_xpm);
+ closed_folder_unreadable_pixmap = gdk_pixbuf_new_from_xpm_data(closed_folder_unreadable_xpm);
#ifdef WIN32
/* get GTK's theme harddrive and removable icons and render it in a pixbuf */
diff --git a/src/cddb.c b/src/cddb.c
index 8d4cf7f..8d4cf7f 100644..100755
--- a/src/cddb.c
+++ b/src/cddb.c
diff --git a/src/easytag.c b/src/easytag.c
index 6d8bd62..38f42ff 100755..100644
--- a/src/easytag.c
+++ b/src/easytag.c
@@ -84,6 +84,18 @@ gboolean SF_HideMsgbox_Delete_File;
/* To remember which button was pressed when deleting file */
gint SF_ButtonPressed_Delete_File;
+#ifdef ENABLE_FLAC
+ #include <FLAC/metadata.h>
+
+ /* Patch from Josh Coalson
+ * FLAC 1.1.3 has FLAC_API_VERSION_CURRENT == 8 *
+ * by LEGACY_FLAC we mean pre-FLAC 1.1.3; in FLAC 1.1.3 the FLAC__FileDecoder was merged into the FLAC__StreamDecoder */
+ #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT < 8
+ #define LEGACY_FLAC // For FLAC version < 1.1.3
+ #else
+ #undef LEGACY_FLAC
+ #endif
+#endif
/**************
@@ -369,14 +381,14 @@ int main (int argc, char *argv[])
/* Vertical pane for Browser Area + FileArea + TagArea */
MainWindowVPaned = gtk_vpaned_new();
gtk_box_pack_start(GTK_BOX(MainVBox),MainWindowVPaned,TRUE,TRUE,0);
- gtk_paned_pack1(GTK_PANED(MainWindowVPaned),MainWindowHPaned,FALSE,FALSE);
+ gtk_paned_pack1(GTK_PANED(MainWindowVPaned),MainWindowHPaned,TRUE,FALSE);
gtk_paned_set_position(GTK_PANED(MainWindowVPaned),PANE_HANDLE_POSITION4);
gtk_widget_show(MainWindowVPaned);
/* Log */
LogArea = Create_Log_Area();
- gtk_paned_pack2(GTK_PANED(MainWindowVPaned),LogArea,TRUE,TRUE);
+ gtk_paned_pack2(GTK_PANED(MainWindowVPaned),LogArea,FALSE,TRUE);
/* Horizontal box for Status bar + Progress bar */
HBox = gtk_hbox_new(FALSE,0);
@@ -2710,7 +2722,9 @@ gint Remove_Dir (const gchar *dirname_old, const gchar *dirname_new)
{
if (rmdir(temp_old)==-1)
{
- if (errno!=ENOTEMPTY)
+ // Patch from vdaghan : ENOTEMPTY & EEXIST are synonymous and used by some systems
+ if (errno != ENOTEMPTY
+ && errno != EEXIST)
{
g_free(temp_old);
g_free(temp_new);
@@ -3990,9 +4004,17 @@ void Tag_Area_Display_Controls (ET_File *ETFile)
gtk_widget_show(GTK_WIDGET(EncodedByLabel));
gtk_widget_show(GTK_WIDGET(EncodedByEntry));
gtk_widget_show(GTK_WIDGET(EncodedByMButton));
- // Picture always supported now...
- /*if (WRITE_ID3_TAGS_IN_FLAC_FILE)
- {*/
+ #ifndef LEGACY_FLAC // Picture supported for FLAC >= 1.1.3...
+ gtk_widget_show(GTK_WIDGET(PictureLabel));
+ gtk_widget_show(GTK_WIDGET(PictureScrollWindow));
+ gtk_widget_show(GTK_WIDGET(PictureMButton));
+ gtk_widget_show(GTK_WIDGET(PictureClearButton));
+ gtk_widget_show(GTK_WIDGET(PictureAddButton));
+ gtk_widget_show(GTK_WIDGET(PictureSaveButton));
+ gtk_widget_show(GTK_WIDGET(PicturePropertiesButton));
+ #else
+ if (WRITE_ID3_TAGS_IN_FLAC_FILE)
+ {
gtk_widget_show(GTK_WIDGET(PictureLabel));
gtk_widget_show(GTK_WIDGET(PictureScrollWindow));
gtk_widget_show(GTK_WIDGET(PictureMButton));
@@ -4000,7 +4022,7 @@ void Tag_Area_Display_Controls (ET_File *ETFile)
gtk_widget_show(GTK_WIDGET(PictureAddButton));
gtk_widget_show(GTK_WIDGET(PictureSaveButton));
gtk_widget_show(GTK_WIDGET(PicturePropertiesButton));
- /*}else
+ }else
{
gtk_widget_hide(GTK_WIDGET(PictureLabel));
gtk_widget_hide(GTK_WIDGET(PictureScrollWindow));
@@ -4009,7 +4031,8 @@ void Tag_Area_Display_Controls (ET_File *ETFile)
gtk_widget_hide(GTK_WIDGET(PictureAddButton));
gtk_widget_hide(GTK_WIDGET(PictureSaveButton));
gtk_widget_hide(GTK_WIDGET(PicturePropertiesButton));
- }*/
+ }
+ #endif
break;
#endif
@@ -4660,62 +4683,9 @@ void Quit_MainWindow (void)
Save_Path_Entry_List(BrowserEntryModel, MISC_COMBO_TEXT);
/* Exit ? */
- if (CONFIRM_BEFORE_EXIT)
- {
- if (ET_Check_If_All_Files_Are_Saved() != TRUE)
- {
- /* Some files haven't been saved */
- msgbox = msg_box_new(_("Confirm..."),
- GTK_WINDOW(MainWindow),
- NULL,
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- _("Some files have been modified but not saved...\nDo you want to save them before exiting the program?"),
- GTK_STOCK_DIALOG_QUESTION,
- GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL,
- GTK_STOCK_NO, GTK_RESPONSE_NO,
- GTK_STOCK_YES, GTK_RESPONSE_YES,
- NULL);
- response = gtk_dialog_run(GTK_DIALOG(msgbox));
- gtk_widget_destroy(msgbox);
- switch (response)
- {
- case GTK_RESPONSE_YES:
- Quit_MainWindow_Save_And_Quit();
- break;
- case GTK_RESPONSE_NO:
- Quit_MainWindow_Confirmed();
- break;
- case GTK_RESPONSE_CANCEL:
- case GTK_RESPONSE_NONE:
- return;
- }
- } else
- {
- msgbox = msg_box_new(_("Confirm..."),
- GTK_WINDOW(MainWindow),
- NULL,
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- _(" Do you really want to exit the program? "),
- GTK_STOCK_DIALOG_QUESTION,
- GTK_STOCK_NO, GTK_RESPONSE_NO,
- GTK_STOCK_YES, GTK_RESPONSE_YES,
- NULL);
- response = gtk_dialog_run(GTK_DIALOG(msgbox));
- gtk_widget_destroy(msgbox);
- switch (response)
- {
- case GTK_RESPONSE_YES:
- Quit_MainWindow_Confirmed();
- break;
- case GTK_RESPONSE_NO:
- case GTK_RESPONSE_NONE:
- return;
- break;
- }
- }
- }else if (ET_Check_If_All_Files_Are_Saved() != TRUE)
+ if (ET_Check_If_All_Files_Are_Saved() != TRUE)
{
- /* Some files aren't saved */
+ /* Some files haven't been saved */
msgbox = msg_box_new(_("Confirm..."),
GTK_WINDOW(MainWindow),
NULL,
@@ -4724,7 +4694,7 @@ void Quit_MainWindow (void)
GTK_STOCK_DIALOG_QUESTION,
GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL,
GTK_STOCK_NO, GTK_RESPONSE_NO,
- GTK_STOCK_YES, GTK_RESPONSE_YES,
+ GTK_STOCK_YES, GTK_RESPONSE_YES,
NULL);
response = gtk_dialog_run(GTK_DIALOG(msgbox));
gtk_widget_destroy(msgbox);
@@ -4740,10 +4710,35 @@ void Quit_MainWindow (void)
case GTK_RESPONSE_NONE:
return;
}
+
+ } else if (CONFIRM_BEFORE_EXIT)
+ {
+ msgbox = msg_box_new(_("Confirm..."),
+ GTK_WINDOW(MainWindow),
+ NULL,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ _(" Do you really want to exit the program? "),
+ GTK_STOCK_DIALOG_QUESTION,
+ GTK_STOCK_NO, GTK_RESPONSE_NO,
+ GTK_STOCK_YES, GTK_RESPONSE_YES,
+ NULL);
+ response = gtk_dialog_run(GTK_DIALOG(msgbox));
+ gtk_widget_destroy(msgbox);
+ switch (response)
+ {
+ case GTK_RESPONSE_YES:
+ Quit_MainWindow_Confirmed();
+ break;
+ case GTK_RESPONSE_NO:
+ case GTK_RESPONSE_NONE:
+ return;
+ break;
+ }
}else
{
Quit_MainWindow_Confirmed();
}
+
}
/*
diff --git a/src/et_core.c b/src/et_core.c
index 35280ab..cace2c5 100644
--- a/src/et_core.c
+++ b/src/et_core.c
@@ -29,6 +29,7 @@
#include <unistd.h>
#include <utime.h>
#include <ctype.h>
+#include <locale.h>
#include "errno.h"
#include "easytag.h"
@@ -484,9 +485,10 @@ GList *ET_Add_File_To_File_List (gchar *filename)
FileTag = ET_File_Tag_Item_New();
FileTag->saved = TRUE; /* The file hasn't been changed, so it's saved */
- /* Patch from Doruk Fisek : avoid upper/lower conversion bugs (like I->i conversion in
- * some locales) in tag parsing. The problem occurs for example with Turkish language
- * where it can't read 'TITLE=' field if it is written as 'Title=' in the file */
+ /* Patch from Doruk Fisek and Onur Kucuk: avoid upper/lower conversion bugs
+ * (like I->i conversion in some locales) in tag parsing. The problem occurs
+ * for example with Turkish language where it can't read 'TITLE=' field if
+ * it is written as 'Title=' in the file */
setlocale(LC_CTYPE, "C");
switch (ETFileDescription->TagType)
@@ -2404,6 +2406,7 @@ gboolean ET_Set_Field_File_Name_Item (gchar **FileNameField, gchar *value)
/*
* Fill content of a FileName item according to the filename passed in argument (UTF-8 filename or not)
* Calculate also the collate key.
+ * It treats numbers intelligently so that "file1" "file10" "file5" is sorted as "file1" "file5" "file10"
*/
gboolean ET_Set_Filename_File_Name_Item (File_Name *FileName, gchar *filename_utf8, gchar *filename)
{
@@ -2429,7 +2432,7 @@ gboolean ET_Set_Filename_File_Name_Item (File_Name *FileName, gchar *filename_ut
{
return FALSE;
}
-
+
return TRUE;
}
diff --git a/src/et_core.h b/src/et_core.h
index 8f275c8..8f275c8 100644..100755
--- a/src/et_core.h
+++ b/src/et_core.h
diff --git a/src/flac_header.c b/src/flac_header.c
index acdf628..acdf628 100644..100755
--- a/src/flac_header.c
+++ b/src/flac_header.c
diff --git a/src/flac_tag.c b/src/flac_tag.c
index 9d3be65..55475fb 100644
--- a/src/flac_tag.c
+++ b/src/flac_tag.c
@@ -105,7 +105,9 @@ gboolean Flac_Tag_Read_File_Tag (gchar *filename, File_Tag *FileTag)
FLAC__Metadata_SimpleIterator *iter;
gchar *string = NULL;
guint i;
+#ifndef LEGACY_FLAC // For FLAC >= 1.1.3
Picture *prev_pic = NULL;
+#endif
//gint j = 1;
@@ -615,49 +617,47 @@ gboolean Flac_Tag_Read_File_Tag (gchar *filename, File_Tag *FileTag)
//
// Read the PICTURE block (severals can exist)
//
+#ifndef LEGACY_FLAC // For FLAC >= 1.1.3
case FLAC__METADATA_TYPE_PICTURE:
{
/***********
* Picture *
***********/
- // For FLAC >= 1.1.3
- #ifndef LEGACY_FLAC
- FLAC__StreamMetadata_Picture *p;
- Picture *pic;
-
- // Get picture data from block
- p = &block->data.picture;
-
- pic = Picture_Allocate();
- if (!prev_pic)
- FileTag->picture = pic;
- else
- prev_pic->next = pic;
- prev_pic = pic;
-
- pic->size = p->data_length;
- pic->data = g_memdup(p->data,pic->size);
- pic->type = p->type;
- pic->description = g_strdup((gchar *)p->description);
- // Not necessary: will be calculated later
- //pic->height = p->height;
- //pic->width = p->width;
-
- //g_print("Picture type : %s\n",FLAC__StreamMetadata_Picture_TypeString[p->type]);
- //g_print("Mime type : %s\n",p->mime_type);
+ FLAC__StreamMetadata_Picture *p;
+ Picture *pic;
+
+ // Get picture data from block
+ p = &block->data.picture;
+
+ pic = Picture_Allocate();
+ if (!prev_pic)
+ FileTag->picture = pic;
+ else
+ prev_pic->next = pic;
+ prev_pic = pic;
+
+ pic->size = p->data_length;
+ pic->data = g_memdup(p->data,pic->size);
+ pic->type = p->type;
+ pic->description = g_strdup((gchar *)p->description);
+ // Not necessary: will be calculated later
+ //pic->height = p->height;
+ //pic->width = p->width;
+
+ //g_print("Picture type : %s\n",FLAC__StreamMetadata_Picture_TypeString[p->type]);
+ //g_print("Mime type : %s\n",p->mime_type);
- #endif
-
break;
}
-
+#endif
+
default:
break;
}
// Free block data
- ////FLAC__metadata_object_delete(block);
+ //FLAC__metadata_object_delete(block);
}
// Free iter
@@ -811,7 +811,8 @@ gboolean Flac_Tag_Write_File_Tag (ET_File *ETFile)
FLAC__StreamMetadata_VorbisComment *vc = &block->data.vorbis_comment;
// Get initial vendor string, to don't alterate it by FLAC__VENDOR_STRING when saving file
- vce_field_vendor_string = vc->vendor_string;
+ vce_field_vendor_string.entry = (FLAC__byte *)g_strdup((gchar *)vc->vendor_string.entry);
+ vce_field_vendor_string.length = strlen((gchar *)vce_field_vendor_string.entry);
vce_field_vendor_string_found = TRUE;
// Free block data
@@ -822,12 +823,14 @@ gboolean Flac_Tag_Write_File_Tag (ET_File *ETFile)
//
// Delete all the PICTURE blocks, and convert to padding
//
+#ifndef LEGACY_FLAC // For FLAC >= 1.1.3
case FLAC__METADATA_TYPE_PICTURE:
{
FLAC__metadata_iterator_delete_block(iter,true);
break;
}
-
+#endif
+
default:
break;
}
@@ -848,7 +851,10 @@ gboolean Flac_Tag_Write_File_Tag (ET_File *ETFile)
// Set the original vendor string, else will be use the version of library
if (vce_field_vendor_string_found)
+ {
FLAC__metadata_object_vorbiscomment_set_vendor_string(vc_block, vce_field_vendor_string, true);
+ g_free(vce_field_vendor_string.entry);
+ }
/*********
@@ -1039,9 +1045,8 @@ gboolean Flac_Tag_Write_File_Tag (ET_File *ETFile)
list = list->next;
}
- // Add the block to the the chain
+ // Add the block to the the chain (so we don't need to free the block)
FLAC__metadata_iterator_insert_block_after(iter, vc_block);
- ////FLAC__metadata_object_delete(vc_block);
}
@@ -1092,9 +1097,8 @@ gboolean Flac_Tag_Write_File_Tag (ET_File *ETFile)
FLAC__metadata_object_delete(picture_block);
}else
{
- // Add the block to the the chain
+ // Add the block to the the chain (so we don't need to free the block)
FLAC__metadata_iterator_insert_block_after(iter, picture_block);
- ////FLAC__metadata_object_delete(picture_block);
}
}
diff --git a/src/id3_tag.c b/src/id3_tag.c
index 8a21abf..8a21abf 100644..100755
--- a/src/id3_tag.c
+++ b/src/id3_tag.c
diff --git a/src/id3v24_tag.c b/src/id3v24_tag.c
index 04da4a8..a627fcd 100644
--- a/src/id3v24_tag.c
+++ b/src/id3v24_tag.c
@@ -412,6 +412,7 @@ gboolean Id3tag_Read_File_Tag (gchar *filename, File_Tag *FileTag)
{
id3_length_t size;
id3_byte_t const *data;
+
data = id3_field_getbinarydata(field, &size);
if (pic->data)
g_free(pic->data);
@@ -665,6 +666,7 @@ libid3tag_Get_Frame_Str(const struct id3_frame *frame, unsigned etag_field_type,
retval = 0;
is_latin = 1, is_utf16 = 0;
+ // Find the encoding used for the field
for (i = 0; (field = id3_frame_field(frame, i)); i++)
{
if (id3_field_type(field) == ID3_FIELD_TYPE_TEXTENCODING)
@@ -782,6 +784,7 @@ gboolean Id3tag_Write_File_v24Tag (ET_File *ETFile)
v1tag = v2tag = NULL;
+ // Write ID3v2 tag
if (FILE_WRITING_ID3V2_WRITE_TAG)
{
struct id3_file *file;
@@ -803,7 +806,8 @@ gboolean Id3tag_Write_File_v24Tag (ET_File *ETFile)
| ID3_TAG_OPTION_ID3V1
| ID3_TAG_OPTION_COMPRESSION
| ID3_TAG_OPTION_APPENDEDTAG,
- ID3_TAG_OPTION_UNSYNCHRONISATION);
+ //ID3_TAG_OPTION_UNSYNCHRONISATION); // Taglib doesn't support frames with unsynchronisation (patch from Alexey Illarionov) http://bugs.kde.org/show_bug.cgi?id=138829
+ 0);
/* XXX Create new tag and copy all frames*/
tagsize = id3_tag_render(tmptag, NULL);
@@ -832,25 +836,27 @@ gboolean Id3tag_Write_File_v24Tag (ET_File *ETFile)
v2tag->paddedsize = 1024;
/* Set options */
- id3_tag_options(v2tag,
- ID3_TAG_OPTION_UNSYNCHRONISATION
- | ID3_TAG_OPTION_APPENDEDTAG
- | ID3_TAG_OPTION_ID3V1
- | ID3_TAG_OPTION_CRC
- | ID3_TAG_OPTION_COMPRESSION,
- ID3_TAG_OPTION_UNSYNCHRONISATION
- );
+ id3_tag_options(v2tag, ID3_TAG_OPTION_UNSYNCHRONISATION
+ | ID3_TAG_OPTION_APPENDEDTAG
+ | ID3_TAG_OPTION_ID3V1
+ | ID3_TAG_OPTION_CRC
+ | ID3_TAG_OPTION_COMPRESSION,
+ //ID3_TAG_OPTION_UNSYNCHRONISATION); // Taglib doesn't support frames with unsynchronisation (patch from Alexey Illarionov) http://bugs.kde.org/show_bug.cgi?id=138829
+ 0);
+
if (FILE_WRITING_ID3V2_USE_CRC32)
id3_tag_options(v2tag, ID3_TAG_OPTION_CRC, ~0);
if (FILE_WRITING_ID3V2_USE_COMPRESSION)
id3_tag_options(v2tag, ID3_TAG_OPTION_COMPRESSION, ~0);
}
+ // Write ID3v1 tag
if (FILE_WRITING_ID3V1_WRITE_TAG)
{
v1tag = id3_tag_new();
if (!v1tag)
return FALSE;
+
id3_tag_options(v1tag, ID3_TAG_OPTION_ID3V1, ~0);
}
@@ -957,10 +963,9 @@ gboolean Id3tag_Write_File_v24Tag (ET_File *ETFile)
***********/
Id3tag_delete_frames(v2tag, "APIC", 0);
- pic = FileTag->picture;
-
if (v2tag)
{
+ pic = FileTag->picture;
while (pic)
{
gint i;
@@ -1328,8 +1333,10 @@ etag_set_tags (const gchar *str,
&& (ftmp = Id3tag_find_and_create_frame(v1tag, frame_name)))
id3taglib_set_field(ftmp, str, field_type, 0, 1, 1);
}else
+ {
if (v2tag)
Id3tag_delete_frames(v2tag, frame_name, 0);
+ }
return 0;
}
@@ -1384,6 +1391,7 @@ etag_write_tags (const gchar *filename,
}
}
}
+
if (v1buf == NULL)
v1size = 0;
if (v2buf == NULL)
@@ -1415,10 +1423,12 @@ etag_write_tags (const gchar *filename,
goto out;
}
}else
+ {
if ((curpos = lseek(fd, 0, SEEK_END)) < 0)
{
goto out;
}
+ }
/* Search id3v2 tags at the end of the file (before any ID3v1 tag) */
/* XXX: Unsafe */
@@ -1441,8 +1451,8 @@ etag_write_tags (const gchar *filename,
/* Write id3v1 tag */
if (v1buf)
- if ( write(fd, v1buf, v1size) != v1size)
- goto out;
+ if ( write(fd, v1buf, v1size) != v1size)
+ goto out;
/* Truncate file (strip tags) */
if ((curpos = lseek(fd, 0, SEEK_CUR)) <= 0 )
@@ -1486,7 +1496,11 @@ etag_write_tags (const gchar *filename,
if (write(fd, ctx, ctxsize) != ctxsize)
{
- g_print("OOPS\n");
+ gchar *filename_utf8 = filename_to_display(filename);
+ gchar *basename_utf8 = g_path_get_basename(filename_utf8);
+ Log_Print(LOG_ERROR,_("Size error while saving tag of '%s'"),basename_utf8);
+ g_free(filename_utf8);
+ g_free(basename_utf8);
goto out;
}
diff --git a/src/libapetag/apetaglib.c b/src/libapetag/apetaglib.c
index 52fc971..52fc971 100644..100755
--- a/src/libapetag/apetaglib.c
+++ b/src/libapetag/apetaglib.c
diff --git a/src/libmpg123/mpg123.c b/src/libmpg123/mpg123.c
index dae9327..dae9327 100644..100755
--- a/src/libmpg123/mpg123.c
+++ b/src/libmpg123/mpg123.c
diff --git a/src/log.c b/src/log.c
index 1218a30..22870d8 100755
--- a/src/log.c
+++ b/src/log.c
@@ -277,7 +277,7 @@ void Log_Print (Log_Error_Type error_type, gchar const *format, ...)
Log_Data *LogData = g_malloc0(sizeof(Log_Data));
LogData->time = Log_Format_Date();
LogData->error_type = error_type;
- LogData->string = string;
+ LogData->string = g_strdup(string);
LogPrintTmpList = g_list_append(LogPrintTmpList,LogData);
//g_print("%s",string);
@@ -308,6 +308,7 @@ void Log_Print (Log_Error_Type error_type, gchar const *format, ...)
first_time = FALSE;
fclose(file);
}
+ g_free(string);
}
diff --git a/src/misc.c b/src/misc.c
index baf8f04..baf8f04 100644..100755
--- a/src/misc.c
+++ b/src/misc.c
diff --git a/src/mp4_tag.c b/src/mp4_tag.c
index ab2bdde..cfdb879 100644..100755
--- a/src/mp4_tag.c
+++ b/src/mp4_tag.c
@@ -85,7 +85,10 @@ gboolean Mp4tag_Read_File_Tag (gchar *filename, File_Tag *FileTag)
u_int8_t *coverArt;
u_int32_t coverSize;
Picture *prev_pic = NULL;
-
+#ifdef NEWMP4
+ gint pic_num;
+#endif
+
if (!filename || !FileTag)
return FALSE;
@@ -187,7 +190,7 @@ gboolean Mp4tag_Read_File_Tag (gchar *filename, File_Tag *FileTag)
#ifdef NEWMP4
// There version can handle multiple pictures!
// Version 1.6 of libmp4v2 introduces an index argument for MP4GetMetadataCoverart
- for (i = 0; (MP4GetMetadataCoverArt( mp4file, &coverArt, &coverSize,i )); i++)
+ for (pic_num = 0; (MP4GetMetadataCoverArt( mp4file, &coverArt, &coverSize,pic_num )); pic_num++)
#else
// There version handle only one picture!
if ( MP4GetMetadataCoverArt( mp4file, &coverArt, &coverSize ) )
diff --git a/src/ogg_tag.c b/src/ogg_tag.c
index bf6e365..bf6e365 100644..100755
--- a/src/ogg_tag.c
+++ b/src/ogg_tag.c
diff --git a/src/picture.c b/src/picture.c
index 6ccfd14..f1de37b 100644
--- a/src/picture.c
+++ b/src/picture.c
@@ -221,7 +221,7 @@ void Picture_Load_Filename (gchar *filename, gpointer user_data)
// Behaviour following the tag type...
switch (ETCore->ETFileDisplayed->ETFileDescription->TagType)
{
- // Only one picture supported
+ // Only one picture supported for MP4
case MP4_TAG:
{
pic->type = PICTURE_TYPE_FRONT_COVER;
diff --git a/src/picture.h b/src/picture.h
index cc8ee2e..cc8ee2e 100644..100755
--- a/src/picture.h
+++ b/src/picture.h
diff --git a/src/prefs.c b/src/prefs.c
index 8ca00fb..c6eae7f 100755..100644
--- a/src/prefs.c
+++ b/src/prefs.c
@@ -61,14 +61,14 @@ gint Check_Config (void);
void Set_Default_Comment_Check_Button_Toggled (void);
void Number_Track_Formated_Toggled (void);
void Number_Track_Formated_Spin_Button_Changed (GtkObject *Label, GtkObject *SpinButton);
-void Change_Id3_Settings_Toggled (void);
-void File_Writing_Id3v2_Write_Tag_Toggled(void);
+void Change_Id3_Settings_Toggled (void);
+void File_Writing_Id3v2_Write_Tag_Toggled (void);
void Use_Non_Standard_Id3_Reading_Character_Set_Toggled (void);
void Scanner_Convert_Check_Button_Toggled_1 (GtkObject *object_rec, GtkObject *object_emi);
void Cddb_Use_Proxy_Toggled (void);
-void DefaultPathToMp3_Combo_Add_String (void);
-void CddbLocalPath_Combo_Add_String (void);
+void DefaultPathToMp3_Combo_Add_String (void);
+void CddbLocalPath_Combo_Add_String (void);
@@ -786,7 +786,7 @@ void Open_OptionsWindow (void)
gtk_combo_box_append_text(GTK_COMBO_BOX(FileWritingId3v2UnicodeCharacterSetCombo), "UTF-8");
gtk_combo_box_append_text(GTK_COMBO_BOX(FileWritingId3v2UnicodeCharacterSetCombo), "UTF-16");
if ( FILE_WRITING_ID3V2_UNICODE_CHARACTER_SET == NULL )
- gtk_combo_box_set_active(GTK_COMBO_BOX(FileWritingId3v2UnicodeCharacterSetCombo), 0);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(FileWritingId3v2UnicodeCharacterSetCombo), 0); // Set UTF-8 by default
else
gtk_combo_box_set_active(GTK_COMBO_BOX(FileWritingId3v2UnicodeCharacterSetCombo),
strcmp(FILE_WRITING_ID3V2_UNICODE_CHARACTER_SET, "UTF-8") ? 1 : 0);
@@ -1487,84 +1487,91 @@ void Use_Non_Standard_Id3_Reading_Character_Set_Toggled (void)
gtk_widget_set_sensitive(FileReadingId3v1v2CharacterSetCombo,
GTK_TOGGLE_BUTTON(UseNonStandardId3ReadingCharacterSet)->active);
}
+
void Change_Id3_Settings_Toggled (void)
{
int active;
if ( !FileWritingId3v2UseUnicodeCharacterSet
- || !FileWritingId3v2UseNoUnicodeCharacterSet
- || !FileWritingId3v2WriteTag
+ || !FileWritingId3v2UseNoUnicodeCharacterSet
+ || !FileWritingId3v2WriteTag
#ifdef ENABLE_ID3LIB
- || !FileWritingId3v2VersionCombo
- || !LabelId3v2Version
+ || !FileWritingId3v2VersionCombo
+ || !LabelId3v2Version
#endif
- || !FileWritingId3v1WriteTag
- || !LabelId3v2Charset
- || !FileWritingId3v2UseUnicodeCharacterSet
- || !FileWritingId3v2UseNoUnicodeCharacterSet
- || !FileWritingId3v2UnicodeCharacterSetCombo
- || !FileWritingId3v2NoUnicodeCharacterSetCombo
- || !LabelAdditionalId3v2IconvOptions
- || !FileWritingId3v2IconvOptionsNo
- || !FileWritingId3v2IconvOptionsTranslit
- || !FileWritingId3v2IconvOptionsIgnore
- || !FileWritingId3v2UseCrc32
- || !FileWritingId3v2UseCompression
- || !ConvertOldId3v2TagVersion
- || !LabelId3v1Charset
- || !FileWritingId3v1CharacterSetCombo
- || !LabelAdditionalId3v1IconvOptions
- || !FileWritingId3v1IconvOptionsNo
- || !FileWritingId3v1IconvOptionsTranslit
- || !FileWritingId3v1IconvOptionsIgnore
- )
+ || !FileWritingId3v1WriteTag
+ || !LabelId3v2Charset
+ || !FileWritingId3v2UseUnicodeCharacterSet
+ || !FileWritingId3v2UseNoUnicodeCharacterSet
+ || !FileWritingId3v2UnicodeCharacterSetCombo
+ || !FileWritingId3v2NoUnicodeCharacterSetCombo
+ || !LabelAdditionalId3v2IconvOptions
+ || !FileWritingId3v2IconvOptionsNo
+ || !FileWritingId3v2IconvOptionsTranslit
+ || !FileWritingId3v2IconvOptionsIgnore
+ || !FileWritingId3v2UseCrc32
+ || !FileWritingId3v2UseCompression
+ || !ConvertOldId3v2TagVersion
+ || !LabelId3v1Charset
+ || !FileWritingId3v1CharacterSetCombo
+ || !LabelAdditionalId3v1IconvOptions
+ || !FileWritingId3v1IconvOptionsNo
+ || !FileWritingId3v1IconvOptionsTranslit
+ || !FileWritingId3v1IconvOptionsIgnore
+ )
return;
active = (GTK_TOGGLE_BUTTON(FileWritingId3v2UseUnicodeCharacterSet)->active != 0);
if (GTK_TOGGLE_BUTTON(FileWritingId3v2WriteTag)->active)
{
- gtk_widget_set_sensitive(LabelId3v2Charset, 1);
+ gtk_widget_set_sensitive(LabelId3v2Charset, TRUE);
#ifdef ENABLE_ID3LIB
- gtk_widget_set_sensitive(LabelId3v2Version, 1);
- gtk_widget_set_sensitive(FileWritingId3v2VersionCombo, 1);
- if (gtk_combo_box_get_active(GTK_COMBO_BOX(FileWritingId3v2VersionCombo)) == 1) {
+ gtk_widget_set_sensitive(LabelId3v2Version, TRUE);
+ gtk_widget_set_sensitive(FileWritingId3v2VersionCombo, TRUE);
+ if (gtk_combo_box_get_active(GTK_COMBO_BOX(FileWritingId3v2VersionCombo)) == 1)
+ {
+ // When "ID3v2.3" is selected
gtk_combo_box_set_active(GTK_COMBO_BOX(FileWritingId3v2UnicodeCharacterSetCombo), 1);
- gtk_widget_set_sensitive(FileWritingId3v2UnicodeCharacterSetCombo, 0);
+ gtk_widget_set_sensitive(FileWritingId3v2UnicodeCharacterSetCombo, FALSE);
}else
+ {
+ // When "ID3v2.4" is selected
+ gtk_combo_box_set_active(GTK_COMBO_BOX(FileWritingId3v2UnicodeCharacterSetCombo), 0); // Set "UTF-8" as default value for this version of tag
gtk_widget_set_sensitive(FileWritingId3v2UnicodeCharacterSetCombo, active);
+ }
#else
gtk_widget_set_sensitive(FileWritingId3v2UnicodeCharacterSetCombo, active);
#endif
- gtk_widget_set_sensitive(FileWritingId3v2UseUnicodeCharacterSet, 1);
- gtk_widget_set_sensitive(FileWritingId3v2UseNoUnicodeCharacterSet, 1);
+ gtk_widget_set_sensitive(FileWritingId3v2UseUnicodeCharacterSet, TRUE);
+ gtk_widget_set_sensitive(FileWritingId3v2UseNoUnicodeCharacterSet, TRUE);
gtk_widget_set_sensitive(FileWritingId3v2NoUnicodeCharacterSetCombo, !active);
gtk_widget_set_sensitive(LabelAdditionalId3v2IconvOptions, !active);
gtk_widget_set_sensitive(FileWritingId3v2IconvOptionsNo, !active);
gtk_widget_set_sensitive(FileWritingId3v2IconvOptionsTranslit, !active);
gtk_widget_set_sensitive(FileWritingId3v2IconvOptionsIgnore, !active);
- gtk_widget_set_sensitive(FileWritingId3v2UseCrc32, 1);
- gtk_widget_set_sensitive(FileWritingId3v2UseCompression, 1);
- gtk_widget_set_sensitive(ConvertOldId3v2TagVersion, 1);
+ gtk_widget_set_sensitive(FileWritingId3v2UseCrc32, TRUE);
+ gtk_widget_set_sensitive(FileWritingId3v2UseCompression, TRUE);
+ gtk_widget_set_sensitive(ConvertOldId3v2TagVersion, TRUE);
}else
{
- gtk_widget_set_sensitive(LabelId3v2Charset, 0);
+ gtk_widget_set_sensitive(LabelId3v2Charset, FALSE);
#ifdef ENABLE_ID3LIB
- gtk_widget_set_sensitive(LabelId3v2Version, 0);
- gtk_widget_set_sensitive(FileWritingId3v2VersionCombo, 0);
+ gtk_widget_set_sensitive(LabelId3v2Version, FALSE);
+ gtk_widget_set_sensitive(FileWritingId3v2VersionCombo, FALSE);
#endif
- gtk_widget_set_sensitive(FileWritingId3v2UseUnicodeCharacterSet, 0);
- gtk_widget_set_sensitive(FileWritingId3v2UseNoUnicodeCharacterSet, 0);
- gtk_widget_set_sensitive(FileWritingId3v2UnicodeCharacterSetCombo, 0);
- gtk_widget_set_sensitive(FileWritingId3v2NoUnicodeCharacterSetCombo, 0);
- gtk_widget_set_sensitive(LabelAdditionalId3v2IconvOptions, 0);
- gtk_widget_set_sensitive(FileWritingId3v2IconvOptionsNo, 0);
- gtk_widget_set_sensitive(FileWritingId3v2IconvOptionsTranslit, 0);
- gtk_widget_set_sensitive(FileWritingId3v2IconvOptionsIgnore, 0);
- gtk_widget_set_sensitive(FileWritingId3v2UseCrc32, 0);
- gtk_widget_set_sensitive(FileWritingId3v2UseCompression, 0);
+ gtk_widget_set_sensitive(FileWritingId3v2UseUnicodeCharacterSet, FALSE);
+ gtk_widget_set_sensitive(FileWritingId3v2UseNoUnicodeCharacterSet, FALSE);
+ gtk_widget_set_sensitive(FileWritingId3v2UnicodeCharacterSetCombo, FALSE);
+ gtk_widget_set_sensitive(FileWritingId3v2NoUnicodeCharacterSetCombo, FALSE);
+ gtk_widget_set_sensitive(LabelAdditionalId3v2IconvOptions, FALSE);
+ gtk_widget_set_sensitive(FileWritingId3v2IconvOptionsNo, FALSE);
+ gtk_widget_set_sensitive(FileWritingId3v2IconvOptionsTranslit, FALSE);
+ gtk_widget_set_sensitive(FileWritingId3v2IconvOptionsIgnore, FALSE);
+ gtk_widget_set_sensitive(FileWritingId3v2UseCrc32, FALSE);
+ gtk_widget_set_sensitive(FileWritingId3v2UseCompression, FALSE);
gtk_widget_set_sensitive(ConvertOldId3v2TagVersion, 0);
}
diff --git a/src/scan.c b/src/scan.c
index 476fbe9..dd24ab6 100644
--- a/src/scan.c
+++ b/src/scan.c
@@ -85,6 +85,7 @@ GtkWidget *ProcessFieldsAllUppercase = NULL;
GtkWidget *ProcessFieldsAllDowncase = NULL;
GtkWidget *ProcessFieldsFirstLetterUppercase = NULL;
GtkWidget *ProcessFieldsFirstLettersUppercase = NULL;
+GtkWidget *ProcessFieldsDetectRomanNumerals = NULL;
GtkWidget *ProcessFieldsRemoveSpace = NULL;
GtkWidget *ProcessFieldsInsertSpace = NULL;
GtkWidget *ProcessFieldsOnlyOneSpace = NULL;
@@ -242,8 +243,9 @@ void Scan_Process_Fields_Functions (gchar **string);
gint Scan_Word_Is_Roman_Numeral (gchar *text);
-void Process_Fields_Check_Button_Toggled (GtkObject *object, GList *list);
-void Process_Fields_Convert_Check_Button_Toggled (GtkObject *object);
+void Process_Fields_Check_Button_Toggled (GtkObject *object, GList *list);
+void Process_Fields_Convert_Check_Button_Toggled (GtkObject *object);
+void Process_Fields_First_Letters_Check_Button_Toggled (GtkObject *object);
void Select_Fields_Invert_Selection (void);
void Select_Fields_Select_Unselect_All (void);
void Select_Fields_Set_Sensitive (void);
@@ -267,6 +269,11 @@ void Scanner_Option_Menu_Activate_Item (GtkWidget *widget, gpointer data);
void Populate_Scan_Tag_Masks();
void Populate_Rename_File_Masks();
+int roman2int (const char *str);
+const char * int2roman (int num);
+char * int2roman_r (int num, char * str, size_t len);
+
+
/*************
* *
@@ -1792,7 +1799,13 @@ gint Scan_Word_Is_Roman_Numeral (gchar *text)
{
gchar *tmp;
gint len;
+ gchar *buf = NULL;
+ gint rn_int;
+ gchar *rn_char;
+ if (!GTK_TOGGLE_BUTTON(ProcessFieldsDetectRomanNumerals)->active)
+ return 0;
+
tmp = text;
len = 0;
@@ -1815,66 +1828,381 @@ gint Scan_Word_Is_Roman_Numeral (gchar *text)
|| *tmp == ','
|| *tmp == '-')
{
- // Found separator => stop
- return len;
+ // A separator was found => end of word
+ // Check if it is a valid roman numeral
+ goto roman_numeral_found;
+
} else
{
return 0;
}
}
- return len;
+ // Found in last word of the string
+
+roman_numeral_found:
+ // Check if it is a valid roman numeral
+ buf = g_strndup(text,len);
+ rn_int = roman2int(buf); // Convert the Roman numeral string to integer
+
+ if (rn_int >= 0 )
+ {
+ // Some strings as "IIIII" or "CCCCC" are returned as valid, which is not correct...
+ // Same problem with: IC MIC IM MIM IL CIL XM MXM VC MVC VM MVM VL MVL LC MLC LD MLD LM MLM MDM
+ // So we convert it again to a string, and compare to the initial one.
+ rn_char = (gchar *)int2roman(rn_int); // Convert the Roman numeral integer to string
+ if (rn_char
+ && strcasecmp(buf,rn_char)==0)
+ {
+ g_free(buf);
+ g_free(rn_char);
+ return len; // Roman numeral valid
+ }else
+ {
+ g_free(buf);
+ g_free(rn_char);
+ return 0;
+ }
+ }else
+ {
+ g_free(buf);
+ return 0;
+ }
}
+
/*
-** roman2long() - Converts a roman numeral string into a long integer
-** public domain by Bob Stout
-** Arguments: 1 - Roman numeral string
-**
-** Returns: Long value if valid, else -1L
-*/
-/*
-long roman2long(const char *str)
+ * Taken from :
+ * Roman Numeral Conversion API (http://sourceforge.net/project/showfiles.php?group_id=211070)
+ * Copyright (c) 2007 David M. Syzdek <roman-project@syzdek.net>
+ */
+/* Convert Roman numeral from integer to string */
+const char * int2roman (int num)
{
- struct numeral {
- long val;
- int ch;
- };
+ #define ROMAN_BUFF_LEN 512
- static struct numeral numerals[] = {
- { 1L, 'I' },
- { 5L, 'V' },
- { 10L, 'X' },
- { 50L, 'L' },
- { 100L, 'C' },
- { 500L, 'D' },
- { 1000L, 'M' }
- };
- int i, j, k;
- long retval = 0L;
-
- if (!str)
- return -1L;
- for (i = 0, k = -1; str[i]; ++i)
+ /* buffer for storing conversions */
+ char roman_string[ROMAN_BUFF_LEN];
+
+ /* wrap long2roman_r() with library buffer */
+ char *result = int2roman_r(num, roman_string, ROMAN_BUFF_LEN);
+
+ if (!result)
+ return NULL;
+ return g_strdup(roman_string);
+}
+char * int2roman_r (int num, char * str, size_t len)
+{
+ // local variables
+ unsigned pos;
+ unsigned u;
+ unsigned dividend;
+
+ // checks arguments
+ if (!str)
+ {
+ return NULL;
+ };
+ // verify that number is withing boundaries
+ if ((num > 5000) || (num < 0))
+ {
+ return NULL;
+ };
+
+ // sets initial values
+ pos = 0;
+ memset(str, 0, len);
+ len--;
+
+ // checks for nullae
+ if (!(num))
+ {
+ str[0] = 'N';
+ return str;
+ };
+
+ // calculates sign
+ if (num < 0)
+ {
+ num *= -1;
+ if (1 > len)
+ {
+ return NULL;
+ };
+ str[pos] = '-';
+ pos++;
+ };
+
+ // calculates thousands
+ dividend = num/1000;
+ if (dividend > (len-1))
+ {
+ return NULL;
+ };
+ for (u = 0; u < dividend; u++)
+ str[pos+u] = 'M';
+ num %= 1000;
+ pos += u;
+
+ // calculates hundreds
+ dividend = num/100;
+ if (dividend > (len-1-pos))
+ {
+ return NULL;
+ };
+ if (dividend == 9)
+ {
+ str[pos+0] = 'C';
+ str[pos+1] = 'M';
+ pos += 2;
+ dividend = 0;
+ };
+ if (dividend >= 5)
+ {
+ str[pos] = 'D';
+ dividend -= 5;
+ pos++;
+ };
+ if (dividend == 4)
+ {
+ str[pos+0] = 'C';
+ str[pos+1] = 'D';
+ dividend -= 4;
+ pos += 2;
+ };
+ for(u = 0; u < dividend; u++)
+ str[pos+u] = 'C';
+ pos += u;
+ num %= 100;
+
+ // calculates tens
+ dividend = num/10;
+ if (dividend > (len-1-pos))
+ {
+ return NULL;
+ };
+ if (dividend == 9)
+ {
+ str[pos+0] = 'X';
+ str[pos+1] = 'C';
+ dividend = 0;
+ pos += 2;
+ };
+ if (dividend >= 5)
+ {
+ str[pos+0] = 'L';
+ dividend -= 5;
+ pos++;
+ };
+ if (dividend == 4)
+ {
+ str[pos+0] = 'X';
+ str[pos+1] = 'L';
+ pos += 2;
+ dividend -= 4;
+ };
+ for (u = 0; u < dividend; u++)
+ str[pos+u] = 'X';
+ pos += u;
+ num %= 10;
+
+ // calculates ones
+ dividend = num;
+ if (dividend > (len-1-pos))
+ {
+ return NULL;
+ };
+ if (dividend == 9)
+ {
+ str[pos+0] = 'I';
+ str[pos+1] = 'X';
+ dividend = 0;
+ pos += 2;
+ };
+ if (dividend >= 5)
+ {
+ str[pos+0] = 'V';
+ dividend -= 5;
+ pos++;
+ };
+ if (dividend == 4)
+ {
+ str[pos+0] = 'I';
+ str[pos+1] = 'V';
+ pos += 2;
+ dividend -= 4;
+ };
+ for(u = 0; u < dividend; u++)
+ str[pos+u] = 'I';
+
+ /* ends function */
+ return str;
+}
+/* Convert Roman numeral from string to integer */
+int roman2int (const char * str)
+{
+ // declares local vars
+ int num;
+ unsigned i;
+ unsigned len;
+ unsigned p[2]; // stores values of previous symbols for error checking
+
+ // checks args
+ if (!(str))
+ {
+ return(0);
+ };
+
+ // sets initial values
+ num = 0;
+ len = strlen(str);
+ p[0] = 1000;
+ p[1] = 1000;
+
+ // loops through characters
+ for(i = 0; i < len; i++)
+ {
+ switch(str[i])
{
- for (j = 0; j < 7; ++j)
+ case 'n':
+ case 'N':
+ if (strlen(str) > 1)
+ {
+ return(-1);
+ };
+ return(0);
+ break;
+ case 'i':
+ case 'I':
+ num += 1;
+ // prevent patterns like IXI
+ if ((p[1] == 1) && (p[0] != 1))
+ {
+ return(-1);
+ };
+
+ // prevent patterns like IIIII and VIIIII
+ if ((!(num%5)) || (!(num%10)))
+ {
+ return(-1);
+ };
+ p[1] = p[0];
+ p[0] = 1;
+ break;
+ case 'v':
+ case 'V':
+ num += 5;
+ if (((p[0] < 5) && (p[1] < 5)) || (p[1] == 5) || (p[0] == 5))
{
- if (numerals[j].ch == toupper(str[i]))
- break;
+ return(-1);
}
- if (7 == j)
- return -1L;
- if (k >= 0 && k < j)
+ else if (p[0] < 5)
+ num -= (p[0] * 2);
+ p[1] = p[0];
+ p[0] = 5;
+ break;
+ case 'x':
+ case 'X':
+ num += 10;
+ // prevent patterns like XCX
+ if (((p[0] < 10) && (p[1] < 10)) || ((p[1] < 10) && (p[0] <= 10)))
+ {
+ return(-1);
+ };
+ if (p[0] == 1)
+ num -= (p[0] * 2);
+ else if (p[0] < 10)
{
- retval -= numerals[k].val * 2;
- retval += numerals[j].val;
+ return(-1);
+ };
+
+ // prevent patterns like XXXXX and VXXXXX
+ if ((!(num%50)) || (!(num%100)))
+ {
+ return(-1);
+ };
+ p[1] = p[0];
+ p[0] = 10;
+ break;
+ case 'l':
+ case 'L':
+ num += 50;
+ if (((p[0] < 50) && (p[1] < 50)) || (p[1] == 50) || (p[0] == 50))
+ {
+ return(-1);
}
- else retval += numerals[j].val;
- k = j;
- }
- return retval;
-}*/
+ else if (p[0] < 50)
+ num -= (p[0] * 2);
+ p[1] = p[0];
+ p[0] = 50;
+ break;
+ case 'c':
+ case 'C':
+ num += 100;
+ // prevent patterns like CMC
+ if (((p[0] < 100) && (p[1] < 100)) || ((p[1] < 100) && (p[0] <= 100)))
+ {
+ return(-1);
+ };
+ if (p[0] == 10)
+ num -= (p[0] * 2);
+ else if (p[0] < 100)
+ {
+ return(-1);
+ };
+
+ // prevent patterns like CCCCC and VCCCCC
+ if ((!(num%500)) || (!(num%1000)))
+ {
+ return(-1);
+ };
+ p[1] = p[0];
+ p[0] = 100;
+ break;
+ case 'd':
+ case 'D':
+ num += 500;
+ if (((p[0] < 500) && (p[1] < 500)) || (p[1] == 500) || (p[0] == 500))
+ {
+ return(-1);
+ }
+ else if (p[0] < 500)
+ num -= (p[0] * 2);
+ p[1] = p[0];
+ p[0] = 500;
+ break;
+ case 'm':
+ case 'M':
+ num += 1000;
+ // prevent patterns like M?M
+ if (((p[0] < 1000) && (p[1] < 1000)) || ((p[1] < 100) && (p[0] <= 1000)))
+ {
+ return(-1);
+ };
+ if (p[0] == 100)
+ num -= (p[0] * 2);
+ else if (p[0] < 1000)
+ {
+ return(-1);
+ };
+
+ // prevent patterns like MMMMM and VMMMMM
+ if ((!(num%5000)) || (!(num%10000)))
+ {
+ return(-1);
+ };
+ p[1] = p[0];
+ p[0] = 1000;
+ break;
+ default:
+ return(-1);
+ };
+ };
+
+ // ends function
+ return(num);
+}
@@ -2359,15 +2687,20 @@ void Open_ScannerWindow (gint scanner_type)
Separator = gtk_hseparator_new();
gtk_box_pack_start(GTK_BOX(VBox),Separator,FALSE,FALSE,0);
+ hbox = gtk_hbox_new(FALSE,0);
+
/* Group: capitalize, ... */
ProcessFieldsAllUppercase = gtk_check_button_new_with_label (_("All uppercase"));
ProcessFieldsAllDowncase = gtk_check_button_new_with_label (_("All downcase"));
ProcessFieldsFirstLetterUppercase = gtk_check_button_new_with_label(_("First letter uppercase"));
ProcessFieldsFirstLettersUppercase = gtk_check_button_new_with_label(_("First letter uppercase of each word"));
+ ProcessFieldsDetectRomanNumerals = gtk_check_button_new_with_label(_("Detect Roman numerals"));
gtk_box_pack_start(GTK_BOX(VBox),ProcessFieldsAllUppercase, FALSE,FALSE,0);
gtk_box_pack_start(GTK_BOX(VBox),ProcessFieldsAllDowncase, FALSE,FALSE,0);
gtk_box_pack_start(GTK_BOX(VBox),ProcessFieldsFirstLetterUppercase, FALSE,FALSE,0);
- gtk_box_pack_start(GTK_BOX(VBox),ProcessFieldsFirstLettersUppercase,FALSE,FALSE,0);
+ gtk_box_pack_start(GTK_BOX(VBox),hbox,FALSE,FALSE,0);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessFieldsFirstLettersUppercase,FALSE,FALSE,0);
+ gtk_box_pack_start(GTK_BOX(hbox),ProcessFieldsDetectRomanNumerals,FALSE,FALSE,0);
/* List creation for check buttons in group */
pf_cb_group2 = g_list_append(pf_cb_group2,ProcessFieldsAllUppercase);
pf_cb_group2 = g_list_append(pf_cb_group2,ProcessFieldsAllDowncase);
@@ -2378,11 +2711,14 @@ void Open_ScannerWindow (gint scanner_type)
g_signal_connect(G_OBJECT(ProcessFieldsAllDowncase), "toggled",G_CALLBACK(Process_Fields_Check_Button_Toggled),pf_cb_group2);
g_signal_connect(G_OBJECT(ProcessFieldsFirstLetterUppercase),"toggled",G_CALLBACK(Process_Fields_Check_Button_Toggled),pf_cb_group2);
g_signal_connect(G_OBJECT(ProcessFieldsFirstLettersUppercase),"toggled",G_CALLBACK(Process_Fields_Check_Button_Toggled),pf_cb_group2);
+ g_signal_connect(G_OBJECT(ProcessFieldsFirstLettersUppercase),"toggled",G_CALLBACK(Process_Fields_First_Letters_Check_Button_Toggled),NULL);
+ g_signal_connect(G_OBJECT(ProcessFieldsDetectRomanNumerals),"toggled",G_CALLBACK(Process_Fields_Check_Button_Toggled),NULL);
/* Set check buttons to init value */
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsAllUppercase),PF_CONVERT_ALL_UPPERCASE);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsAllDowncase),PF_CONVERT_ALL_DOWNCASE);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsFirstLetterUppercase),PF_CONVERT_FIRST_LETTER_UPPERCASE);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsFirstLettersUppercase),PF_CONVERT_FIRST_LETTERS_UPPERCASE);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ProcessFieldsDetectRomanNumerals),PF_DETECT_ROMAN_NUMERALS);
/* Tooltips */
gtk_tooltips_set_tip(Tips,ProcessFieldsAllUppercase,
_("Convert all words in all fields to upper case. "
@@ -2396,6 +2732,9 @@ void Open_ScannerWindow (gint scanner_type)
gtk_tooltips_set_tip(Tips,ProcessFieldsFirstLettersUppercase,
_("Convert the initial of each word in all fields to upper case. "
"Example, before: 'Text in an ENTRY', after: 'Text In An Entry'."),NULL);
+ gtk_tooltips_set_tip(Tips,ProcessFieldsDetectRomanNumerals,
+ _("Force to convert to upper case the Roman numerals. "
+ "Example, before: 'ix. text in an entry', after: 'IX. Text In An Entry'."),NULL);
/* Separator line */
Separator = gtk_hseparator_new();
@@ -2430,6 +2769,7 @@ void Open_ScannerWindow (gint scanner_type)
gtk_tooltips_set_tip(Tips,ProcessFieldsOnlyOneSpace,
_("Duplicated spaces or underscores are removed. "
"Example, before: 'Text__In__An Entry', after: 'Text_In_An Entry'."),NULL);
+ Select_Fields_Set_Sensitive();
/*
* Frame to display codes legend
@@ -2626,6 +2966,7 @@ void Open_ScannerWindow (gint scanner_type)
g_signal_emit_by_name(G_OBJECT(LegendButton),"toggled"); /* To hide legend frame */
g_signal_emit_by_name(G_OBJECT(MaskEditorButton),"toggled"); /* To hide mask editor frame */
g_signal_emit_by_name(G_OBJECT(ProcessFieldsConvert),"toggled");/* To enable / disable entries */
+ g_signal_emit_by_name(G_OBJECT(ProcessFieldsDetectRomanNumerals),"toggled");/* To enable / disable entries */
// Activate the current menu in the option menu
gtk_combo_box_set_active(GTK_COMBO_BOX(ScannerOptionCombo), scanner_type);
@@ -2778,6 +3119,7 @@ void ScannerWindow_Apply_Changes (void)
PF_CONVERT_ALL_DOWNCASE = GTK_TOGGLE_BUTTON(ProcessFieldsAllDowncase)->active;
PF_CONVERT_FIRST_LETTER_UPPERCASE = GTK_TOGGLE_BUTTON(ProcessFieldsFirstLetterUppercase)->active;
PF_CONVERT_FIRST_LETTERS_UPPERCASE = GTK_TOGGLE_BUTTON(ProcessFieldsFirstLettersUppercase)->active;
+ PF_DETECT_ROMAN_NUMERALS = GTK_TOGGLE_BUTTON(ProcessFieldsDetectRomanNumerals)->active;
/* Group: remove/insert space */
PF_REMOVE_SPACE = GTK_TOGGLE_BUTTON(ProcessFieldsRemoveSpace)->active;
@@ -3022,6 +3364,11 @@ void Process_Fields_Convert_Check_Button_Toggled (GtkObject *object)
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsConvertFrom),GTK_TOGGLE_BUTTON(object)->active);
}
+void Process_Fields_First_Letters_Check_Button_Toggled (GtkObject *object)
+{
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsDetectRomanNumerals),GTK_TOGGLE_BUTTON(object)->active);
+}
+
/*
* Small buttons of Process Fields scanner
@@ -3100,6 +3447,7 @@ void Select_Fields_Set_Sensitive (void)
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsAllDowncase), TRUE);
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsFirstLetterUppercase), TRUE);
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsFirstLettersUppercase),TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsDetectRomanNumerals), TRUE);
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsRemoveSpace), TRUE);
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsInsertSpace), TRUE);
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsOnlyOneSpace), TRUE);
@@ -3115,6 +3463,7 @@ void Select_Fields_Set_Sensitive (void)
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsAllDowncase), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsFirstLetterUppercase), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsFirstLettersUppercase),FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsDetectRomanNumerals), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsRemoveSpace), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsInsertSpace), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(ProcessFieldsOnlyOneSpace), FALSE);
diff --git a/src/setting.c b/src/setting.c
index 217ab2d..d90221a 100755..100644
--- a/src/setting.c
+++ b/src/setting.c
@@ -222,6 +222,7 @@ tConfigVariable Config_Variables[] =
{"pf_convert_all_downcase", CV_TYPE_BOOL, &PF_CONVERT_ALL_DOWNCASE },
{"pf_convert_first_letter_uppercase", CV_TYPE_BOOL, &PF_CONVERT_FIRST_LETTER_UPPERCASE },
{"pf_convert_first_letters_uppercase", CV_TYPE_BOOL, &PF_CONVERT_FIRST_LETTERS_UPPERCASE },
+ {"pf_detect_roman_numerals", CV_TYPE_BOOL, &PF_DETECT_ROMAN_NUMERALS },
{"pf_remove_space", CV_TYPE_BOOL, &PF_REMOVE_SPACE },
{"pf_insert_space", CV_TYPE_BOOL, &PF_INSERT_SPACE },
{"pf_only_one_space", CV_TYPE_BOOL, &PF_ONLY_ONE_SPACE },
@@ -487,6 +488,7 @@ void Init_Config_Variables (void)
PF_CONVERT_ALL_DOWNCASE = 0;
PF_CONVERT_FIRST_LETTER_UPPERCASE = 0;
PF_CONVERT_FIRST_LETTERS_UPPERCASE = 1;
+ PF_DETECT_ROMAN_NUMERALS = 1;
PF_REMOVE_SPACE = 0;
PF_INSERT_SPACE = 0;
PF_ONLY_ONE_SPACE = 1;
diff --git a/src/setting.h b/src/setting.h
index a2b3042..90c0df0 100755..100644
--- a/src/setting.h
+++ b/src/setting.h
@@ -177,6 +177,7 @@ gint PF_CONVERT_ALL_UPPERCASE;
gint PF_CONVERT_ALL_DOWNCASE;
gint PF_CONVERT_FIRST_LETTER_UPPERCASE;
gint PF_CONVERT_FIRST_LETTERS_UPPERCASE;
+gint PF_DETECT_ROMAN_NUMERALS;
gint PF_REMOVE_SPACE;
gint PF_INSERT_SPACE;
gint PF_ONLY_ONE_SPACE;