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

459 lines
11 KiB
C

/*
* Windows Calendar
* Copyright (c) 1985 by Microsoft Corporation, all rights reserved.
* Written by Mark L. Chamberlin, consultant to Microsoft.
*
* ***** calmon2.c
*
*/
#include "cal.h"
/**** FMonthPrev ****/
BOOL APIENTRY FMonthPrev ()
{
if (vd3To.wMonth != MONTHJAN)
vd3To.wMonth--;
else
{
if (vd3To.wYear == YEAR1980)
return (FALSE);
vd3To.wYear--;
vd3To.wMonth = MONTHDEC;
}
return (TRUE);
}
/**** FMonthNext ****/
BOOL APIENTRY FMonthNext ()
{
if (vd3To.wMonth != MONTHDEC)
vd3To.wMonth++;
else
{
if (vd3To.wYear == YEAR2099)
return (FALSE);
vd3To.wYear++;
vd3To.wMonth = MONTHJAN;
}
return (TRUE);
}
/**** ShowMonthPrevNext ****/
VOID APIENTRY ShowMonthPrevNext (BOOL fNext)
{
/* First see if able to move to previous or next month. (Can't
move back if already January 1980, can't move forward if already
December 2099.)
*/
if (fNext ? FMonthNext () : FMonthPrev ())
UpdateMonth ();
}
/**** UpdateMonth - update the month display after the month has been
changed, or when switching from day mode to month mode.
Set the selected day to the minimum of the sticky day or the
last day of the month.
****/
VOID APIENTRY FAR UpdateMonth ()
{
HDC hDC;
/* See if the data can be fetched for the target date. If not,
don't switch to that date. If so, switch.
*/
vd3To.wDay = (WORD)min ((INT)(CDaysMonth (&vd3To) - 1), (INT)vwDaySticky);
if (FFetchTargetDate ())
{
vd3Sel=vd3To;
SetScrollPos(vhwnd2B, SB_VERT, vd3Sel.wYear*12+vd3Sel.wMonth, TRUE);
SetUpMonth ();
InvalidateMonth ();
UpdateWindow (vhwnd0); /* changed from vhwnd2B to fix scrollbar
repaint problems */
SetNotesEc ();
hDC=GetDC(vhwnd2A);
DispDate (hDC, &vd3To);
ReleaseDC(vhwnd2A, hDC);
}
}
/**** MouseSelectDay - we have a click in the monthly calendar. Map
it to a day and move the selection.
*****/
VOID APIENTRY MouseSelectDay (
MPOINT point, /* Screen coordinates of mouse where click
occurred.
*/
BOOL fDblClk) /* TRUE for double click. */
{
INT ixco, iyco, irgb;
if (FMapCoToIGrid (point.x, vrgxcoGrid, 7, &ixco) &&
FMapCoToIGrid (point.y, vrgycoGrid, vcWeeksMonth, &iyco) &&
vrgbMonth [irgb = 7 * iyco + ixco +7*vmScrollPos + hmScrollPos]
!= 0)
{
vd3To = vd3Sel;
MoveSelCurMonth (irgb - vwWeekdayFirst );
/* Give the focus to the calendar if it doesn't already have it. */
if (GetFocus () != vhwnd2B)
CalSetFocus (vhwnd2B);
/* Switch to day mode for the day the user double clicked on. */
if (fDblClk)
DayMode (&vd3Sel);
}
}
/**** FScrollMonth */
/************************************************************************
*
* VOID PASCAL FScrollMonth (code, posNew)
*
* purpose : calculates sone vertical scroll globals and scrolls
* the month display vertically.
*
***********************************************************************/
VOID APIENTRY FScrollMonth (
INT code,
UINT posNew)
{
INT dy;
RECT rect;
/* calculate the step size for the scroll. The step size is
approximately the height of the month grid */
if (hmScrollMax == 0)
dy = (vcyWnd2BBot - vcyBorder +vcyHScrollBar)/ vcWeeksMonth;
else
dy = (vcyWnd2BBot - vcyBorder)/ vcWeeksMonth;
switch (code)
{
case SB_LINEUP :
vmScrollInc = -1;
break;
case SB_LINEDOWN:
vmScrollInc = 1;
break;
case SB_TOP:
vmScrollInc = -vmScrollPos;
break;
case SB_BOTTOM :
vmScrollInc = vmScrollMax - vmScrollPos;
break;
case SB_PAGEUP :
case SB_PAGEDOWN :
break;
case SB_THUMBTRACK :
vmScrollInc = posNew -vmScrollPos;
break;
default:
vmScrollInc = 0;
}
if ((vmScrollInc = max(-vmScrollPos,
min (vmScrollInc, vmScrollMax-vmScrollPos))) != 0)
{
GetClientRect (vhwnd2B, (LPRECT)&rect);
rect.top = vcyWnd2BTop;
rect.bottom = vcyWnd2BBot + 2*dy;
if (vmScrollMax ==1)
rect.bottom += dy;
vmScrollPos +=vmScrollInc;
ScrollWindow (vhwnd2B, 0, -dy * vmScrollInc, &rect, &rect);
SetScrollPos (vhwnd2B, SB_VERT, vmScrollPos, TRUE);
/* refresh screen to get rid of caret droppings */
rect.bottom = vcyWnd2BBot;
rect.top -= 3*vcyLineToLine;
InvalidateRect(vhwnd2B, (LPRECT)&rect, TRUE);
UpdateWindow (vhwnd2B);
}
}
/************************************************************************
*
* VOID PASCAL FHorizScrollMonth (code, posNew)
*
* purpose : calculates some horizontal scroll globals and scrolls the
* month display vertically.
*
***********************************************************************/
VOID APIENTRY FHorizScrollMonth (
INT code,
WORD posNew)
{
RECT rect;
INT dx;
/* calculate the step size for the scroll. The step size
is approximately the width of the month grid */
if (vmScrollMax == 0)
dx = (vcxWnd2B + vcxBorder+ vcxVScrollBar)/7;
else
dx = (vcxWnd2B + vcxBorder)/7;
switch (code)
{
case SB_LINEUP:
hmScrollInc = -1;
break;
case SB_LINEDOWN:
hmScrollInc = 1;
break;
case SB_TOP :
hmScrollInc = -hmScrollPos;
break;
case SB_BOTTOM:
hmScrollInc = hmScrollMax -hmScrollPos;
break;
case SB_PAGEUP:
case SB_PAGEDOWN:
break;
case SB_THUMBTRACK:
hmScrollInc = posNew - hmScrollPos;
break;
default:
hmScrollInc = 0;
}
if ((hmScrollInc = max(-hmScrollPos,
min(hmScrollInc, hmScrollMax - hmScrollPos))) != 0)
{
GetClientRect (vhwnd2B, (LPRECT)&rect);
rect.top = vcyWnd2BTop - vcyLineToLine;
rect.bottom = vycoQdMax;
hmScrollPos += hmScrollInc;
ScrollWindow ( vhwnd2B , -dx*hmScrollInc, 0, &rect, &rect);
SetScrollPos ( vhwnd2B, SB_HORZ, hmScrollPos, TRUE );
/* refresh screen to get rid of caret droppings */
rect.bottom += vcyHScrollBar;
rect.top -= 2* vcyLineToLine;
InvalidateRect(vhwnd2B, (LPRECT)&rect, TRUE);
UpdateWindow ( vhwnd2B );
}
}
/**** FCalKey ****/
BOOL APIENTRY FCalKey (
HWND hwnd,
WPARAM kc) /* The virtual key code. */
{
register INT iTemp;
if (!vfDayMode && hwnd == vhwnd2B)
{
vd3To = vd3Sel;
switch (kc)
{
case VK_LEFT:
if (vd3To.wDay != 0)
MoveSelCurMonth (vd3To.wDay - 1);
else
if (FMonthPrev ())
MoveSelNewMonth (CDaysMonth (&vd3To) - 1);
break;
case VK_RIGHT:
if ((iTemp = vd3To.wDay + 1) < vcDaysMonth)
MoveSelCurMonth (iTemp);
else
if (FMonthNext ())
MoveSelNewMonth (0);
break;
case VK_UP:
if ((iTemp = vd3To.wDay - 7) >= 0)
MoveSelCurMonth (iTemp);
else
if (FMonthPrev ())
MoveSelNewMonth (CDaysMonth (&vd3To) + iTemp);
break;
case VK_DOWN:
if ((iTemp = vd3To.wDay + 7) < vcDaysMonth)
MoveSelCurMonth (iTemp);
else
{
iTemp -= vcDaysMonth;
if (FMonthNext ())
MoveSelNewMonth (iTemp);
}
break;
case VK_PRIOR:
ShowMonthPrevNext (FALSE);
break;
case VK_NEXT:
ShowMonthPrevNext (TRUE);
break;
case VK_TAB:
/* Switch to the notes area. */
CalSetFocus (vhwnd2C);
break;
case VK_RETURN:
/* Switch to day mode for the selected day. */
DayMode (&vd3Sel);
break;
default:
return (FALSE);
}
return (TRUE);
}
return (FALSE);
}
/**** MoveSelCurMonth ****/
VOID APIENTRY MoveSelCurMonth (UINT uiDaySel)
{
HDC hDC;
WORD wDaySel = (WORD)uiDaySel;
/* Only switch if we can fetch the data for the target date. */
vd3To.wDay = wDaySel;
if (FFetchTargetDate ())
{
hDC = CalGetDC (vhwnd2B);
InvertDay (hDC, vd3Sel.wDay);
InvertDay (hDC, vwDaySticky = vd3Sel.wDay = wDaySel);
ReleaseDC (vhwnd2B, hDC);
hDC=GetDC(vhwnd2A);
DispDate (hDC, &vd3Sel);
ReleaseDC(vhwnd2A, hDC);
PositionCaret ();
SetNotesEc ();
}
}
/**** MoveSelNewMonth ****/
VOID APIENTRY MoveSelNewMonth (UINT uiDaySel)
{
WORD wDaySel = (WORD)uiDaySel;
vd3To.wDay = wDaySel;
/* Don't change vwDaySticky unless we can successfully switch to the
target date.
*/
if (FFetchTargetDate ())
{
vwDaySticky = wDaySel;
UpdateMonth ();
}
}
/**** JumpDate - Jump to specified date in month mode. ****/
VOID APIENTRY JumpDate (D3*pd3)
{
register WORD wDay;
wDay = pd3 -> wDay;
if (pd3 -> wMonth == vd3Sel.wMonth && pd3 -> wYear == vd3Sel.wYear)
{
/* The target date is in the same month as the one we are
currently displaying - just move the highlight.
*/
MoveSelCurMonth (wDay);
}
else
{
/* The target date is not in the current month. Need to
update the entire month display.
*/
vd3To = *pd3;
MoveSelNewMonth (wDay);
}
}
/**** InvalidateMonth ****/
VOID APIENTRY InvalidateMonth ()
{
InvalidateRect (vhwnd2B, NULL, TRUE);
}
/**** FFetchTargetDate ****/
BOOL APIENTRY FFetchTargetDate ()
{
register HWND hwndFocus;
register BOOL fOk;
/* FGetDateDr leaves the focus NULL if it succeeds, so remember who
has it now, and set it back when finished.
*/
hwndFocus = GetFocus ();
fOk = FGetDateDr (DtFromPd3 (&vd3To));
CalSetFocus (hwndFocus);
return (fOk);
}