1 /*---------------------------------------------------------------------------- 2 -- 3 -- Module: xtmAlarmProc 4 -- 5 -- Project: Xdiary 6 -- System: xtm - X Desktop Calendar 7 -- Subsystem: <> 8 -- Function block: <> 9 -- 10 -- Description: 11 -- Process that alarms the user of evebts defined in the XDiary 12 -- database. Each process controls a single diary database and can be 13 -- started as a standalone program or be integrated in the XDiary 14 -- environment. 15 -- 16 -- Syntax: 17 -- XDalarm [flags] 18 -- 19 -- Flags: 20 -- -alarmTags : Display alarms containing one of these tags. 21 -- -dbName : Name of the database(s) to use. 22 -- -usage : Displays some help. 23 -- -help : Same as above. 24 -- 25 -- Filename: xtmAlarmProc.c 26 -- 27 -- Authors: Roger Larsson, Ulrika Bornetun 28 -- Creation date: 1991-07-01 29 -- 30 -- 31 -- (C) Copyright Ulrika Bornetun, Roger Larsson (1995) 32 -- All rights reserved 33 -- 34 -- Permission to use, copy, modify, and distribute this software and its 35 -- documentation for any purpose and without fee is hereby granted, 36 -- provided that the above copyright notice appear in all copies. Ulrika 37 -- Bornetun and Roger Larsson make no representations about the usability 38 -- of this software for any purpose. It is provided "as is" without express 39 -- or implied warranty. 40 ----------------------------------------------------------------------------*/ 41 42 /* SCCS module identifier. */ 43 static char SCCSID[] = "@(#) Module: xtmAlarmProc.c, Version: 1.1, Date: 95/02/18 16:01:50"; 44 45 46 /*---------------------------------------------------------------------------- 47 -- Include files 48 ----------------------------------------------------------------------------*/ 49 50 #include <errno.h> 51 #include <fcntl.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <string.h> 55 #include <time.h> 56 #include <unistd.h> 57 #include <ctype.h> 58 #include <sys/signal.h> 59 #include <sys/types.h> 60 #include <sys/stat.h> 61 62 #include <X11/Intrinsic.h> 63 #include <X11/Shell.h> 64 #include <X11/StringDefs.h> 65 66 #include <Xm/Xm.h> 67 #include <Xm/BulletinB.h> 68 #include <Xm/Form.h> 69 #include <Xm/RowColumn.h> 70 #include <Xm/Scale.h> 71 #include <Xm/SeparatoG.h> 72 73 #include "System.h" 74 #include "LstLinked.h" 75 #include "Message.h" 76 #include "SigHandler.h" 77 #include "TimDate.h" 78 79 #include "msgXdiary.h" 80 #include "xtmGlobal.h" 81 #include "xtmCalDb.h" 82 #include "xtmCustBase.h" 83 #include "xtmDbTools.h" 84 #include "xtmIcons.h" 85 #include "xtmResource.h" 86 #include "xtmUpdate.h" 87 #include "xitError.h" 88 #include "xitStickyMsg.h" 89 #include "xitTools.h" 90 #include "xtmTools.h" 91 #include "xtmHoliday.h" 92 #include "xtmFormat.h" 93 #include "xtmDbTools.h" 94 95 /*---------------------------------------------------------------------------- 96 -- Macro definitions 97 ----------------------------------------------------------------------------*/ 98 99 /* Name of program. */ 100 #define PROGRAM_NAME "xdalarm" 101 102 /* Program class (also the name of the application defaults file). */ 103 #define PROGRAM_CLASS "XDiary" 104 105 106 /* Local widgets in the day list view window. */ 107 #define markerPx dataLocalW[ 0 ] 108 #define messageLa dataLocalW[ 1 ] 109 110 /* Local widgets in the snooze window. */ 111 #define snoozeLa dataLocalW[ 0 ] 112 #define snoozeSc dataLocalW[ 1 ] 113 114 115 /* Number of alarms per entry. */ 116 #define MAX_ALARMS 5 117 118 /* Number of tune files. */ 119 #define MAX_TUNES 5 120 121 /* The number of database we can watch simultaneously. */ 122 #define MAX_DATABASE_CHECK 50 123 124 /* Maximun number of entry alarms that can be ignored. */ 125 #define MAX_ENTRIES_IGNORE 100 126 127 /* Maximum number of snooze alarms. */ 128 #define MAX_SNOOZE_ALARM 100 129 130 /* Maximum number of alarms in the cache. */ 131 #define MAX_ALARM_CACHE 200 132 133 /* Maximum number of displayed alarm windows we keep track of. */ 134 #define MAX_TRACK_ALARM_WIN 100 135 136 /* Name of database file (we should actually no know this!). */ 137 #define DATABASE_FILE "idDB.pag" 138 139 140 141 /*---------------------------------------------------------------------------- 142 -- Type declarations 143 ----------------------------------------------------------------------------*/ 144 145 /* A single alarm record. */ 146 typedef struct { 147 Boolean can_do_action; 148 UINT32 id; 149 UINT32 flags; 150 char db_name[ XTM_GL_MAX_CAL_NAME + 1 ]; 151 TIM_TIME_REF entry_date; 152 TIM_TIME_REF time; 153 } ALARM_CACHE; 154 155 156 /* Information about the databases we check. */ 157 typedef struct { 158 char db_name[ XTM_GL_MAX_CAL_NAME + 1 ]; 159 time_t last_modified; 160 } DATABASE_CHECK; 161 162 163 /* Entries to ignore. */ 164 typedef struct { 165 UINT32 id; 166 char db_name[ XTM_GL_MAX_CAL_NAME + 1 ]; 167 } IGNORE_ENTRY; 168 169 170 /* Basic data structure for the XDalarm appliaction. */ 171 typedef struct { 172 173 /* Command line flags. */ 174 Boolean startup_help; 175 Boolean version_help; 176 177 /* Do animation when displaying alarms. */ 178 Boolean do_animate_alarm; 179 180 /* Volume for alarms. */ 181 int alarm_volume; 182 183 /* Default snooze time. */ 184 int snooze_minutes; 185 186 /* Pipe to use when communicating with the parent. */ 187 char *cmd_pipe_id; 188 189 /* Alarms for these databases. */ 190 char *default_db_alarms; 191 192 /* Display alarms inluding one of these tags. */ 193 char *filter_alarm_tags; 194 195 /* Default script (program) to use. */ 196 char *launch_def_script; 197 198 /* Shell to use when starting alarm action. */ 199 char *launch_use_shell; 200 201 /* We keep track of displayed windows. */ 202 Widget *track_alarm_win; 203 204 /* The X application context. */ 205 XtAppContext context; 206 207 /* The alarm cache containing alarms to check. */ 208 ALARM_CACHE alarms[ MAX_ALARM_CACHE ]; 209 210 /* Snooze alarms. */ 211 ALARM_CACHE snooze[ MAX_SNOOZE_ALARM ]; 212 213 /* The databases we check. */ 214 DATABASE_CHECK db_check[ MAX_DATABASE_CHECK ]; 215 216 /* File pointer for the command pipe. */ 217 int cmd_pipe_ref; 218 219 /* Entries that can be ignored. */ 220 IGNORE_ENTRY ignore_entry[ MAX_ENTRIES_IGNORE ]; 221 222 /* The current date. */ 223 TIM_TIME_REF current_date; 224 225 /* Customization data. */ 226 XTM_GL_CUSTOM_DATA_REF custom_data; 227 228 } XTM_AP_BASE_DATA, *XTM_AP_BASE_DATA_REF; 229 230 231 /* User data necessary for alarm window. */ 232 typedef struct { 233 Boolean important; 234 int curr_pixmap; 235 UINT32 id; 236 char db_name[ XTM_GL_MAX_CAL_NAME + 1 ]; 237 Widget alarmW; 238 Widget snoozeW; 239 XtIntervalId timer_id; 240 TIM_TIME_REF entry_date; 241 XTM_AP_BASE_DATA_REF appl_data_ref; 242 } USER_DATA, *USER_DATA_REF; 243 244 245 246 /*---------------------------------------------------------------------------- 247 -- Global definitions 248 ----------------------------------------------------------------------------*/ 249 250 /* Name of program. */ 251 static char *program_name; 252 253 /* Name of text domain. */ 254 static char *text_domain = "XDiary"; 255 256 /* Name of module. */ 257 static char *module_name = "xtmAlarmProcess"; 258 259 /* Application data. */ 260 static XTM_AP_BASE_DATA appl_data; 261 262 static Widget toplevel; 263 264 /* Pixmaps and pixmap sequence used. */ 265 static Boolean init_pixmap = True; 266 static Pixmap ani_pixmap[ 10 ]; 267 268 static int ani_pixmap_blink[] = { 269 0, 5, 0, 5, 0, 5, 0, -1 270 }; 271 272 static int ani_pixmap_seq[] = { 273 1, 2, 3, 4, 5, 6, 7, 8, 9, 274 8, 7, 6, 5, 4, 3, 2, 1, 275 2, 3, 4, 5, 6, 7, 8, 276 7, 6, 5, 4, 3, 2, 277 3, 4, 5, 6, 7, 278 6, 5, 4, 279 3, 4, 5, 6, 7, 280 6, 5, 4, 3, 281 4, 5, 6, 282 6, 5, 283 4, 5, 6, 284 6, 5, 4, 285 5, -1 286 }; 287 288 289 /* Program options. */ 290 static XrmOptionDescRec options[] = { 291 { "-alarmTags", "*.FilterAlarmTags", XrmoptionSepArg, NULL }, 292 { "-alarmtags", "*.FilterAlarmTags", XrmoptionSepArg, NULL }, 293 { "-cmdPipeId", "*.CmdPipeId", XrmoptionSepArg, NULL }, 294 { "-dbName", "*.DefaultDbAlarms", XrmoptionSepArg, NULL }, 295 { "-dbname", "*.DefaultDbAlarms", XrmoptionSepArg, NULL }, 296 { "-calendars", "*.DefaultDbAlarms", XrmoptionSepArg, NULL }, 297 { "-debug", "*.debug", XrmoptionNoArg, "True" }, 298 { "-h", "*.StartupHelp", XrmoptionNoArg, "True" }, 299 { "-help", "*.StartupHelp", XrmoptionNoArg, "True" }, 300 { "-lan", "*.msgLanguage", XrmoptionSepArg, NULL }, 301 { "-language", "*.msgLanguage", XrmoptionSepArg, NULL }, 302 { "-noFileLock", "*.useFileLock", XrmoptionNoArg, "False" }, 303 { "-nofilelock", "*.useFileLock", XrmoptionNoArg, "False" }, 304 { "-usage", "*.StartupHelp", XrmoptionNoArg, "True" }, 305 { "-version", "*.VersionHelp", XrmoptionNoArg, "True" }, 306 }; 307 308 /* Application resources. */ 309 static XtResource base_resources[] = { 310 311 { "cmdPipeId", "CmdPipeId", XtRString, sizeof( String ), 312 XtOffset( XTM_AP_BASE_DATA_REF, cmd_pipe_id ), 313 XtRString, "" }, 314 315 { "defaultDbAlarms", "DefaultDbAlarms", XtRString, sizeof( String ), 316 XtOffset( XTM_AP_BASE_DATA_REF, default_db_alarms ), 317 XtRString, "" }, 318 319 { "doAnimateAlarm", "DoAnimateAlarm", XtRBoolean, sizeof( Boolean ), 320 XtOffset( XTM_AP_BASE_DATA_REF, do_animate_alarm ), 321 XtRString, "True" }, 322 323 { "filterAlarmTags", "FilterAlarmTags", XtRString, sizeof( String ), 324 XtOffset( XTM_AP_BASE_DATA_REF, filter_alarm_tags ), 325 XtRString, "" }, 326 327 { "launchDefScript", "LaunchDefScript", XtRString, sizeof( String ), 328 XtOffset( XTM_AP_BASE_DATA_REF, launch_def_script ), 329 XtRString, "XDiary.alarmdo" }, 330 331 { "launchUseShell", "LaunchUseShell", XtRString, sizeof( String ), 332 XtOffset( XTM_AP_BASE_DATA_REF, launch_use_shell ), 333 XtRString, "/bin/sh" }, 334 335 { "startupHelp", "StartupHelp", XtRBoolean, sizeof( Boolean ), 336 XtOffset( XTM_AP_BASE_DATA_REF, startup_help ), 337 XtRString, "False" }, 338 339 { "snoozeMinutes", "SnoozeMinutes", XtRInt, sizeof( int ), 340 XtOffset( XTM_AP_BASE_DATA_REF, snooze_minutes ), 341 XtRString, "5" }, 342 343 { "versionHelp", "VersionHelp", XtRBoolean, sizeof( Boolean ), 344 XtOffset( XTM_AP_BASE_DATA_REF, version_help ), 345 XtRString, "False" }, 346 347 }; 348 349 350 /*---------------------------------------------------------------------------- 351 -- Function prototypes 352 ----------------------------------------------------------------------------*/ 353 354 static void 355 alarmConfirmCB( Widget widget, 356 USER_DATA_REF user_data, 357 XmAnyCallbackStruct *call_data ); 358 359 static void 360 alarmDeleteCB( Widget widget, 361 USER_DATA_REF user_data, 362 XtPointer call_data ); 363 364 static void 365 alarmNoMoreCB( Widget widget, 366 USER_DATA_REF user_data, 367 XtPointer call_data ); 368 369 static void 370 alarmSnoozeCB( Widget widget, 371 USER_DATA_REF user_data, 372 XtPointer call_data ); 373 374 static void 375 alarmViewCB( Widget widget, 376 USER_DATA_REF user_data, 377 XtPointer call_data ); 378 379 static void 380 checkAlarms( XTM_AP_BASE_DATA_REF appl_data_ref, 381 TIM_TIME_REF time_now ); 382 383 static void 384 deleteEntryCB( Widget widget, 385 USER_DATA_REF user_data, 386 XtPointer call_data ); 387 388 static void 389 destroyCB( Widget widget, 390 USER_DATA_REF user_data, 391 XtPointer call_data ); 392 393 static void 394 displayAlarm( XTM_AP_BASE_DATA_REF appl_data_ref, 395 ALARM_CACHE *alarm_ref ); 396 397 static void 398 displayUsage(); 399 400 static void 401 doActionAlarm( XTM_AP_BASE_DATA_REF appl_data_ref, 402 ALARM_CACHE *alarm_ref ); 403 404 static void 405 doAnimateCB( USER_DATA_REF user_data ); 406 407 static void 408 doBlinkCB( USER_DATA_REF user_data ); 409 410 static Boolean 411 fetchAlarms( XTM_AP_BASE_DATA_REF appl_data_ref, 412 XTM_CD_CAL_INFO *db_info ); 413 414 static void 415 processCommandCB( XTM_AP_BASE_DATA_REF appl_data_ref, 416 int *fd, 417 XtInputId *id ); 418 419 static Boolean 420 setupCmdPipe( XTM_AP_BASE_DATA_REF appl_data_ref ); 421 422 static void 423 snoozeOkCB( Widget widget, 424 USER_DATA_REF user_data, 425 XtPointer call_data ); 426 427 static void 428 startAlarmForCal( XTM_AP_BASE_DATA_REF appl_data_ref, 429 char *db_name, 430 char *db_location ); 431 432 int 433 startProcess( Widget parent, 434 char *process_args[] ); 435 436 static void 437 stopAlarmForCal( XTM_AP_BASE_DATA_REF appl_data_ref, 438 char *db_name ); 439 440 static void 441 terminateCB( int this_signal, 442 void *user_data ); 443 444 static void 445 updateCB( UINT32 flags, 446 void *user_data, 447 void *update_user_data ); 448 449 450 451 /*---------------------------------------------------------------------------- 452 -- Functions 453 ----------------------------------------------------------------------------*/ 454 455 int main(int argc,char * argv[])456 main( int argc, char *argv[] ) 457 { 458 459 /* Variables. */ 460 int index; 461 char *char_ref; 462 Arg args[ 10 ]; 463 Cardinal n; 464 Display *display; 465 TIM_STATUS_TYPE time_status; 466 XTM_CB_STATUS custom_status; 467 XTM_GL_CUSTOM_DATA custom_data; 468 469 470 /* Code. */ 471 472 /* Fetch the name of the program. */ 473 program_name = PROGRAM_NAME; 474 xitErSetApplicationName( program_name ); 475 476 477 /* Save the original command parameters. */ 478 custom_data.orig_argc = argc; 479 custom_data.orig_argv = (char**) XtMalloc( argc * sizeof( char* ) ); 480 481 for( index = 0; index < argc; index++ ) 482 custom_data.orig_argv[ index ] = XtNewString( argv[ index ] ); 483 484 /* NLS enabled. */ 485 xtmToSetLocale( program_name ); 486 487 488 /* Initialize the signal handler module. */ 489 SigInitialize(); 490 491 /* Initialize. */ 492 SysInitializeEnvironment(); 493 xtmDbInitializeProcessId(); 494 495 496 /* Initialize toolkit and open display. */ 497 XtToolkitInitialize(); 498 499 appl_data.context = XtCreateApplicationContext(); 500 display = XtOpenDisplay( appl_data.context, NULL, 501 NULL, PROGRAM_CLASS, 502 options, XtNumber( options ), 503 #if XtSpecificationRelease < 5 504 (Cardinal *) &argc, 505 #else 506 (int *) &argc, 507 #endif 508 argv ); 509 510 if( display == NULL ) 511 xitErMessage( NULL, XIT_ER_FATAL, 512 module_name, "main", 513 "Cannot open display, check your DISPLAY variable." ); 514 515 /* Resource mapping.*/ 516 xtmToInitializeResourceMapping( argc, argv, display ); 517 518 /* Create application shell. */ 519 n = 0; 520 toplevel = XtAppCreateShell( NULL, PROGRAM_CLASS, 521 applicationShellWidgetClass, 522 display, 523 args, n ); 524 525 526 /* Get base application resources. */ 527 XtGetApplicationResources( toplevel, (XtPointer) &appl_data, 528 base_resources, 529 XtNumber( base_resources ), 530 NULL, 0 ); 531 532 /* Get customize resources. */ 533 xtmRsFetchCustomResources( &custom_data, toplevel ); 534 535 /* Reset application data. */ 536 custom_data.cal_db_handle = NULL; 537 custom_data.group_db_handle = NULL; 538 custom_data.archive_files = NULL; 539 custom_data.include_files = NULL; 540 541 appl_data.current_date = 0; 542 appl_data.cmd_pipe_ref = -1; 543 appl_data.custom_data = &custom_data; 544 545 for( index = 0; index < MAX_DATABASE_CHECK; index++ ) 546 appl_data.db_check[ index ].db_name[ 0 ] = '\0'; 547 548 for( index = 0; index < MAX_ALARM_CACHE; index++ ) 549 appl_data.alarms[ index ].id = 0; 550 551 for( index = 0; index < MAX_ENTRIES_IGNORE; index++ ) 552 appl_data.ignore_entry[ index ].id = 0; 553 554 for( index = 0; index < MAX_SNOOZE_ALARM; index++ ) 555 appl_data.snooze[ index ].id = 0; 556 557 558 appl_data.track_alarm_win = (Widget *) 559 SysMalloc( sizeof( Widget ) * MAX_TRACK_ALARM_WIN ); 560 561 for( index = 0; index < MAX_TRACK_ALARM_WIN; index++ ) 562 *(appl_data.track_alarm_win + index) = NULL; 563 564 565 /* Display current version? */ 566 if( appl_data.version_help ) { 567 printf( "%s: Version: %s\n", program_name, VERSION_ID ); 568 exit( 0 ); 569 } 570 571 /* Help requested? */ 572 if( appl_data.startup_help ) { 573 displayUsage(); 574 exit( 0 ); 575 } 576 577 578 /* Get customized data from file. */ 579 custom_status = xtmCbGetDataFromFile( appl_data.custom_data ); 580 581 if( custom_status == XTM_CB_WRONG_VERSION ) { 582 char_ref = (char *) 583 SysMalloc( strlen( msgGetText( MXDI_CUST_WRONG_VERSION ) ) + 50 ); 584 585 sprintf( char_ref, msgGetText( MXDI_CUST_WRONG_VERSION ), 586 xtmCbWhatVersion() ); 587 588 xitStDisplaySticky( toplevel, char_ref, XmUNSPECIFIED_PIXMAP, 589 msgGetText( MXDI_OK_BUTTON ), NULL, 590 NULL, NULL, NULL, 591 NULL ); 592 SysFree( char_ref ); 593 } 594 595 596 /* Initialize necessary text domains. */ 597 msgInitialize(); 598 msgInitCatalogue( text_domain, NULL, custom_data.msg_language, 599 msgXdiaryTexts ); 600 601 /* Default catalogue Xdiary. */ 602 msgTextDomain( text_domain ); 603 604 605 /* Initialize the time formats. */ 606 time_status = TimInitializeFormat( custom_data.date_format, 607 custom_data.time_format ); 608 if( time_status != TIM_OK ) 609 xitErMessage( toplevel, XIT_ER_ERROR, 610 module_name, "main", 611 msgGetText( MXDI_ERRMSG_DATE_OR_TIME_FORMAT ) ); 612 613 614 /* Set colors and fonts in the resource database. */ 615 xtmRsFetchColors( &custom_data, toplevel ); 616 617 618 /* Initialize holidays. */ 619 xtmHoInitialize( custom_data.holidays_db_dir, custom_data.workdays ); 620 621 622 /* Use file locking? */ 623 xtmDbUseFileLock( custom_data.use_file_lock ); 624 625 /* Initialize the update module. */ 626 xtmUpInitialize( appl_data.context, 0 ); 627 628 629 /* If controlled by the XDiary process, watch out for commands. */ 630 if( *appl_data.cmd_pipe_id != '\0' ) 631 (void) setupCmdPipe( &appl_data ); 632 633 634 /* Any default databases given? */ 635 if( strlen( appl_data.default_db_alarms ) > 0 ) 636 startAlarmForCal( &appl_data, appl_data.default_db_alarms, "" ); 637 638 639 /* Signal handlers. */ 640 (void) SigRegister( SIGHUP, 0, terminateCB, &appl_data ); 641 (void) SigRegister( SIGTERM, 0, terminateCB, &appl_data ); 642 (void) SigRegister( SIGINT, 0, terminateCB, &appl_data ); 643 (void) SigRegister( SIGILL, 0, terminateCB, &appl_data ); 644 (void) SigRegister( SIGQUIT, 0, terminateCB, &appl_data ); 645 (void) SigRegister( SIGABRT, 0, terminateCB, &appl_data ); 646 647 /* Register for updates? */ 648 (void) xtmUpRegister( XTM_UP_MINUTE_TICK, updateCB, (void *) &appl_data ); 649 650 651 /* Enter the event loop. */ 652 XtAppMainLoop( appl_data.context ); 653 654 655 } /* main */ 656 657 658 /*----------------------------------------------------------------------*/ 659 660 static void checkAlarms(XTM_AP_BASE_DATA_REF appl_data_ref,TIM_TIME_REF time_now)661 checkAlarms( XTM_AP_BASE_DATA_REF appl_data_ref, 662 TIM_TIME_REF time_now ) 663 { 664 665 /* Variables. */ 666 Boolean give_alarm; 667 int index; 668 int index1; 669 670 671 /* Code. */ 672 673 /* Debug information? */ 674 if( appl_data_ref -> custom_data -> debug_mode ) { 675 char buffer[ 50 ]; 676 677 xtmFoFormatTime( time_now, buffer, sizeof( buffer ) ); 678 679 printf( "Time now: %s\n", buffer ); 680 } 681 682 /* Check all alarms in the list. */ 683 for( index = 0; index < MAX_ALARM_CACHE; index++ ) { 684 685 ALARM_CACHE *alarm_ref; 686 687 alarm_ref = &appl_data_ref -> alarms[ index ]; 688 689 /* A valid alarm? */ 690 if( alarm_ref -> id == 0 ) 691 continue; 692 693 give_alarm = False; 694 695 /* Debug information? */ 696 if( appl_data_ref -> custom_data -> debug_mode ) { 697 char buffer[ 50 ]; 698 699 xtmFoFormatTime( alarm_ref -> time, buffer, sizeof( buffer ) ); 700 printf( " Checking time: %s\n", buffer ); 701 } 702 703 if( TimTimeInSecondsRange( alarm_ref -> time, time_now, 50 ) == TIM_YES ) { 704 705 give_alarm = True; 706 707 /* Ignore this alarm? */ 708 for( index1 = 0; index1 < MAX_ENTRIES_IGNORE; index1++ ) { 709 710 if( appl_data_ref -> ignore_entry[ index1 ].id == alarm_ref -> id ) { 711 if( strcmp( appl_data_ref -> ignore_entry[ index1 ].db_name, 712 alarm_ref -> db_name ) == 0 ) { 713 714 give_alarm = False; 715 break; 716 } 717 } 718 719 } /* loop */ 720 721 722 if( give_alarm ) { 723 724 /* Visual alarm? */ 725 if( flagIsSet( alarm_ref -> flags, XTM_DB_FLAG_ALARM ) ) 726 displayAlarm( appl_data_ref, alarm_ref ); 727 728 /* Action alarm (call script)? */ 729 if( flagIsSet( alarm_ref -> flags, XTM_DB_FLAG_ACTION_SCRIPT ) ) 730 doActionAlarm( appl_data_ref, alarm_ref ); 731 732 /* Action alarm (use text as script)? */ 733 if( flagIsSet( alarm_ref -> flags, XTM_DB_FLAG_ACTION_TEXT ) ) 734 doActionAlarm( appl_data_ref, alarm_ref ); 735 736 } /* if */ 737 738 } /* if */ 739 740 } /* loop */ 741 742 743 /* Check all snooze alarms. */ 744 for( index = 0; index < MAX_SNOOZE_ALARM; index++ ) { 745 746 ALARM_CACHE *snooze_ref; 747 748 snooze_ref = &appl_data_ref -> snooze[ index ]; 749 750 /* Valid snooze alarm? */ 751 if( snooze_ref -> id != 0 ) { 752 753 if( TimTimeInSecondsRange( snooze_ref -> time, 754 time_now, 50 ) == TIM_YES ) 755 displayAlarm( appl_data_ref, snooze_ref ); 756 757 } 758 759 } /* loop */ 760 761 762 return; 763 764 } /* checkAlarms */ 765 766 767 /*----------------------------------------------------------------------*/ 768 769 static void displayAlarm(XTM_AP_BASE_DATA_REF appl_data_ref,ALARM_CACHE * alarm_ref)770 displayAlarm( XTM_AP_BASE_DATA_REF appl_data_ref, 771 ALARM_CACHE *alarm_ref ) 772 { 773 774 /* Variables. */ 775 int alarm_melody; 776 int index; 777 int lines_read; 778 int size; 779 UINT32 can_do; 780 UINT32 operations; 781 char buffer[ 100 ]; 782 char *char_ref; 783 char *entry_text_ref = NULL; 784 char *message; 785 char *tune_file; 786 Arg args[ 10 ]; 787 Cardinal n; 788 Widget alarmTl; 789 Widget dataLocalW[ 2 ]; 790 Widget tempW; 791 Widget workFo; 792 USER_DATA_REF user_data; 793 XTM_DB_ALL_ENTRY_DEF entry_record; 794 XTM_DB_ENTRY_DATABASES database; 795 XTM_DB_OPEN_REQUEST open_request; 796 XTM_DB_STATUS db_status; 797 XTM_CD_CAL_INFO db_info; 798 799 static XIT_ACTION_AREA_ITEM action_buttons[] = { 800 { "", alarmConfirmCB, NULL }, 801 { "", alarmNoMoreCB, NULL }, 802 { "", alarmSnoozeCB, NULL }, 803 { "", alarmViewCB, NULL }, 804 { "", alarmDeleteCB, NULL }, 805 }; 806 807 808 /* Code. */ 809 810 /* Alarm is hidden? */ 811 if( flagIsSet( alarm_ref -> flags, XTM_DB_FLAG_HIDE_IN_ALARM ) ) 812 return; 813 814 815 /* Fetch database information. */ 816 (void) xtmCdFetchNamedDb( appl_data_ref -> custom_data -> cal_db_handle, 817 alarm_ref -> db_name, 818 &db_info, NULL ); 819 820 /* Check operations. */ 821 xtmDbCheckDbOperations( db_info.directory, True, &operations ); 822 823 824 /* Open the database. */ 825 open_request.name = db_info.short_name; 826 open_request.directory = db_info.directory; 827 open_request.operations = XTM_DB_FLAG_MODE_READ; 828 open_request.database = XTM_DB_ALL_ENTRY_DB; 829 830 831 /* Try to open the database. */ 832 db_status = xtmDbOpenEntryDb( &open_request, &database ); 833 834 if( db_status != XTM_DB_OK ) { 835 836 if( db_status == XTM_DB_LOCKED ) 837 xitErMessage( toplevel, XIT_ER_ERROR, 838 module_name, "displayAlarm", 839 msgGetText( MXDI_ERRMSG_DB_LOCKED ) ); 840 else 841 xitErMessage( toplevel, XIT_ER_ERROR, 842 module_name, "displayAlarm", 843 msgGetText( MXDI_ERRMSG_CANNOT_OPEN_DB ) ); 844 845 raise exception; 846 847 } /* if */ 848 849 850 /* Fetch the entry to display. */ 851 db_status = xtmDbFetchEntry( &database, alarm_ref -> id, 852 &entry_record, &entry_text_ref ); 853 854 xtmDbCloseEntryDb( &database ); 855 856 if( db_status != XTM_DB_OK ) { 857 xitErMessage( NULL, XIT_ER_ERROR, 858 module_name, "displayAlarm", 859 msgGetText( MXDI_ERRMSG_FETCH_ENTRY ) ); 860 861 raise exception; 862 } 863 864 865 /* Does the entry have the correct tag? */ 866 if( *appl_data_ref -> filter_alarm_tags != '\0' && 867 strstr( appl_data_ref -> filter_alarm_tags, 868 entry_record.entry.tag ) == NULL ) 869 raise exception; 870 871 872 /* No messages for private entries (if you are not privileged). */ 873 if( flagIsSet( entry_record.entry.flags, XTM_DB_FLAG_PRIVATE ) && 874 ! flagIsSet( operations, XTM_DB_FLAG_MODE_PRIV ) ) 875 raise exception; 876 877 878 /* Allocate memory for our user data. */ 879 user_data = SysNew( USER_DATA ); 880 881 user_data -> appl_data_ref = appl_data_ref; 882 user_data -> entry_date = alarm_ref -> entry_date; 883 user_data -> id = alarm_ref -> id; 884 885 strcpy( user_data -> db_name, alarm_ref -> db_name ); 886 887 if( flagIsSet( entry_record.entry.flags, XTM_DB_FLAG_IMPORTANT ) ) 888 user_data -> important = True; 889 else 890 user_data -> important = False; 891 892 893 /* Create a separate window. */ 894 action_buttons[ 0 ].label = msgGetText( MXDI_ALARM_CONFIRM ); 895 action_buttons[ 0 ].data = user_data; 896 action_buttons[ 1 ].label = msgGetText( MXDI_ALARM_NO_MORE ); 897 action_buttons[ 1 ].data = user_data; 898 action_buttons[ 2 ].label = msgGetText( MXDI_ALARM_SNOOZE ); 899 action_buttons[ 2 ].data = user_data; 900 action_buttons[ 3 ].label = msgGetText( MXDI_ALARM_VIEW ); 901 action_buttons[ 3 ].data = user_data; 902 action_buttons[ 4 ].label = msgGetText( MXDI_ALARM_DELETE ); 903 action_buttons[ 4 ].data = user_data; 904 905 alarmTl = xitCreateToplevelDialog( toplevel, "AlarmTl", 906 1, 0, 907 action_buttons, 908 XtNumber( action_buttons ) ); 909 910 XtAddCallback( alarmTl, XmNdestroyCallback, 911 (XtCallbackProc) destroyCB, (XtPointer) user_data ); 912 913 914 /* Create the message window. */ 915 sprintf( buffer, "%s %s", 916 alarm_ref -> db_name, msgGetText( MXDI_ALARM_TITLE ) ); 917 918 n = 0; 919 XtSetArg( args[ n ], XmNtitle, buffer ); n++; 920 XtSetArg( args[ n ], XmNiconName, buffer ); n++; 921 XtSetValues( alarmTl, args, n ); 922 923 924 /* Form to hold the alarm message. */ 925 workFo = XtNameToWidget( alarmTl, "AlarmTlBase.AlarmTlFo" ); 926 927 928 929 /* Pixelmap label. */ 930 markerPx = xitCreateLabel( workFo, "MarkerPx", "", -1 ); 931 932 933 /* Initialize the pixmaps? */ 934 if( init_pixmap ) { 935 ani_pixmap[ 0 ] = xtmIcFetchSimplePixmap( 936 workFo, XTM_IC_ICON_ALARM_CLOCK5INV, False ); 937 ani_pixmap[ 1 ] = xtmIcFetchSimplePixmap( 938 workFo, XTM_IC_ICON_ALARM_CLOCK1, False ); 939 ani_pixmap[ 2 ] = xtmIcFetchSimplePixmap( 940 workFo, XTM_IC_ICON_ALARM_CLOCK2, False ); 941 ani_pixmap[ 3 ] = xtmIcFetchSimplePixmap( 942 workFo, XTM_IC_ICON_ALARM_CLOCK3, False ); 943 ani_pixmap[ 4 ] = xtmIcFetchSimplePixmap( 944 workFo, XTM_IC_ICON_ALARM_CLOCK4, False ); 945 ani_pixmap[ 5 ] = xtmIcFetchSimplePixmap( 946 workFo, XTM_IC_ICON_ALARM_CLOCK5, False ); 947 ani_pixmap[ 6 ] = xtmIcFetchSimplePixmap( 948 workFo, XTM_IC_ICON_ALARM_CLOCK6, False ); 949 ani_pixmap[ 7 ] = xtmIcFetchSimplePixmap( 950 workFo, XTM_IC_ICON_ALARM_CLOCK7, False ); 951 ani_pixmap[ 8 ] = xtmIcFetchSimplePixmap( 952 workFo, XTM_IC_ICON_ALARM_CLOCK8, False ); 953 ani_pixmap[ 9 ] = xtmIcFetchSimplePixmap( 954 workFo, XTM_IC_ICON_ALARM_CLOCK9, False ); 955 956 init_pixmap = False; 957 } 958 959 n = 0; 960 XtSetArg( args[ n ], XmNlabelPixmap, ani_pixmap[ 1 ] ); n++; 961 XtSetArg( args[ n ], XmNlabelType, XmPIXMAP ); n++; 962 XtSetValues( markerPx, args, n ); 963 964 965 /* We cannot delete entries in a read only db. */ 966 xtmDbGetEntryPermissions( operations, 967 entry_record.entry.owner, 968 entry_record.entry.flags, 969 &can_do ); 970 971 if( flagIsClear( can_do, XTM_DB_PROT_DELETE ) ) { 972 tempW = XtNameToWidget( alarmTl, "AlarmTlBase.Bu5" ); 973 974 XtSetSensitive( tempW, False ); 975 } 976 977 978 /* Make a copy of the entry text. */ 979 if( entry_text_ref != NULL ) 980 size = strlen( entry_text_ref ) + 75; 981 else 982 size = strlen( entry_record.entry.text ) + 75; 983 984 message = SysMalloc( size ); 985 *message = '\0'; 986 987 xtmFoFormatDate( alarm_ref -> entry_date, 988 buffer, sizeof( buffer ) ); 989 990 strcat( message, buffer ); 991 strcat( message, ", " ); 992 993 TimFormatStrTime( alarm_ref -> entry_date, "%A", 994 buffer, sizeof( buffer ) ); 995 996 strcat( message, buffer ); 997 strcat( message, " " ); 998 999 xtmFoFormatTime( entry_record.entry.time_stamp, 1000 buffer, sizeof( buffer ) ); 1001 1002 strcat( message, buffer ); 1003 strcat( message, "\n" ); 1004 1005 1006 if( entry_text_ref != NULL ) 1007 strcat( message, entry_text_ref ); 1008 else 1009 strcat( message, entry_record.entry.text ); 1010 1011 1012 1013 /* Number of lines to write? */ 1014 lines_read = 0; 1015 char_ref = message; 1016 1017 while( lines_read < entry_record.entry.alarm_lines + 1 ) { 1018 char_ref = strchr( char_ref, '\n' ); 1019 if( char_ref == NULL ) 1020 break; 1021 lines_read++; 1022 char_ref++; 1023 } 1024 1025 if( char_ref != NULL ) 1026 *char_ref = '\0'; 1027 1028 1029 /* Message label. */ 1030 messageLa = xitCreateLabel( workFo, "MessageLa", 1031 message, XmALIGNMENT_BEGINNING ); 1032 1033 1034 /* Put the Parts together. */ 1035 xitAttachWidget( markerPx, 1036 XmATTACH_FORM, NULL, XmATTACH_FORM, NULL, 1037 XmATTACH_NONE, NULL, XmATTACH_NONE, NULL ); 1038 xitAttachWidget( messageLa, 1039 XmATTACH_FORM, NULL, XmATTACH_WIDGET, markerPx, 1040 XmATTACH_NONE, NULL, XmATTACH_NONE, NULL ); 1041 1042 /* Make sure there is enough space between the children. */ 1043 n = 0; 1044 XtSetArg( args[ n ], XmNtopOffset, 5 ); n++; 1045 XtSetArg( args[ n ], XmNleftOffset, 5 ); n++; 1046 XtSetArg( args[ n ], XmNrightOffset, 5 ); n++; 1047 XtSetArg( args[ n ], XmNbottomOffset, 5 ); n++; 1048 XtSetValues( markerPx, args, n ); 1049 XtSetValues( messageLa, args, n ); 1050 1051 /* Manage the widgets. */ 1052 xitManageChildren( dataLocalW, XtNumber( dataLocalW ) ); 1053 1054 1055 /* Set icon for this window. */ 1056 xtmIcSetSimpleIcon( alarmTl, workFo, XTM_IC_ICON_DEFAULT ); 1057 1058 /* Set the size of the window. */ 1059 xitSetSizeToplevelDialog( alarmTl, True ); 1060 1061 1062 XtPopup( alarmTl, XtGrabNone ); 1063 1064 1065 /* Free allocated data. */ 1066 if( entry_text_ref != NULL ) 1067 SysFree( entry_text_ref ); 1068 1069 1070 /* Give an alarm, a boring bell or a nice melody. */ 1071 alarm_melody = entry_record.entry.alarm_melody; 1072 1073 if( alarm_melody > 0 && alarm_melody < 6 ) 1074 tune_file = appl_data_ref -> custom_data -> tune_file[ alarm_melody - 1 ]; 1075 else 1076 tune_file = NULL; 1077 1078 xtmToPlayMelody( alarmTl, 1079 appl_data_ref -> custom_data -> tune_player, 1080 appl_data_ref -> custom_data -> tune_player_param, 1081 tune_file, 1082 appl_data_ref -> alarm_volume, 1083 appl_data_ref -> custom_data -> tune_dur_delta ); 1084 1085 /* Display animation pixmap. */ 1086 user_data -> timer_id = (XtIntervalId) 0; 1087 1088 if( appl_data_ref -> do_animate_alarm ) { 1089 user_data -> curr_pixmap = 0; 1090 user_data -> timer_id = XtAppAddTimeOut( 1091 appl_data_ref -> context, 0L, 1092 (XtTimerCallbackProc) doAnimateCB, 1093 (XtPointer) user_data ); 1094 } 1095 1096 1097 /* We keep track of windows on the screen. */ 1098 for( index = 0; index < MAX_TRACK_ALARM_WIN; index++ ) { 1099 if( *(appl_data_ref -> track_alarm_win + index) == NULL ) { 1100 *(appl_data_ref -> track_alarm_win + index) = alarmTl; 1101 break; 1102 } 1103 } 1104 1105 user_data -> alarmW = alarmTl; 1106 1107 return; 1108 1109 1110 /* Exception handler. */ 1111 exception: 1112 1113 if( entry_text_ref != NULL ) 1114 SysFree( entry_text_ref ); 1115 1116 return; 1117 1118 } /* displayAlarm */ 1119 1120 1121 /*----------------------------------------------------------------------*/ 1122 1123 static void displayUsage()1124 displayUsage() 1125 { 1126 1127 printf( 1128 "\n" 1129 "%s (%s): Alarm process for a single diary database\n" 1130 "\n" 1131 "Start an alarm process for one or more diary databases. The\n" 1132 "default database in Diary in your home directory.\n" 1133 "\n" 1134 "Usage:\n" 1135 " %s [flags]\n" 1136 "\n" 1137 "Flags:\n" 1138 " -alarmTags : Display alarms containing one of these tags.\n" 1139 " -fmap large : Use a large font.\n" 1140 " -fmap medium : Use a medium font.\n" 1141 " -fmap small : Use a small font.\n" 1142 " -help : Display this help.\n" 1143 " -h : See above.\n" 1144 " -language <lan> : Use the language <lan>.\n" 1145 " -lan <lan> : See above.\n" 1146 " -noFileLock : Don't use any file locking.\n" 1147 " -palette gray : Use color palette Gray.\n" 1148 " -palette lila : Use color palette Lila.\n" 1149 " -palette motif : Use color palette Motif.\n" 1150 " -palette neon : Use color palette Neon.\n" 1151 " -palette nordic : Use color palette Nordic.\n" 1152 " -palette red : Use color palette Red.\n" 1153 " -palette sea : Use color palette Sea.\n" 1154 " -palette sky : Use color palette Sky.\n" 1155 " -palette wood : Use color palette Wood.\n" 1156 " -usage : Display this help.\n" 1157 " -version : Display the current version.\n" 1158 "\n", 1159 program_name, VERSION_ID, program_name ); 1160 1161 1162 return; 1163 1164 } /* displayUsage */ 1165 1166 1167 /*----------------------------------------------------------------------*/ 1168 1169 static void doActionAlarm(XTM_AP_BASE_DATA_REF appl_data_ref,ALARM_CACHE * alarm_ref)1170 doActionAlarm( XTM_AP_BASE_DATA_REF appl_data_ref, 1171 ALARM_CACHE *alarm_ref ) 1172 { 1173 1174 /* Variables. */ 1175 int pid; 1176 UINT32 operations; 1177 char date_buffer[ 50 ]; 1178 char time_buffer[ 50 ]; 1179 char *process_args[ 10 ]; 1180 char *entry_text_ref; 1181 XTM_DB_ALL_ENTRY_DEF entry_record; 1182 XTM_DB_ENTRY_DATABASES database; 1183 XTM_DB_OPEN_REQUEST open_request; 1184 XTM_DB_STATUS db_status; 1185 XTM_CD_CAL_INFO db_info; 1186 1187 1188 /* Code. */ 1189 1190 /* Should we do action alarm? */ 1191 if( ! alarm_ref -> can_do_action ) 1192 return; 1193 1194 /* Fetch database information. */ 1195 (void) xtmCdFetchNamedDb( appl_data_ref -> custom_data -> cal_db_handle, 1196 alarm_ref -> db_name, 1197 &db_info, NULL ); 1198 1199 /* Check operations. */ 1200 xtmDbCheckDbOperations( db_info.directory, True, &operations ); 1201 1202 1203 /* Open the database. */ 1204 open_request.name = db_info.short_name; 1205 open_request.directory = db_info.directory; 1206 open_request.operations = XTM_DB_FLAG_MODE_READ; 1207 open_request.database = XTM_DB_ALL_ENTRY_DB; 1208 1209 /* Try to open the database. */ 1210 db_status = xtmDbOpenEntryDb( &open_request, &database ); 1211 1212 if( db_status != XTM_DB_OK ) { 1213 1214 if( db_status == XTM_DB_LOCKED ) 1215 xitErMessage( toplevel, XIT_ER_ERROR, 1216 module_name, "doActionAlarm", 1217 msgGetText( MXDI_ERRMSG_DB_LOCKED ) ); 1218 else 1219 xitErMessage( toplevel, XIT_ER_ERROR, 1220 module_name, "doActionAlarm", 1221 msgGetText( MXDI_ERRMSG_CANNOT_OPEN_DB ) ); 1222 return; 1223 1224 } /* if */ 1225 1226 1227 /* Fetch the entry to use. */ 1228 db_status = xtmDbFetchEntry( &database, alarm_ref -> id, 1229 &entry_record, &entry_text_ref ); 1230 1231 xtmDbCloseEntryDb( &database ); 1232 1233 if( db_status != XTM_DB_OK ) { 1234 xitErMessage( NULL, XIT_ER_ERROR, 1235 module_name, "doActionAlarm", 1236 msgGetText( MXDI_ERRMSG_FETCH_ENTRY ) ); 1237 1238 return; 1239 } 1240 1241 /* Does the entry have the correct tag? */ 1242 if( *appl_data_ref -> filter_alarm_tags != '\0' && 1243 strstr( appl_data_ref -> filter_alarm_tags, 1244 entry_record.entry.tag ) == NULL ) 1245 return; 1246 1247 1248 /* No actions for private entries (if you are not privileged). */ 1249 if( flagIsSet( entry_record.entry.flags, XTM_DB_FLAG_PRIVATE ) && 1250 ! flagIsSet( operations, XTM_DB_FLAG_MODE_PRIV ) ) 1251 return; 1252 1253 1254 /* Entry date and time. */ 1255 xtmFoFormatDate( entry_record.entry.time_stamp, 1256 date_buffer, sizeof( date_buffer ) ); 1257 1258 xtmFoFormatTime( entry_record.entry.time_stamp, 1259 time_buffer, sizeof( time_buffer ) ); 1260 1261 1262 /* Start entry action shell script? */ 1263 if( flagIsSet( entry_record.entry.flags, XTM_DB_FLAG_ACTION_TEXT ) ) { 1264 1265 /* Process arguments. */ 1266 process_args[ 0 ] = appl_data_ref -> launch_use_shell; 1267 process_args[ 1 ] = "-c"; 1268 1269 if( entry_text_ref == NULL ) 1270 process_args[ 2 ] = entry_record.entry.text; 1271 else 1272 process_args[ 2 ] = entry_text_ref; 1273 1274 process_args[ 3 ] = NULL; 1275 1276 pid = startProcess( toplevel, process_args ); 1277 1278 } /* if */ 1279 1280 1281 /* Start entry action with entry text as shell script? */ 1282 if( flagIsSet( entry_record.entry.flags, XTM_DB_FLAG_ACTION_SCRIPT ) ) { 1283 1284 /* Process arguments. */ 1285 process_args[ 0 ] = appl_data_ref -> launch_def_script; 1286 process_args[ 1 ] = entry_record.entry.tag; 1287 process_args[ 2 ] = date_buffer; 1288 process_args[ 3 ] = time_buffer; 1289 1290 if( entry_text_ref != NULL ) 1291 process_args[ 4 ] = entry_text_ref; 1292 else 1293 process_args[ 4 ] = entry_record.entry.text; 1294 1295 process_args[ 5 ] = NULL; 1296 1297 pid = startProcess( toplevel, process_args ); 1298 1299 } /* if */ 1300 1301 if( entry_text_ref != NULL ) 1302 SysFree( entry_text_ref ); 1303 1304 1305 return; 1306 1307 } /* doActionAlarm */ 1308 1309 1310 /*----------------------------------------------------------------------*/ 1311 1312 static Boolean fetchAlarms(XTM_AP_BASE_DATA_REF appl_data_ref,XTM_CD_CAL_INFO * db_info)1313 fetchAlarms( XTM_AP_BASE_DATA_REF appl_data_ref, 1314 XTM_CD_CAL_INFO *db_info ) 1315 { 1316 1317 /* Variables. */ 1318 int index; 1319 UINT32 search_flags; 1320 LST_DESC_TYPE list_ref[ 2 ]; 1321 LST_STATUS lst_status; 1322 TIM_TIME_REF current_day; 1323 TIM_TIME_REF end_day; 1324 TIM_TIME_REF now; 1325 TIM_TIME_REF start_day; 1326 XTM_DB_ALL_ENTRY_DEF entry_record; 1327 XTM_DB_ENTRY_DATABASES database; 1328 XTM_DB_OPEN_REQUEST open_request; 1329 XTM_DB_STATUS db_status; 1330 1331 1332 /* Code. */ 1333 1334 if( appl_data_ref -> custom_data -> debug_mode ) 1335 printf( "Fetching db: %s\n", db_info -> short_name ); 1336 1337 1338 /* Remove all old alarms for this database. */ 1339 for( index = 0; index < MAX_ALARM_CACHE; index++ ) { 1340 if( strcmp( appl_data_ref -> alarms[ index ].db_name, 1341 db_info -> short_name ) == 0 ) 1342 appl_data_ref -> alarms[ index ].id = 0; 1343 } 1344 1345 1346 /* Open the database. */ 1347 open_request.name = db_info -> short_name; 1348 open_request.directory = db_info -> directory; 1349 open_request.operations = XTM_DB_FLAG_MODE_READ; 1350 open_request.database = XTM_DB_ALL_ENTRY_DB; 1351 1352 db_status = xtmDbOpenEntryDb( &open_request, &database ); 1353 1354 if( db_status != XTM_DB_OK ) { 1355 1356 if( db_status == XTM_DB_LOCKED ) 1357 xitErMessage( toplevel, XIT_ER_ERROR, 1358 module_name, "fetchAlarms", 1359 msgGetText( MXDI_ERRMSG_DB_LOCKED ) ); 1360 else 1361 xitErMessage( toplevel, XIT_ER_ERROR, 1362 module_name, "fetchAlarms", 1363 msgGetText( MXDI_ERRMSG_CANNOT_OPEN_DB ) ); 1364 1365 return( False ); 1366 1367 } /* if */ 1368 1369 /* Fetch entries from today and 7 days before/after. */ 1370 now = TimLocalTime( TimMakeTimeNow() ); 1371 start_day = TimMakeTime( TimIndexOfYear( now ), 1372 TimIndexOfMonth( now ), 1373 TimIndexOfDay( now ), 1374 0, 0, 0 ); 1375 1376 TimAddDays( &start_day, -7 ); 1377 current_day = start_day; 1378 end_day = start_day; 1379 TimAddDays( &end_day, 14 ); 1380 1381 /* Fetch all entries. */ 1382 while( current_day <= end_day ) { 1383 1384 db_status = xtmDbFetchEntriesInDay( &database, 1385 current_day, 1386 XTM_DB_FETCH_STANDING, 1387 &list_ref[ 0 ], &list_ref[ 1 ] ); 1388 1389 if( db_status != XTM_DB_OK ) { 1390 xitErMessage( NULL, XIT_ER_ERROR, 1391 module_name, "displayAlarm", 1392 msgGetText( MXDI_ERRMSG_FETCH_ENTRY ) ); 1393 1394 return( False ); 1395 } 1396 1397 search_flags = (XTM_DB_FLAG_ALARM | 1398 XTM_DB_FLAG_ACTION_SCRIPT | 1399 XTM_DB_FLAG_ACTION_TEXT); 1400 1401 /* Ignore any notes and save the alarms. */ 1402 lst_status = LstLinkCurrentFirst( list_ref[ 0 ] ); 1403 1404 while( lst_status == LST_OK ) { 1405 1406 lst_status = LstLinkGetCurrent( list_ref[ 0 ], &entry_record ); 1407 1408 /* Do we want alarms for this entry? */ 1409 if( flagIsClear( entry_record.entry.flags, search_flags ) ) { 1410 lst_status = LstLinkCurrentNext( list_ref[ 0 ] ); 1411 1412 continue; 1413 } 1414 1415 1416 /* Process all alarms. */ 1417 for( index = 0; index < MAX_ALARMS; index++ ) { 1418 1419 int minute_offset; 1420 int slot; 1421 UINT32 entry_id; 1422 UINT32 flags; 1423 TIM_TIME_REF alarm_time; 1424 1425 /* Is the alarm valid? */ 1426 if( entry_record.entry.alarm_valid[ index ] ) { 1427 minute_offset = entry_record.entry.alarm_offset[ index ]; 1428 entry_id = entry_record.entry.id; 1429 flags = entry_record.entry.flags; 1430 1431 /* Calculate the absolute alarm time. */ 1432 alarm_time = current_day; 1433 alarm_time = TimAddTime( alarm_time, 1434 entry_record.entry.time_stamp ); 1435 TimAddMinutes( &alarm_time, minute_offset ); 1436 1437 /* Find a free slot where the alarm can be stored. */ 1438 for( slot = 0; slot < MAX_ALARM_CACHE; slot++ ) { 1439 if( appl_data_ref -> alarms[ slot ].id == 0 ) 1440 break; 1441 } 1442 1443 1444 /* Save alarm time and other data. */ 1445 if( slot < MAX_ALARM_CACHE ) { 1446 1447 UINT32 action_flag = 0; 1448 1449 /* Can do action alarm? */ 1450 switch( index + 1 ) { 1451 case 1: 1452 action_flag = XTM_DB_FLAG_ACTION_ALARM1; 1453 break; 1454 case 2: 1455 action_flag = XTM_DB_FLAG_ACTION_ALARM2; 1456 break; 1457 case 3: 1458 action_flag = XTM_DB_FLAG_ACTION_ALARM3; 1459 break; 1460 case 4: 1461 action_flag = XTM_DB_FLAG_ACTION_ALARM4; 1462 break; 1463 case 5: 1464 action_flag = XTM_DB_FLAG_ACTION_ALARM5; 1465 break; 1466 } 1467 1468 appl_data_ref -> alarms[ slot ].entry_date = current_day; 1469 appl_data_ref -> alarms[ slot ].time = alarm_time; 1470 appl_data_ref -> alarms[ slot ].id = entry_id; 1471 appl_data_ref -> alarms[ slot ].flags = flags; 1472 appl_data_ref -> alarms[ slot ].can_do_action = False; 1473 1474 if( flagIsSet( flags, action_flag ) ) 1475 appl_data_ref -> alarms[ slot ].can_do_action = True; 1476 1477 strcpy( appl_data_ref -> alarms[ slot ].db_name, 1478 db_info -> short_name ); 1479 1480 if( appl_data_ref -> custom_data -> debug_mode ) 1481 printf( "Alarm time %d (%d) '%s'\n", 1482 (int) alarm_time, slot, 1483 entry_record.entry.text ); 1484 } 1485 1486 } /* if */ 1487 1488 } /* loop */ 1489 1490 1491 /* Next entry. */ 1492 lst_status = LstLinkCurrentNext( list_ref[ 0 ] ); 1493 1494 } /* while */ 1495 1496 1497 /* Free any data occupied. */ 1498 LstLinkClear( list_ref[ 0 ] ); 1499 LstLinkClear( list_ref[ 1 ] ); 1500 1501 /* Next day. */ 1502 TimAddDays( ¤t_day, 1 ); 1503 1504 } /* while */ 1505 1506 1507 /* Close the database. */ 1508 xtmDbCloseEntryDb( &database ); 1509 1510 1511 return( True ); 1512 1513 } /* fetchAlarms */ 1514 1515 1516 /*----------------------------------------------------------------------*/ 1517 1518 static Boolean setupCmdPipe(XTM_AP_BASE_DATA_REF appl_data_ref)1519 setupCmdPipe( XTM_AP_BASE_DATA_REF appl_data_ref ) 1520 { 1521 1522 /* Variables. */ 1523 int fd; 1524 1525 1526 /* Code. */ 1527 1528 if( *appl_data_ref -> cmd_pipe_id == '\0' ) 1529 return( False ); 1530 1531 1532 fd = open( appl_data_ref -> cmd_pipe_id, O_RDONLY ); 1533 if( fd < 0 ) 1534 return( False ); 1535 1536 appl_data_ref -> cmd_pipe_ref = fd; 1537 1538 1539 /* Add callback to call when input is pending. */ 1540 XtAppAddInput( appl_data_ref -> context, 1541 appl_data_ref -> cmd_pipe_ref, 1542 (XtPointer) XtInputReadMask, 1543 (XtInputCallbackProc) processCommandCB, 1544 (XtPointer) appl_data_ref ); 1545 1546 1547 return( True ); 1548 1549 } /* setupCmdPipe */ 1550 1551 1552 /*----------------------------------------------------------------------*/ 1553 1554 static void startAlarmForCal(XTM_AP_BASE_DATA_REF appl_data_ref,char * db_name,char * db_location)1555 startAlarmForCal( XTM_AP_BASE_DATA_REF appl_data_ref, 1556 char *db_name, 1557 char *db_location ) 1558 { 1559 1560 /* Variables. */ 1561 Boolean ok; 1562 UINT32 operations; 1563 int save_to_index; 1564 int index; 1565 XTM_CD_CAL_INFO db_info; 1566 1567 1568 /* Code. */ 1569 1570 /* Fetch database information. */ 1571 ok = xtmCdFetchNamedDb( appl_data_ref -> custom_data -> cal_db_handle, 1572 db_name, &db_info, NULL ); 1573 1574 /* If we did not find the database, see if we can add it 'on the fly'. */ 1575 if( ! ok ) { 1576 1577 /* We need at least read access. */ 1578 xtmDbCheckDbOperations( db_location, True, &operations ); 1579 1580 if( flagIsClear( operations, XTM_DB_FLAG_MODE_READ ) ) 1581 return; 1582 1583 /* Add the calendar. */ 1584 xtmCdAddDatabase( appl_data_ref -> custom_data -> cal_db_handle, 1585 db_name, db_location, 0 ); 1586 1587 (void) xtmCdFetchNamedDb( appl_data_ref -> custom_data -> cal_db_handle, 1588 db_name, &db_info, NULL ); 1589 1590 } /* if */ 1591 1592 1593 save_to_index = -1; 1594 1595 /* Save the database name (if already there, ignore it). */ 1596 for( index = 0; index < MAX_DATABASE_CHECK; index++ ) { 1597 1598 DATABASE_CHECK *db_ref; 1599 1600 db_ref = &appl_data_ref -> db_check[ index ]; 1601 1602 /* Already there? */ 1603 if( strcmp( db_ref -> db_name, db_name ) == 0 ) { 1604 save_to_index = -1; 1605 break; 1606 } 1607 1608 /* Free slot? */ 1609 if( db_ref -> db_name[ 0 ] == '\0' && save_to_index == -1 ) 1610 save_to_index = index; 1611 1612 } /* loop */ 1613 1614 1615 /* Save the database? */ 1616 if( save_to_index >= 0 ) { 1617 if( appl_data_ref -> custom_data -> debug_mode ) 1618 printf( "Starting alarm for: %s\n", db_name ); 1619 1620 strcpy( appl_data_ref -> db_check[ save_to_index ].db_name, db_name ); 1621 appl_data_ref -> db_check[ save_to_index ].last_modified = 0; 1622 } 1623 1624 1625 return; 1626 1627 } /* startAlarmForCal */ 1628 1629 1630 /*----------------------------------------------------------------------*/ 1631 1632 static void stopAlarmForCal(XTM_AP_BASE_DATA_REF appl_data_ref,char * db_name)1633 stopAlarmForCal( XTM_AP_BASE_DATA_REF appl_data_ref, 1634 char *db_name ) 1635 { 1636 1637 /* Variables. */ 1638 int index; 1639 1640 1641 /* Code. */ 1642 1643 /* Remove from databases db. */ 1644 for( index = 0; index < MAX_DATABASE_CHECK; index++ ) { 1645 if( strcmp( appl_data_ref -> db_check[ index ].db_name, db_name ) == 0 ) 1646 appl_data_ref -> db_check[ index ].db_name[ 0 ] = '\0'; 1647 } 1648 1649 1650 /* Remove from alarm_cache. */ 1651 for( index = 0; index < MAX_ALARM_CACHE; index++ ) { 1652 if( strcmp( appl_data_ref -> alarms[ index ].db_name, db_name ) == 0 ) 1653 appl_data_ref -> alarms[ index ].id = 0; 1654 } 1655 1656 1657 /* Remove from ignore entries. */ 1658 for( index = 0; index < MAX_ENTRIES_IGNORE; index++ ) { 1659 if( strcmp( appl_data_ref -> ignore_entry[ index ].db_name, 1660 db_name ) == 0 ) 1661 appl_data_ref -> ignore_entry[ index ].id = 0; 1662 } 1663 1664 1665 /* Remove from snooze. */ 1666 for( index = 0; index < MAX_SNOOZE_ALARM; index++ ) { 1667 if( strcmp( appl_data_ref -> snooze[ index ].db_name, db_name ) == 0 ) 1668 appl_data_ref -> snooze[ index ].id = 0; 1669 } 1670 1671 1672 return; 1673 1674 } /* stopAlarmForCal */ 1675 1676 1677 /*----------------------------------------------------------------------*/ 1678 1679 int startProcess(Widget parent,char * process_args[])1680 startProcess( Widget parent, 1681 char *process_args[] ) 1682 { 1683 1684 /* Variables. */ 1685 int pid; 1686 int status; 1687 Display *display = NULL; 1688 1689 1690 /* Code. */ 1691 1692 if( parent != NULL ) 1693 display = XtDisplay( parent ); 1694 1695 /* Does the executable file exist? */ 1696 status = access( process_args[ 0 ], (R_OK | X_OK) ); 1697 1698 if( status != 0 ) { 1699 xitErMessage( parent, XIT_ER_ERROR, 1700 module_name, "startProcess", 1701 msgGetText( MXDI_PROCESS_NO_FILE ) ); 1702 return( 0 ); 1703 } 1704 1705 /* Start the alarm process. */ 1706 pid = fork(); 1707 1708 switch( pid ) { 1709 1710 /* Child running. */ 1711 case 0: 1712 if( display != NULL ) 1713 close( ConnectionNumber( display ) ); 1714 1715 /* Start the process. */ 1716 execv( process_args[ 0 ], process_args ); 1717 1718 { 1719 char buffer[ 200 ]; 1720 1721 sprintf( buffer, 1722 msgGetText( MXDI_ERRMSG_EXECUTE_PROCESS ), 1723 process_args[ 0 ] ); 1724 1725 xitErMessage( NULL, XIT_ER_ERROR, 1726 module_name, "startProcess", 1727 buffer ); 1728 } /* block */ 1729 1730 exit( 1 ); 1731 1732 /* Error in fork. */ 1733 case -1: 1734 xitErMessage( parent, XIT_ER_ERROR, 1735 module_name, "startProcess", 1736 msgGetText( MXDI_PROCESS_CANNOT_FORK ) ); 1737 return( 0 ); 1738 1739 /* Parent */ 1740 default: 1741 break; 1742 1743 } /* switch */ 1744 1745 /* Catch this process when we return. */ 1746 (void) SigRegister( SIGCHLD, pid, NULL, NULL ); 1747 1748 1749 return( pid ); 1750 1751 } /* startProcess */ 1752 1753 1754 /*----------------------------------------------------------------------*/ 1755 1756 static void alarmConfirmCB(Widget widget,USER_DATA_REF user_data,XmAnyCallbackStruct * call_data)1757 alarmConfirmCB( Widget widget, 1758 USER_DATA_REF user_data, 1759 XmAnyCallbackStruct *call_data ) 1760 { 1761 1762 /* Variables. */ 1763 int index; 1764 XTM_AP_BASE_DATA_REF appl_data_ref; 1765 1766 1767 /* Code. */ 1768 1769 appl_data_ref = user_data -> appl_data_ref; 1770 1771 1772 /* The shift modifier key confirms all alarm windows on screen. */ 1773 if( (call_data -> event -> xbutton.state & ShiftMask) != 0 ) { 1774 1775 for( index = 0; index < MAX_TRACK_ALARM_WIN; index++ ) { 1776 if( *(appl_data_ref -> track_alarm_win + index) == user_data -> alarmW ) 1777 ; 1778 else if( *(appl_data_ref -> track_alarm_win + index) != NULL ) 1779 XtDestroyWidget( *(appl_data_ref -> track_alarm_win + index) ); 1780 } 1781 1782 } 1783 1784 1785 XtDestroyWidget( user_data -> alarmW ); 1786 1787 1788 return; 1789 1790 } /* alarmConfirmCB */ 1791 1792 1793 /*----------------------------------------------------------------------*/ 1794 1795 static void alarmDeleteCB(Widget widget,USER_DATA_REF user_data,XtPointer call_data)1796 alarmDeleteCB( Widget widget, 1797 USER_DATA_REF user_data, 1798 XtPointer call_data ) 1799 { 1800 1801 /* Variables. */ 1802 Widget tempW; 1803 1804 1805 /* Code. */ 1806 1807 /* Does the user confirm? */ 1808 if( user_data -> appl_data_ref -> custom_data -> confirm_actions ) { 1809 1810 tempW = xitCreateQuestionDialog( 1811 user_data -> alarmW, "QuestionDialog", 1812 msgGetText( MXDI_DELETE_ENTRY_TITLE ), 1813 msgGetText( MXDI_DELETE_ENTRY_CONF ), 1814 deleteEntryCB, user_data, 1815 NULL, NULL ); 1816 1817 return; 1818 } 1819 1820 /* Remove the entry. */ 1821 deleteEntryCB( widget, user_data, NULL ); 1822 1823 1824 return; 1825 1826 } /* alarmDeleteCB */ 1827 1828 1829 /*----------------------------------------------------------------------*/ 1830 1831 static void alarmNoMoreCB(Widget widget,USER_DATA_REF user_data,XtPointer call_data)1832 alarmNoMoreCB( Widget widget, 1833 USER_DATA_REF user_data, 1834 XtPointer call_data ) 1835 { 1836 1837 /* Variables. */ 1838 int index; 1839 1840 1841 /* Code. */ 1842 1843 /* Mark this entry as ignored. */ 1844 for( index = 0; index < MAX_ENTRIES_IGNORE; index++ ) { 1845 1846 if( user_data -> appl_data_ref -> ignore_entry[ index ].id == 0 ) { 1847 user_data -> appl_data_ref -> ignore_entry[ index ].id = 1848 user_data -> id; 1849 strcpy( user_data -> appl_data_ref -> ignore_entry[ index ].db_name, 1850 user_data -> db_name ); 1851 break; 1852 } 1853 1854 } /* loop */ 1855 1856 XtDestroyWidget( user_data -> alarmW ); 1857 1858 1859 return; 1860 1861 } /* alarmNoMoreCB */ 1862 1863 1864 /*----------------------------------------------------------------------*/ 1865 1866 static void alarmSnoozeCB(Widget widget,USER_DATA_REF user_data,XtPointer call_data)1867 alarmSnoozeCB( Widget widget, 1868 USER_DATA_REF user_data, 1869 XtPointer call_data ) 1870 { 1871 1872 /* Variables. */ 1873 Arg args[ 10 ]; 1874 Cardinal n; 1875 Widget dataLocalW[ 2 ]; 1876 Widget snoozeFd; 1877 Widget snoozeFo; 1878 1879 static XIT_ACTION_AREA_ITEM action_buttons[] = { 1880 { "", snoozeOkCB, NULL }, 1881 { NULL, NULL, NULL }, 1882 { NULL, NULL, NULL }, 1883 { NULL, NULL, NULL }, 1884 { NULL, NULL, NULL }, 1885 { "", NULL, NULL }, 1886 }; 1887 1888 1889 /* Code. */ 1890 1891 action_buttons[ 0 ].label = msgGetText( MXDI_OK_BUTTON ); 1892 action_buttons[ 0 ].data = user_data; 1893 action_buttons[ 5 ].label = msgGetText( MXDI_CANCEL_BUTTON ); 1894 action_buttons[ 5 ].data = user_data; 1895 1896 1897 /* Create a form dialog with buttons. */ 1898 snoozeFd = xitCreateFormDialog( user_data -> alarmW, "SnoozeFd", 1899 1, 0, 1900 action_buttons, 1901 XtNumber( action_buttons ) ); 1902 1903 n = 0; 1904 XtSetArg( args[ n ], XmNtitle, msgGetText( MXDI_SNOOZE_TITLE ) ); n++; 1905 XtSetValues( XtParent( snoozeFd ), args, n ); 1906 1907 n = 0; 1908 XtSetArg( args[ n ], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL ); n++; 1909 XtSetValues( snoozeFd, args, n ); 1910 1911 1912 /* Container for the contents of the snooze window. */ 1913 snoozeFo = XtNameToWidget( snoozeFd, "SnoozeFdFo" ); 1914 1915 1916 snoozeLa = xitCreateLabel( snoozeFo, "SnoozeLa", 1917 msgGetText( MXDI_SNOOZE_LABEL ), -1 ); 1918 1919 /* Create a slide bar with the time in minutes to wait. */ 1920 n = 0; 1921 XtSetArg( args[ n ], XmNvalue, 1 ); n++; 1922 XtSetArg( args[ n ], XmNminimum, 1 ); n++; 1923 XtSetArg( args[ n ], XmNmaximum, 120 ); n++; 1924 XtSetArg( args[ n ], XmNprocessingDirection, XmMAX_ON_RIGHT ); n++; 1925 XtSetArg( args[ n ], XmNshowValue, True ); n++; 1926 XtSetArg( args[ n ], XmNorientation, XmHORIZONTAL ); n++; 1927 snoozeSc = XmCreateScale( snoozeFo, "SnoozeSc", args, n ); 1928 1929 1930 /* Put the elements together. */ 1931 xitAttachWidget( snoozeLa, 1932 XmATTACH_FORM, NULL, XmATTACH_FORM, NULL, 1933 XmATTACH_NONE, NULL, XmATTACH_NONE, NULL ); 1934 xitAttachWidget( snoozeSc, 1935 XmATTACH_WIDGET, snoozeLa, XmATTACH_FORM, NULL, 1936 XmATTACH_FORM, NULL, XmATTACH_NONE, NULL ); 1937 1938 1939 /* Make sure there is enough space between the children. */ 1940 n = 0; 1941 XtSetArg( args[ n ], XmNtopOffset, 5 ); n++; 1942 XtSetArg( args[ n ], XmNleftOffset, 5 ); n++; 1943 XtSetArg( args[ n ], XmNrightOffset, 5 ); n++; 1944 XtSetArg( args[ n ], XmNbottomOffset, 5 ); n++; 1945 XtSetValues( snoozeLa, args, n ); 1946 XtSetValues( snoozeSc, args, n ); 1947 1948 1949 /* Manage the widgets. */ 1950 xitManageChildren( dataLocalW, XtNumber( dataLocalW ) ); 1951 1952 XtManageChild( snoozeFd ); 1953 1954 1955 /* Default snooze minutes. */ 1956 XmScaleSetValue( snoozeSc, user_data -> appl_data_ref -> snooze_minutes ); 1957 1958 1959 user_data -> snoozeW = snoozeFd; 1960 1961 1962 return; 1963 1964 } /* alarmSnoozeCB */ 1965 1966 1967 /*----------------------------------------------------------------------*/ 1968 1969 static void alarmViewCB(Widget widget,USER_DATA_REF user_data,XtPointer call_data)1970 alarmViewCB( Widget widget, 1971 USER_DATA_REF user_data, 1972 XtPointer call_data ) 1973 { 1974 1975 /* Variables. */ 1976 char *char_ref; 1977 char *entry_text_ref; 1978 XTM_AP_BASE_DATA_REF appl_data_ref; 1979 XTM_DB_ALL_ENTRY_DEF entry_record; 1980 XTM_DB_ENTRY_DATABASES database; 1981 XTM_DB_OPEN_REQUEST open_request; 1982 XTM_DB_STATUS db_status; 1983 XTM_CD_CAL_INFO db_info; 1984 1985 1986 /* Code. */ 1987 1988 appl_data_ref = user_data -> appl_data_ref; 1989 1990 1991 /* Fetch database information. */ 1992 (void) xtmCdFetchNamedDb( appl_data_ref -> custom_data -> cal_db_handle, 1993 user_data -> db_name, 1994 &db_info, NULL ); 1995 1996 /* Open the database. */ 1997 open_request.name = db_info.short_name; 1998 open_request.directory = db_info.directory; 1999 open_request.operations = XTM_DB_FLAG_MODE_READ; 2000 open_request.database = XTM_DB_ALL_ENTRY_DB; 2001 2002 db_status = xtmDbOpenEntryDb( &open_request, &database ); 2003 2004 if( db_status != XTM_DB_OK ) { 2005 2006 if( db_status == XTM_DB_LOCKED ) 2007 xitErMessage( user_data -> alarmW, XIT_ER_ERROR, 2008 module_name, "alarmViewCB", 2009 msgGetText( MXDI_ERRMSG_DB_LOCKED ) ); 2010 else 2011 xitErMessage( user_data -> alarmW, XIT_ER_ERROR, 2012 module_name, "alarmViewCB", 2013 msgGetText( MXDI_ERRMSG_CANNOT_OPEN_DB ) ); 2014 2015 return; 2016 2017 } /* if */ 2018 2019 2020 /* Fetch the entry to display. */ 2021 db_status = xtmDbFetchEntry( &database, user_data -> id, 2022 &entry_record, &entry_text_ref ); 2023 2024 xtmDbCloseEntryDb( &database ); 2025 2026 if( db_status != XTM_DB_OK ) { 2027 xitErMessage( user_data -> alarmW, XIT_ER_ERROR, 2028 module_name, "alarmViewCB", 2029 msgGetText( MXDI_ERRMSG_FETCH_ENTRY ) ); 2030 return; 2031 } 2032 2033 2034 /* View the entry. */ 2035 if( entry_text_ref != NULL ) 2036 char_ref = entry_text_ref; 2037 else 2038 char_ref = entry_record.entry.text; 2039 2040 xitViewText( user_data -> alarmW, char_ref, 2041 " ", msgGetText( MXDI_CLOSE_BUTTON ) ); 2042 2043 2044 return; 2045 2046 } /* alarmViewCB */ 2047 2048 2049 /*----------------------------------------------------------------------*/ 2050 2051 static void deleteEntryCB(Widget widget,USER_DATA_REF user_data,XtPointer call_data)2052 deleteEntryCB( Widget widget, 2053 USER_DATA_REF user_data, 2054 XtPointer call_data ) 2055 { 2056 2057 /* Variables. */ 2058 Widget tempW; 2059 XTM_AP_BASE_DATA_REF appl_data_ref; 2060 XTM_DB_ENTRY_DATABASES database; 2061 XTM_DB_OPEN_REQUEST open_request; 2062 XTM_DB_STATUS db_status; 2063 XTM_CD_CAL_INFO db_info; 2064 2065 2066 /* Code. */ 2067 2068 appl_data_ref = user_data -> appl_data_ref; 2069 2070 2071 /* Fetch database information. */ 2072 (void) xtmCdFetchNamedDb( appl_data_ref -> custom_data -> cal_db_handle, 2073 user_data -> db_name, 2074 &db_info, NULL ); 2075 2076 /* Open the database. */ 2077 open_request.name = db_info.short_name; 2078 open_request.directory = db_info.directory; 2079 open_request.operations = XTM_DB_FLAG_MODE_WRITE; 2080 open_request.database = XTM_DB_ALL_ENTRY_DB; 2081 2082 db_status = xtmDbOpenEntryDb( &open_request, &database ); 2083 2084 if( db_status != XTM_DB_OK ) { 2085 2086 if( db_status == XTM_DB_LOCKED ) 2087 xitErMessage( user_data -> alarmW, XIT_ER_ERROR, 2088 module_name, "deleteEntryCB", 2089 msgGetText( MXDI_ERRMSG_DB_LOCKED ) ); 2090 else 2091 xitErMessage( user_data -> alarmW, XIT_ER_ERROR, 2092 module_name, "deleteEntryCB", 2093 msgGetText( MXDI_ERRMSG_CANNOT_OPEN_DB ) ); 2094 2095 return; 2096 2097 } /* if */ 2098 2099 2100 /* Delete the entry. */ 2101 db_status = xtmDbDeleteEntry( &database, user_data -> id ); 2102 2103 xtmDbCloseEntryDb( &database ); 2104 2105 if( db_status != XTM_DB_OK ) { 2106 xitErMessage( user_data -> alarmW, XIT_ER_ERROR, 2107 module_name, "deleteEntryCB", 2108 msgGetText( MXDI_NO_ENTRY ) ); 2109 return; 2110 } 2111 2112 2113 /* If the entry could be deleted, invalidate some buttons. */ 2114 if( db_status == XTM_DB_OK ) { 2115 tempW = XtNameToWidget( user_data -> alarmW, "AlarmTlBase.Bu2" ); 2116 XtSetSensitive( tempW, False ); 2117 2118 tempW = XtNameToWidget( user_data -> alarmW, "AlarmTlBase.Bu3" ); 2119 XtSetSensitive( tempW, False ); 2120 2121 tempW = XtNameToWidget( user_data -> alarmW, "AlarmTlBase.Bu4" ); 2122 XtSetSensitive( tempW, False ); 2123 2124 tempW = XtNameToWidget( user_data -> alarmW, "AlarmTlBase.Bu5" ); 2125 XtSetSensitive( tempW, False ); 2126 } 2127 2128 /* Inform the user that it's time to refresh the day list. */ 2129 tempW = xitCreateInformationDialog( 2130 user_data -> alarmW, "InformationDialog", 2131 msgGetText( MXDI_INFORMATION_LABEL ), 2132 msgGetText( MXDI_ALARM_ENTRY_DELETE_INFO ), 2133 NULL, NULL ); 2134 2135 2136 return; 2137 2138 } /* deleteEntryCB */ 2139 2140 2141 /*----------------------------------------------------------------------*/ 2142 2143 static void destroyCB(Widget widget,USER_DATA_REF user_data,XtPointer call_data)2144 destroyCB( Widget widget, 2145 USER_DATA_REF user_data, 2146 XtPointer call_data ) 2147 { 2148 2149 /* Variables. */ 2150 int index; 2151 XTM_AP_BASE_DATA_REF appl_data_ref; 2152 2153 2154 /* Code. */ 2155 2156 appl_data_ref = user_data -> appl_data_ref; 2157 2158 2159 for( index = 0; index < MAX_TRACK_ALARM_WIN; index++ ) { 2160 if( *(appl_data_ref -> track_alarm_win + index) == user_data -> alarmW ) 2161 *(appl_data_ref -> track_alarm_win + index) = NULL; 2162 } 2163 2164 SysFree( user_data ); 2165 2166 /* Remove timeout ID? */ 2167 if( user_data -> timer_id != (XtIntervalId) 0 ) 2168 XtRemoveTimeOut( user_data -> timer_id ); 2169 2170 2171 return; 2172 2173 } /* destroyCB */ 2174 2175 2176 /*----------------------------------------------------------------------*/ 2177 2178 static void doAnimateCB(USER_DATA_REF user_data)2179 doAnimateCB( USER_DATA_REF user_data ) 2180 { 2181 2182 /* Variables. */ 2183 int pixmap_no; 2184 Arg args[ 10 ]; 2185 Cardinal n; 2186 Widget tempW; 2187 XTM_AP_BASE_DATA_REF appl_data_ref; 2188 2189 2190 /* Code. */ 2191 2192 appl_data_ref = user_data -> appl_data_ref; 2193 pixmap_no = ani_pixmap_seq[ user_data -> curr_pixmap ]; 2194 2195 /* Are we done? */ 2196 if( pixmap_no < 0 ) { 2197 if( user_data -> important ) { 2198 user_data -> curr_pixmap = 0; 2199 user_data -> timer_id = XtAppAddTimeOut( 2200 appl_data_ref -> context, 0L, 2201 (XtTimerCallbackProc) doBlinkCB, 2202 (XtPointer) user_data ); 2203 } else { 2204 user_data -> timer_id = (XtIntervalId) 0; 2205 } 2206 2207 return; 2208 } 2209 2210 /* Display the pixmap. */ 2211 tempW = XtNameToWidget( user_data -> alarmW, 2212 "AlarmTlBase.AlarmTlFo.MarkerPx" ); 2213 2214 n = 0; 2215 XtSetArg( args[ n ], XmNlabelPixmap, ani_pixmap[ pixmap_no ] ); n++; 2216 XtSetValues( tempW, args, n ); 2217 2218 /* Next pixmap in the sequence. */ 2219 user_data -> curr_pixmap++; 2220 2221 user_data -> timer_id = XtAppAddTimeOut( 2222 appl_data_ref -> context, 150L, 2223 (XtTimerCallbackProc) doAnimateCB, 2224 (XtPointer) user_data ); 2225 2226 2227 return; 2228 2229 } /* doAnimateCB */ 2230 2231 2232 /*----------------------------------------------------------------------*/ 2233 2234 static void doBlinkCB(USER_DATA_REF user_data)2235 doBlinkCB( USER_DATA_REF user_data ) 2236 { 2237 2238 /* Variables. */ 2239 int pixmap_no; 2240 Arg args[ 10 ]; 2241 Cardinal n; 2242 Widget tempW; 2243 XTM_AP_BASE_DATA_REF appl_data_ref; 2244 2245 2246 /* Code. */ 2247 2248 appl_data_ref = user_data -> appl_data_ref; 2249 pixmap_no = ani_pixmap_blink[ user_data -> curr_pixmap ]; 2250 2251 /* Are we done? */ 2252 if( pixmap_no < 0 ) { 2253 user_data -> timer_id = (XtIntervalId) 0; 2254 return; 2255 } 2256 2257 /* Display the pixmap. */ 2258 tempW = XtNameToWidget( user_data -> alarmW, 2259 "AlarmTlBase.AlarmTlFo.MarkerPx" ); 2260 2261 n = 0; 2262 XtSetArg( args[ n ], XmNlabelPixmap, ani_pixmap[ pixmap_no ] ); n++; 2263 XtSetValues( tempW, args, n ); 2264 2265 /* Next pixmap in the sequence. */ 2266 user_data -> curr_pixmap++; 2267 2268 user_data -> timer_id = XtAppAddTimeOut( 2269 appl_data_ref -> context, 500L, 2270 (XtTimerCallbackProc) doBlinkCB, 2271 (XtPointer) user_data ); 2272 2273 2274 return; 2275 2276 } /* doBlinkCB */ 2277 2278 2279 /*----------------------------------------------------------------------*/ 2280 2281 static void processCommandCB(XTM_AP_BASE_DATA_REF appl_data_ref,int * fd,XtInputId * id)2282 processCommandCB( XTM_AP_BASE_DATA_REF appl_data_ref, 2283 int *fd, 2284 XtInputId *id ) 2285 { 2286 2287 /* Variables. */ 2288 int bytes; 2289 int items; 2290 char buffer[ 5000 ]; 2291 char cal_name[ 50 ]; 2292 char command[ 60 ]; 2293 char location[ 150 ]; 2294 char line[ 300 ]; 2295 char *buffer_ref; 2296 2297 2298 /* Code. */ 2299 2300 /* Read the command pipe. */ 2301 bytes = read( appl_data_ref -> cmd_pipe_ref, buffer, sizeof( buffer ) ); 2302 2303 if( bytes == 0 ) 2304 return; 2305 2306 if( bytes == -1 ) { 2307 xitErMessage( NULL, XIT_ER_FATAL, 2308 module_name, "processCommandCB", "Exiting!" ); 2309 2310 terminateCB( SIGTERM, (void *) appl_data_ref ); 2311 } 2312 2313 buffer[ bytes ] = '\0'; 2314 2315 if( appl_data_ref -> custom_data -> debug_mode ) 2316 printf( "Command over pipe:\n" ); 2317 2318 2319 /* There can be one or more commands in the buffer. */ 2320 buffer_ref = buffer; 2321 2322 while( True ) { 2323 2324 while( isspace( *buffer_ref ) ) 2325 buffer_ref++; 2326 2327 if( *buffer_ref == '\0' ) 2328 return; 2329 2330 bytes = strlen( buffer_ref ); 2331 sscanf( buffer_ref, "%[^\n]%n", line, &bytes ); 2332 buffer_ref = buffer_ref + bytes + 1; 2333 2334 /* Fetch the command (if any). */ 2335 items = sscanf( line, "%50s", command ); 2336 if( items == 0 ) 2337 return; 2338 2339 2340 /* Start alarm process? */ 2341 if( strcmp( command, "start:" ) == 0 ) { 2342 2343 cal_name[ 0 ] = '\0'; 2344 location[ 0 ] = '\0'; 2345 2346 sscanf( line, "%s %s %s", command, cal_name, location ); 2347 2348 if( appl_data_ref -> custom_data -> debug_mode ) 2349 printf( " command: '%s' '%s' '%s'\n", command, cal_name, location ); 2350 2351 startAlarmForCal( appl_data_ref, cal_name, location ); 2352 2353 2354 /* Stop running process. */ 2355 } else if( strcmp( command, "stop:" ) == 0 ) { 2356 2357 cal_name[ 0 ] = '\0'; 2358 2359 sscanf( line, "%s %s", command, cal_name ); 2360 2361 if( appl_data_ref -> custom_data -> debug_mode ) 2362 printf( " command: '%s' '%s'\n", command, cal_name ); 2363 2364 stopAlarmForCal( appl_data_ref, cal_name ); 2365 2366 2367 /* Unknown command. */ 2368 } else { 2369 sprintf( line, "Unexpected command: %s\n", command ); 2370 2371 xitErMessage( NULL, XIT_ER_FATAL, 2372 module_name, "processCommandCB", line ); 2373 2374 } /* if */ 2375 2376 } /* while */ 2377 2378 2379 } /* processCommandCB */ 2380 2381 2382 /*----------------------------------------------------------------------*/ 2383 2384 static void snoozeOkCB(Widget widget,USER_DATA_REF user_data,XtPointer call_data)2385 snoozeOkCB( Widget widget, 2386 USER_DATA_REF user_data, 2387 XtPointer call_data ) 2388 { 2389 2390 /* Variables. */ 2391 int index; 2392 int minutes; 2393 Widget tempW; 2394 TIM_TIME_REF alarm_time; 2395 TIM_TIME_REF now; 2396 XTM_AP_BASE_DATA_REF appl_data_ref; 2397 2398 2399 /* Code. */ 2400 2401 appl_data_ref = user_data -> appl_data_ref; 2402 2403 2404 /* Fetch the slider value. */ 2405 tempW = XtNameToWidget( user_data -> snoozeW, "SnoozeFdFo.SnoozeSc" ); 2406 2407 XmScaleGetValue( tempW, &minutes ); 2408 2409 if( minutes <= 0 ) 2410 return; 2411 2412 2413 /* Calculate the alarm time. */ 2414 now = TimMakeTimeNow(); 2415 2416 alarm_time = TimMakeTime( TimIndexOfYear( now ), 2417 TimIndexOfMonth( now ), 2418 TimIndexOfDay( now ), 2419 TimHour( now ), 2420 TimMinute( now ), 2421 0 ); 2422 alarm_time = TimLocalTime( alarm_time ); 2423 2424 TimAddMinutes( &alarm_time, minutes ); 2425 2426 2427 /* Store the time. */ 2428 for( index = 0; index < MAX_SNOOZE_ALARM; index++ ) { 2429 2430 if( appl_data_ref -> snooze[ index ].id == 0 ) { 2431 2432 appl_data_ref -> snooze[ index ].id = user_data -> id; 2433 appl_data_ref -> snooze[ index ].entry_date = user_data -> entry_date; 2434 appl_data_ref -> snooze[ index ].time = alarm_time; 2435 2436 strcpy( appl_data_ref -> snooze[ index ].db_name, 2437 user_data -> db_name ); 2438 break; 2439 } 2440 2441 } /* loop */ 2442 2443 XtDestroyWidget( user_data -> snoozeW ); 2444 2445 2446 return; 2447 2448 } /* snoozeOkCB */ 2449 2450 2451 /*----------------------------------------------------------------------*/ 2452 2453 static void updateCB(UINT32 flags,void * user_data,void * update_user_data)2454 updateCB( UINT32 flags, 2455 void *user_data, 2456 void *update_user_data ) 2457 { 2458 2459 /* Variables. */ 2460 Boolean new_day = False; 2461 int parent_id; 2462 int index; 2463 TIM_TIME_REF time_now; 2464 XTM_AP_BASE_DATA_REF appl_data_ref; 2465 2466 2467 /* Code. */ 2468 2469 appl_data_ref = (XTM_AP_BASE_DATA_REF) user_data; 2470 2471 2472 if( appl_data_ref -> custom_data -> debug_mode ) 2473 printf( "UpdateCB called\n" ); 2474 2475 /* If our parent process is 1 the our real parent died. */ 2476 parent_id = getppid(); 2477 if( parent_id <= 1 ) 2478 terminateCB( SIGTERM, (void *) appl_data_ref ); 2479 2480 time_now = TimLocalTime( TimMakeTimeNow() ); 2481 2482 /* Has the date changed (over midnight)? */ 2483 if( TimIsSameDate( appl_data_ref -> current_date, time_now ) != TIM_YES ) { 2484 2485 appl_data_ref -> current_date = time_now; 2486 2487 new_day = True; 2488 } 2489 2490 2491 /* If this is a new day, cancel all 'no more' entries. */ 2492 if( new_day ) { 2493 for( index = 0; index < MAX_ENTRIES_IGNORE; index++ ) 2494 appl_data.ignore_entry[ index ].id = 0; 2495 } 2496 2497 2498 /* Did any of our databases change since last checked? */ 2499 for( index = 0; index < MAX_DATABASE_CHECK; index++ ) { 2500 2501 Boolean ok; 2502 char buffer[ 200 ]; 2503 struct stat file_status; 2504 XTM_DB_STATUS db_status; 2505 XTM_CD_CAL_INFO db_info; 2506 2507 if( appl_data_ref -> db_check[ index ].db_name[ 0 ] == '\0' ) 2508 continue; 2509 2510 if( appl_data_ref -> custom_data -> debug_mode ) 2511 printf( "Check db changed: '%s'\n", 2512 appl_data_ref -> db_check[ index ].db_name ); 2513 2514 /* Fetch complete information for the database. */ 2515 ok = xtmCdFetchNamedDb( appl_data_ref -> custom_data -> cal_db_handle, 2516 appl_data_ref -> db_check[ index ].db_name, 2517 &db_info, NULL ); 2518 if( ! ok ) 2519 continue; 2520 2521 /* Build the file name for the database. */ 2522 sprintf( buffer, "%s/%s", 2523 db_info.directory, DATABASE_FILE ); 2524 2525 /* If the database changed, fetch new information. */ 2526 db_status = xtmDbFetchFileInfo( buffer, &file_status ); 2527 2528 if( new_day || 2529 (db_status == XTM_DB_OK && 2530 file_status.st_mtime != 2531 appl_data_ref -> db_check[ index ].last_modified) ) { 2532 2533 fetchAlarms( appl_data_ref, &db_info ); 2534 2535 appl_data_ref -> db_check[ index ].last_modified = 2536 file_status.st_mtime; 2537 } 2538 2539 } /* loop */ 2540 2541 2542 /* Check if any alarms to give? */ 2543 checkAlarms( appl_data_ref, time_now ); 2544 2545 2546 return; 2547 2548 } /* updateCB */ 2549 2550 2551 /*----------------------------------------------------------------------*/ 2552 2553 static void terminateCB(int this_signal,void * user_data)2554 terminateCB( int this_signal, 2555 void *user_data ) 2556 { 2557 2558 /* Variables. */ 2559 XTM_AP_BASE_DATA_REF appl_data_ref; 2560 2561 2562 /* Code. */ 2563 2564 appl_data_ref = (XTM_AP_BASE_DATA_REF) user_data; 2565 2566 if( appl_data_ref -> cmd_pipe_ref != -1 ) { 2567 close( appl_data_ref -> cmd_pipe_ref ); 2568 2569 (void) unlink( appl_data_ref -> cmd_pipe_id ); 2570 } 2571 2572 exit( 0 ); 2573 2574 } /* terminateCB */ 2575