201 lines
6.8 KiB
C
201 lines
6.8 KiB
C
|
/*
|
||
|
* Windows Calendar
|
||
|
* Copyright (c) 1985 by Microsoft Corporation, all rights reserved.
|
||
|
* Written by Mark L. Chamberlin, consultant to Microsoft.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
*****
|
||
|
***** calspecl.c
|
||
|
*****
|
||
|
*/
|
||
|
|
||
|
#include "cal.h"
|
||
|
|
||
|
/* Notes about special times - 9/13/85 - MLC:
|
||
|
|
||
|
I want to explain some things about special times because the design
|
||
|
is not as clean as it should be and can lead to some confusion.
|
||
|
As I originally planned it, a special time was defined to be an
|
||
|
appointment time that had been inserted with the Options Special Time
|
||
|
Insert command. An appointment time inserted this way had the fSpecial
|
||
|
bit set in its associated QR. This is still the case, but from the
|
||
|
user's point of view the definition of a special time is different.
|
||
|
The problem was that user confusion could result from the original
|
||
|
definition. For example, suppose that with the interval set to 15
|
||
|
minutes, the user types text into a 9:15 appointment. At some
|
||
|
point he switches the interval to 60 minutes. The 9:15 appointment
|
||
|
is still present because it has data associated with it, and given
|
||
|
the 60 minute interval, it sure looks like a special time to the
|
||
|
user (particularly if he is looking at it days later and doesn't
|
||
|
remember that it was inserted when he had the interval set to 15
|
||
|
minutes). He tries to deleted it with the Options Special Time
|
||
|
Delete command, but since its fSpecial bit is not set, he is
|
||
|
told that it is not a special time, which totally confuses him,
|
||
|
and he sues Tandy Trower. The only way to get rid of the 9:15
|
||
|
appointment is to make it "empty" (no text, no alarm).
|
||
|
So to avoid user confusion I ended up saying that for purposes
|
||
|
of the Options Special Time Delete command, a special time is
|
||
|
any time that does not fall on a regular interval given the
|
||
|
current interval setting.
|
||
|
The fSpecial bit now serves only one semi-rediculous purpose:
|
||
|
With the interval set to 60, the user inserts the special time
|
||
|
of 10:30. He types no text into that time, and there is no
|
||
|
alarm set. He switches to 30 minute interval, and then back
|
||
|
to 60 minute interval. Were it not for the fSpecial bit, the
|
||
|
appointment would have disappeared because in 30 minute mode
|
||
|
it would not look like a special time. But the fSpecial bit
|
||
|
keeps the appointment from going away.
|
||
|
I now consider the whole business of the fSpecial
|
||
|
bit to be unnecessary baggage, and I am tempted to get rid of it.
|
||
|
I am short on time, and it's not really worth making such a change
|
||
|
at this late stage, so I won't, but if I had it to do
|
||
|
over, I would not have the fSpecial bit.
|
||
|
My apologies in advance to anyone who has to work on special times -
|
||
|
I hope this explanation helps.
|
||
|
*/
|
||
|
|
||
|
|
||
|
/**** InsertSpecial - insert a special time. */
|
||
|
|
||
|
VOID APIENTRY InsertSpecial ()
|
||
|
|
||
|
{
|
||
|
|
||
|
QR qrNew;
|
||
|
|
||
|
/* Record the current edits and prevent them from later using an
|
||
|
invalid tld (which we are about to invalidate by fooling around
|
||
|
with the tqr).
|
||
|
*/
|
||
|
CalSetFocus ((HWND)NULL);
|
||
|
|
||
|
/* Insert a new QR for the special time with the special time bit set.
|
||
|
The special time bit prevents keeps the QR in the tqr even though
|
||
|
it has no appointment text and the alarm is not set.
|
||
|
Note that FSearchTqr was called by the Special Time dialog so
|
||
|
votqrNext is already set up.
|
||
|
*/
|
||
|
qrNew.cb = CBQRHEAD + 1;
|
||
|
qrNew.fAlarm = FALSE;
|
||
|
qrNew.fSpecial = TRUE;
|
||
|
qrNew.tm = vtmSpecial;
|
||
|
qrNew.qd [0] = '\0';
|
||
|
|
||
|
if (FInsertQr (votqrNext, &qrNew))
|
||
|
{
|
||
|
/* Adjust up the scroll bar range. */
|
||
|
AdjustDayScrollRange (1);
|
||
|
|
||
|
/* Fix up the display. */
|
||
|
SpecialTimeFin ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** DeleteSpecial - delete a special time. */
|
||
|
|
||
|
VOID APIENTRY DeleteSpecial ()
|
||
|
|
||
|
{
|
||
|
|
||
|
register BOOL fAlarm;
|
||
|
register DR *pdr;
|
||
|
INT itdd;
|
||
|
FT ftTemp;
|
||
|
|
||
|
/* Note that FSearchTqr was
|
||
|
called by the special time dialog code, and the result was
|
||
|
TRUE. Therefore, votqrCur has been set up.
|
||
|
*/
|
||
|
|
||
|
/* Record the current edits and prevent them from later using an
|
||
|
invalid tld (which we are about to invalidate by fooling around
|
||
|
with the tqr).
|
||
|
*/
|
||
|
CalSetFocus ((HWND)NULL);
|
||
|
|
||
|
/* Before deleting the QR, see if it had an alarm. */
|
||
|
fAlarm = ((PQR )(PbTqrFromPdr (pdr = PdrLockCur ()) + votqrCur))
|
||
|
-> fAlarm;
|
||
|
ftTemp.dt = pdr -> dt;
|
||
|
DrUnlockCur ();
|
||
|
|
||
|
/* Delete the QR for the special time. */
|
||
|
DeleteQr (votqrCur);
|
||
|
|
||
|
if (fAlarm)
|
||
|
{
|
||
|
/* There is an alarm for the special time we're deleting.
|
||
|
Decrement the count of alarms for this date.
|
||
|
*/
|
||
|
FSearchTdd (ftTemp.dt, &itdd);
|
||
|
(TddLock () + itdd) -> cAlarms--;
|
||
|
TddUnlock ();
|
||
|
|
||
|
ftTemp.tm = vtmSpecial;
|
||
|
if (CompareFt (&ftTemp, &vftAlarmNext) == 0)
|
||
|
{
|
||
|
/* Cancelling the next armed alarm. Need to arm the one
|
||
|
after it. Since the one we are cancelling has not yet
|
||
|
gone off, it can't be time for the one after it to
|
||
|
go off either, so there is no need to call AlarmCheck -
|
||
|
just let it go off naturally.
|
||
|
Note this be done AFTER the QR has been deleted and
|
||
|
the count has been decremented so
|
||
|
GetNextAlarm doesn't find the same alarm again.
|
||
|
*/
|
||
|
GetNextAlarm (&vftCur, &vftCur, TRUE, (HWND)NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Adjust down the range of the scroll bar. */
|
||
|
AdjustDayScrollRange (-1);
|
||
|
|
||
|
/* Fix up the display. */
|
||
|
SpecialTimeFin ();
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** SpecialTimeFin */
|
||
|
|
||
|
VOID APIENTRY SpecialTimeFin ()
|
||
|
|
||
|
{
|
||
|
|
||
|
register INT ln;
|
||
|
|
||
|
/* Mark the DR and the file as dirty. */
|
||
|
PdrLockCur () -> fDirty = vfDirty = TRUE;
|
||
|
DrUnlockCur ();
|
||
|
|
||
|
/* Fill the tld, using the special time as the starting time.
|
||
|
In the insert case, FillTld will use the new special time.
|
||
|
In the delete case, FillTld will use the first appointment
|
||
|
time greater than the special time that was just deleted.
|
||
|
*/
|
||
|
FillTld (vtmSpecial);
|
||
|
|
||
|
/* Find the ln of the new special time (insert) or of the appointment
|
||
|
time following the old special time (delete). It's not
|
||
|
necessarily on the top line since there may not have been
|
||
|
enough appointment times following it to fill up the screen.
|
||
|
*/
|
||
|
for (ln = 0; ln < vlnLast && vtld [ln].tm < vtmSpecial; ln++)
|
||
|
;
|
||
|
|
||
|
/* Give it the focus. (Need to set vhwndFocus before calling
|
||
|
SetQdEc because we want the focus to go to the appointment
|
||
|
even if it's currently in the notes area.
|
||
|
*/
|
||
|
vhwndFocus = vhwnd3;
|
||
|
SetQdEc (ln);
|
||
|
|
||
|
/* Set the thumb, and repaint the appointments. */
|
||
|
SetDayScrollPos (-1);
|
||
|
InvalidateRect (vhwnd2B, (LPRECT)NULL, TRUE);
|
||
|
|
||
|
}
|