#
# old_revision [2a48eee9ca61b361fdcea65d94dfa403aad3388f]
#
# patch "SOPE/NGCards/iCalDailyRecurrenceCalculator.m"
#  from [f4abeb2c617d8ffdccd8044b6dba57360cc16168]
#    to [dd01d13e5d98da301110bee1c641706c77371d68]
# 
# patch "SOPE/NGCards/iCalRecurrenceRule.h"
#  from [77406b397c6aba6d5b0e9aab2d3d453e8e478aed]
#    to [d59c3197244bfc225bcf33d2190906639ffa8085]
# 
# patch "SOPE/NGCards/iCalRecurrenceRule.m"
#  from [9fc9d136f8eb901c30cfe0722a4d5984c92187ec]
#    to [48256c8bf3395d83fb88c1a29d5bc1d35a18d03f]
# 
# patch "UI/Scheduler/UIxComponentEditor.m"
#  from [feff5835f0974c20aa318a011590e6f077088c12]
#    to [edd1145aae23402f52cd8b13d812a1161055ae3e]
# 
# patch "UI/WebServerResources/UIxRecurrenceEditor.js"
#  from [bfe8647fac9f61e394b0ffa75de78d84e6770c81]
#    to [7a8a784805e38ccb8f56ecfb264ca574e60e8c11]
#
============================================================
--- SOPE/NGCards/iCalDailyRecurrenceCalculator.m	f4abeb2c617d8ffdccd8044b6dba57360cc16168
+++ SOPE/NGCards/iCalDailyRecurrenceCalculator.m	dd01d13e5d98da301110bee1c641706c77371d68
@@ -29,6 +29,7 @@
 
 #import "iCalRecurrenceCalculator.h"
 #import "iCalRecurrenceRule.h"
+#import "iCalByDayMask.h"
 
 @interface iCalDailyRecurrenceCalculator : iCalRecurrenceCalculator
 @end
@@ -90,24 +91,17 @@
       if ([startDate compare: currentStartDate] == NSOrderedAscending ||
 	  [startDate compare: currentStartDate] == NSOrderedSame)
 	{
-	  BOOL wrongDay = NO;
-	  unsigned int mask;
 	  NGCalendarDateRange *r;
+          iCalByDayMask *mask;
 
-	  if ([rrule byDayMask])
-	    {
-	      mask = ([currentStartDate dayOfWeek]
-		      ? (unsigned int) 1 << ([currentStartDate dayOfWeek])
-		      : iCalWeekDaySunday);
-	      if (([rrule byDayMask] & mask) != mask)
-		wrongDay = YES;
-	    }
-
-	  if (wrongDay == NO)
-	    {
-	      currentEndDate = [currentStartDate addTimeInterval: [firstRange duration]];
-	      r = [NGCalendarDateRange calendarDateRangeWithStartDate: currentStartDate
-				       endDate: currentEndDate];
+          mask = [rrule byDayMask];
+	  if (!mask || [mask occursOnDay: [currentStartDate dayOfWeek]])
+            {
+	      currentEndDate
+                = [currentStartDate addTimeInterval: [firstRange duration]];
+	      r = [NGCalendarDateRange
+                    calendarDateRangeWithStartDate: currentStartDate
+                                           endDate: currentEndDate];
 	      if ([_r containsDateRange: r])
 		[ranges addObject: r];
 	    }
============================================================
--- SOPE/NGCards/iCalRecurrenceRule.h	77406b397c6aba6d5b0e9aab2d3d453e8e478aed
+++ SOPE/NGCards/iCalRecurrenceRule.h	d59c3197244bfc225bcf33d2190906639ffa8085
@@ -45,18 +45,22 @@ typedef enum {
   iCalRecurrenceFrequenceYearly   = 7,
 } iCalRecurrenceFrequency;
 
+extern NSString *iCalWeekDayString[];
+
 typedef enum {
-  iCalWeekDaySunday    = 1,
-  iCalWeekDayMonday    = 2,
-  iCalWeekDayTuesday   = 4,
-  iCalWeekDayWednesday = 8,
-  iCalWeekDayThursday  = 16,
-  iCalWeekDayFriday    = 32,
-  iCalWeekDaySaturday  = 64,
+  iCalWeekDaySunday    = 0,
+  iCalWeekDayMonday    = 1,
+  iCalWeekDayTuesday   = 2,
+  iCalWeekDayWednesday = 3,
+  iCalWeekDayThursday  = 4,
+  iCalWeekDayFriday    = 5,
+  iCalWeekDaySaturday  = 6,
 } iCalWeekDay;
 
 @class NSString, NSCalendarDate, NGCalendarDateRange, NSArray;
 
+@class iCalByDayMask;
+
 @interface iCalRecurrenceRule : CardElement
 // {
 //   iCalRecurrenceFrequency frequency;
@@ -92,12 +96,14 @@ typedef enum {
 - (void) setWeekStart: (iCalWeekDay) _weekStart;
 - (iCalWeekDay) weekStart;
 
-- (void) setByDayMask: (unsigned int) _mask;
-- (unsigned int) byDayMask;
-- (int) byDayOccurence1;
+- (void) setByDay: (NSString *) newByDay;
+- (NSString *) byDay;
 
+- (void) setByDayMask: (iCalByDayMask *) newMask;
+- (iCalByDayMask *) byDayMask;
+
 - (NSArray *) byMonthDay;
-  
+
 /* count and untilDate are mutually exclusive */
 
 - (void) setRepeatCount: (int) _repeatCount;
============================================================
--- SOPE/NGCards/iCalRecurrenceRule.m	9fc9d136f8eb901c30cfe0722a4d5984c92187ec
+++ SOPE/NGCards/iCalRecurrenceRule.m	48256c8bf3395d83fb88c1a29d5bc1d35a18d03f
@@ -27,13 +27,16 @@
 
 #import <ctype.h>
 
+#import "iCalByDayMask.h"
 #import "NSCalendarDate+NGCards.h"
+#import "NSCalendarDate+ICal.h"
 #import "NSString+NGCards.h"
 
-#import "NSCalendarDate+ICal.h"
-
 #import "iCalRecurrenceRule.h"
 
+NSString *iCalWeekDayString[] = { @"SU", @"MO", @"TU", @"WE", @"TH", @"FR",
+                                  @"SA" };
+
 /*
   freq       = rrFreq;
   until      = rrUntil;
@@ -273,56 +276,56 @@
   return [self weekDayFromICalRepresentation: [self wkst]];
 }
 
-- (void) setByDayMask: (unsigned) _mask
+- (void) setByDay: (NSString *) newByDay
 {
-  NSMutableArray *days;
-  unsigned int count;
-  unsigned char maskDays[] = { iCalWeekDaySunday, iCalWeekDayMonday,
-			       iCalWeekDayTuesday, iCalWeekDayWednesday,
-			       iCalWeekDayThursday, iCalWeekDayFriday,
-			       iCalWeekDaySaturday };
-  days = [NSMutableArray arrayWithCapacity: 7];
-  if (_mask)
-    {
-      for (count = 0; count < 7; count++)
-        if (_mask & maskDays[count])
-          [days addObject:
-                  [self iCalRepresentationForWeekDay: maskDays[count]]];
-    }
+  [self setNamedValue: @"byday" to: newByDay];
+}
 
-  [self setNamedValue: @"byday" to: [days componentsJoinedByString: @","]];
+- (NSString *) byDay
+{
+  return [self namedValue: @"byday"];
 }
 
-- (unsigned int) byDayMask
+- (void) setByDayMask: (iCalByDayMask *) newByDayMask
 {
-  NSArray *days;
-  unsigned int mask, count, max;
-  NSString *day, *value;
+  [self setByDay: [newByDayMask asRuleString]];
+}
 
-  mask = 0;
+- (iCalByDayMask *) byDayMask
+{
+  return [iCalByDayMask byDayMaskWithRuleString: [self byDay]];
+}
 
-  value = [self namedValue: @"byday"];
-  if ([value length] > 0)
-    {
-      days = [value componentsSeparatedByString: @","];
-      max = [days count];
-      for (count = 0; count < max; count++)
-	{
-	  day = [days objectAtIndex: count];
-	  mask |= [self weekDayFromICalRepresentation: day];
-	}
-    }
+// - (unsigned int) byDayMask
+// {
+//   NSArray *days;
+//   unsigned int mask, count, max;
+//   NSString *day, *value;
 
-  return mask;
-}
+//   mask = 0;
 
-#warning this is bad
-- (int) byDayOccurence1
-{
-  return 0;
-//   return byDayOccurence1;
-}
+//   value = [self namedValue: @"byday"];
+//   if ([value length] > 0)
+//     {
+//       days = [value componentsSeparatedByString: @","];
+//       max = [days count];
+//       for (count = 0; count < max; count++)
+// 	{
+// 	  day = [days objectAtIndex: count];
+// 	  mask |= [self weekDayFromICalRepresentation: day];
+// 	}
+//     }
 
+//   return mask;
+// }
+
+// #warning this is bad
+// - (int) byDayOccurence1
+// {
+//   return 0;
+// //   return byDayOccurence1;
+// }
+
 - (NSArray *) byMonthDay
 {
   NSArray *byMonthDay;
============================================================
--- UI/Scheduler/UIxComponentEditor.m	feff5835f0974c20aa318a011590e6f077088c12
+++ UI/Scheduler/UIxComponentEditor.m	edd1145aae23402f52cd8b13d812a1161055ae3e
@@ -1731,15 +1731,22 @@ RANGE(2);
 	    [theRule setInterval: [self repeat1]];
 
 	    // We recur on specific days...
-	    if ([[self repeat2] intValue] == 1
-		&& [[self repeat5] intValue] > 0)
-	      {
-		[theRule setNamedValue: @"bymonthday" to: [self repeat5]];
+	    if ([[self repeat2] intValue] == 0)
+              {
+                NSString *day;
+                int weekDayNumber;
+
+                day = [theRule iCalRepresentationForWeekDay: [[self repeat4] intValue]];
+                weekDayNumber = [[self repeat3] intValue] + 1;
+                [theRule setNamedValue: @"byday"
+                                    to: [NSString stringWithFormat: @"%d%@",
+                                                  weekDayNumber, day]];
+              }
+            else
+              {
+                if ([[self repeat5] intValue] > 0)
+                  [theRule setNamedValue: @"bymonthday" to: [self repeat5]];
 	      }
-	    else
-	      {
-		// TODO
-	      }
 	  }
       }
       break;
============================================================
--- UI/WebServerResources/UIxRecurrenceEditor.js	bfe8647fac9f61e394b0ffa75de78d84e6770c81
+++ UI/WebServerResources/UIxRecurrenceEditor.js	7a8a784805e38ccb8f56ecfb264ca574e60e8c11
@@ -241,31 +241,31 @@ function handleMonthlyRecurrence() {
 
     var radioValue = $('recurrence_form').getRadioValue('monthlyRadioButtonName');
 
-    // FIXME - right now we do not support rules
-    //         such as The Second Tuesday...
-    if (radioValue == 0)
-        window.alert(recurrenceUnsupported);
-    else {
-        // We check if the monthlyMonthsField really contains an integer
-        var showError = true;
+    /* Xth day of the month:
+     repeat1: tous les X mois
+     repeat2: 0
+     repeat3: Xième jour Y du moins:
+     repeat4: jour Y: */
 
-        var fieldValue = "" + $('monthlyMonthsField').value;
-        if (fieldValue.length > 0) {
-            var v = parseInt(fieldValue);
-            if (!isNaN(v) && v > 0) {
-                validate = true;
-                showError = false;
-                parent$("repeat1").value = fieldValue;
-                parent$("repeat2").value = radioValue;
-                parent$("repeat3").value = $('monthlyRepeat').value;
-                parent$("repeat4").value = $('monthlyDay').value;
-                parent$("repeat5").value = getSelectedDays("month");
-            }
+    // We check if the monthlyMonthsField really contains an integer
+    var showError = true;
+
+    var fieldValue = "" + $('monthlyMonthsField').value;
+    if (fieldValue.length > 0) {
+        var v = parseInt(fieldValue);
+        if (!isNaN(v) && v > 0) {
+            validate = true;
+            showError = false;
+            parent$("repeat1").value = fieldValue;
+            parent$("repeat2").value = radioValue;
+            parent$("repeat3").value = $('monthlyRepeat').value;
+            parent$("repeat4").value = $('monthlyDay').value;
+            parent$("repeat5").value = getSelectedDays("month");
         }
+    }
 
-        if (showError)
-            window.alert(monthFieldInvalid);
-    }
+    if (showError)
+        window.alert(monthFieldInvalid);
 
     return validate;
 }
