windows-nt/Source/XPSP1/NT/shell/osshell/accesory/calendar/calday2.c
2020-09-26 16:20:57 +08:00

247 lines
6.2 KiB
C

/*
* Windows Calendar
* Copyright (c) 1985 by Microsoft Corporation, all rights reserved.
* Written by Mark L. Chamberlin, consultant to Microsoft.
*
*/
/*
*****
***** calday2.c
*****
*/
#include "cal.h"
/**** SetDayScrollRange */
VOID APIENTRY SetDayScrollRange ()
{
/* Set the range so that the minimum thumb position corresponds to
having the first TM of the day at the top of the window and
the maximum thumb position corresponds to having the last TM
of the day at the bottom of the window. We want to always be
able to work from the first TM in the window, so we observe
that the last TM of the day is at the bottom of the window
when the last windowful (or page) of TMs is up, and this
is when the (ctmDay - vcln)th TM is at the top of the window.
For example, if there are 100 TMs (0 - 99), and we can display
10 TMs in the window (vcln == 10), we are maxed out when
90 through 99 are in the window.
Note that calling ItmFromTm with TMNILHIGH returns the count
of TMs in the day.
*/
SetScrollRange (vhwnd2B, SB_VERT, 0, ItmFromTm (TMNILHIGH) - vcln, FALSE);
}
/**** AdjustDayScrollRange - adjust the scroll bar range by the specified
number of TMs.
*/
VOID APIENTRY AdjustDayScrollRange (INT ctm)
{
INT itmMin;
INT itmMax;
GetScrollRange (vhwnd2B, SB_VERT, (LPINT)&itmMin, (LPINT)&itmMax);
SetScrollRange (vhwnd2B, SB_VERT, 0, itmMax + ctm, FALSE);
}
/**** SetDayScrollPos - position the thumb. */
VOID APIENTRY SetDayScrollPos (register INT itm)
{
/* If called with itm == -1, position the thumb based on the TM
at the top of the window.
*/
if (itm == -1)
itm = ItmFromTm (vtld [0].tm);
SetScrollPos (vhwnd2B, SB_VERT, itm, TRUE);
}
/**** AdjustDayScrollPos - adjust the position of the thumb relative
to its old position.
*/
VOID APIENTRY AdjustDayScrollPos (INT ctm)
/* Positive to increase thumb position (towards
bottom of window), negative to decrease thumb
(towards top of window).
*/
{
SetDayScrollPos (GetScrollPos (vhwnd2B, SB_VERT) + ctm);
}
/**** ItmFromTm - map a TM to an index within the range of TMs for the day.
If tmToMap does not exist within the day (not a regular time and
not in the tqr), we return the index of the next
highest TM. Therefore, to find out how many TMs there are in
the day, call ItmFromTm with tmToMap == TMNILHIGH. SetDayScrollRange
depends on this.
Note - tmToMap must be in the closed interval 0 through TMNILHIGH.
*/
INT APIENTRY ItmFromTm (TM tmToMap)
{
INT itm;
itm = -1;
MapTmAndItm (&tmToMap, &itm);
return (itm);
}
/**** TmFromItm - map TM to an index within the range of TMs for this date. */
TM APIENTRY TmFromItm (INT itm)
{
TM tm;
MapTmAndItm (&tm, &itm);
return (tm);
}
/**** MapTmAndItm - map TM to itm and vice versa.
To map a TM to an itm: *ptmMap == TM to map, *pitmMap == -1.
To map an itm to a TM:: *ptmMap == don't care, *pitmMap == itm to map.
*/
VOID APIENTRY MapTmAndItm (
TM *ptmMap,
INT *pitmMap)
{
register TM tmCur;
register TM tmFromQr;
TM tmMap;
DR *pdr;
PQR pqrCur;
PQR pqrMax;
INT itm;
BOOL fMapTmToItm;
tmMap = ((fMapTmToItm = *pitmMap) == -1) ? *ptmMap : TMNILHIGH;
/* Lock the DR, and get First and Max pointers for the tqr. */
pdr = PdrLockCur ();
pqrMax = (PQR)((BYTE*)(pqrCur = (PQR)PbTqrFromPdr(pdr)) + pdr->cbTqr);
/* Find the first QR time. */
tmFromQr = TmFromQr (&pqrCur, pqrMax);
/* Starting at the first possible TM of the day (0), keep going
until we find a TM greater than or equal to the one we're mapping.
*/
for (itm = (INT)(tmCur = 0); tmCur < tmMap && itm != *pitmMap; itm++)
{
if ((tmCur = TmNextRegular (tmCur)) >= tmFromQr)
{
/* The QR TM is less than or equal to the next
regular TM, so use the one from the QR in order to
skip over it.
Note - At this point, both tmCur and tmFromQr could
be TMNILHIGH (because there aren't anymore QRs
and there are no more regular times. This works OK
since we end up using TMNILHIGH which will terminate
terminate the loop since TMNILHIGH is the highest value
the caller is permitted to pass. Calling TmFromQr
with pqrCur == pqrMax works OK too, so no problem there.
*/
if ((tmFromQr = TmFromQr (&pqrCur, pqrMax)) < tmCur)
tmCur = tmFromQr;
}
}
DrUnlockCur ();
/* Pass back the mapped value to the caller. */
if (fMapTmToItm)
*pitmMap = itm;
else
*ptmMap = tmCur;
}
/**** TmFromQr - return TM of the current QR or TMNILHIGH if there
isn't one. Also update pqrCur to point past the last QR we inspect.
Note - Guaranteed to do the right thing if called with
pqrCur == pqrMax. In this case we return TMNILHIGH and pqrCur
is unchanged.
*/
TM APIENTRY TmFromQr (
PQR *ppqrCur, /* Input - pqrCur points to the current QR.
Output - pqrCur points to the next QR or
is equal to pqrMax if no next QR.
*/
PQR pqrMax)
{
register PQR pqr;
register TM tm;
/* Assume there are no more QRs. */
tm = TMNILHIGH;
if ((pqr = *ppqrCur) < pqrMax)
{
tm = pqr -> tm;
*ppqrCur = (PQR)((BYTE*)pqr + pqr->cb);
}
return (tm);
}
/**** TmNextRegular - return the next regular TM or TMNILHIGH if there
is no next regular TM.
*/
TM APIENTRY TmNextRegular (register TM tm)
{
register TM tmNext;
/* Calculate the next regular appointment time. */
tmNext = tm + vcMinInterval - (tm % vcMinInterval);
/* Return TMNILHIGH if beyond the end of the day. */
if (tmNext > TMLAST)
tmNext = TMNILHIGH;
return (tmNext);
}