diff -U4 -r gnucash-2.2.9/src/backend/file/gnc-freqspec-xml-v2.c gnucash-2.2.9+dd/src/backend/file/gnc-freqspec-xml-v2.c
--- gnucash-2.2.9/src/backend/file/gnc-freqspec-xml-v2.c 2008-01-08 01:05:36.000000000 +0000
+++ gnucash-2.2.9+dd/src/backend/file/gnc-freqspec-xml-v2.c 2008-11-10 19:38:08.000000000 +0000
@@ -100,8 +100,9 @@
gint64 interval; /* all [except once] */
gint64 offset; /* all [except once] */
gint64 day; /* monthly or month-relative */
gint64 occurrence; /* month-relative */
+ gint64 weekend_adj; /* monthly/yearly */
GList *list; /* composite */
UIFreqType uift;
} fsParseData;
@@ -117,8 +118,9 @@
= fspd->offset
= fspd->day
= fspd->occurrence
= 0;
+ fspd->weekend_adj = WEEKEND_ADJ_NONE;
g_date_clear( &fspd->once_day, 1 );
}
static struct dom_tree_handler fs_dom_handlers[];
@@ -242,8 +244,22 @@
}
static
gboolean
+fs_weekend_adj_handler( xmlNodePtr node, gpointer data )
+{
+ fsParseData *fspd = data;
+ gboolean ret;
+ gint64 foo;
+ ret = dom_tree_to_integer( node, &foo );
+ if ( !ret )
+ return ret;
+ fspd->weekend_adj = foo;
+ return TRUE;
+}
+
+static
+gboolean
fs_subelement_handler( xmlNodePtr node, gpointer data )
{
fsParseData *fspd = data;
GList *recurrences;
@@ -261,24 +277,25 @@
if (fspd->uift == UIFREQ_SEMI_MONTHLY)
{
// complementry hack around 'once' freqspects not being valid. :/
recurrence_date = recurrenceGetDate(r);
- recurrenceSet(r, recurrenceGetMultiplier(r), PERIOD_MONTH, &recurrence_date);
+ recurrenceSet(r, recurrenceGetMultiplier(r), PERIOD_MONTH, &recurrence_date, recurrenceGetWeekendAdjust(r));
}
fspd->recurrence_list = g_list_append(fspd->recurrence_list, r);
}
}
return TRUE;
}
struct dom_tree_handler fs_union_dom_handlers[] = {
- { "fs:date", fs_date_handler, 0, 0 },
- { "fs:interval", fs_interval_handler, 0, 0 },
- { "fs:offset", fs_offset_handler, 0, 0 },
- { "fs:day", fs_day_handler, 0, 0 },
- { "fs:weekday", fs_weekday_handler, 0, 0 },
- { "fs:occurrence", fs_occurrence_handler, 0, 0 },
- { "gnc:freqspec", fs_subelement_handler, 0, 0 },
+ { "fs:date", fs_date_handler, 0, 0 },
+ { "fs:interval", fs_interval_handler, 0, 0 },
+ { "fs:offset", fs_offset_handler, 0, 0 },
+ { "fs:day", fs_day_handler, 0, 0 },
+ { "fs:weekday", fs_weekday_handler, 0, 0 },
+ { "fs:occurrence", fs_occurrence_handler, 0, 0 },
+ { "fs:weekend_adj", fs_weekend_adj_handler, 0, 0 },
+ { "gnc:freqspec", fs_subelement_handler, 0, 0 },
{ NULL, NULL, 0, 0 },
};
static gboolean
@@ -303,9 +320,9 @@
fs_union_dom_handlers,
fspd );
if ( !successful )
return FALSE;
- recurrenceSet(fspd->recurrence, 0, PERIOD_ONCE, &fspd->once_day);
+ recurrenceSet(fspd->recurrence, 0, PERIOD_ONCE, &fspd->once_day, WEEKEND_ADJ_NONE);
return TRUE;
}
@@ -320,9 +337,9 @@
return FALSE;
g_date_clear(&offset_date, 1);
g_date_set_julian(&offset_date, fspd->offset == 0 ? 7 : fspd->offset);
- recurrenceSet(fspd->recurrence, fspd->interval, PERIOD_DAY, &offset_date);
+ recurrenceSet(fspd->recurrence, fspd->interval, PERIOD_DAY, &offset_date, WEEKEND_ADJ_NONE);
return TRUE;
}
@@ -340,9 +357,9 @@
return FALSE;
g_date_clear(&offset_date, 1);
g_date_set_julian(&offset_date, fspd->offset == 0 ? 7 : fspd->offset);
- recurrenceSet(fspd->recurrence, fspd->interval, PERIOD_WEEK, &offset_date);
+ recurrenceSet(fspd->recurrence, fspd->interval, PERIOD_WEEK, &offset_date, WEEKEND_ADJ_NONE);
return TRUE;
}
@@ -366,13 +383,13 @@
g_date_set_day(&offset_date, fspd->day);
if (fspd->uift == UIFREQ_ONCE)
{
// hack...
- recurrenceSet(fspd->recurrence, fspd->interval, PERIOD_ONCE, &offset_date);
+ recurrenceSet(fspd->recurrence, fspd->interval, PERIOD_ONCE, &offset_date, WEEKEND_ADJ_NONE);
}
else
{
- recurrenceSet(fspd->recurrence, fspd->interval, PERIOD_MONTH, &offset_date);
+ recurrenceSet(fspd->recurrence, fspd->interval, PERIOD_MONTH, &offset_date, fspd->weekend_adj);
}
return successful;
}
diff -U4 -r gnucash-2.2.9/src/backend/file/gnc-recurrence-xml-v2.c gnucash-2.2.9+dd/src/backend/file/gnc-recurrence-xml-v2.c
--- gnucash-2.2.9/src/backend/file/gnc-recurrence-xml-v2.c 2008-01-08 01:05:37.000000000 +0000
+++ gnucash-2.2.9+dd/src/backend/file/gnc-recurrence-xml-v2.c 2008-11-27 19:32:22.000000000 +0000
@@ -46,8 +46,9 @@
#define recurrence_root "gnc:recurrence"
#define recurrence_mult "recurrence:mult"
#define recurrence_period_type "recurrence:period_type"
#define recurrence_start "recurrence:start"
+#define recurrence_weekend_adj "recurrence:weekend_adj"
//TODO: I think three of these functions rightly belong in Recurrence.c.
static gboolean
@@ -82,12 +83,27 @@
{
return dom_tree_to_guint16(node, &((Recurrence *)r)->mult);
}
+static gboolean
+recurrence_weekend_adj_handler(xmlNodePtr node, gpointer d)
+{
+ WeekendAdjust wadj;
+ char *nodeTxt;
+
+ nodeTxt = dom_tree_to_text(node);
+ g_return_val_if_fail(nodeTxt, FALSE);
+ wadj= recurrenceWeekendAdjustFromString(nodeTxt);
+ ((Recurrence *) d)->wadj = wadj;
+ g_free(nodeTxt);
+ return (wadj != -1);
+}
+
static struct dom_tree_handler recurrence_dom_handlers[] = {
{ recurrence_mult, recurrence_mult_handler, 1, 0 },
{ recurrence_period_type, recurrence_period_type_handler, 1, 0 },
{ recurrence_start, recurrence_start_date_handler, 1, 0 },
+ { recurrence_weekend_adj, recurrence_weekend_adj_handler, 0, 0 },
{ NULL, NULL, 0, 0 }
};
Recurrence*
@@ -112,8 +128,9 @@
{
xmlNodePtr n;
PeriodType pt;
GDate d;
+ WeekendAdjust wadj;
n = xmlNewNode(NULL, tag);
xmlSetProp(n, "version", recurrence_version_string );
xmlAddChild(n, guint_to_dom_tree(recurrence_mult,
@@ -122,6 +139,9 @@
xmlAddChild(n, text_to_dom_tree(recurrence_period_type,
recurrencePeriodTypeToString(pt)));
d = recurrenceGetDate(r);
xmlAddChild(n, gdate_to_dom_tree(recurrence_start, &d));
+ wadj = recurrenceGetWeekendAdjust(r);
+ xmlAddChild(n, text_to_dom_tree(recurrence_weekend_adj,
+ recurrenceWeekendAdjustToString(wadj)));
return n;
}
diff -U4 -r gnucash-2.2.9/src/backend/file/gnc-schedxaction-xml-v2.c gnucash-2.2.9+dd/src/backend/file/gnc-schedxaction-xml-v2.c
--- gnucash-2.2.9/src/backend/file/gnc-schedxaction-xml-v2.c 2008-01-08 01:05:37.000000000 +0000
+++ gnucash-2.2.9+dd/src/backend/file/gnc-schedxaction-xml-v2.c 2008-11-10 19:38:08.000000000 +0000
@@ -393,18 +393,19 @@
recurrenceSet(r,
recurrenceGetMultiplier(r),
recurrenceGetPeriodType(r),
- &next);
+ &next,
+ recurrenceGetWeekendAdjust(r));
}
if (g_list_length(schedule) == 1
&& recurrenceGetPeriodType((Recurrence*)g_list_nth_data(schedule, 0)) == PERIOD_ONCE)
{
char date_buf[128];
Recurrence *fixup = (Recurrence*)g_list_nth_data(schedule, 0);
g_date_strftime(date_buf, 127, "%x", sx_start_date);
- recurrenceSet(fixup, 1, PERIOD_ONCE, sx_start_date);
+ recurrenceSet(fixup, 1, PERIOD_ONCE, sx_start_date, WEEKEND_ADJ_NONE);
g_debug("fixed up period=ONCE Recurrence to date [%s]", date_buf);
}
}
diff -U4 -r gnucash-2.2.9/src/engine/gnc-budget.c gnucash-2.2.9+dd/src/engine/gnc-budget.c
--- gnucash-2.2.9/src/engine/gnc-budget.c 2008-01-08 01:06:42.000000000 +0000
+++ gnucash-2.2.9+dd/src/engine/gnc-budget.c 2008-11-10 19:38:08.000000000 +0000
@@ -125,9 +125,9 @@
qof_instance_init_data (&budget->inst, GNC_ID_BUDGET, book);
g_date_set_time_t(&date, time(NULL));
g_date_subtract_days(&date, g_date_get_day(&date)-1);
- recurrenceSet(&budget->recurrence, 1, PERIOD_MONTH, &date);
+ recurrenceSet(&budget->recurrence, 1, PERIOD_MONTH, &date, WEEKEND_ADJ_NONE);
gnc_budget_begin_edit(budget);
gnc_budget_set_name(budget, _("Unnamed Budget"));
gnc_budget_set_description(budget, "");
diff -U4 -r gnucash-2.2.9/src/engine/Recurrence.c gnucash-2.2.9+dd/src/engine/Recurrence.c
--- gnucash-2.2.9/src/engine/Recurrence.c 2008-04-25 23:37:14.000000000 +0100
+++ gnucash-2.2.9+dd/src/engine/Recurrence.c 2008-11-10 22:02:57.000000000 +0000
@@ -42,10 +42,14 @@
static gchar *period_type_strings[NUM_PERIOD_TYPES] = {
"once", "day", "week", "month", "end of month",
"nth weekday", "last weekday", "year",
};
+static gchar *weekend_adj_strings[NUM_WEEKEND_ADJS] = {
+ "none", "back", "forward",
+};
-#define VALID_PERIOD_TYPE(pt) ((0 <= (pt)) && ((pt) < NUM_PERIOD_TYPES))
+#define VALID_PERIOD_TYPE(pt) ((0 <= (pt)) && ((pt) < NUM_PERIOD_TYPES))
+#define VALID_WEEKEND_ADJ(wadj) ((0 <= (wadj)) && ((wadj) < NUM_WEEKEND_ADJS))
PeriodType
recurrenceGetPeriodType(const Recurrence *r)
{
@@ -63,10 +67,16 @@
{
return r ? r->start : invalid_gdate;
}
+WeekendAdjust
+recurrenceGetWeekendAdjust(const Recurrence *r)
+{
+ return r ? r->wadj : WEEKEND_ADJ_INVALID;
+}
+
void
-recurrenceSet(Recurrence *r, guint16 mult, PeriodType pt, const GDate *_start)
+recurrenceSet(Recurrence *r, guint16 mult, PeriodType pt, const GDate *_start, WeekendAdjust wadj)
{
r->ptype = VALID_PERIOD_TYPE(pt) ? pt : PERIOD_MONTH;
r->mult = (pt == PERIOD_ONCE) ? 0 : (mult > 0 ? mult : 1);
@@ -96,8 +106,19 @@
r->ptype = PERIOD_LAST_WEEKDAY;
break;
default: break;
}
+
+ switch (r->ptype) {
+ case PERIOD_MONTH:
+ case PERIOD_END_OF_MONTH:
+ case PERIOD_YEAR:
+ r->wadj = wadj;
+ break;
+ default:
+ r->wadj = WEEKEND_ADJ_NONE;
+ break;
+ }
}
/* nth_weekday_compare() is a helper function for the
PERIOD_{NTH,LAST}_WEEKDAY case. It returns the offset, in days,
@@ -139,8 +160,9 @@
{
PeriodType pt;
const GDate *start;
guint mult;
+ WeekendAdjust wadj;
g_return_if_fail(r);
g_return_if_fail(ref);
g_return_if_fail(g_date_valid(&r->start));
@@ -157,17 +179,65 @@
/* Step 1: move FORWARD one period, passing exactly one occurrence. */
mult = r->mult;
pt = r->ptype;
+ wadj = r->wadj;
switch (pt) {
case PERIOD_YEAR:
mult *= 12; /* fall-through */
case PERIOD_MONTH:
case PERIOD_NTH_WEEKDAY:
case PERIOD_LAST_WEEKDAY:
case PERIOD_END_OF_MONTH:
/* Takes care of short months. */
- if ( g_date_is_last_of_month(next) ||
+ if (r->wadj == WEEKEND_ADJ_BACK &&
+ (pt == PERIOD_YEAR || pt == PERIOD_MONTH || pt == PERIOD_END_OF_MONTH) &&
+ (g_date_get_weekday(next) == G_DATE_SATURDAY || g_date_get_weekday(next) == G_DATE_SUNDAY)) {
+ /* Allows the following Friday-based calculations to proceed if 'next'
+ is between Friday and the target day. */
+ g_date_subtract_days(next, g_date_get_weekday(next) == G_DATE_SATURDAY ? 1 : 2);
+ }
+ if (r->wadj == WEEKEND_ADJ_BACK &&
+ (pt == PERIOD_YEAR || pt == PERIOD_MONTH || pt == PERIOD_END_OF_MONTH) &&
+ g_date_get_weekday(next) == G_DATE_FRIDAY) {
+ GDate tmp_sat;
+ GDate tmp_sun;
+ g_date_set_julian(&tmp_sat, g_date_get_julian(next));
+ g_date_set_julian(&tmp_sun, g_date_get_julian(next));
+ g_date_add_days(&tmp_sat, 1);
+ g_date_add_days(&tmp_sun, 2);
+
+ if (pt == PERIOD_END_OF_MONTH) {
+ if (g_date_is_last_of_month(next) ||
+ g_date_is_last_of_month(&tmp_sat) ||
+ g_date_is_last_of_month(&tmp_sun))
+ g_date_add_months(next, mult);
+ else
+ /* one fewer month fwd because of the occurrence in this month */
+ g_date_add_months(next, mult - 1);
+ } else {
+ if (g_date_get_day(&tmp_sat) == g_date_get_day(start)) {
+ g_date_add_days(next, 1);
+ g_date_add_months(next, mult);
+ } else if (g_date_get_day(&tmp_sun) == g_date_get_day(start)) {
+ g_date_add_days(next, 2);
+ g_date_add_months(next, mult);
+ } else if (g_date_get_day(next) >= g_date_get_day(start)) {
+ g_date_add_months(next, mult);
+ } else if (g_date_is_last_of_month(next)) {
+ g_date_add_months(next, mult);
+ } else if (g_date_is_last_of_month(&tmp_sat)) {
+ g_date_add_days(next, 1);
+ g_date_add_months(next, mult);
+ } else if (g_date_is_last_of_month(&tmp_sun)) {
+ g_date_add_days(next, 2);
+ g_date_add_months(next, mult);
+ } else {
+ /* one fewer month fwd because of the occurrence in this month */
+ g_date_add_months(next, mult - 1);
+ }
+ }
+ } else if ( g_date_is_last_of_month(next) ||
((pt == PERIOD_MONTH || pt == PERIOD_YEAR) &&
g_date_get_day(next) >= g_date_get_day(start)) ||
((pt == PERIOD_NTH_WEEKDAY || pt == PERIOD_LAST_WEEKDAY) &&
nth_weekday_compare(start, next, pt) <= 0) )
@@ -212,8 +282,25 @@
g_date_set_day(next, dim); /* last day in the month */
else
g_date_set_day(next, g_date_get_day(start)); /*same day as start*/
+ /* Adjust for dates on the weekend. */
+ if (pt == PERIOD_YEAR || pt == PERIOD_MONTH || pt == PERIOD_END_OF_MONTH) {
+ if (g_date_get_weekday(next) == G_DATE_SATURDAY || g_date_get_weekday(next) == G_DATE_SUNDAY) {
+ switch (wadj) {
+ case WEEKEND_ADJ_BACK:
+ g_date_subtract_days(next, g_date_get_weekday(next) == G_DATE_SATURDAY ? 1 : 2);
+ break;
+ case WEEKEND_ADJ_FORWARD:
+ g_date_add_days(next, g_date_get_weekday(next) == G_DATE_SATURDAY ? 2 : 1);
+ break;
+ case WEEKEND_ADJ_NONE:
+ default:
+ break;
+ }
+ }
+ }
+
} break;
case PERIOD_WEEK:
case PERIOD_DAY:
g_date_subtract_days(next, g_date_days_between(start, next) % mult);
@@ -359,8 +446,25 @@
return i;
return -1;
}
+gchar *
+recurrenceWeekendAdjustToString(WeekendAdjust wadj)
+{
+ return VALID_WEEKEND_ADJ(wadj) ? g_strdup(weekend_adj_strings[wadj]) : NULL;
+}
+
+WeekendAdjust
+recurrenceWeekendAdjustFromString(const gchar *str)
+{
+ int i;
+
+ for (i = 0; i < NUM_WEEKEND_ADJS; i++)
+ if (safe_strcmp(weekend_adj_strings[i], str) == 0)
+ return i;
+ return -1;
+}
+
gboolean
recurrenceListIsSemiMonthly(GList *recurrences)
{
if (g_list_length(recurrences) != 2)
diff -U4 -r gnucash-2.2.9/src/engine/Recurrence.h gnucash-2.2.9+dd/src/engine/Recurrence.h
--- gnucash-2.2.9/src/engine/Recurrence.h 2008-01-08 01:06:42.000000000 +0000
+++ gnucash-2.2.9+dd/src/engine/Recurrence.h 2008-11-10 19:38:08.000000000 +0000
@@ -56,14 +56,23 @@
NUM_PERIOD_TYPES,
PERIOD_INVALID = -1,
} PeriodType;
+typedef enum {
+ WEEKEND_ADJ_NONE,
+ WEEKEND_ADJ_BACK, /* Previous weekday */
+ WEEKEND_ADJ_FORWARD, /* Next weekday */
+ NUM_WEEKEND_ADJS,
+ WEEKEND_ADJ_INVALID = -1,
+} WeekendAdjust;
+
/* Recurrences represent both the phase and period of a recurring event. */
typedef struct {
- GDate start; /* First date in the recurrence; specifies phase. */
- PeriodType ptype; /* see PeriodType enum */
- guint16 mult; /* a period multiplier */
+ GDate start; /* First date in the recurrence; specifies phase. */
+ PeriodType ptype; /* see PeriodType enum */
+ guint16 mult; /* a period multiplier */
+ WeekendAdjust wadj; /* see WeekendAdjust enum */
} Recurrence;
/* recurrenceSet() will enforce internal consistency by overriding
@@ -89,14 +98,15 @@
date's day-of-week is used.
*/
void recurrenceSet(Recurrence *r, guint16 mult, PeriodType pt,
- const GDate *date);
+ const GDate *date, WeekendAdjust wadj);
/* get the fields */
PeriodType recurrenceGetPeriodType(const Recurrence *r);
guint recurrenceGetMultiplier(const Recurrence *r);
GDate recurrenceGetDate(const Recurrence *r);
+WeekendAdjust recurrenceGetWeekendAdjust(const Recurrence *r);
/* Get the occurence immediately after refDate.
*
* This function has strict and precise post-conditions:
@@ -134,11 +144,13 @@
/** @return the earliest of the next occurances -- a "composite" recurrence **/
void recurrenceListNextInstance(const GList *r, const GDate *refDate,
GDate *nextDate);
-/* These two functions are only for xml storage, not user presentation. */
+/* These four functions are only for xml storage, not user presentation. */
gchar *recurrencePeriodTypeToString(PeriodType pt);
PeriodType recurrencePeriodTypeFromString(const gchar *str);
+gchar *recurrenceWeekendAdjustToString(WeekendAdjust wadj);
+WeekendAdjust recurrenceWeekendAdjustFromString(const gchar *str);
/* For debugging. Caller owns the returned string. Not intl. */
gchar *recurrenceToString(const Recurrence *r);
gchar *recurrenceListToString(const GList *rlist);
diff -U4 -r gnucash-2.2.9/src/engine/test/test-recurrence.c gnucash-2.2.9+dd/src/engine/test/test-recurrence.c
--- gnucash-2.2.9/src/engine/test/test-recurrence.c 2008-01-08 01:06:41.000000000 +0000
+++ gnucash-2.2.9+dd/src/engine/test/test-recurrence.c 2008-11-10 19:38:08.000000000 +0000
@@ -133,29 +133,33 @@
GDate d_start, d_start_reg;
GDate d_ref, d_next;
guint16 mult, mult_reg;
PeriodType pt, pt_reg;
+ WeekendAdj wadj, wadj_reg;
gint32 j1, j2;
gint i_ref;
for (pt = PERIOD_ONCE; pt < NUM_PERIOD_TYPES; pt++) {
- for (j1 = JULIAN_START; j1 < JULIAN_START + NUM_DATES_TO_TEST; j1++) {
- g_date_set_julian(&d_start, j1);
- for (i_ref = 0; i_ref < NUM_DATES_TO_TEST_REF; i_ref++) {
- j2 = (guint32) get_random_int_in_range(1, 1 << 19);
- g_date_set_julian(&d_ref, j2);
-
- for (mult = 0; mult < NUM_MULT_TO_TEST; mult++) {
- recurrenceSet(&r, mult, pt, &d_start);
- pt_reg = recurrenceGetPeriodType(&r);
- d_start_reg = recurrenceGetDate(&r);
- mult_reg = recurrenceGetMultiplier(&r);
-
- recurrenceNextInstance(&r, &d_ref, &d_next);
- check_valid(&d_next, &d_ref, &d_start_reg,
- mult_reg, pt_reg);
+ for (wadj = WEEKEND_ADJ_NONE; wadj < NUM_WEEKEND_ADJS; wadj++) {
+ for (j1 = JULIAN_START; j1 < JULIAN_START + NUM_DATES_TO_TEST; j1++) {
+ g_date_set_julian(&d_start, j1);
+ for (i_ref = 0; i_ref < NUM_DATES_TO_TEST_REF; i_ref++) {
+ j2 = (guint32) get_random_int_in_range(1, 1 << 19);
+ g_date_set_julian(&d_ref, j2);
+
+ for (mult = 0; mult < NUM_MULT_TO_TEST; mult++) {
+ recurrenceSet(&r, mult, pt, &d_start, wadj);
+ pt_reg = recurrenceGetPeriodType(&r);
+ d_start_reg = recurrenceGetDate(&r);
+ mult_reg = recurrenceGetMultiplier(&r);
+ wadj_reg = recurrenceGetWeekendAdjust(&r);
+
+ recurrenceNextInstance(&r, &d_ref, &d_next);
+ check_valid(&d_next, &d_ref, &d_start_reg,
+ mult_reg, pt_reg, wadj_reg);
- }
+ }
+ }
}
}
}
}
diff -U4 -r gnucash-2.2.9/src/engine/test-core/test-engine-stuff.c gnucash-2.2.9+dd/src/engine/test-core/test-engine-stuff.c
--- gnucash-2.2.9/src/engine/test-core/test-engine-stuff.c 2008-01-08 01:06:40.000000000 +0000
+++ gnucash-2.2.9+dd/src/engine/test-core/test-engine-stuff.c 2008-11-10 19:38:08.000000000 +0000
@@ -2147,17 +2147,17 @@
static Recurrence*
daily_freq(GDate* start, int multiplier)
{
Recurrence *r = g_new0(Recurrence, 1);
- recurrenceSet(r, multiplier, PERIOD_DAY, start);
+ recurrenceSet(r, multiplier, PERIOD_DAY, start, WEEKEND_ADJ_NONE);
return r;
}
static Recurrence*
once_freq(GDate *when)
{
Recurrence *r = g_new0(Recurrence, 1);
- recurrenceSet(r, 1, PERIOD_ONCE, when);
+ recurrenceSet(r, 1, PERIOD_ONCE, when, WEEKEND_ADJ_NONE);
return r;
}
static SchedXaction*
diff -U4 -r gnucash-2.2.9/src/gnome/dialog-sx-from-trans.c gnucash-2.2.9+dd/src/gnome/dialog-sx-from-trans.c
--- gnucash-2.2.9/src/gnome/dialog-sx-from-trans.c 2008-01-08 01:06:36.000000000 +0000
+++ gnucash-2.2.9+dd/src/gnome/dialog-sx-from-trans.c 2008-11-10 19:38:08.000000000 +0000
@@ -301,17 +301,17 @@
switch (index)
{
case FREQ_DAILY: {
Recurrence *r = g_new0(Recurrence, 1);
- recurrenceSet(r, 1, PERIOD_DAY, date);
+ recurrenceSet(r, 1, PERIOD_DAY, date, WEEKEND_ADJ_NONE);
*recurrences = g_list_append(*recurrences, r);
} break;
case FREQ_WEEKLY:
case FREQ_BIWEEKLY: {
Recurrence *r = g_new0(Recurrence, 1);
int mult = (index == FREQ_BIWEEKLY ? 2 : 1);
- recurrenceSet(r, mult, PERIOD_WEEK, date);
+ recurrenceSet(r, mult, PERIOD_WEEK, date, WEEKEND_ADJ_NONE);
*recurrences = g_list_append(*recurrences, r);
} break;
case FREQ_MONTHLY:
@@ -322,9 +322,9 @@
? 1
: (index == FREQ_QUARTERLY
? 3
: 12));
- recurrenceSet(r, mult, PERIOD_MONTH, date);
+ recurrenceSet(r, mult, PERIOD_MONTH, date, recurrenceGetWeekendAdjust(r));
*recurrences = g_list_append(*recurrences, r);
} break;
default:
diff -U4 -r gnucash-2.2.9/src/gnome/druid-acct-period.c gnucash-2.2.9+dd/src/gnome/druid-acct-period.c
--- gnucash-2.2.9/src/gnome/druid-acct-period.c 2008-07-22 23:43:12.000000000 +0100
+++ gnucash-2.2.9+dd/src/gnome/druid-acct-period.c 2008-11-10 19:38:08.000000000 +0000
@@ -543,9 +543,9 @@
g_date_add_years (&info->closing_date, 1);
{
Recurrence *r = g_new0(Recurrence, 1);
- recurrenceSet(r, 1, PERIOD_MONTH, &info->closing_date);
+ recurrenceSet(r, 1, PERIOD_MONTH, &info->closing_date, WEEKEND_ADJ_NONE);
info->period = NULL;
info->period = g_list_append(info->period, r);
}
diff -U4 -r gnucash-2.2.9/src/gnome/druid-loan.c gnucash-2.2.9+dd/src/gnome/druid-loan.c
--- gnucash-2.2.9/src/gnome/druid-loan.c 2008-07-22 23:43:11.000000000 +0100
+++ gnucash-2.2.9+dd/src/gnome/druid-loan.c 2008-11-10 19:38:08.000000000 +0000
@@ -803,9 +803,9 @@
ldd->ld.loan_schedule= NULL;
ldd->ld.repayment_schedule = NULL;
{
Recurrence *r = g_new0(Recurrence, 1);
- recurrenceSet(r, 1, PERIOD_MONTH, ldd->ld.startDate);
+ recurrenceSet(r, 1, PERIOD_MONTH, ldd->ld.startDate, WEEKEND_ADJ_NONE);
ldd->ld.repayment_schedule = g_list_append(ldd->ld.repayment_schedule, r);
}
ldd->ld.repMemo = g_strdup( _("Loan") );
@@ -1661,9 +1661,9 @@
rod = ldd->ld.repayOpts[ ldd->currentIdx ];
if ( rod->schedule == NULL ) {
Recurrence *r = g_new0(Recurrence, 1);
- recurrenceSet(r, 1, PERIOD_MONTH, ldd->ld.startDate);
+ recurrenceSet(r, 1, PERIOD_MONTH, ldd->ld.startDate, WEEKEND_ADJ_NONE);
rod->schedule = g_list_append(rod->schedule, r);
}
if ( rod->startDate == NULL ) {
rod->startDate = g_date_new();
diff -U4 -r gnucash-2.2.9/src/gnome/glade/sched-xact.glade gnucash-2.2.9+dd/src/gnome/glade/sched-xact.glade
--- gnucash-2.2.9/src/gnome/glade/sched-xact.glade 2008-01-08 01:06:30.000000000 +0000
+++ gnucash-2.2.9+dd/src/gnome/glade/sched-xact.glade 2008-11-10 19:38:08.000000000 +0000
@@ -1891,8 +1891,49 @@
True
True
+
+
+
+ True
+ except on weekends:
+ False
+ False
+ GTK_JUSTIFY_RIGHT
+ False
+ False
+ 1
+ 0.5
+ 0
+ 0
+ PANGO_ELLIPSIZE_NONE
+ -1
+ False
+ 0
+
+
+ 2
+ False
+ True
+
+
+
+
+
+ True
+ No change
+Use previous weekday
+Use next weekday
+ False
+ True
+
+
+ 0
+ False
+ False
+
+
3
False
@@ -1981,8 +2022,49 @@
False
False
+
+
+
+ True
+ except on weekends:
+ False
+ False
+ GTK_JUSTIFY_RIGHT
+ False
+ False
+ 1
+ 0.5
+ 0
+ 0
+ PANGO_ELLIPSIZE_NONE
+ -1
+ False
+ 0
+
+
+ 2
+ False
+ True
+
+
+
+
+
+ True
+ No change
+Use previous weekday
+Use next weekday
+ False
+ True
+
+
+ 0
+ False
+ False
+
+
3
False
@@ -2201,18 +2283,59 @@
False
False
+
+
+
+ True
+ except on weekends:
+ False
+ False
+ GTK_JUSTIFY_RIGHT
+ False
+ False
+ 1
+ 0.5
+ 0
+ 0
+ PANGO_ELLIPSIZE_NONE
+ -1
+ False
+ 0
+
+
+ 2
+ False
+ True
+
+
+
+
+
+ True
+ No change
+Use previous weekday
+Use next weekday
+ False
+ True
+
+
+ 0
+ False
+ False
+
+
- 5
+ 3
False
True
- 5
+ 3
True
True
diff -U4 -r gnucash-2.2.9/src/gnome/gnc-plugin-page-budget.c gnucash-2.2.9+dd/src/gnome/gnc-plugin-page-budget.c
--- gnucash-2.2.9/src/gnome/gnc-plugin-page-budget.c 2008-01-08 01:06:36.000000000 +0000
+++ gnucash-2.2.9+dd/src/gnome/gnc-plugin-page-budget.c 2008-11-10 19:38:08.000000000 +0000
@@ -295,9 +295,9 @@
priv->fd.show_hidden = FALSE;
priv->fd.show_zero_total = TRUE;
priv->sigFigs = 1;
- recurrenceSet(&priv->r, 1, PERIOD_MONTH, NULL);
+ recurrenceSet(&priv->r, 1, PERIOD_MONTH, NULL, WEEKEND_ADJ_NONE);
LEAVE("page %p, priv %p, action group %p",
plugin_page, priv, action_group);
}
@@ -935,9 +935,10 @@
r = gnc_budget_get_recurrence(priv->budget);
gnc_date_edit_get_gdate(GNC_DATE_EDIT(gde), &date);
recurrenceSet(&priv->r, recurrenceGetMultiplier(r),
- recurrenceGetPeriodType(r), &date);
+ recurrenceGetPeriodType(r), &date,
+ recurrenceGetWeekendAdjust(r));
priv->sigFigs =
gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dtr));
gtk_tree_selection_selected_foreach(sel, estimate_budget_helper, page);
diff -U4 -r gnucash-2.2.9/src/gnome/gnc-plugin-page-sx-list.c gnucash-2.2.9+dd/src/gnome/gnc-plugin-page-sx-list.c
--- gnucash-2.2.9/src/gnome/gnc-plugin-page-sx-list.c 2008-01-08 01:06:36.000000000 +0000
+++ gnucash-2.2.9+dd/src/gnome/gnc-plugin-page-sx-list.c 2008-11-10 19:38:08.000000000 +0000
@@ -475,9 +475,9 @@
GList *schedule;
g_date_clear(&now, 1);
g_date_set_time_t(&now, time(NULL));
- recurrenceSet(r, 1, PERIOD_MONTH, &now);
+ recurrenceSet(r, 1, PERIOD_MONTH, &now, WEEKEND_ADJ_NONE);
schedule = gnc_sx_get_schedule(new_sx);
schedule = g_list_append(schedule, r);
gnc_sx_set_schedule(new_sx, schedule);
}
diff -U4 -r gnucash-2.2.9/src/gnome-utils/gnc-frequency.c gnucash-2.2.9+dd/src/gnome-utils/gnc-frequency.c
--- gnucash-2.2.9/src/gnome-utils/gnc-frequency.c 2008-01-08 01:06:26.000000000 +0000
+++ gnucash-2.2.9+dd/src/gnome-utils/gnc-frequency.c 2008-11-10 19:38:08.000000000 +0000
@@ -156,13 +156,16 @@
static const struct comboBoxTuple {
char *name;
void (*fn)();
} comboBoxes[] = {
- { "freq_combobox", freq_combo_changed },
- { "semimonthly_first", semimonthly_sel_changed },
- { "semimonthly_second", semimonthly_sel_changed },
- { "monthly_day", monthly_sel_changed },
- { NULL, NULL }
+ { "freq_combobox", freq_combo_changed },
+ { "semimonthly_first", semimonthly_sel_changed },
+ { "semimonthly_first_weekend", semimonthly_sel_changed },
+ { "semimonthly_second", semimonthly_sel_changed },
+ { "semimonthly_second_weekend", semimonthly_sel_changed },
+ { "monthly_day", monthly_sel_changed },
+ { "monthly_weekend", monthly_sel_changed },
+ { NULL, NULL }
};
static const struct spinvalTuple {
char *name;
@@ -408,10 +411,14 @@
gtk_spin_button_set_value(GTK_SPIN_BUTTON(multiplier_spin), recurrenceGetMultiplier(first));
dom_combobox = glade_xml_get_widget(gf->gxml, "semimonthly_first");
gtk_combo_box_set_active(GTK_COMBO_BOX(dom_combobox), _get_monthly_combobox_index(first));
+ dom_combobox = glade_xml_get_widget(gf->gxml, "semimonthly_first_weekend");
+ gtk_combo_box_set_active(GTK_COMBO_BOX(dom_combobox), recurrenceGetWeekendAdjust(first));
dom_combobox = glade_xml_get_widget(gf->gxml, "semimonthly_second");
gtk_combo_box_set_active(GTK_COMBO_BOX(dom_combobox), _get_monthly_combobox_index(second));
+ dom_combobox = glade_xml_get_widget(gf->gxml, "semimonthly_second_weekend");
+ gtk_combo_box_set_active(GTK_COMBO_BOX(dom_combobox), recurrenceGetWeekendAdjust(second));
gtk_notebook_set_current_page(gf->nb, PAGE_SEMI_MONTHLY);
gtk_combo_box_set_active(gf->freqComboBox, PAGE_SEMI_MONTHLY);
}
@@ -460,9 +467,9 @@
case PERIOD_MONTH:
case PERIOD_YEAR:
case PERIOD_LAST_WEEKDAY: {
guint multiplier;
- GtkWidget *multipler_spin, *day_of_month;
+ GtkWidget *multipler_spin, *day_of_month, *weekend_mode;
multipler_spin = glade_xml_get_widget(gf->gxml, "monthly_spin");
multiplier = recurrenceGetMultiplier(r);
if (recurrenceGetPeriodType(r) == PERIOD_YEAR)
@@ -470,8 +477,10 @@
gtk_spin_button_set_value(GTK_SPIN_BUTTON(multipler_spin), multiplier);
day_of_month = glade_xml_get_widget(gf->gxml, "monthly_day");
gtk_combo_box_set_active(GTK_COMBO_BOX(day_of_month), _get_monthly_combobox_index(r));
+ weekend_mode = glade_xml_get_widget(gf->gxml, "monthly_weekend");
+ gtk_combo_box_set_active(GTK_COMBO_BOX(weekend_mode), recurrenceGetWeekendAdjust(r));
gtk_notebook_set_current_page(gf->nb, PAGE_MONTHLY);
gtk_combo_box_set_active(gf->freqComboBox, PAGE_MONTHLY);
} break;
@@ -497,14 +506,16 @@
return gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(multiplier_spin));
}
static Recurrence*
-_get_day_of_month_recurrence(GncFrequency *gf, GDate *start_date, int multiplier, char *combo_name)
+_get_day_of_month_recurrence(GncFrequency *gf, GDate *start_date, int multiplier, char *combo_name, char *combo_weekend_name)
{
int last_day_of_month_option_index = 31;
Recurrence *r;
GtkWidget *day_of_month_combo = glade_xml_get_widget(gf->gxml, combo_name);
int day_of_month_index = gtk_combo_box_get_active(GTK_COMBO_BOX(day_of_month_combo));
+ GtkWidget *weekend_adjust_combo = glade_xml_get_widget(gf->gxml, combo_weekend_name);
+ int weekend_adjust = gtk_combo_box_get_active(GTK_COMBO_BOX(weekend_adjust_combo));
r = g_new0(Recurrence, 1);
if (day_of_month_index > LAST_DAY_OF_MONTH_OPTION_INDEX)
{
@@ -513,14 +524,14 @@
// increment until we align on the DOW, but stay inside the month
g_date_set_day(day_of_week_date, 1);
while (g_date_get_weekday(day_of_week_date) != selected_day_of_week)
g_date_add_days(day_of_week_date, 1);
- recurrenceSet(r, multiplier, PERIOD_LAST_WEEKDAY, day_of_week_date);
+ recurrenceSet(r, multiplier, PERIOD_LAST_WEEKDAY, day_of_week_date, weekend_adjust);
}
else if (day_of_month_index == LAST_DAY_OF_MONTH_OPTION_INDEX)
{
GDate *day_of_month = g_date_new_julian(g_date_get_julian(start_date));
- recurrenceSet(r, multiplier, PERIOD_END_OF_MONTH, day_of_month);
+ recurrenceSet(r, multiplier, PERIOD_END_OF_MONTH, day_of_month, weekend_adjust);
}
else
{
int allowable_date = -1;
@@ -528,9 +539,9 @@
allowable_date = MIN(day_of_month_index + 1,
g_date_get_days_in_month(g_date_get_month(day_of_month),
g_date_get_year(day_of_month)));
g_date_set_day(day_of_month, allowable_date);
- recurrenceSet(r, multiplier, PERIOD_MONTH, day_of_month);
+ recurrenceSet(r, multiplier, PERIOD_MONTH, day_of_month, weekend_adjust);
}
return r;
}
@@ -555,15 +566,15 @@
// empty-recurrence list ~~ none.
} break;
case PAGE_ONCE: {
Recurrence *r = g_new0(Recurrence, 1);
- recurrenceSet(r, 1, PERIOD_ONCE, &start_date);
+ recurrenceSet(r, 1, PERIOD_ONCE, &start_date, WEEKEND_ADJ_NONE);
*recurrences = g_list_append(*recurrences, r);
} break;
case PAGE_DAILY: {
gint multiplier = _get_multiplier_from_widget(gf, "daily_spin");
Recurrence *r = g_new0(Recurrence, 1);
- recurrenceSet(r, multiplier, PERIOD_DAY, &start_date);
+ recurrenceSet(r, multiplier, PERIOD_DAY, &start_date, WEEKEND_ADJ_NONE);
*recurrences = g_list_append(*recurrences, r);
} break;
case PAGE_WEEKLY: {
int multiplier = _get_multiplier_from_widget(gf, "weekly_spin");
@@ -583,21 +594,21 @@
while ((g_date_get_weekday(day_of_week_aligned_date) % 7) != checkbox_idx)
g_date_add_days(day_of_week_aligned_date, 1);
r = g_new0(Recurrence, 1);
- recurrenceSet(r, multiplier, PERIOD_WEEK, day_of_week_aligned_date);
+ recurrenceSet(r, multiplier, PERIOD_WEEK, day_of_week_aligned_date, WEEKEND_ADJ_NONE);
*recurrences = g_list_append(*recurrences, r);
}
} break;
case PAGE_SEMI_MONTHLY: {
int multiplier = _get_multiplier_from_widget(gf, "semimonthly_spin");
- *recurrences = g_list_append(*recurrences, _get_day_of_month_recurrence(gf, &start_date, multiplier, "semimonthly_first"));
- *recurrences = g_list_append(*recurrences, _get_day_of_month_recurrence(gf, &start_date, multiplier, "semimonthly_second"));
+ *recurrences = g_list_append(*recurrences, _get_day_of_month_recurrence(gf, &start_date, multiplier, "semimonthly_first", "semimonthly_first_weekend"));
+ *recurrences = g_list_append(*recurrences, _get_day_of_month_recurrence(gf, &start_date, multiplier, "semimonthly_second", "semimonthly_second_weekend"));
} break;
case PAGE_MONTHLY: {
int multiplier = _get_multiplier_from_widget(gf, "monthly_spin");
- Recurrence *r = _get_day_of_month_recurrence(gf, &start_date, multiplier, "monthly_day");
+ Recurrence *r = _get_day_of_month_recurrence(gf, &start_date, multiplier, "monthly_day", "monthly_weekend");
*recurrences = g_list_append(*recurrences, r);
} break;
default:
g_error("unknown page index [%d]", page_index);
diff -U4 -r gnucash-2.2.9/src/gnome-utils/gnc-recurrence.c gnucash-2.2.9+dd/src/gnome-utils/gnc-recurrence.c
--- gnucash-2.2.9/src/gnome-utils/gnc-recurrence.c 2008-01-08 01:06:22.000000000 +0000
+++ gnucash-2.2.9+dd/src/gnome-utils/gnc-recurrence.c 2008-11-10 19:38:08.000000000 +0000
@@ -165,9 +165,9 @@
gnc_recurrence_init( GncRecurrence *gr )
{
GtkVBox *vb;
- recurrenceSet(&gr->recurrence, 1, PERIOD_MONTH, NULL);
+ recurrenceSet(&gr->recurrence, 1, PERIOD_MONTH, NULL, WEEKEND_ADJ_NONE);
gr->xml = gnc_glade_xml_new("budget.glade", "RecurrenceEntryVBox");
vb = GTK_VBOX(glade_xml_get_widget(gr->xml, "RecurrenceEntryVBox"));
gr->gde_start = GNOME_DATE_EDIT(glade_xml_get_widget(gr->xml,
@@ -285,9 +285,9 @@
pt = PERIOD_INVALID;
}
- recurrenceSet(&gr->recurrence, mult, pt, &start);
+ recurrenceSet(&gr->recurrence, mult, pt, &start, WEEKEND_ADJ_NONE);
return &gr->recurrence;
}
static void