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