static GncSxInstances* _gnc_sx_gen_instances(gpointer *data, gpointer user_data) { GncSxInstances *instances = g_new0(GncSxInstances, 1); SchedXaction *sx = (SchedXaction*)data; GDate *range_end = (GDate*)user_data; GDate creation_end, remind_end; GDate cur_date; void *sequence_ctx; instances->sx = sx; creation_end = *range_end; g_date_add_days(&creation_end, xaccSchedXactionGetAdvanceCreation(sx)); remind_end = creation_end; g_date_add_days(&remind_end, xaccSchedXactionGetAdvanceReminder(sx)); /* postponed */ { GList *postponed = gnc_sx_get_defer_instances(sx); for ( ; postponed != NULL; postponed = postponed->next) { GDate inst_date; int seq_num; GncSxInstance *inst; g_date_clear(&inst_date, 1); inst_date = xaccSchedXactionGetNextInstance(sx, postponed->data); seq_num = gnc_sx_get_instance_count(sx, postponed->data); inst = gnc_sx_instance_new(instances, SX_INSTANCE_STATE_POSTPONED, &inst_date, postponed->data, seq_num); instances->instance_list = g_list_append(instances->instance_list, inst); } } /* to-create */ g_date_clear(&cur_date, 1); sequence_ctx = gnc_sx_create_temporal_state(sx); cur_date = xaccSchedXactionGetInstanceAfter(sx, &cur_date, sequence_ctx); instances->next_instance_date = cur_date; while (g_date_valid(&cur_date) && g_date_compare(&cur_date, &creation_end) <= 0) { GncSxInstance *inst; int seq_num; seq_num = gnc_sx_get_instance_count(sx, sequence_ctx); inst = gnc_sx_instance_new(instances, SX_INSTANCE_STATE_TO_CREATE, &cur_date, sequence_ctx, seq_num); instances->instance_list = g_list_append(instances->instance_list, inst); gnc_sx_incr_temporal_state(sx, sequence_ctx); cur_date = xaccSchedXactionGetInstanceAfter(sx, &cur_date, sequence_ctx); } /* reminders */ while (g_date_valid(&cur_date) && g_date_compare(&cur_date, &remind_end) <= 0) { GncSxInstance *inst; int seq_num; seq_num = gnc_sx_get_instance_count(sx, sequence_ctx); inst = gnc_sx_instance_new(instances, SX_INSTANCE_STATE_REMINDER, &cur_date, sequence_ctx, seq_num); instances->instance_list = g_list_append(instances->instance_list, inst); gnc_sx_incr_temporal_state(sx, sequence_ctx); cur_date = xaccSchedXactionGetInstanceAfter(sx, &cur_date, sequence_ctx); } return instances; }
gint gnc_sx_get_num_occur_daterange(const SchedXaction *sx, const GDate* start_date, const GDate* end_date) { gint result = 0; SXTmpStateData *tmpState; gboolean countFirstDate; /* SX still active? If not, return now. */ if ((xaccSchedXactionHasOccurDef(sx) && xaccSchedXactionGetRemOccur(sx) <= 0) || (xaccSchedXactionHasEndDate(sx) && g_date_compare(xaccSchedXactionGetEndDate(sx), start_date) < 0)) { return result; } tmpState = gnc_sx_create_temporal_state (sx); /* Should we count the first valid date we encounter? Only if the * SX has not yet occurred so far, or if its last valid date was * before the start date. */ countFirstDate = !g_date_valid(&tmpState->last_date) || (g_date_compare(&tmpState->last_date, start_date) < 0); /* No valid date? SX has never occurred so far. */ if (!g_date_valid(&tmpState->last_date)) { /* SX has never occurred so far */ gnc_sx_incr_temporal_state (sx, tmpState); if (xaccSchedXactionHasOccurDef(sx) && tmpState->num_occur_rem < 0) { gnc_sx_destroy_temporal_state (tmpState); return result; } } /* Increase the tmpState until we are in our interval of * interest. Only calculate anything if the sx hasn't already * ended. */ while (g_date_compare(&tmpState->last_date, start_date) < 0) { gnc_sx_incr_temporal_state (sx, tmpState); if (xaccSchedXactionHasOccurDef(sx) && tmpState->num_occur_rem < 0) { gnc_sx_destroy_temporal_state (tmpState); return result; } } /* Now we are in our interval of interest. Increment the * occurrence date until we are beyond the end of our * interval. Make sure to check for invalid dates here: It means * the SX has ended. */ while (g_date_valid(&tmpState->last_date) && (g_date_compare(&tmpState->last_date, end_date) <= 0) && (!xaccSchedXactionHasEndDate(sx) || g_date_compare(&tmpState->last_date, xaccSchedXactionGetEndDate(sx)) <= 0) && (!xaccSchedXactionHasOccurDef(sx) /* The >=0 (i.e. the ==) is important here, otherwise * we miss the last valid occurrence of a SX which is * limited by num_occur */ || tmpState->num_occur_rem >= 0)) { ++result; gnc_sx_incr_temporal_state (sx, tmpState); } /* If the first valid date shouldn't be counted, decrease the * result number by one. */ if (!countFirstDate && result > 0) --result; gnc_sx_destroy_temporal_state (tmpState); return result; }