                                  Calendars

                                    "A word fitly spoken is like apples
                                     of gold in pictures of silver"
                                                       Proverbs 25.11

Introduction

          The GOLDCAL unit contains Gold's calendaring support. With one
     simple call to RunCalendar, you can add calendars to your
     application. By default, Gold will display a single
     month-at-a-glance calendar (see figure 7-1). The fussy developers
     (e.g. Oregon inhabitants) can customize the calendar to meet their
     specific needs. For example, the calendar can be displayed within a
     larger window.

          If you are not familiar with Julian dates, you should consider
     reading the introduction to Chapter 19.


     Figure 7.1
     A Month-at-a-Glance
     Calendar


Activating a Calendar Window

          To display a (modal) calendar in a pop-up window use the
     RunCalendar command which is defined as follows:

     RunCalendar(StartDate:Dates;Tit:string):dates;

          Displays a month-at-a-glance calendar in a pop-up window. The
     first parameter is the Julian date of any day in the month which is
     to be displayed. The second argument is the window title. The
     function returns the day that was highlighted when the window was
     closed, or zero if the user presses Esc or clicks on the close
     icon.

          If you want to display a fully functional calendar but don't
     want to have a specific day highlighted, set the boolean variable
     CalVars.ChooseDay to false.


     Run the demo DEMCAL1.PAS to display a month-at-a-glance calendar.

Customizing the Calendar Icons and Keystrokes

          A user can easily change months and years by clicking on the 4
     navigation icons. You can change the appearance of the icons by
     modifying the following four character variables defined in
     CalVars:

          CalVars.NextMchar - icon to move to next month
          CalVars.PrevMchar - icon to move to previous month
          CalVars.NextYchar - icon to move to next year
          CalVars.PrevYchar - icon to move to previous year

          The corresponding keystrokes to change months and years are:
     PgDn and PgUp to change months, Ctrl-PgDn and Ctrl-PgUp to change
     years. These too can be customized by changing the following word
     variables defined in CalVars:

          CalVars.NextMkey
          CalVars.PrevMkey
          CalVars.NextYkey
          CalVars.PrevYkey


          International users can modify the two character day strings
     by editing the variable CalVars.DayLetters which is defined as
     follows:

          CalVars.DayLetters := 'SuMoTuWeThFrSa';

Controlling the Calendar Colors

          You can customize the calendar display colors by modifying the
     following elements of TINT using the function GoldSetColor:

          CalBorder
          CalTitle
          CalIcons
          CalActiveMonth
          CalEdgeMonth
          CalToday
          CalHiDay


          The following code is an extract from DEMCAL2.PAS which
     customizes the calendar colors:

          procedure CustomizeColors;
          {}
          begin
             GoldSetColor(CalBorder,WhiteOnMagenta);
             GoldSetColor(CalIcons,GreenOnMagenta);
             GoldSetColor(CalTitle,YellowOnMagenta);
             GoldSetColor(CalActiveMonth,YellowOnMagenta);
             GoldSetColor(CalEdgeMonth,LightgrayOnMagenta);
             GoldSetColor(CalToday,GreenOnMagenta);
             GoldSetColor(CalHiday,LightMagentaOnBlack);
          end; { CustomizeColors }

          The color used to display each day individually can be
     customized using a calendar hook. This very flexible technique is
     discussed later in the chapter.

Drawing a Plain Calendar

          One of the core routines used by the RunCalendar function is
     DrawMonth, which draws a plain calendar without the icons. If you
     want to draw a calendar for informational purposes, i.e. with no
     input support, you can use DrawMonth, which is defined as follows:

     DrawMonth(Mon,Yr:word;X1,Y1:byte;Active:boolean):Dates;

          The first two word parameters identify the month and year
     which is to be displayed. The next two byte parameters indicate the
     position of the top left of the calendar. The final parameter
     indicates whether the calendar should be drawn using the active
     months colors, or the edge month colors. The function returns the
     Julian date of the top left day in the seven by six day matrix.

     DrawMonth is used in the demo file DEMCAL7.PAS.

Customizing the Window Size

          By default, the window size is designed to be just large
     enough to accommodate the monthly calendar. The window size,
     however, can be made larger so that additional information may be
     written to the window; such as a daily event log or a To Do list.

          To change the window size, modify the following CalVars
     variables before calling RunCalendar: CalVars.WX1, CalVars.WY1,
     CalVars.WX2, CalVars.WY2. These four variables define the total
     dimensions of the calendar window. The position of the top left
     corner of the calendar relative to the window is defined in the
     following two variables: CalVars.CX1 and CalVars.CY1.

          Listed below is an extract from DEMCAL3.PAS which shows how
     the window size and position can be customized:

          with CALVars do
          begin
            WX1 := 10;
            WY1 := 5;
            WX2 := 70;
            WY2 := 20;
            CX1 := 36;
            CY1 := 1;
          end;
          MouseShow(true);
          Answer := RunCalendar(TodayInJul,'A Big Calendar');

Using Calendar Hooks

          The RunCalendar function is designed to be easy to use, but
     very flexible and customizable. The majority of the flexibility is
     implemented in calendar hooks. There are three main hooks: a
     character hook, a color hook and a change hook. If you are not
     familiar with the principle of hooks in Gold, refer to the section
     Understanding Hooks in Chapter 3.

          By using a combination of these hooks, you can create
     sophisticated calendaring applications.

The Character Hook

          A character hook is a procedure which is called every time a
     key is pressed or a mouse button is clicked. The hooked procedure
     is called before the key is processed, i.e. before the character is
     passed to RunCalendar for processing. The hook is particularly
     useful for trapping special keys like F1 for help or Alt-N to
     pop-up a set of notes.

          All you have to do is create a procedure following some
     specific rules, and then call the AssignCalCharHook procedure to
     instruct Gold to call your procedure every time a key is pressed.

          For a procedure to be eligible as a character hook it must
     adhere to the following rules:

          The procedure must be declared as a far procedure at the root
          level. Refer to the section Understanding Hooks in Chapter 3
          for further information.

          The procedure must be declared with one variable parameter of
          type word, and two variable parameters of type byte. These
          parameters identify the user input, i.e. the Key, X and Y.

     The following procedure declaration follows these rules:

          {$F+}
          procedure MyCalendarHook(var Code:word;var X,Y:byte);
          begin
             {some code}
          end; {MyCalendarHook}
          {$F-}

          The following procedure is then called to instruct Gold to
     call your procedure after each calendar input:

     AssignCalCharHook(Hook:KeyPressedHook);

          Instructs Gold to call the specified procedure before
     processing each user input to the calendar window.

          If subsequently, you want to remove the character hook,
     execute the command RemoveCalCharHook.

          Run the demo programs DEMCAL4.PAS and DEMCAL6.PAS to see the
     character hook in action.

The Color Hook

          The calendar color hook allows a program to customize the
     display color of each day display on the calendar. Using this
     feature an application might, for example, displays days with
     appointments in one color and vacation days in another color.

          All you have to do is create a procedure following some
     specific rules, and then call the AssignCalColorHook procedure to
     instruct Gold to call your procedure every time a day is about to
     be written to the window.

          For a procedure to be eligible as a color hook it must adhere
     to the following rules:

          The procedure must be declared as a far procedure at the root
          level. Refer to the section Understanding Hooks in Chapter 3
          for further information.

          The procedure must be declared with one parameter of type
          Dates, and one variable parameter of type byte. These
          parameters identify the Julian date of the day to be drawn,
          and the color which will be used to draw the day. The last
          parameter, TheCol, is passed to the procedure with the value
          that would be used if the hook were not in place.

     The following procedure declaration follows these rules:

          {$F+}
          procedure ChangeFriSatSun(TheDay:Dates; var TheCol:byte);
          {}
          var DOW: byte;
          begin
             if TheCol = Tint[CalActiveMonth] then
             begin
                DOW := DOWJul(TheDay);
                case DOW of
                   5: TheCol := LightGreenOnBlue;
                   0,6: TheCol := GreenOnBlue;
                end;
             end;
          end; { ChangeFriSatSun }
          {$F-}

          The following procedure is then called to instruct Gold to
     call your procedure after each calendar input:

     AssignCalColorHook(Hook:CalColorProc);

          Instructs Gold to call the specified procedure to determine
     the color used to draw the day numbers in the calendar grille.

          If subsequently, you want to remove the color hook, execute
     the command RemoveCalColorHook.

     Run the demo programs DEMCAL5.PAS to see the color hook in action.

The Change Hook

          The calendar change hook is designed for sophisticated
     applications which want to update other parts of the display when
     the user changes the active day or month on the calendar. For
     example, a change hook could be used to display a list of the
     selected day's appointments to the left of the calendar.

          All you have to do is create a procedure following some
     specific rules, and then call the AssignCalChangeHook procedure to
     instruct Gold to call your procedure every time a day is about to
     be written to the window.

          For a procedure to be eligible as a change hook it must adhere
     to the following rules:

          The procedure must be declared as a far procedure at the root
          level. Refer to the section Understanding Hooks in Chapter 3
          for further information.

          The procedure must be declared with one parameter of type
          gCalChange, and two parameters of type longint. The first
          parameter indicates the type of change that is about to occur.
          The other two parameters represent dates; the specific date is
          dependent upon the type of change.


     The following procedure declaration follows these rules:

          {$F+}
          procedure ChangeHook(CType:gCalChange;Val1,Val2:dates);
          {}
          begin
             if CType = ChangeDay then
             begin
                SelectedDay := Val2;
                ActivateBackground;
                WriteCenter(21,0,
                PadCenter(FancyDateStr(val2,true,true), 40,' '));
                ActivateTopWindow;
                WinDrawAll;
             end;
          end; { ChangeHook }
          {$F-}

          The following procedure is then called to instruct Gold to
     call your procedure after each calendar input:

     AssignCalChangeHook(Hook:CalChangeProc);

          Instructs Gold to call the specified procedure every time the
     active month or day is changed, and when the window is repainted.

          If subsequently, you want to remove the color hook, execute
     the command RemoveCalColorHook.

Understanding the Passed Parameters

          There are three different occasions when a change hook is
     called: when the calendar window is repainted, when the visible
     month is changed, and when the selected day is changed. The first
     parameter passed to the hook procedure indicates which hook event
     is occurring and is of type gCalChange.

     The enumerated type gCalChange is declared in GOLDCAL as follows:

          gCalChange = (Paint,ChangeDay,ChangeMonth);

          The meaning of the two Dates parameters is dependent upon the
     value of the first parameter as follows:

          Paint - The first date is the active month and the second date
     is the active year, e.g. 8 and 1995.

          ChangeDay - The first date is the old selected date and the
     second parameter is the date which is about to become selected.
     Both values represent the Julian date, e.g. 2449583 and 2449584.

          ChangeMonth - The first date is the active month and the
     second date is the active year, e.g. 7 and 1996.

          The majority of applications will only use the ChangeDay
     function, since this hook is called whenever the active day, month
     or year is changed. Respond to the paint hook when an application
     uses an enlarged window to write additional information (e.g. daily
     appointments) to the non-calendar parts of the window. The contents
     of the window should be refreshed when the paint message is
     received.

     Run the demo programs DEMCAL6.PAS to see the change hook in action.


Error Handling

          Since the calendar is displayed in a window, there is the
     potential for an Out of Memory error. After calling RunCalendar, be
     sure to call the function LastCalError to see if the calendar was
     successfully displayed.

