1 /*---------------------------------------------------------------------------- 2 -- 3 -- Module: xtmSchedTool 4 -- 5 -- Project: XDiary 6 -- System: xtm - X Desktop Calendar 7 -- Subsystem: <> 8 -- Function block: <> 9 -- 10 -- Description: 11 -- Various tools for the schedule. 12 -- 13 -- Filename: xtmSchedTool.c 14 -- 15 -- Authors: Roger Larsson, Ulrika Bornetun 16 -- Creation date: 1992-05-01 17 -- 18 -- 19 -- (C) Copyright Ulrika Bornetun, Roger Larsson (1995) 20 -- All rights reserved 21 -- 22 -- Permission to use, copy, modify, and distribute this software and its 23 -- documentation for any purpose and without fee is hereby granted, 24 -- provided that the above copyright notice appear in all copies. Ulrika 25 -- Bornetun and Roger Larsson make no representations about the usability 26 -- of this software for any purpose. It is provided "as is" without express 27 -- or implied warranty. 28 ----------------------------------------------------------------------------*/ 29 30 /* SCCS module identifier. */ 31 static char SCCSID[] = "@(#) Module: xtmSchedTool.c, Version: 1.1, Date: 95/02/18 15:52:46"; 32 33 34 /*---------------------------------------------------------------------------- 35 -- Include files 36 ----------------------------------------------------------------------------*/ 37 38 #include <math.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 43 #include <X11/Intrinsic.h> 44 #include <X11/StringDefs.h> 45 #include <X11/cursorfont.h> 46 47 #include <Xm/Xm.h> 48 49 #include "Message.h" 50 #include "System.h" 51 #include "TimDate.h" 52 53 #include "msgXdiary.h" 54 #include "xtmGlobal.h" 55 56 #include "xtmSchedPriv.h" 57 #include "xtmSchedTool.h" 58 59 #include "xitTools.h" 60 #include "xtmFormat.h" 61 62 /*---------------------------------------------------------------------------- 63 -- Macro definitions 64 ----------------------------------------------------------------------------*/ 65 66 67 /*---------------------------------------------------------------------------- 68 -- Type declarations 69 ----------------------------------------------------------------------------*/ 70 71 72 /*---------------------------------------------------------------------------- 73 -- Global definitions 74 ----------------------------------------------------------------------------*/ 75 76 /* Name of module. */ 77 static char *module_name = "xtmSchedTools"; 78 79 80 /*---------------------------------------------------------------------------- 81 -- Function prototypes 82 ----------------------------------------------------------------------------*/ 83 84 85 86 /*---------------------------------------------------------------------------- 87 -- Functions 88 ----------------------------------------------------------------------------*/ 89 90 void xtmStClearEntryTime(SCHED_REC_REF sched_ref)91 xtmStClearEntryTime( SCHED_REC_REF sched_ref ) 92 { 93 94 /* Variables. */ 95 Widget mainW; 96 Widget tempW; 97 98 99 /* Code. */ 100 101 mainW = XtNameToWidget( sched_ref -> scheduleW, "SchedTlBase.SchedTlFo" ); 102 103 tempW = XtNameToWidget( mainW, "SchedPa.Pane2Fo.TrackLa" ); 104 xitStringSetLabel( tempW, " " ); 105 106 { 107 Arg args[ 10 ]; 108 Cardinal n; 109 Pixmap use_pixmap; 110 111 tempW = XtNameToWidget( mainW, "SchedPa.Pane2Fo.TrackPx" ); 112 113 use_pixmap = sched_ref -> tick_pixmap[ 0 ]; 114 115 n = 0; 116 XtSetArg( args[ n ], XmNlabelPixmap, use_pixmap ); n++; 117 XtSetValues( tempW, args, n ); 118 119 sched_ref -> tick_pixmap_index = 0; 120 } 121 122 123 return; 124 125 } /* xtmStClearEntryTime */ 126 127 128 /*----------------------------------------------------------------------*/ 129 130 ENTRY_INFO xtmStFetchSelectedInfo(SCHED_REC_REF sched_ref)131 *xtmStFetchSelectedInfo( SCHED_REC_REF sched_ref ) 132 { 133 134 /* Variables. */ 135 Arg args[ 10 ]; 136 Cardinal n; 137 ENTRY_INFO *entry_info_ref; 138 139 140 /* Code. */ 141 142 if( sched_ref -> selected_widget == NULL ) 143 return( NULL ); 144 145 /* Selected entry. */ 146 n = 0; 147 XtSetArg( args[ n ], XmNuserData, &entry_info_ref ); n++; 148 XtGetValues( sched_ref -> selected_widget, args, n ); 149 150 if( entry_info_ref == NULL ) 151 return( NULL ); 152 153 154 return( entry_info_ref ); 155 156 } /* xtmStFetchSelectedInfo */ 157 158 159 /*----------------------------------------------------------------------*/ 160 161 Dimension xtmStHeightEntry(SCHED_REC_REF sched_ref,int duration)162 xtmStHeightEntry( SCHED_REC_REF sched_ref, 163 int duration ) 164 { 165 166 /* Variables. */ 167 float pixel_per_min; 168 Dimension dimension; 169 170 171 /* Code. */ 172 173 pixel_per_min = (2.0 * sched_ref -> time_line_height) / 174 sched_ref -> entry_delta; 175 176 dimension = (Dimension) ( duration * pixel_per_min + 0.1 ); 177 if( dimension < 5 ) 178 dimension = 5; 179 180 181 return( dimension ); 182 183 } /* xtmStHeightEntry */ 184 185 186 /*----------------------------------------------------------------------*/ 187 188 Boolean xtmStPickDate(SCHED_REC_REF sched_ref,XTM_ST_PICK_WHAT pick_what,TIM_TIME_REF * picked_date)189 xtmStPickDate( SCHED_REC_REF sched_ref, 190 XTM_ST_PICK_WHAT pick_what, 191 TIM_TIME_REF *picked_date ) 192 { 193 194 /* Variables. */ 195 int dummy; 196 char *msg_ref; 197 Cursor cursor; 198 Widget eventW; 199 Widget mainW; 200 Widget tempW; 201 Widget wrapW = NULL; 202 Window confine_to_win = None; 203 XEvent event; 204 XtAppContext context; 205 206 207 /* Code. */ 208 209 mainW = XtNameToWidget( sched_ref -> scheduleW, "SchedTlBase.SchedTlFo" ); 210 211 msg_ref = msgGetText( MXDI_PICK_A_DAY_LABEL ); 212 213 eventW = XtNameToWidget( mainW, "SchedPa.Pane2Fo.EntrySw" ); 214 eventW = XtNameToWidget( eventW, "ClipWindow.EntryBb" ); 215 216 switch( pick_what ) { 217 case XTM_ST_PICK_NOTE: 218 wrapW = XtNameToWidget( mainW, "SchedPa.Pane1Fo.NoteSw" ); 219 wrapW = XtNameToWidget( wrapW, "ClipWindow.NoteBb" ); 220 break; 221 222 case XTM_ST_PICK_APP: 223 default: 224 wrapW = eventW; 225 break; 226 }; 227 228 context = XtWidgetToApplicationContext( eventW ); 229 230 231 /* Tell the user what we are up to. */ 232 tempW = XtNameToWidget( mainW, "SchedPa.Pane2Fo.TrackLa" ); 233 xitStringSetLabel( tempW, msg_ref ); 234 235 236 /* We should have a nice cursor. */ 237 cursor = XCreateFontCursor( XtDisplay( eventW ), XC_draped_box ); 238 239 /* Grab the pointer to get all events we want. */ 240 if( ! sched_ref -> appl_data_ref -> custom_data -> wrap_bug ) 241 confine_to_win = XtWindow( wrapW ); 242 243 XGrabPointer( XtDisplay( eventW ), XtWindow( eventW ), 244 False, 245 (ButtonPressMask | ButtonMotionMask | ButtonReleaseMask), 246 GrabModeAsync, GrabModeAsync, 247 confine_to_win, cursor, CurrentTime ); 248 249 250 /* This is our local event handler. */ 251 do { 252 253 XtAppNextEvent( context, &event ); 254 255 /* Exit on button press. */ 256 if( event.xany.type == ButtonRelease ) 257 break; 258 259 /* Do not report any button events. */ 260 if( event.xany.type != ButtonPress ) 261 XtDispatchEvent( &event ); 262 263 } while( True ); 264 265 266 /* Clean up. */ 267 XUngrabPointer( XtDisplay( eventW ), CurrentTime ); 268 xtmStClearEntryTime( sched_ref ); 269 270 271 /* Button 1 is the select button, anything else is abort. */ 272 if( event.xbutton.button != 1 ) 273 return( False ); 274 275 276 /* Convert the position to a date. */ 277 xtmStPosXToDate( sched_ref, (int) event.xbutton.x, picked_date, &dummy ); 278 279 280 return( True ); 281 282 } /* xtmStPickDate */ 283 284 285 /*----------------------------------------------------------------------*/ 286 287 Position xtmStPositionEntryX(SCHED_REC_REF sched_ref,int day_index)288 xtmStPositionEntryX( SCHED_REC_REF sched_ref, 289 int day_index ) 290 { 291 292 /* Variables. */ 293 Position position; 294 295 296 /* Code. */ 297 298 position = (Position) (day_index * sched_ref -> day_width + 6); 299 300 301 return( position ); 302 303 } /* xtmStPositionEntryX */ 304 305 306 /*----------------------------------------------------------------------*/ 307 308 Position xtmStPositionEntryY(SCHED_REC_REF sched_ref,TIM_TIME_REF entry_start)309 xtmStPositionEntryY( SCHED_REC_REF sched_ref, 310 TIM_TIME_REF entry_start ) 311 { 312 313 /* Variables. */ 314 float pixel_per_min; 315 Position position; 316 TIM_DELTA_TYPE delta; 317 318 319 /* Code. */ 320 321 pixel_per_min = (2.0 * sched_ref -> time_line_height) / 322 sched_ref -> entry_delta; 323 324 (void) TimDelta( entry_start, sched_ref -> entry_start, &delta ); 325 326 position = (Position) (delta.minutes * pixel_per_min + 327 sched_ref -> time_line_height / 2) + 4; 328 329 330 return( position ); 331 332 } /* xtmStPositionEntryY */ 333 334 335 /*----------------------------------------------------------------------*/ 336 337 Position xtmStPositionNoteX(SCHED_REC_REF sched_ref,int day_index)338 xtmStPositionNoteX( SCHED_REC_REF sched_ref, 339 int day_index ) 340 { 341 342 /* Variables. */ 343 Position position; 344 345 346 /* Code. */ 347 348 position = (Position) (day_index * sched_ref -> day_width + 6); 349 350 351 return( position ); 352 353 } /* xtmStPositionNoteX */ 354 355 356 /*----------------------------------------------------------------------*/ 357 358 void xtmStPosXToDate(SCHED_REC_REF sched_ref,int pos_x,TIM_TIME_REF * new_start_date,int * new_pos_x)359 xtmStPosXToDate( SCHED_REC_REF sched_ref, 360 int pos_x, 361 TIM_TIME_REF *new_start_date, 362 int *new_pos_x ) 363 { 364 365 /* Variables. */ 366 int day_number; 367 368 369 /* Code. */ 370 371 *new_start_date = sched_ref -> schedule_start; 372 day_number = pos_x / (int) sched_ref -> day_width; 373 374 TimAddDays( new_start_date, day_number ); 375 *new_pos_x = day_number * sched_ref -> day_width + 6; 376 377 378 return; 379 380 } /* xtmStPosXToDate */ 381 382 383 /*----------------------------------------------------------------------*/ 384 385 void xtmStPosYToDuration(SCHED_REC_REF sched_ref,int pos_y_start,int pos_y_end,float grid_minutes,int * minutes,int * new_pos_y_end)386 xtmStPosYToDuration( SCHED_REC_REF sched_ref, 387 int pos_y_start, 388 int pos_y_end, 389 float grid_minutes, 390 int *minutes, 391 int *new_pos_y_end ) 392 { 393 394 /* Variables. */ 395 int delta_y; 396 float pixel_per_min; 397 398 399 /* Code. */ 400 401 pixel_per_min = (2.0 * sched_ref -> time_line_height) / 402 sched_ref -> entry_delta; 403 404 delta_y = abs( pos_y_end - pos_y_start + 1 ); 405 406 *minutes = (int) (delta_y / pixel_per_min); 407 *minutes = (int) ((int) (*minutes / grid_minutes) * grid_minutes ); 408 *new_pos_y_end = (int) (pixel_per_min * *minutes); 409 410 411 return; 412 413 } /* xtmStPosYToDuration */ 414 415 416 /*----------------------------------------------------------------------*/ 417 418 void xtmStPosYToTime(SCHED_REC_REF sched_ref,int pos_y,float grid_minutes,TIM_TIME_REF * new_start_time,int * new_pos_y)419 xtmStPosYToTime( SCHED_REC_REF sched_ref, 420 int pos_y, 421 float grid_minutes, 422 TIM_TIME_REF *new_start_time, 423 int *new_pos_y ) 424 { 425 426 /* Variables. */ 427 int minutes; 428 int offset; 429 float pixel_per_min; 430 431 432 /* Code. */ 433 434 *new_start_time = sched_ref -> entry_start; 435 offset = sched_ref -> time_line_height / 2 + 4; 436 437 pixel_per_min = (2.0 * sched_ref -> time_line_height) / 438 sched_ref -> entry_delta; 439 440 pos_y = pos_y - offset; 441 442 minutes = (int) (pos_y / pixel_per_min); 443 minutes = (int) ((int) (minutes / grid_minutes) * grid_minutes ); 444 445 TimAddMinutes( new_start_time, minutes ); 446 *new_pos_y = (int) (pixel_per_min * minutes) + offset; 447 448 449 return; 450 451 } /* xtmStPosYToTime */ 452 453 454 /*----------------------------------------------------------------------*/ 455 456 void xtmStPresentEntryTime(SCHED_REC_REF sched_ref,Boolean only_start_time,Boolean display_pixmap,XTM_ST_ANI_DIRECTION ani_direction,TIM_TIME_REF start_time,int duration)457 xtmStPresentEntryTime( SCHED_REC_REF sched_ref, 458 Boolean only_start_time, 459 Boolean display_pixmap, 460 XTM_ST_ANI_DIRECTION ani_direction, 461 TIM_TIME_REF start_time, 462 int duration ) 463 { 464 465 /* Variables. */ 466 char buffer[ 50 ]; 467 char time_buffer[ 50 ]; 468 Widget mainW; 469 Widget tempW; 470 TIM_TIME_REF temp_time; 471 XTM_GL_CUSTOM_DATA_REF custom_data_ref; 472 473 474 /* Code. */ 475 476 custom_data_ref = sched_ref -> appl_data_ref -> custom_data; 477 478 mainW = XtNameToWidget( sched_ref -> scheduleW, "SchedTlBase.SchedTlFo" ); 479 480 481 /* We always display the start time. */ 482 xtmFoFormatTime( start_time, buffer, sizeof( buffer ) ); 483 484 strcpy( time_buffer, " " ); 485 strcat( time_buffer, buffer ); 486 487 488 /* Include the end time? */ 489 if( ! only_start_time && duration > 0 ) { 490 491 temp_time = start_time; 492 TimAddMinutes( &temp_time, duration ); 493 494 xtmFoFormatTime( temp_time, buffer, sizeof( buffer ) ); 495 496 strcat( time_buffer, " - " ); 497 strcat( time_buffer, buffer ); 498 499 sprintf( buffer, "%d:%02d", duration / 60, duration % 60 ); 500 501 strcat( time_buffer, " (" ); 502 strcat( time_buffer, buffer ); 503 strcat( time_buffer, ")" ); 504 505 } /* if */ 506 507 508 tempW = XtNameToWidget( mainW, "SchedPa.Pane2Fo.TrackLa" ); 509 xitStringSetLabel( tempW, time_buffer ); 510 511 /* Time pixmap. */ 512 if( display_pixmap ) { 513 514 Arg args[ 10 ]; 515 Cardinal n; 516 Pixmap use_pixmap; 517 518 if( sched_ref -> tick_pixmap_index < 1 ) 519 sched_ref -> tick_pixmap_index = 1; 520 521 /* Move in what direction? */ 522 if( ani_direction == XTM_ST_ANI_FORWARD ) 523 sched_ref -> tick_pixmap_index++; 524 else if( ani_direction == XTM_ST_ANI_BACKWARD ) 525 sched_ref -> tick_pixmap_index--; 526 527 if( sched_ref -> tick_pixmap_index >= 7 ) 528 sched_ref -> tick_pixmap_index = 1; 529 else if( sched_ref -> tick_pixmap_index < 1 ) 530 sched_ref -> tick_pixmap_index = 6; 531 532 tempW = XtNameToWidget( mainW, "SchedPa.Pane2Fo.TrackPx" ); 533 534 use_pixmap = sched_ref -> tick_pixmap[ sched_ref -> tick_pixmap_index ]; 535 536 n = 0; 537 XtSetArg( args[ n ], XmNlabelPixmap, use_pixmap ); n++; 538 XtSetValues( tempW, args, n ); 539 540 } /* if */ 541 542 543 return; 544 545 } /* xtmStPresentEntryTime */ 546 547 548 /*----------------------------------------------------------------------*/ 549 550 void xtmStStartOnDay(SCHED_REC_REF sched_ref,TIM_TIME_REF * start_time)551 xtmStStartOnDay( SCHED_REC_REF sched_ref, 552 TIM_TIME_REF *start_time ) 553 { 554 555 /* Code. */ 556 557 /* Start the day view on a specific day? */ 558 if( sched_ref -> appl_data_ref -> custom_data -> start_day_view_on == 0 ) 559 return; 560 561 while( True ) { 562 if( TimIndexOfDayInIsoWeek( *start_time ) == 563 sched_ref -> appl_data_ref -> custom_data -> start_day_view_on ) 564 break; 565 566 TimAddDays( start_time, -1 ); 567 } 568 569 570 return; 571 572 } /* xtmStStartOnDay */ 573 574 575 /*----------------------------------------------------------------------*/ 576 577 void xtmStUpdateMinuteMarker(SCHED_REC_REF sched_ref)578 xtmStUpdateMinuteMarker( SCHED_REC_REF sched_ref ) 579 { 580 581 /* Variables. */ 582 Arg args[ 10 ]; 583 Cardinal n; 584 Dimension height; 585 Position position; 586 Widget mainW; 587 Widget tempW; 588 TIM_TIME_REF now; 589 590 591 /* Code. */ 592 now = TimLocalTime( TimMakeTimeNow() ); 593 now = TimMakeTime( 1970, 1, 1, TimHour( now ), TimMinute( now ), 0 ); 594 595 mainW = XtNameToWidget( sched_ref -> scheduleW, "SchedTlBase.SchedTlFo" ); 596 597 tempW = XtNameToWidget( mainW, "SchedPa.Pane2Fo.TimeDispSw" ); 598 tempW = XtNameToWidget( tempW, "ClipWindow" ); 599 600 tempW = XtNameToWidget( tempW, "TimeDispBb.TimeIndicatorAr" ); 601 602 if( flagIsClear( sched_ref -> flags, XTM_SM_LIST_LAYOUT ) && 603 now > sched_ref -> entry_start && 604 now < sched_ref -> entry_stop ) { 605 606 n = 0; 607 XtSetArg( args[ n ], XmNheight, &height ); n++; 608 XtGetValues( tempW, args, n ); 609 610 position = xtmStPositionEntryY( sched_ref, now ); 611 position = position - (height / 2); 612 613 n = 0; 614 XtSetArg( args[ n ], XmNy, position ); n++; 615 XtSetArg( args[ n ], XmNx, 0 ); n++; 616 XtSetValues( tempW, args, n ); 617 618 XtManageChild( tempW ); 619 XRaiseWindow( XtDisplay( tempW ), XtWindow( tempW ) ); 620 621 } else { 622 623 XtUnmanageChild( tempW ); 624 625 } /* if */ 626 627 628 return; 629 630 } /* xtmStUpdateMinuteMarker */ 631 632 633 /*----------------------------------------------------------------------*/ 634 635 Dimension xtmStWidthEntry(SCHED_REC_REF sched_ref)636 xtmStWidthEntry( SCHED_REC_REF sched_ref ) 637 { 638 639 /* Variables. */ 640 Dimension dimension; 641 642 643 /* Code. */ 644 645 if( flagIsClear( sched_ref -> flags, XTM_SM_LIST_LAYOUT ) && 646 flagIsSet( sched_ref -> flags, XTM_SM_ENTRY_HANDLES ) ) 647 dimension = (Dimension) (sched_ref -> day_width - 30); 648 else 649 dimension = (Dimension) (sched_ref -> day_width - 10); 650 651 if( dimension < 5 ) 652 dimension = 5; 653 654 655 return( dimension ); 656 657 } /* xtmStWidthEntry */ 658 659 660 /*----------------------------------------------------------------------*/ 661 662 Dimension xtmStWidthNote(SCHED_REC_REF sched_ref)663 xtmStWidthNote( SCHED_REC_REF sched_ref ) 664 { 665 666 /* Variables. */ 667 Dimension dimension; 668 669 670 /* Code. */ 671 672 dimension = (Dimension) (sched_ref -> day_width - 10); 673 674 if( dimension < 5 ) 675 dimension = 5; 676 677 678 return( dimension ); 679 680 } /* xtmStWidthNote */ 681 682 683