710 lines
19 KiB
C
710 lines
19 KiB
C
|
/*
|
||
|
* Windows Calendar
|
||
|
* Copyright (c) 1985 by Microsoft Corporation, all rights reserved.
|
||
|
* Written by Mark L. Chamberlin, consultant to Microsoft.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
*****
|
||
|
***** calday.c
|
||
|
*****
|
||
|
*/
|
||
|
|
||
|
#include "cal.h"
|
||
|
|
||
|
#define FIXEDFONTWIDTH 0
|
||
|
|
||
|
UINT wID;
|
||
|
|
||
|
BOOL vfUpdate = TRUE; /* flag to disable setqdec() update fix. 27-Oct-1987 */
|
||
|
|
||
|
/**** DayMode - Switch to day mode. */
|
||
|
|
||
|
VOID APIENTRY DayMode (D3 *pd3)
|
||
|
{
|
||
|
|
||
|
RECT rect;
|
||
|
HDC hDC;
|
||
|
|
||
|
if (!vfDayMode)
|
||
|
{
|
||
|
/* Say we are in day mode. */
|
||
|
vfDayMode = TRUE;
|
||
|
|
||
|
/* Disable focus for now. If in notes area, leave it there,
|
||
|
otherwise set up to give focus to appointment description.
|
||
|
*/
|
||
|
CalSetFocus ((HWND)NULL);
|
||
|
if (vhwndFocus != vhwnd2C)
|
||
|
vhwndFocus = vhwnd3;
|
||
|
|
||
|
/* Clear the window so we don't get a blank region appearing
|
||
|
in the middle of the monthly calendar when we ShowWindow
|
||
|
the appointment description edit control.
|
||
|
*/
|
||
|
GetClientRect (vhwnd2B, (LPRECT)&rect);
|
||
|
rect.bottom -= vcyBorder;
|
||
|
|
||
|
hDC = CalGetDC (vhwnd2B);
|
||
|
FillRect (hDC, (LPRECT)&rect, vhbrBackSub);
|
||
|
ReleaseDC (vhwnd2B, hDC);
|
||
|
/* Make the appointment description edit control visible. */
|
||
|
SetEcText(vhwnd3, "");
|
||
|
|
||
|
SetScrollRange (vhwnd2B, SB_HORZ, 0, 0, TRUE);
|
||
|
SetScrollPos (vhwnd2B, SB_HORZ, 0,TRUE);
|
||
|
|
||
|
/*InvalidateRect (vhwnd2B, (LPRECT)NULL, FALSE);*/
|
||
|
UpdateWindow (vhwnd2B);
|
||
|
ShowWindow (vhwnd3, SHOW_OPENWINDOW);
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
/* Switch to the specified date. Note that this gets done even if
|
||
|
we were already in day mode. This means that the View Day command
|
||
|
can be used to get back to the starting time of the currently
|
||
|
displayed day. It also is necessary because there callers who
|
||
|
want the day redisplayed even if already in day mode (like New).
|
||
|
*/
|
||
|
SwitchToDate (pd3);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** SwitchToDate - the ONLY routine that changes the selected day in
|
||
|
day mode.
|
||
|
*/
|
||
|
|
||
|
VOID APIENTRY SwitchToDate ( D3 *pd3 )
|
||
|
{
|
||
|
RECT rect;
|
||
|
|
||
|
register BOOL fNewMonth;
|
||
|
|
||
|
if (FGetDateDr (DtFromPd3 (pd3)))
|
||
|
{
|
||
|
fNewMonth = vd3Sel.wMonth != pd3 -> wMonth
|
||
|
|| vd3Sel.wYear != pd3 -> wYear;
|
||
|
vd3Sel = *pd3;
|
||
|
if (fNewMonth)
|
||
|
SetUpMonth ();
|
||
|
}
|
||
|
|
||
|
FillTld (vtmStart);
|
||
|
SetQdEc (0);
|
||
|
|
||
|
/* If focus is on notes area put it there. Otherwise it has already
|
||
|
been set up by SetQdEc.
|
||
|
*/
|
||
|
if (vhwndFocus == vhwnd2C)
|
||
|
CalSetFocus (vhwnd2C);
|
||
|
|
||
|
/* Set the scroll bar range and thumb position. (The scroll bar range
|
||
|
depends on the number of TM in the day, so it must be set up each
|
||
|
time the day is changed.)
|
||
|
*/
|
||
|
|
||
|
SetDayScrollRange ();
|
||
|
SetDayScrollPos (-1);
|
||
|
|
||
|
/* Repaint Wnd2A to display "Schedule for: ..." message. */
|
||
|
InvalidateRect (vhwnd2A, (LPRECT)NULL, TRUE);
|
||
|
UpdateWindow (vhwnd2A);
|
||
|
|
||
|
/* Redraw the appointments. */
|
||
|
GetClientRect (vhwnd1, (LPRECT)&rect);
|
||
|
rect.bottom = vycoWnd2C;
|
||
|
rect.top = vcyWnd2A;
|
||
|
|
||
|
InvalidateRect (vhwnd1, (LPRECT)&rect, TRUE);
|
||
|
/* UpdateWindow (vhwnd1); */
|
||
|
|
||
|
/* Set up the notes area. */
|
||
|
SetNotesEc ();
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** DayPaint */
|
||
|
|
||
|
VOID APIENTRY DayPaint (HDC hDC)
|
||
|
{
|
||
|
|
||
|
CHAR sz [CCHTIMESZ];
|
||
|
register INT ycoText;
|
||
|
register INT ln;
|
||
|
INT cch;
|
||
|
TM tm;
|
||
|
CHAR *pchQd;
|
||
|
RECT rectQd;
|
||
|
BYTE *pbTqr;
|
||
|
DWORD iSelFirst;
|
||
|
DWORD iSelLast;
|
||
|
#ifdef DISABLE
|
||
|
DWORD iSelFirstT;
|
||
|
DWORD iSelLastT;
|
||
|
#endif
|
||
|
|
||
|
pbTqr = PbTqrLock ();
|
||
|
rectQd.right = vxcoQdMax ;
|
||
|
rectQd.left = vxcoQdFirst;
|
||
|
|
||
|
for (ln = 0; ln < vcln; ln++)
|
||
|
{
|
||
|
ycoText = YcoFromLn (ln);
|
||
|
|
||
|
if (FAlarm (ln))
|
||
|
DrawAlarmBell (hDC, ycoText);
|
||
|
|
||
|
cch = GetTimeSz (tm = vtld [ln].tm, sz);
|
||
|
|
||
|
/* Display am or pm only for the first appointment in the window
|
||
|
and for noon.
|
||
|
*/
|
||
|
if (ln != 0 && tm != TMNOON)
|
||
|
cch = 5;
|
||
|
|
||
|
TextOut (hDC, vxcoApptTime, ycoText, (LPSTR)sz, cch);
|
||
|
|
||
|
rectQd.top = YcoFromLn (ln);
|
||
|
rectQd.bottom = rectQd.top + vcyFont;
|
||
|
pchQd = "";
|
||
|
if (vtld [ln].otqr != OTQRNIL)
|
||
|
pchQd = (CHAR *)(pbTqr + vtld [ln].otqr + CBQRHEAD);
|
||
|
|
||
|
DrawText (hDC, (LPSTR)pchQd, -1, (LPRECT)&rectQd,
|
||
|
DT_NOPREFIX | DT_SINGLELINE | DT_LEFT | DT_TOP);
|
||
|
if (ln == vlnCur)
|
||
|
{
|
||
|
/* We have just painted the appointment that has the
|
||
|
edit control. In order to keep "flashing" to a minimum,
|
||
|
we want to prevent the edit control from repainting,
|
||
|
but we do need to get the highlight back up.
|
||
|
So:
|
||
|
1) Validate the edit control to prevent repainting.
|
||
|
2) Disable redraw.
|
||
|
3) Fetch and save the current selection.
|
||
|
4) Set the selection to null (redraw is off, so this
|
||
|
will not affect the highlight).
|
||
|
5) Enable redraw.
|
||
|
6) Set the selection back to the saved value. Since redraw
|
||
|
is enabled this will highlight the selected characters.
|
||
|
*/
|
||
|
#ifdef DISABLE
|
||
|
ValidateRect (vhwnd3, (LPRECT)NULL);
|
||
|
SendMessage (vhwnd3, WM_SETREDRAW, FALSE, 0L);
|
||
|
MSendMsgEM_GETSEL(vhwnd3, &iSelFirst, &iSelLast);
|
||
|
iselFirstT = iSelFirst;
|
||
|
iselLastT = iSelLast;
|
||
|
iselFirst = iSelLast = 0;
|
||
|
SendMessage(vhwnd3, EM_SETSEL, iSelFirst, (LONG)iSelLast);
|
||
|
SendMessage(vhwnd3, WM_SETREDRAW, TRUE, 0L);
|
||
|
SendMessage(vhwnd3, EM_SETSEL, iSelFirstT, (LONG)iSelLastT);
|
||
|
#else
|
||
|
/* don't try to be fancy. If only part of hilight in update
|
||
|
* region, there was bug with selection being half inverted,
|
||
|
* half normal. This solved it. 10-Jun-1987.
|
||
|
*/
|
||
|
MSendMsgEM_GETSEL(vhwnd3, &iSelFirst, &iSelLast);
|
||
|
SendMessage(vhwnd3, EM_SETSEL, iSelFirst, (LONG)iSelLast);
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
DrUnlockCur ();
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** FillTld */
|
||
|
|
||
|
VOID APIENTRY FillTld (TM tmFirst)
|
||
|
{
|
||
|
|
||
|
LD *pldCur;
|
||
|
LD *pldLast;
|
||
|
INT cldEmpty;
|
||
|
|
||
|
/* Find the first appointment less than or equal to the specified
|
||
|
one. Note that since tmFirst must be greater than or equal to
|
||
|
0 (midnight), calling FGetPrevLd with tmFirst + 1 is guaranteed
|
||
|
to find something, so there is no need to check the return value.
|
||
|
*/
|
||
|
FGetPrevLd (tmFirst + 1, vtld);
|
||
|
|
||
|
/* Work forward filling in the tld. Stop when the end of the
|
||
|
table is reached or the end of the day is reached.
|
||
|
*/
|
||
|
for (pldLast = (pldCur = vtld) + vlnLast; pldCur < pldLast
|
||
|
&& FGetNextLd (pldCur -> tm, pldCur + 1); pldCur++)
|
||
|
;
|
||
|
|
||
|
|
||
|
/* If we stopped going forward because we reached the end of the day
|
||
|
instead of the end of the tld, there are empty entries at the end
|
||
|
of the tld. In this case, we scroll the tld down to put the
|
||
|
empty space at the top, and then we fill in the empty space by
|
||
|
getting the earlier appointment times. There will always be
|
||
|
enough appointment times to fill the tld since the maximum interval
|
||
|
(1 hour) gives 24 appointment times, and we don't have that many
|
||
|
lines for displaying appointments. So there is no need to check
|
||
|
the return value of FGetPrevLd below, and we can rest assured that
|
||
|
the tld will get completely filled.
|
||
|
*/
|
||
|
if ((cldEmpty = (INT)(pldLast - pldCur)) > 0)
|
||
|
{
|
||
|
ScrollDownTld (cldEmpty);
|
||
|
for (pldCur = vtld + cldEmpty; pldCur > vtld; pldCur--)
|
||
|
FGetPrevLd (pldCur -> tm, pldCur - 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** ScrollDownTld - Scroll the tld down (towards the bottom of the screen,
|
||
|
but higher in memory) the specified number of ld,
|
||
|
making room for new lds at the top of the tld.
|
||
|
*/
|
||
|
|
||
|
VOID APIENTRY ScrollDownTld (INT cld)
|
||
|
{
|
||
|
BltByte ((BYTE *)vtld, (BYTE *)(vtld + cld),
|
||
|
(WORD)((vcln - cld) * sizeof (LD)));
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** ScrollUpTld - Scroll the tld up (towards the top of the screen,
|
||
|
but lower in memory) the specified number of ld,
|
||
|
making room for new lds at the bottom of the tld.
|
||
|
*/
|
||
|
|
||
|
VOID APIENTRY ScrollUpTld (INT cld)
|
||
|
{
|
||
|
BltByte ((BYTE *)(vtld + cld), (BYTE *)vtld,
|
||
|
(WORD)((vcln - cld) * sizeof (LD)));
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** FGetNextLd */
|
||
|
|
||
|
BOOL APIENTRY FGetNextLd (
|
||
|
TM tm,
|
||
|
LD *pld)
|
||
|
{
|
||
|
|
||
|
TM tmFromTqr;
|
||
|
DR *pdr;
|
||
|
|
||
|
|
||
|
FSearchTqr (tm);
|
||
|
tmFromTqr = TMNILHIGH;
|
||
|
if (votqrNext != (pdr = PdrLockCur ()) -> cbTqr)
|
||
|
tmFromTqr = ((PQR )(PbTqrFromPdr (pdr) + votqrNext)) -> tm;
|
||
|
DrUnlockCur ();
|
||
|
|
||
|
if ((tm = min (tmFromTqr, TmNextRegular (tm))) == TMNILHIGH)
|
||
|
return (FALSE);
|
||
|
|
||
|
pld -> tm = tm;
|
||
|
pld -> otqr = tm == tmFromTqr ? votqrNext : OTQRNIL;
|
||
|
return (TRUE);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** FGetPrevLd */
|
||
|
|
||
|
BOOL APIENTRY FGetPrevLd (
|
||
|
TM tm,
|
||
|
LD *pld)
|
||
|
{
|
||
|
|
||
|
TM tmFromTqr;
|
||
|
TM tmInterval;
|
||
|
|
||
|
FSearchTqr (tm);
|
||
|
tmFromTqr = TMNILLOW;
|
||
|
if ((WORD)votqrPrev != OTQRNIL)
|
||
|
{
|
||
|
tmFromTqr = ((PQR )(PbTqrLock () + votqrPrev)) -> tm;
|
||
|
DrUnlockCur ();
|
||
|
}
|
||
|
|
||
|
/* Calculate the previous regular appointment time. */
|
||
|
tmInterval = tm - 1;
|
||
|
if (tm == 0 || (tmInterval -= tmInterval % vcMinInterval) < 0)
|
||
|
tmInterval = TMNILLOW;
|
||
|
|
||
|
if ((tm = max (tmFromTqr, tmInterval)) == TMNILLOW)
|
||
|
return (FALSE);
|
||
|
|
||
|
pld -> tm = tm;
|
||
|
pld -> otqr = tm == tmFromTqr ? votqrPrev : OTQRNIL;
|
||
|
return (TRUE);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** FScrollDay */
|
||
|
|
||
|
BOOL APIENTRY FScrollDay (
|
||
|
INT code,
|
||
|
UINT posNew)
|
||
|
{
|
||
|
|
||
|
wID=code;
|
||
|
|
||
|
switch (code)
|
||
|
{
|
||
|
case SB_LINEUP:
|
||
|
ScrollDownDay (1, TRUE, FALSE);
|
||
|
break;
|
||
|
|
||
|
case SB_LINEDOWN:
|
||
|
ScrollUpDay (1, TRUE);
|
||
|
break;
|
||
|
|
||
|
case SB_PAGEUP:
|
||
|
ScrollDownDay (vlnLast, TRUE, FALSE);
|
||
|
break;
|
||
|
|
||
|
case SB_PAGEDOWN:
|
||
|
ScrollUpDay (vlnLast, TRUE);
|
||
|
break;
|
||
|
|
||
|
case SB_THUMBPOSITION:
|
||
|
/* Record current edits (before changing the tld). */
|
||
|
if (vhwndFocus == vhwnd3)
|
||
|
CalSetFocus ((HWND)NULL);
|
||
|
FillTld (TmFromItm (posNew));
|
||
|
|
||
|
/* Move the call to SetQdEc() after the call to SetDayScrollPos(), and
|
||
|
use GetScrollPos() to find out if the location passed was beyond the
|
||
|
end of the scrollbar. If not, 0 will be passed as before. If true,
|
||
|
the call to SetQdEc() will step down to the appropriate location on
|
||
|
the display. Tracked down to solve Bug #2502.
|
||
|
16 July 1989 Clark Cyr */
|
||
|
|
||
|
#if DISABLE
|
||
|
SetQdEc (0);
|
||
|
#endif
|
||
|
SetDayScrollPos (posNew);
|
||
|
SetQdEc(posNew - GetScrollPos(vhwnd2B, SB_VERT));
|
||
|
InvalidateRect (vhwnd2B, (LPRECT)NULL, TRUE);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
return (TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** ScrollDownDay
|
||
|
ctNew is number of lines to scroll. fScrollBar is true if we
|
||
|
are not being scrolled by cursor movement. fSizing is true iff
|
||
|
we are scrolling as a result of resizing. */
|
||
|
VOID APIENTRY ScrollDownDay (
|
||
|
INT ctmNew,
|
||
|
BOOL fScrollBar,
|
||
|
BOOL fSizing)
|
||
|
|
||
|
{
|
||
|
|
||
|
register INT ctm;
|
||
|
register INT ln;
|
||
|
LD ldTemp;
|
||
|
RECT rect;
|
||
|
HDC hDC;
|
||
|
TM tmFirstOld;
|
||
|
extern INT cchTimeMax;
|
||
|
CHAR sz[CCHTIMESZ];
|
||
|
INT cch;
|
||
|
INT iHeight;
|
||
|
INT iWidth;
|
||
|
|
||
|
/* Register current changes and hide the caret. */
|
||
|
if (vhwndFocus == vhwnd3)
|
||
|
CalSetFocus ((HWND)NULL);
|
||
|
|
||
|
tmFirstOld = vtld [0].tm;
|
||
|
|
||
|
|
||
|
for (ctm = 0; ctm <(ctmNew) && FGetPrevLd (vtld [0].tm, &ldTemp) ; ctm++)
|
||
|
{
|
||
|
ScrollDownTld (1);
|
||
|
vtld [0] = ldTemp;
|
||
|
}
|
||
|
|
||
|
if (ctm != 0)
|
||
|
{
|
||
|
/* Get rid of am or pm on top line of window if it's not noon.
|
||
|
Note - it's OK to execute this code even if in 24 hour mode
|
||
|
since we will just be putting spaces over spaces.
|
||
|
*/
|
||
|
if (tmFirstOld != TMNOON)
|
||
|
{
|
||
|
hDC = CalGetDC (vhwnd2B);
|
||
|
cch = GetTimeSz (tmFirstOld, sz);
|
||
|
MGetTextExtent(hDC, sz, 5, &iHeight, &iWidth); /* width of time string
|
||
|
+ the blank following it */
|
||
|
//- KLUDGE: TextOut (hDC, vxcoApptTime + iWidth, vycoQdFirst,
|
||
|
//- KLUDGE: (LPSTR)vszBlankString,cchTimeMax+3);
|
||
|
//- For some reason, the above code no longer blanks out the
|
||
|
//- correct area. It puts a space in the center of the time.
|
||
|
TextOut (hDC, vxcoApptTime + iWidth + 19, vycoQdFirst,
|
||
|
(LPSTR)" ",12);
|
||
|
ReleaseDC (vhwnd2B, hDC);
|
||
|
}
|
||
|
|
||
|
GetClientRect (vhwnd2B, (LPRECT)&rect);
|
||
|
rect.top = vycoQdFirst;
|
||
|
rect.bottom = vycoQdMax;
|
||
|
ScrollWindow (vhwnd2B, 0, ctm * vcyLineToLine, &rect,&rect);
|
||
|
}
|
||
|
|
||
|
/* Need to reset focus even if nothing has scrolled since
|
||
|
the focus got turned off above.
|
||
|
*/
|
||
|
ln = 0;
|
||
|
if (fScrollBar)
|
||
|
ln = min (vlnCur + ctm , vlnLast);
|
||
|
|
||
|
vfUpdate = FALSE;
|
||
|
SetQdEc (ln);
|
||
|
vfUpdate = TRUE;
|
||
|
|
||
|
/* When SetQdEc validates the appointment edit control, the
|
||
|
corresponding rectangle of its parent (wnd2B) gets validated
|
||
|
too. If this is in the portion of wnd2B that was invalidated
|
||
|
by the scroll, we must invalidate it now so it gets painted
|
||
|
by DayPaint.
|
||
|
We brought in ctm new lines at the top of wnd2B, so if the
|
||
|
new ln (the position of the appointment edit control) is
|
||
|
less than ctm, it's in the invalidated portion of wnd2B.
|
||
|
Note that if ctm == 0, ln can't be less, so this case is OK.
|
||
|
If we are resizing, whole window will be repainted.
|
||
|
*/
|
||
|
if (ln < ctm || fSizing)
|
||
|
InvalidateParentQdEc (ln);
|
||
|
|
||
|
if (ctm != 0)
|
||
|
{
|
||
|
UpdateWindow (vhwnd2B);
|
||
|
AdjustDayScrollPos (-ctm);
|
||
|
|
||
|
/* Need to update edit ctl window incase obscurred by popup. */
|
||
|
if (AnyPopup() && vhwnd3)
|
||
|
{
|
||
|
InvalidateRect(vhwnd3, (LPRECT)NULL, TRUE);
|
||
|
UpdateWindow(vhwnd3);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** ScrollUpDay */
|
||
|
|
||
|
VOID APIENTRY ScrollUpDay (
|
||
|
INT ctmNew,
|
||
|
BOOL fScrollBar)
|
||
|
{
|
||
|
|
||
|
register INT ctm;
|
||
|
register INT ln;
|
||
|
LD ldTemp;
|
||
|
RECT rect;
|
||
|
HDC hDC;
|
||
|
|
||
|
|
||
|
/* Register current edits and hide the caret. */
|
||
|
if (vhwndFocus == vhwnd3)
|
||
|
CalSetFocus ((HWND)NULL);
|
||
|
|
||
|
for (ctm = 0; ctm < (ctmNew) && FGetNextLd (vtld [vlnLast].tm, &ldTemp);
|
||
|
ctm++)
|
||
|
{
|
||
|
ScrollUpTld (1);
|
||
|
vtld [vlnLast] = ldTemp;
|
||
|
}
|
||
|
|
||
|
if (ctm != 0)
|
||
|
{
|
||
|
GetClientRect (vhwnd2B, (LPRECT)&rect);
|
||
|
rect.top = vycoQdFirst;
|
||
|
rect.bottom = vycoQdMax;
|
||
|
ScrollWindow (vhwnd2B, 0, -ctm * vcyLineToLine, &rect, &rect);
|
||
|
|
||
|
if (wID==SB_PAGEDOWN)
|
||
|
{
|
||
|
/* Fix the problem of not repainting some times when scrolling */
|
||
|
rect.top=vycoQdFirst;
|
||
|
rect.bottom =vycoQdMax-(ctm*vcyLineToLine);
|
||
|
rect.right=vxcoQdMax;
|
||
|
rect.left=0;
|
||
|
InvalidateRect(vhwnd2B, &rect, TRUE);
|
||
|
}
|
||
|
|
||
|
/* If in 12 hour mode, put am/pm on first appointment in the window. */
|
||
|
if (!vfHour24)
|
||
|
{
|
||
|
#if FIXEDFONTWIDTH
|
||
|
CHAR *sz;
|
||
|
extern CHAR sz1159[];
|
||
|
extern CHAR sz2359[];
|
||
|
#else
|
||
|
CHAR sz[CCHTIMESZ];
|
||
|
INT cch;
|
||
|
#endif
|
||
|
|
||
|
hDC = CalGetDC (vhwnd2B);
|
||
|
|
||
|
/* This has the problem that spaces do not have the same width as numbers
|
||
|
in the new system fonts. Depending on vxcoAmPm as the constant position
|
||
|
for where AM and PM should be offset is no longer safe. This is just a
|
||
|
bandaid and should be written correctly later. 17 July 1989 Clark Cyr */
|
||
|
|
||
|
#if FIXEDFONTWIDTH
|
||
|
sz=(vtld[0].tm < TMNOON ? sz1159 : sz2359);
|
||
|
TextOut(hDC, vxcoAmPm, vycoQdFirst, sz , lstrlen(sz));
|
||
|
#else
|
||
|
cch = GetTimeSz (vtld[0].tm, sz);
|
||
|
TextOut (hDC, vxcoApptTime, vycoQdFirst, (LPSTR)sz, cch);
|
||
|
#endif
|
||
|
ReleaseDC (vhwnd2B, hDC);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
/* Need to reset focus even if nothing has scrolled since
|
||
|
the focus got turned off above.
|
||
|
*/
|
||
|
ln = vlnLast;
|
||
|
if (fScrollBar)
|
||
|
ln = max (vlnCur - ctm, 0);
|
||
|
|
||
|
vfUpdate = FALSE;
|
||
|
SetQdEc (ln);
|
||
|
vfUpdate = TRUE;
|
||
|
|
||
|
/* When SetQdEc validates the appointment edit control, the
|
||
|
corresponding rectangle of its parent (wnd2B) gets validated
|
||
|
too. If this is in the portion of wnd2B that was invalidated
|
||
|
by the scroll, we must invalidate it now so it gets painted
|
||
|
by DayPaint.
|
||
|
We brought in ctm new lines at the bottom of wnd2B, so if the
|
||
|
new ln (the position of the appointment edit control) is
|
||
|
greater than vlnLast - ctm, it's in the invalidated portion of wnd2B.
|
||
|
Note that if ctm == 0, ln can't be greater, so this case is OK.
|
||
|
*/
|
||
|
if (ln > vlnLast - ctm)
|
||
|
InvalidateParentQdEc (ln);
|
||
|
|
||
|
if (ctm != 0)
|
||
|
{
|
||
|
rect.top = YcoFromLn(vlnLast);
|
||
|
rect.bottom = rect.top + vcyLineToLine;
|
||
|
InvalidateRect(vhwnd2B, (LPRECT)&rect, TRUE);
|
||
|
UpdateWindow (vhwnd2B);
|
||
|
AdjustDayScrollPos (ctm);
|
||
|
|
||
|
/* Need to update edit ctl window incase obscurred by popup. */
|
||
|
if (AnyPopup() && vhwnd3)
|
||
|
{
|
||
|
InvalidateRect(vhwnd3, (LPRECT)NULL, TRUE);
|
||
|
UpdateWindow(vhwnd3);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** InvalidateParentQdEc */
|
||
|
|
||
|
VOID APIENTRY InvalidateParentQdEc (INT ln)
|
||
|
{
|
||
|
|
||
|
RECT rect;
|
||
|
|
||
|
rect.top = YcoFromLn (ln);
|
||
|
rect.bottom = rect.top + vcyFont;
|
||
|
rect.left = vxcoQdFirst;
|
||
|
rect.right = vxcoQdMax;
|
||
|
|
||
|
InvalidateRect (vhwnd2B, &rect, TRUE);
|
||
|
OffsetRect(&rect, 0, vcyWnd2A);
|
||
|
InvalidateRect (vhwnd1, &rect, TRUE);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** YcoFromLn - given line number, return yco within Wnd2B */
|
||
|
|
||
|
INT APIENTRY YcoFromLn (INT ln)
|
||
|
{
|
||
|
return (vycoQdFirst + ln * vcyLineToLine);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** LnFromYco - given yco within Wnd2B, return line number. */
|
||
|
|
||
|
INT APIENTRY LnFromYco (INT yco)
|
||
|
{
|
||
|
return (min (max (yco - vycoQdFirst, 0) / vcyLineToLine, vlnLast));
|
||
|
}
|
||
|
|
||
|
|
||
|
/**** SetQdEc - Position and set the text of the appointment description
|
||
|
edit control.
|
||
|
*/
|
||
|
|
||
|
VOID APIENTRY SetQdEc (INT ln)
|
||
|
{
|
||
|
|
||
|
register BYTE *pbTqr;
|
||
|
register CHAR *pchQd;
|
||
|
RECT rc;
|
||
|
|
||
|
/* Store edits for current appointment description. */
|
||
|
if (vhwndFocus == vhwnd3)
|
||
|
CalSetFocus ((HWND)NULL);
|
||
|
|
||
|
/* Set the new current ln. */
|
||
|
vlnCur = ln;
|
||
|
|
||
|
/* do this to fix bug when scrolling before window is
|
||
|
* actually painted on screen. the movewindow below
|
||
|
* forces the parents update region to clip out where
|
||
|
* the child window was, and it would not get erased.
|
||
|
* if in the scrollup/dn code, don't do the update or
|
||
|
* you get an unnecessary flash. vfUpdate will be false.
|
||
|
* 27-Oct-1987. davidhab.
|
||
|
*/
|
||
|
if (vfUpdate && GetUpdateRect(vhwnd2B, (LPRECT)&rc, FALSE)) {
|
||
|
GetWindowRect(vhwnd3, (LPRECT)&rc);
|
||
|
UpdateWindow(vhwnd2B);
|
||
|
}
|
||
|
|
||
|
|
||
|
ShowWindow(vhwnd3, SW_HIDE);
|
||
|
MoveWindow (vhwnd3, vxcoQdFirst, YcoFromLn (ln),
|
||
|
vxcoQdMax - vxcoQdFirst , vcyFont, FALSE);
|
||
|
|
||
|
pbTqr = PbTqrLock ();
|
||
|
pchQd = "";
|
||
|
if (vtld [ln].otqr != OTQRNIL)
|
||
|
pchQd = (CHAR *)(pbTqr + vtld [ln].otqr + CBQRHEAD);
|
||
|
/*SendMessage (vhwnd3, WM_SETREDRAW, FALSE, 0L);*/
|
||
|
SetEcText(vhwnd3, pchQd);
|
||
|
ShowWindow(vhwnd3, SW_SHOW);
|
||
|
/*SendMessage (vhwnd3, WM_SETREDRAW, TRUE, 0L);
|
||
|
ValidateRect (vhwnd3, (LPRECT)NULL);*/
|
||
|
DrUnlockCur ();
|
||
|
|
||
|
/* If not in the notes area, give the focus to the appointment
|
||
|
description edit control.
|
||
|
*/
|
||
|
if (vhwndFocus == vhwnd3)
|
||
|
CalSetFocus (vhwnd3);
|
||
|
|
||
|
|
||
|
|
||
|
}
|