/* * 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); }