================================GETDATE.TXT====================================
Files contained:
GETDATE.TXT   - This file; describes the GETDATE.SC script and procedure it 
                 contains
GETDATE.SC    - Source code for dGetDate and related procs
FIG1.GIF      - GIF file containing screen print of the d-box produced by 
                GETDATE.SC.

All files and source code were developed by Professional Information
Consulting, Inc. (PIC) and are copyrighted.  PIC grants you the right to use
the provided procedures, free of charge, in your own applications as long as
the copyright accompanys them and proper credit is given to the author.

PIC can be contacted at:

  PIC
  3605 Long Beach Blvd.
  Suite 320
  Long Beach, CA  90807
  p (310) 490-2092
  f (310) 490-2094
  C.I.S.  72077,1421
  MCI 474-5422 (Professional Information Consulting)

Enjoy!


Introduction
------------
I don't think I have ever written a PAL application in which I didn't have to
prompt the user to specify a date at some point.  There are hundreds of
situations in which the user needs to select a date or range of dates, for
example

- To specify a range of dates to be covered in a report
- To indicate when a particular event took place (e.g., an 
  inventory arrival)
- To select a particular set of personnel records in an 
  inquiry

In many cases, all the user really requires is the ability to directly enter
the date with an 'accept line' (and indeed some users may always prefer this
method of selecting na date).  However, there are situations in which it would
be nice to be able to select the date visually from a calendar.  It would also
be nice if you could scroll through months or years on the calendar.  For
example, if you have to select a date based on its day of the week (Sunday,
Monday, Tuesday, etc.) a calendar would come in very handy indeed.

Well, with Paradox 4.0's powerful dialog box (d-box) capabilities and a bit of
elbow grease, all of this functionality can be easily provided (well, almost
easily).

How does it work?
-----------------
Well, it probably works exactly as you would expect.  You call the procedure
dGetDate() with a default date.  It displays the d-box using the
"month-at-a-glance" calendar with the default date selected.  You can click
the mouse on a different day and use the "mouse buttons" (just below the
calendar display) to change the month and year.  In addition, there is a
keyboard interface:

  Key		Action
  ------------------------------------
  Left        previous day
  Right       next day
  Up	         previous week
  Down        next week
  PgUp        same day, previous month
  PgDn        same day, next month
  Ctrl+PgUp   same day, previous year
  Ctrl+PgDn   same day, next year
  Enter       Ok
  Esc         Cancel

You can also select the "accept" control and directly enter the date--the
calendar display will be updated as soon as you leave the accept control!
When you click on Ok (or hit [Enter]), dGetDate() returns the currently
selected date.  If you hit Cancel or [Esc] then it returns a blank date value.

Below is a brief discussion of the procedures used and the functions they
perform.  The source code is thoroughly commented, too.

dGetDate()
----------
This procedure displays the d-box, accepting a default date and returning the
selected date or a blank date depending on whether the user selected Ok or
Cancel to quit.  The calendar display is simply a formatted text string
produced in NewMonth().  Because the text string is formatted so that can be
divided into lines that are the same length, it can be painted over a
rectangular area with one paintcanvas command.

SetUpCal()
----------
This procedure is called by dGetDate() to initialize a number of variables
throughout the procedures.  It calls NewMonth() and NewDay() to build the
calendar and position the cursor, respectively.

dbpGetDate()
------------
This is the "dialog box procedure" for dGetDate().  Like all d-box procs, it
is called when any of the events specified in the d-box spec occur.  It
controls all processing of mouse clicks and keystrokes.  The calendar is
essentially a variable painted on the d-box.  In order to process mouse clicks
on the calendar, this proc uses the localize event command to localize the
mouse click coordinates relative to the d-box window.  It also synchronizes
the calendar when the user directly enters a date in the accept control.
Finally, it calls the other procedures to act upon user- generated events
(primarily, IncreaseDate() and DecreaseDate()).

IncreaseDate()
--------------
This procedure is used to increment the current date by the time period
specified in its single parameter, aPeriod.  aPeriod will be set to either
DAY, WEEK, MONTH or YEAR.  The processing for DAY and WEEK increments is very
simple.  The functionality desired for MONTH and YEAR was to attempt to move
the cursor to the same numeric day (e.g., the 30th) of the month in the new
month or year.  This gets sticky when the new month doesn't have a 30th day
(e.g., February)!

DecreaseDate()
--------------
This proc is almost identical to IncreaseDate(), but it works in the opposite
direction.

NewMonth()
----------
This very important procedure initializes the variables used to display the
calendar for the date passed to it as a parameter.  The calendar is just a
formatted text string.  It is broken down and formatted into a dynamic array
in order for NewDay() to determine in which row and column the cursor is to be
placed.

NewDay()
--------
This procedure is called to determine the cursor coordinates for the new date,
passed as a parameter.  It will be called when ever the day, month or year is
changed.

How to call dGetDate()
----------------------
The source code provides an example of a typical method for calling dGetDate.
Here are some other interesting examples of how you can call the dGetDate()
procedure.

From a d-box.  One clever trick is to call a procedure that returns a value in
a pushbutton's value clause.  Because there are no longer restrictions on how
you call procedures (from a "swapping consideration" perspective), you can
replace the value clause in a pushbutton with a procedure call.  When the user
clicks on the button, the procedure is called.  The value returned from the
procedure is used as the value stored in the pushbutton's control variable.
For example, if you were using the pushbutton spec below in a showdialog
command:

...
pushbutton @ 13,2 width 13              ;Declare pushbutton
   "Get Date"
   value dGetDate(dDfltDate)            ;This results in a call to dGetDate()
   tag "DATEBTN"
   to dDateButton
...

When the user pushes the button labeled "Get Date", the proc dGetDate() would
be called, and the value it returned would be stored in the dDateButton
variable.

In a data entry session.  You may want to provide a pulldown or popup menu
option that calls dGetDate().  You could also set up a 'hot-key' for the
menu's "until key" clause, or a hot key that could be processed by your wait
clause's key list.  Another idea would be to set up a trigger that called the
dGetDate().  For example, you may want to prompt the user for the date
whenever s/he moves the cursor into a new, blank row.  This could be done by
checking the recordstatus() function whenever an ARRIVEROW trigger gets fired
off.

While using dGetDate() to obtain a date from a user is not appropriate in all
situations, I imagine you'll find many examples where it is useful.  Best of
luck!

--Leon Chalnick
