aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/scan.c')
-rw-r--r--src/scan.c441
1 files changed, 395 insertions, 46 deletions
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);