/* 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); } } |