diff options
author | Alex Bennee <alex@bennee.com> | 2010-07-14 16:03:56 +0100 |
---|---|---|
committer | Alex Bennee <alex@bennee.com> | 2010-07-14 16:03:56 +0100 |
commit | a3e202820fd12e3c368c9ed2446740e9b1d16fd7 (patch) | |
tree | cf5b62c17350cd172c301146c8cba4dae01a2110 /src | |
parent | 26b8e06374c71e42be86694f5d5c4ee920ae4d26 (diff) |
EasyTag 2.1.5
Diffstat (limited to 'src')
-rwxr-xr-x[-rw-r--r--] | src/Makefile.am | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/Makefile.mingw | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/about.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/base64.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/base64.h | 0 | ||||
-rw-r--r-- | src/browser.c | 66 | ||||
-rwxr-xr-x[-rw-r--r--] | src/cddb.c | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/easytag.c | 123 | ||||
-rw-r--r-- | src/et_core.c | 11 | ||||
-rwxr-xr-x[-rw-r--r--] | src/et_core.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/flac_header.c | 0 | ||||
-rw-r--r-- | src/flac_tag.c | 74 | ||||
-rwxr-xr-x[-rw-r--r--] | src/id3_tag.c | 0 | ||||
-rw-r--r-- | src/id3v24_tag.c | 42 | ||||
-rwxr-xr-x[-rw-r--r--] | src/libapetag/apetaglib.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/libmpg123/mpg123.c | 0 | ||||
-rwxr-xr-x | src/log.c | 3 | ||||
-rwxr-xr-x[-rw-r--r--] | src/misc.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/mp4_tag.c | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | src/ogg_tag.c | 0 | ||||
-rw-r--r-- | src/picture.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | src/picture.h | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/prefs.c | 111 | ||||
-rw-r--r-- | src/scan.c | 441 | ||||
-rw-r--r--[-rwxr-xr-x] | src/setting.c | 2 | ||||
-rw-r--r--[-rwxr-xr-x] | src/setting.h | 1 |
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, ¤tIter, iter); gtk_tree_store_set(directoryTreeModel, ¤tIter, @@ -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 @@ -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); } @@ -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; |