Solaris 共通デスクトップ環境 プログラマーズ・ガイド

コールバックを登録し、通知プログラムを保持するには


例 10-9 コールバックを登録し、通知プログラムを保持する

/* このコーディング例では、csa_register_callback、csa_read_next_reminder、
  * および csa_call_callbacks の使用方法について示します。
  * 基本となるコードでは、イベント CSA_CB_ENTRY_ADDED、CSA_CB_ENTRY_DELETED、
  * および CSA_CB_ENTRY_UPDATED 用のコールバック・ルーチンを登録します。
  * また、別のコールバック・ルーチンを、CSA_CB_CALENDAR_ATTRIBUTE_UPDATE 
  * イベント用に登録します。
  * 通知デリバリ用のタイマを設定する方法も示します。
  * ISO 8601 書式の時間表記を UTC 1970 年 1 月 1 日 00:00:00 からの経過秒数を示す
  * ティック数への変換用の 2 つのユーティリティ・ルーチンも含みます。
  */ 

#include <csa/csa.h> 
#include <time.h> 
#include <unistd.h>  

CSA_session_handle	cal;	 /* カレンダ・セッション */
time_t			run_time; /* 通知プログラムを実行する時間 */ 
CSA_uint32		num_rems; /* 返される通知数 */
CSA_reminder_reference	*rems;	  /* 通知情報の配列 */

void 
set_up_callback_handler() 
{
 	CSA_return_code		stat;
 	CSA_flags		flags;

	/* Xt ベースのアプリケーションは、コールバック・ルーチンが非同期に呼び出せるように
	 * するため、CSA_X_XT_APP_CONTEXT_EXT 拡張を使用して、
	 * Xt アプリケーションのコンテキストを指定できます。
  *
  *	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;
  *
  * callback_ext を最後のパラメータとして、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) {
		/* エラー処理コード */
 	}

  	stat = csa_register_callback(cal, CSA_CB_CALENDAR_ATTRIBUTE_UPDATED,
 		calendar_update_callback, NULL, NULL);
  	if (stat != CSA_SUCCESS) {
		/* エラー処理コード */
 	} 
}  

/*  * このルーチンはライブラリをポーリングし、特定のイベントが発生していた場合に、
 * 登録されているコールバックを呼び出します。
 * アプリケーションが CSA_X_XT_APP_CONTEXT_EXT 拡張を使用してコールバックの
 * 呼び出しを非同期に設定していない場合、csa_call_callbacks を呼び出して、
 * コールバックの呼び出しを強制する必要があります。
 */ 

check_events(CSA_flags event)
{
 	csa_call_callbacks(cal, event, NULL); 
}

  /*
  * これは、イベント CSA_CB_ENTRY_ADDED、CSA_CB_ENTRY_ADDED、および 
  * 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) 
{
	/* エントリが追加、削除、または更新されます。
	 * このコールバック・ルーチンで行う可能性があるのは次のとおりです。
	 *
	 * 1. カレンダ表示の更新
	 * 2. ユーザ自身のカレンダの場合は、通知情報の更新
	 *
	 * このルーチンのコーディング例は通知情報を更新します。
 	 */ 	reset_reminder();
}
 /*
 * これは CSA_CB_CALENDAR_ATTRIBUTE_UPDATED イベントのための
 * コールバック・ルーチンです。
 */ 
void 
calendar_update_callback(
 	CSA_session_handle	cal,
 	CSA_flags		flags,
 	CSA_buffer		call_data,
 	CSA_buffer		client_data,
 	CSA_extension		*ext) 
{
 	/* カレンダ属性を更新する */
}

   /*
  * このルーチンは通知情報を更新します。
  *	 - 既存の情報がある場合は削除する
  *	 - csa_read_next_reminder() を呼び出して、次に転送する通知を取得する
  *	 - 実行時間をチェックし、タイマーを設定する
  */ 
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);

	/* 既存の情報を削除する */
 	if (rems) {
		/* この比較の目的は、最後に実行された時刻から、現在の時刻までの間に実行された
		 * 通知が失われていないかを確認することです。
 		 */
 		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;

		/* タイマーを設定し、通知を転送する。
		 * sigset() を使用して、SIGALRM シグナルのためのシグナル処理を設定します。
 		 */
 		from_iso8601_time(reminders[0].run_time, &run_time);
 		remain = run_time - time(NULL);
 		alarm((remain > 0) ? remain : 1);

		/* Xt ベースのアプリケーションは、XtAppAddTimeOut を使用して
		 * タイマーを設定できます。
 		 */
 	}
}

/*
  * このルーチンは、ISO 8601 書式の時間表記を、UTC 1970 年 1 月 1 日 00:00:00 
  * からの経過秒数を示すティック数へ変換します。
  * このティックはローカル時間に調整されます。
  */ 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) {

		/* ローカル・タイムゾーンに調整 */
 		if (time_str.tm_isdst == 0)
 			*tick_out -= timezone;
 		else
 			*tick_out -= altzone;
  		return(0);
 	} else
 		return(-1); 
}  

/*
  * このルーチンは、UTC 1970 年 1 月 1 日 00:00:00 からの経過秒数を示すティック数を、
  * ISO 8601 書式の時間表記へ変換します。
  */ 
int 
to_iso8601_time(time_t tick, char *buf_out) 
{
 	struct tm	time_str;
  	if (gmtime_r(&tick, &time_str)) {

		/* 書式文字列が固定幅 (ゼロで埋め込み) フィールドを強制する。 */
 		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);
 	} 
}