To Register Callback and Keep Reminders
/* The example code shows the usage of csa_register_callback,
* csa_read_next_reminder, and csa_call_callbacks.
* The skeleton code registers a callback routine for
* events CSA_CB_ENTRY_ADDED, CSA_CB_ENTRY_DELETED, and
* CSA_CB_ENTRY_UPDATED; and another callback routine for the
* CSA_CB_CALENDAR_ATTRIBUTE_UPDATED event.
* It also shows how to set up a timer for reminder delivery.
* Two utilities routines for conversion between time representation
* in the ISO 8601 format and the tick representing time in seconds
* since 00:00:00 UTC 1/1/70 are also included.
*/
#include <csa/csa.h>
#include <time.h>
#include <unistd.h>
CSA_session_handle cal; /* a calendar session */
time_t run_time; /* the time the reminders is to be run */
CSA_uint32 num_rems; /* number of reminders returned */
CSA_reminder_reference *rems; /* an array of reminder information */
void
set_up_callback_handler()
{
CSA_return_code stat;
CSA_flags flags;
/* Xt based applications can use the CSA_X_XT_APP_CONTEXT_EXT
* extension to specify the Xt application context so that
* callback routines will be invoked asynchronously
*
* CSA_extension callback_ext;
* callback_ext.item_code = CSA_X_XT_APP_CONTEXT_EXT;
* callback_ext.item_data = (CSA_uint32)application_context;
* callback_ext.extension_flags = CSA_EXT_LAST_ELEMENT;
*
* Pass the callback_ext as the last parameter to
* csa_register_callback.
*/
flags = CSA_CB_ENTRY_ADDED|CSA_CB_ENTRY_DELETED|CSA_CB_ENTRY_UPDATED;
stat = csa_register_callback(cal, flags, entry_update_callback,
NULL, NULL);
if (stat != CSA_SUCCESS) {
/* error handling code */
}
stat = csa_register_callback(cal, CSA_CB_CALENDAR_ATTRIBUTE_UPDATED,
calendar_update_callback, NULL, NULL);
if (stat != CSA_SUCCESS) {
/* error handling code */
}
}
/* * This routine polls the library and causes the registered
* callback to be invoked if the interested event has occurred.
* If an application does not use the CSA_X_XT_APP_CONTEXT_EXT
* extension to set up asynchronously callback invocation,
* it needs to call csa_call_callbacks to force the invocation
* of callbacks.
*/
check_events(CSA_flags event)
{
csa_call_callbacks(cal, event, NULL);
}
/*
* This is the callback routine for events CSA_CB_ENTRY_ADDED,
* CSA_CB_ENTRY_ADDED, and CSA_CB_ENTRY_UPDATED.
*/
void
entry_update_callback(
CSA_session_handle cal,
CSA_flags flags,
CSA_buffer call_data,
CSA_buffer client_data,
CSA_extension *ext)
{
/* An entry is either added, deleted or updated.
* Possible things to do in this callback routine:
*
* 1. Update the calendar view, or
* 2. If this is your own calendar, update reminder information.
*
* The sample code in this routine updates reminder information
*/ reset_reminder();
}
/*
* This is the callback routine for the CSA_CB_CALENDAR_ATTRIBUTE_UPDATED
* event
*/
void
calendar_update_callback(
CSA_session_handle cal,
CSA_flags flags,
CSA_buffer call_data,
CSA_buffer client_data,
CSA_extension *ext)
{
/* update calendar attributes */
}
/*
* This routine updates reminder information:
* - get rid of existing information if any
* - call csa_read_next_reminder() to get the next
* reminder to deliver
* - check the run time and set timer
*/
void
reset_reminder() {
CSA_return_code stat;
time_t current_time;
char isotime[BUFSIZ];
CSA_uint32 number_reminders;
CSA_reminder_reference *reminders;
current_time = time(NULL);
/* get rid of existing information */
if (rems) {
/* this comparison is to make sure that we don't lose
* any reminders whose run time is between the last
* run time and the current time
*/
if (current_time > run_time)
current_time = run_time;
csa_free((CSA_buffer)rems);
}
to_iso8601_time(current_time, isotime);
stat = csa_read_next_reminder(cal, 0, NULL, isotime,
&number_reminders, &reminders, NULL);
if (stat == CSA_SUCCESS && num_rems > 0) {
num_rems = number_reminders;
rems = reminders;
/* Set timer to deliver the reminder.
* sigset() should be used to set up the signal
* disposition for the SIGALRM signal.
*/
from_iso8601_time(reminders[0].run_time, &run_time);
remain = run_time - time(NULL);
alarm((remain > 0) ? remain : 1);
/* Xt based application can set the timer using
* XtAppAddTimeOut
*/
}
}
/*
* This routine converts a time value in the iso8601 format to
* a tick (representing time in seconds since 00:00:00 UTC, 1/1/70).
* The tick is adjusted to the local time.
*/ int from_iso8601_time(char *buf, time_t *tick_out)
{
int year, month, day, hour, min, sec;
struct tm time_str;
sscanf(buf, "%4d%2d%2dT%2d%2d%2dZ",
&year, &month, &day, &hour, &min, &sec);
time_str.tm_year = year - 1900;
time_str.tm_mon = month - 1;
time_str.tm_mday = day;
time_str.tm_hour = hour;
time_str.tm_min = min;
time_str.tm_sec = sec;
time_str.tm_isdst = -1;
*tick_out = mktime(&time_str);
if (*tick_out != (long)-1) {
/* adjust for local time zone */
if (time_str.tm_isdst == 0)
*tick_out -= timezone;
else
*tick_out -= altzone;
return(0);
} else
return(-1);
}
/*
* This routine converts a tick (representing time in seconds
* since 00:00:00 UTC, 1/1/70) to the iso8601 format.
*/
int
to_iso8601_time(time_t tick, char *buf_out)
{
struct tm time_str;
if (gmtime_r(&tick, &time_str)) {
/* format string forces fixed width (zero-padded) fields */
sprintf(buf_out, "%04d%02d%02dT%02d%02d%02dZ",
time_str.tm_year + 1900,
time_str.tm_mon + 1,
time_str.tm_mday,
time_str.tm_hour,
time_str.tm_min,
time_str.tm_sec);
return (0);
} else {
return (-1);
}
}