Ignore:
Timestamp:
Aug 14, 1999, 6:13:16 PM (26 years ago)
Author:
cbratschi
Message:

wine-990731 update

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/comctl32/monthcal.c

    r94 r496  
    1 /* $Id: monthcal.c,v 1.3 1999-06-10 16:22:01 achimha Exp $ */
    2 /*
    3  * Month calendar control
     1
     2/* Month calendar control
     3
     4
    45 *
    5  * Copyright 1998, 1999 Eric Kohl
    6  * Copyright 1999 Achim Hasenmueller
    7  *
    8  * NOTES
    9  *   This is just a dummy control. An author is needed! Any volunteers?
    10  *   I will only improve this control once in a while.
    11  *     Eric <ekohl@abo.rhein-zeitung.de>
     6 * Copyright 1998, 1999 Eric Kohl (ekohl@abo.rhein-zeitung.de)
     7 * Copyright 1999  Alex Priem (alexp@sci.kun.nl)
     8 * Copyright 1999 Christoph Bratschi
    129 *
    1310 * TODO:
    14  *   - All messages.
    15  *   - All notifications.
     11 *   - Notifications.
    1612 *
     13 *
     14 *  FIXME: refresh should ask for rect of required length. (?)
     15 *  FIXME: we refresh to often; especially in LButtonDown/MouseMove.
     16 *  FIXME: handle resources better (doesn't work now); also take care
     17           of internationalization.
     18 *  FIXME: keyboard handling.
    1719 */
    1820
    1921#include "winbase.h"
     22#include "win.h"
    2023#include "commctrl.h"
     24#include "comctl32.h"
    2125#include "monthcal.h"
    22 
     26#include "winnls.h"
     27#include <stdio.h>
     28#include <string.h>
     29#include <stdlib.h>
     30
     31//DEFAULT_DEBUG_CHANNEL(monthcal)
     32
     33/* take #days/month from ole/parsedt.c;
     34 * we want full month-names, and abbreviated weekdays, so these are
     35 * defined here */
    2336
    2437#define MONTHCAL_GetInfoPtr(hwnd) ((MONTHCAL_INFO *)GetWindowLongA (hwnd, 0))
    2538
    26 
    27 
    28 
     39/* helper functions
     40 * MONTHCAL_ValidateTime: is time a valid date/time combo?
     41 */
     42
     43int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};
     44
     45int DayOfWeekTable[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
     46
     47static char *daytxt[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
     48
     49static char *monthtxt[] = {"January", "February", "March", "April", "May",
     50                           "June", "July", "August", "September", "October",
     51                           "November", "December"};
     52
     53/* CHECKME: all these validations OK? */
     54
     55static int MONTHCAL_ValidateTime (SYSTEMTIME time)
     56
     57{
     58 if (time.wMonth > 12) return FALSE;
     59 if (time.wDayOfWeek > 6) return FALSE;
     60 if (time.wDay > mdays[time.wMonth]) return FALSE;
     61 if (time.wMonth > 23) return FALSE;
     62 if (time.wMinute > 60) return FALSE;
     63 if (time.wSecond > 60) return FALSE;
     64 if (time.wMilliseconds > 100) return FALSE;
     65 return TRUE;
     66}
     67
     68void MONTHCAL_CopyTime (const SYSTEMTIME *from, SYSTEMTIME *to)
     69
     70{
     71 to->wYear=from->wYear;
     72 to->wMonth=from->wMonth;
     73 to->wDayOfWeek=from->wDayOfWeek;
     74 to->wDay=from->wDay;
     75 to->wHour=from->wHour;
     76 to->wMinute=from->wMinute;
     77 to->wSecond=from->wSecond;
     78 to->wMilliseconds=from->wMilliseconds;
     79}
     80
     81
     82/* Note:Depending on DST, this may be offset by a day.
     83   Need to find out if we're on a DST place & adjust the clock accordingly.
     84   Above function assumes we have a valid data.
     85   Valid for year>1752;  d <= 1 <= 31, 1 <= m <= 12.
     86   0=Monday.
     87*/
     88
     89
     90int MONTHCAL_CalculateDayOfWeek (DWORD day, DWORD month, DWORD year)
     91
     92{
     93 year -= month < 3;
     94 return (year + year/4 - year/100 + year/400 +
     95         DayOfWeekTable[month-1] + day - 1 ) % 7;
     96}
     97
     98
     99static int MONTHCAL_CalcDayFromPos (MONTHCAL_INFO *infoPtr, int x, int y)
     100
     101{
     102    int daypos,weekpos,retval,firstDay;
     103
     104    daypos=(x - infoPtr->prevmonth.left) / infoPtr->textWidth ;
     105    weekpos=(y - infoPtr->days.bottom - infoPtr->rcClient.top) /
     106                     (infoPtr->textHeight*1.25);
     107        firstDay=MONTHCAL_CalculateDayOfWeek (1,infoPtr->currentMonth,infoPtr->currentYear);
     108    retval=daypos + 7*weekpos - firstDay;
     109        //TRACE ("%d %d %d\n",daypos,weekpos,retval);
     110        return retval;
     111}
     112
     113
     114static void MONTHCAL_CalcDayXY (MONTHCAL_INFO *infoPtr, int day, int month,
     115                                 int *x, int *y)
     116
     117{
     118  int firstDay,prevMonth;
     119
     120  firstDay=MONTHCAL_CalculateDayOfWeek (1,infoPtr->currentMonth,infoPtr->currentYear);
     121
     122  if (month==infoPtr->currentMonth) {
     123        *x=(day+firstDay) & 7;
     124        *y=(day+firstDay-*x) / 7;
     125                return;
     126        }
     127  if (month < infoPtr->currentMonth) {
     128                prevMonth=month - 1;
     129                if (prevMonth==0) prevMonth=11;
     130        *x=(mdays[prevMonth]-firstDay) & 7;
     131                *y=0;
     132        }
     133
     134  *y=mdays[month] / 7;
     135  *x=(day+firstDay+mdays[month]) & 7;
     136}
     137
     138
     139static void MONTHCAL_CalcDayRect (MONTHCAL_INFO *infoPtr, RECT *r, int x, int y)
     140{
     141  r->left   = infoPtr->prevmonth.left + x * infoPtr->textWidth;
     142  r->right  = r->left + infoPtr->textWidth;
     143  r->top    = infoPtr->rcClient.top + y * 1.25 * infoPtr->textHeight
     144                                   + infoPtr->days.bottom;
     145  r->bottom = r->top + infoPtr->textHeight;
     146
     147}
     148
     149static void MONTHCAL_CalcPosFromDay (MONTHCAL_INFO *infoPtr,
     150                                            int day, int month, RECT *r)
     151
     152{
     153  int x,y;
     154
     155  MONTHCAL_CalcDayXY (infoPtr, day, month, &x, &y);
     156  MONTHCAL_CalcDayRect (infoPtr, r, x, y);
     157}
     158
     159
     160
     161
     162static void MONTHCAL_CircleDay (HDC hdc, MONTHCAL_INFO *infoPtr, int i, int j)
     163
     164{
     165        HPEN hRedPen = CreatePen(PS_SOLID, 2, RGB (255,0,0) );
     166    HPEN hOldPen2 = SelectObject( hdc, hRedPen );
     167        POINT points[7];
     168        int x,y;
     169
     170 /* use prevmonth to calculate position because it contains the extra width
     171  * from MCS_WEEKNUMBERS
     172  */
     173
     174        x=infoPtr->prevmonth.left + (i+0.5)*infoPtr->textWidth;
     175        y=infoPtr->rcClient.top + 1.25*(j+0.5)*infoPtr->textHeight + infoPtr->days.bottom;
     176        points[0].x = x;
     177        points[0].y = y-0.25*infoPtr->textHeight;
     178        points[1].x = x-1.0*infoPtr->textWidth;
     179        points[1].y = y;
     180        points[2].x = x;
     181        points[2].y = y+0.6*infoPtr->textHeight;
     182        points[3].x = x+0.5*infoPtr->textWidth;
     183        points[3].y = y;
     184        points[4].x = x+0.3*infoPtr->textWidth;
     185        points[4].y = y-0.5*infoPtr->textHeight;
     186        points[5].x = x-0.25*infoPtr->textWidth;
     187        points[5].y = y-0.5*infoPtr->textHeight;
     188        points[6].x = x-0.5*infoPtr->textWidth;
     189        points[6].y = y-0.45*infoPtr->textHeight;
     190
     191        PolyBezier (hdc,points,4);
     192        PolyBezier (hdc,points+3,4);
     193    DeleteObject (hRedPen);
     194        SelectObject (hdc, hOldPen2);
     195}
     196
     197
     198
     199
     200
     201static void MONTHCAL_DrawDay (HDC hdc, MONTHCAL_INFO *infoPtr,
     202                                                        int day, int month, int x, int y, int bold)
     203
     204{
     205  char buf[10];
     206  RECT r;
     207  static int haveBoldFont,haveSelectedDay=FALSE;
     208  HBRUSH hbr;
     209  COLORREF oldCol,oldBk;
     210
     211  sprintf (buf,"%d",day);
     212
     213
     214
     215/* No need to check styles: when selection is not valid, it is set to zero.
     216 * 1<day<31, so evertyhing's OK.
     217 */
     218
     219  MONTHCAL_CalcDayRect (infoPtr, &r, x, y);
     220
     221  if ((day>=infoPtr->minSel.wDay) && (day<=infoPtr->maxSel.wDay)
     222      && (month==infoPtr->currentMonth)) {
     223                HRGN hrgn;
     224                RECT r2;
     225
     226                //TRACE ("%d %d %d\n",day,infoPtr->minSel.wDay,infoPtr->maxSel.wDay);
     227                //TRACE ("%d %d %d %d\n", r.left, r.top, r.right, r.bottom);
     228                oldCol=SetTextColor (hdc, infoPtr->monthbk);
     229                oldBk=SetBkColor (hdc,infoPtr->trailingtxt);
     230                hbr= GetSysColorBrush (COLOR_GRAYTEXT);
     231                hrgn=CreateEllipticRgn (r.left,r.top, r.right,r.bottom);
     232                FillRgn (hdc,hrgn,hbr);
     233
     234                r2.left   = r.left-0.25*infoPtr->textWidth;
     235                r2.top    = r.top;
     236                r2.right  = r.left+0.5*infoPtr->textWidth;
     237                r2.bottom = r.bottom;
     238                if (haveSelectedDay) FillRect (hdc,&r2,hbr);
     239                haveSelectedDay=TRUE;
     240        } else {
     241                haveSelectedDay=FALSE;
     242        }
     243
     244
     245
     246/* need to add some code for multiple selections */
     247
     248  if ((bold) && (!haveBoldFont)) {
     249        SelectObject (hdc, infoPtr->hBoldFont);
     250                haveBoldFont=TRUE;
     251        }
     252  if ((!bold) && (haveBoldFont)) {
     253        SelectObject (hdc, infoPtr->hFont);
     254                haveBoldFont=FALSE;
     255        }
     256
     257
     258
     259  DrawTextA ( hdc, buf, lstrlenA(buf), &r,
     260                         DT_CENTER | DT_VCENTER | DT_SINGLELINE );
     261  if (haveSelectedDay) {
     262                SetTextColor(hdc, oldCol);
     263                SetBkColor (hdc, oldBk);
     264        }
     265
     266  if ((day==infoPtr->curSelDay) && (month==infoPtr->currentMonth)) {
     267                HPEN hNewPen, hOldPen;
     268
     269                hNewPen = CreatePen(PS_DOT, 0, GetSysColor(COLOR_WINDOWTEXT) );
     270                hbr= GetSysColorBrush (COLOR_WINDOWTEXT);
     271                hOldPen = SelectObject( hdc, hNewPen );
     272                r.left+=2;
     273                r.right-=2;
     274                r.top-=1;
     275                r.bottom+=1;
     276                FrameRect (hdc, &r, hbr);
     277                SelectObject( hdc, hOldPen );
     278  }
     279}
     280
     281
     282/* CHECKME: For `todays date', do we need to check the locale?*/
     283/* CHECKME: For `todays date', how do is Y2K handled?*/
     284/* FIXME:  todays date circle */
     285
     286static void MONTHCAL_Refresh (HWND hwnd, HDC hdc)
     287
     288{
     289    MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     290        RECT *rcClient=&infoPtr->rcClient;
     291        RECT *title=&infoPtr->title;
     292        RECT *prev=&infoPtr->titlebtnprev;
     293        RECT *next=&infoPtr->titlebtnnext;
     294        RECT *titlemonth=&infoPtr->titlemonth;
     295        RECT *titleyear=&infoPtr->titleyear;
     296        RECT *prevmonth=&infoPtr->prevmonth;
     297        RECT *nextmonth=&infoPtr->nextmonth;
     298        RECT *days=&infoPtr->days;
     299        RECT *weeknums=&infoPtr->weeknums;
     300        RECT *rtoday=&infoPtr->today;
     301    int i,j,m,mask,day,firstDay, weeknum,prevMonth;
     302    int textHeight,textWidth;
     303        SIZE size;
     304        HBRUSH hbr;
     305    HFONT currentFont;
     306        TEXTMETRICA tm;
     307/*    LOGFONTA logFont; */
     308        char buf[20],*thisMonthtxt;
     309    COLORREF oldTextColor,oldBkColor;
     310    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
     311        BOOL prssed;
     312
     313
     314    oldTextColor = SetTextColor(hdc, GetSysColor( COLOR_WINDOWTEXT));
     315
     316    currentFont = SelectObject (hdc, infoPtr->hFont);
     317
     318        /* FIXME: need a way to determine current font, without setting it */
     319/*
     320        if (infoPtr->hFont!=currentFont) {
     321        SelectObject (hdc, currentFont);
     322                infoPtr->hFont=currentFont;
     323                GetObjectA (currentFont, sizeof (LOGFONTA), &logFont);
     324        logFont.lfWeight=FW_BOLD;
     325        infoPtr->hBoldFont = CreateFontIndirectA (&logFont);
     326        }
     327*/
     328
     329        GetTextMetricsA (hdc, &tm);
     330        infoPtr->textHeight=textHeight=tm.tmHeight + tm.tmExternalLeading;
     331    GetTextExtentPoint32A (hdc, "Sun",3, &size);
     332        infoPtr->textWidth=textWidth=size.cx+2;
     333
     334    GetClientRect (hwnd, rcClient);
     335    hbr =  CreateSolidBrush (RGB(255,255,255));
     336    DrawEdge (hdc, rcClient, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
     337    FillRect (hdc, rcClient, hbr);
     338    DeleteObject (hbr);
     339
     340/* calculate whole client area & title area */
     341
     342        infoPtr->rcClient.right=7*infoPtr->textWidth;
     343        if (dwStyle & MCS_WEEKNUMBERS)
     344          infoPtr->rcClient.right+=infoPtr->textWidth;
     345
     346        title->top    = rcClient->top + 1;
     347        title->bottom = title->top + 2*textHeight + 4;
     348        title->left   = rcClient->left + 1;
     349        title->right  = rcClient->right - 1;
     350        infoPtr->rcClient.bottom=title->bottom + 6*textHeight;
     351
     352
     353/* draw header */
     354
     355    hbr =  CreateSolidBrush (infoPtr->titlebk);
     356    FillRect (hdc, title, hbr);
     357
     358        prev->top                 = next->top        = title->top + 6;
     359        prev->bottom      = next->bottom     = title->top + 2*textHeight - 3;
     360        prev->right       = title->left  + 28;
     361        prev->left        = title->left  + 4;
     362        next->left        = title->right - 28;
     363        next->right       = title->right - 4;
     364        titlemonth->bottom= titleyear->bottom = prev->top + 2*textHeight - 3;
     365        titlemonth->top   = titleyear->top    = title->top + 6;
     366        titlemonth->left  = title->left;
     367        titlemonth->right = title->right;
     368        prssed=FALSE;
     369
     370        if (!(infoPtr->status & MC_PREVPRESSED))
     371           DrawFrameControl(hdc, prev, DFC_SCROLL,
     372                        DFCS_SCROLLLEFT | (dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
     373
     374        if (!(infoPtr->status & MC_NEXTPRESSED))
     375        DrawFrameControl(hdc, next, DFC_SCROLL,
     376                DFCS_SCROLLRIGHT | (dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
     377
     378    oldBkColor=SetBkColor (hdc,infoPtr->titlebk);
     379    SetTextColor(hdc, infoPtr->titletxt);
     380        SelectObject (hdc, infoPtr->hBoldFont);
     381
     382        thisMonthtxt=monthtxt[infoPtr->currentMonth - 1];
     383        sprintf (buf,"%s %ld",thisMonthtxt,infoPtr->currentYear);
     384    DrawTextA ( hdc, buf, strlen(buf), titlemonth,
     385                        DT_CENTER | DT_VCENTER | DT_SINGLELINE );
     386        SelectObject (hdc, infoPtr->hFont);
     387
     388 /* titlemonth left/right contained rect for whole titletxt ('June  1999')
     389  * MCM_HitTestInfo wants month & year rects, so prepare these now.
     390  * (no, we can't draw them separately; the whole text is centered)
     391  */
     392
     393    GetTextExtentPoint32A (hdc, buf,lstrlenA (buf), &size);
     394        titlemonth->left = title->right/2 - size.cx/2;
     395        titleyear->right = title->right/2 + size.cx/2;
     396    GetTextExtentPoint32A (hdc, thisMonthtxt,lstrlenA (thisMonthtxt), &size);
     397    titlemonth->right= titlemonth->left+size.cx;
     398    titleyear->right = titlemonth->right;
     399
     400/* draw line under day abbreviatons */
     401
     402         if (dwStyle & MCS_WEEKNUMBERS)
     403                MoveToEx (hdc, rcClient->left+textWidth+3,
     404                       title->bottom + textHeight + 2, NULL);
     405         else
     406                MoveToEx (hdc, rcClient->left+3, title->bottom + textHeight + 2, NULL);
     407     LineTo   (hdc, rcClient->right-3, title->bottom + textHeight + 2);
     408
     409/* draw day abbreviations */
     410
     411    SetBkColor (hdc, infoPtr->monthbk);
     412    SetTextColor(hdc, infoPtr->trailingtxt);
     413
     414        days->left   = rcClient->left;
     415        if (dwStyle & MCS_WEEKNUMBERS) days->left+=textWidth;
     416    days->right  = days->left + textWidth;
     417    days->top    = title->bottom + 2;
     418    days->bottom = title->bottom + textHeight + 2;
     419        i=infoPtr->firstDay;
     420
     421        for (j=0; j<7; j++) {
     422            DrawTextA ( hdc, daytxt[i], strlen(daytxt[i]), days,
     423                         DT_CENTER | DT_VCENTER | DT_SINGLELINE );
     424                        i++;
     425                        if (i>7) i-=7;
     426                        days->left+=textWidth;
     427                        days->right+=textWidth;
     428        }
     429
     430        days->left   = rcClient->left + j;
     431        if (dwStyle & MCS_WEEKNUMBERS) days->left+=textWidth;
     432    days->right  = rcClient->left + (j+1)*textWidth-2;
     433
     434/* draw day numbers; first, the previous month */
     435
     436        prevmonth->left=0;
     437        if (dwStyle & MCS_WEEKNUMBERS) prevmonth->left=textWidth;
     438
     439        firstDay=MONTHCAL_CalculateDayOfWeek (1,infoPtr->currentMonth,infoPtr->currentYear);
     440        prevMonth=infoPtr->currentMonth-1;
     441        if (prevMonth==0) prevMonth=11;
     442        day=mdays[prevMonth]-firstDay;
     443        mask=1<<(day-1);
     444
     445        i=0;
     446        m=0;
     447        while (day<=mdays[prevMonth]) {
     448                        MONTHCAL_DrawDay (hdc, infoPtr, day, prevMonth, i, 0,
     449                                                infoPtr->monthdayState[m] & mask);
     450                        mask<<=1;
     451                        day++;
     452                        i++;
     453        }
     454
     455        prevmonth->right = prevmonth->left+i*textWidth;
     456        prevmonth->top   = days->bottom;
     457        prevmonth->bottom= prevmonth->top + textHeight;
     458
     459/* draw `current' month  */
     460
     461        day=1;
     462        infoPtr->firstDayplace=i;
     463    SetTextColor(hdc, infoPtr->txt);
     464        m++;
     465        mask=1;
     466        while (i<7) {
     467                        MONTHCAL_DrawDay (hdc, infoPtr, day, infoPtr->currentMonth, i, 0,
     468                                                infoPtr->monthdayState[m] & mask);
     469                        if ((infoPtr->currentMonth==infoPtr->todaysDate.wMonth) &&
     470                (day==infoPtr->todaysDate.wDay))
     471                                        MONTHCAL_CircleDay (hdc, infoPtr, i,j);
     472                        mask<<=1;
     473                        day++;
     474                        i++;
     475                }
     476
     477        j=1;
     478        i=0;
     479        while (day<=mdays[infoPtr->currentMonth]) {
     480                        MONTHCAL_DrawDay (hdc, infoPtr, day, infoPtr->currentMonth, i, j,
     481                                                infoPtr->monthdayState[m] & mask);
     482                        if ((infoPtr->currentMonth==infoPtr->todaysDate.wMonth) &&
     483                (day==infoPtr->todaysDate.wDay))
     484                                        MONTHCAL_CircleDay (hdc, infoPtr, i,j);
     485                        mask<<=1;
     486                        day++;
     487                        i++;
     488                        if (i>6) {
     489                                i=0;
     490                                j++;
     491                        }
     492        }
     493
     494/*  draw `next' month */
     495
     496/* note: the nextmonth rect only hints for the `half-week' that needs to be
     497 * drawn to complete the current week. An eventual next week that needs to
     498 * be drawn to complete the month calendar is not taken into account in
     499 * this rect -- HitTest knows about this.*/
     500
     501
     502
     503        nextmonth->left   = prevmonth->left+i*textWidth;
     504        nextmonth->right  = rcClient->right;
     505        nextmonth->top    = days->bottom+(j+1)*textHeight;
     506        nextmonth->bottom = nextmonth->top + textHeight;
     507
     508        day=1;
     509        m++;
     510        mask=1;
     511    SetTextColor(hdc, infoPtr->trailingtxt);
     512        while ((i<7) && (j<6)) {
     513                        MONTHCAL_DrawDay (hdc, infoPtr, day, infoPtr->currentMonth+1, i, j,
     514                                                infoPtr->monthdayState[m] & mask);
     515                        mask<<=1;
     516                        day++;
     517                        i++;
     518                        if (i==7) {
     519                                i=0;
     520                                j++;
     521                        }
     522        }
     523    SetTextColor(hdc, infoPtr->txt);
     524
     525
     526
     527/* draw `today' date if style allows it, and draw a circle before today's
     528 * date if necessairy */
     529
     530        if (!( dwStyle & MCS_NOTODAY))  {
     531        int offset=0;
     532        if (!( dwStyle & MCS_NOTODAYCIRCLE))  {
     533                        MONTHCAL_CircleDay (hdc, infoPtr, 0, 6);
     534                        offset+=textWidth;
     535                }
     536
     537                MONTHCAL_CalcDayRect (infoPtr, rtoday, offset==textWidth, 6);
     538                sprintf (buf,"Today: %d/%d/%d",infoPtr->todaysDate.wMonth,
     539                        infoPtr->todaysDate.wDay, infoPtr->todaysDate.wYear-1900);
     540                rtoday->right  = rcClient->right;
     541        SelectObject (hdc, infoPtr->hBoldFont);
     542            DrawTextA ( hdc, buf, lstrlenA(buf), rtoday,
     543                         DT_LEFT | DT_VCENTER | DT_SINGLELINE );
     544        SelectObject (hdc, infoPtr->hFont);
     545        }
     546
     547        if (dwStyle & MCS_WEEKNUMBERS)  {
     548                        /* display weeknumbers*/
     549
     550                weeknums->left   = 0;
     551                weeknums->right  = textWidth;
     552                weeknums->top    = days->bottom + 2;
     553                weeknums->bottom = days->bottom + 2 + textHeight;
     554
     555                weeknum=0;
     556                for (i=0; i<infoPtr->currentMonth-1; i++)
     557                        weeknum+=mdays[i];
     558
     559                weeknum/=7;
     560                for (i=0; i<6; i++) {
     561                        sprintf (buf,"%d",weeknum+i);
     562                DrawTextA ( hdc, buf, lstrlenA(buf), weeknums,
     563                         DT_CENTER | DT_BOTTOM | DT_SINGLELINE );
     564                        weeknums->top+=textHeight*1.25;
     565                        weeknums->bottom+=textHeight*1.25;
     566                }
     567
     568            MoveToEx (hdc, weeknums->right, days->bottom+5 , NULL);
     569        LineTo   (hdc, weeknums->right, weeknums->bottom-1.25*textHeight-5);
     570
     571        }
     572
     573                                 /* currentFont was font at entering Refresh */
     574
     575    SetBkColor (hdc, oldBkColor);
     576    SelectObject (hdc, currentFont);
     577    SetTextColor (hdc, oldTextColor);
     578}
     579
     580
     581static LRESULT
     582MONTHCAL_GetMinReqRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
     583
     584{
     585    MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     586        LPRECT lpRect=(LPRECT) lParam;
     587        //TRACE ("%x %lx\n",wParam,lParam);
     588
     589  /* validate parameters */
     590
     591    if ( (infoPtr==NULL) || (lpRect == NULL) ) return FALSE;
     592
     593        lpRect->left=infoPtr->rcClient.left;
     594        lpRect->right=infoPtr->rcClient.right;
     595        lpRect->top=infoPtr->rcClient.top;
     596        lpRect->bottom=infoPtr->rcClient.bottom;
     597        return TRUE;
     598}
     599
     600static LRESULT
     601MONTHCAL_GetColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
     602
     603{
     604    MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     605
     606        //TRACE ("%x %lx\n",wParam,lParam);
     607
     608        switch ((int)wParam) {
     609                case MCSC_BACKGROUND:
     610                        return infoPtr->bk;
     611                case MCSC_TEXT:
     612                        return infoPtr->txt;
     613                case MCSC_TITLEBK:
     614                        return infoPtr->titlebk;
     615                case MCSC_TITLETEXT:
     616                        return infoPtr->titletxt;
     617                case MCSC_MONTHBK:
     618                        return infoPtr->monthbk;
     619                case MCSC_TRAILINGTEXT:
     620                        return infoPtr->trailingtxt;
     621        }
     622
     623 return -1;
     624}
     625
     626static LRESULT
     627MONTHCAL_SetColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
     628
     629{
     630    MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     631        int prev=-1;
     632
     633        //TRACE ("%x %lx\n",wParam,lParam);
     634
     635        switch ((int)wParam) {
     636                case MCSC_BACKGROUND:
     637                        prev=infoPtr->bk;
     638                        infoPtr->bk=(COLORREF) lParam;
     639                        break;
     640                case MCSC_TEXT:
     641                        prev=infoPtr->txt;
     642                        infoPtr->txt=(COLORREF) lParam;
     643                        break;
     644                case MCSC_TITLEBK:
     645                        prev=infoPtr->titlebk;
     646                        infoPtr->titlebk=(COLORREF) lParam;
     647                        break;
     648                case MCSC_TITLETEXT:
     649                        prev=infoPtr->titletxt;
     650                        infoPtr->titletxt=(COLORREF) lParam;
     651                        break;
     652                case MCSC_MONTHBK:
     653                        prev=infoPtr->monthbk;
     654                        infoPtr->monthbk=(COLORREF) lParam;
     655                        break;
     656                case MCSC_TRAILINGTEXT:
     657                        prev=infoPtr->trailingtxt;
     658                        infoPtr->trailingtxt=(COLORREF) lParam;
     659                        break;
     660        }
     661
     662 return prev;
     663}
     664
     665static LRESULT
     666MONTHCAL_GetMonthDelta (HWND hwnd, WPARAM wParam, LPARAM lParam)
     667
     668{
     669    MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     670
     671        //TRACE ("%x %lx\n",wParam,lParam);
     672
     673        if (infoPtr->delta) return infoPtr->delta;
     674        else return infoPtr->visible;
     675}
     676
     677static LRESULT
     678MONTHCAL_SetMonthDelta (HWND hwnd, WPARAM wParam, LPARAM lParam)
     679
     680{
     681    MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     682    int prev=infoPtr->delta;
     683
     684        //TRACE ("%x %lx\n",wParam,lParam);
     685
     686        infoPtr->delta=(int) wParam;
     687        return prev;
     688}
     689
     690
     691
     692static LRESULT
     693MONTHCAL_GetFirstDayOfWeek (HWND hwnd, WPARAM wParam, LPARAM lParam)
     694{
     695    MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     696
     697        return infoPtr->firstDay;
     698}
     699
     700/* FIXME: we need more error checking here */
     701
     702static LRESULT
     703MONTHCAL_SetFirstDayOfWeek (HWND hwnd, WPARAM wParam, LPARAM lParam)
     704
     705{
     706    MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     707    int prev=infoPtr->firstDay;
     708        char buf[40];
     709        int day;
     710
     711        //TRACE ("%x %lx\n",wParam,lParam);
     712
     713        if ((lParam>=0) && (lParam<7)) {
     714                        infoPtr->firstDay=(int) lParam;
     715                        GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IFIRSTDAYOFWEEK,
     716                buf, sizeof(buf));
     717                //TRACE ("%s %d\n",buf,strlen(buf));
     718            if ((sscanf(buf,"%d",&day)==1) && (infoPtr->firstDay!=day))
     719                                infoPtr->firstDay|=HIWORD(TRUE);
     720
     721        }
     722    return prev;
     723}
     724
     725
     726
     727/* FIXME: fill this in */
     728
     729static LRESULT
     730MONTHCAL_GetMonthRange (HWND hwnd, WPARAM wParam, LPARAM lParam)
     731{
     732  MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     733
     734  //TRACE ("%x %lx\n",wParam,lParam);
     735
     736  return infoPtr->monthRange;
     737}
     738
     739static LRESULT
     740MONTHCAL_GetMaxTodayWidth (HWND hwnd)
     741
     742{
     743 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     744
     745 return (infoPtr->today.right-infoPtr->today.left);
     746}
     747
     748/* FIXME: are validated times taken from current date/time or simply
     749 * copied?
     750 * FIXME:    check whether MCM_GETMONTHRANGE shows correct result after
     751 *            adjusting range with MCM_SETRANGE
     752 */
     753
     754static LRESULT
     755MONTHCAL_SetRange (HWND hwnd, WPARAM wParam, LPARAM lParam)
     756{
     757  MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     758  SYSTEMTIME lprgSysTimeArray[1];
     759  int prev;
     760
     761  //TRACE ("%x %lx\n",wParam,lParam);
     762
     763  if (wParam & GDTR_MAX) {
     764                if (MONTHCAL_ValidateTime(lprgSysTimeArray[1])){
     765                        MONTHCAL_CopyTime (&lprgSysTimeArray[1],&infoPtr->maxDate);
     766                        infoPtr->rangeValid|=GDTR_MAX;
     767                } else  {
     768                        GetSystemTime (&infoPtr->todaysDate);
     769                        MONTHCAL_CopyTime (&infoPtr->todaysDate,&infoPtr->maxDate);
     770                        }
     771                }
     772  if (wParam & GDTR_MIN) {
     773                if (MONTHCAL_ValidateTime(lprgSysTimeArray[0])) {
     774                        MONTHCAL_CopyTime (&lprgSysTimeArray[0],&infoPtr->maxDate);
     775                        infoPtr->rangeValid|=GDTR_MIN;
     776                } else {
     777                        GetSystemTime (&infoPtr->todaysDate);
     778                        MONTHCAL_CopyTime (&infoPtr->todaysDate,&infoPtr->maxDate);
     779                        }
     780            }
     781
     782  prev=infoPtr->monthRange;
     783  infoPtr->monthRange=infoPtr->maxDate.wMonth-infoPtr->minDate.wMonth;
     784  if (infoPtr->monthRange!=prev)
     785        COMCTL32_ReAlloc (infoPtr->monthdayState,
     786                infoPtr->monthRange*sizeof(MONTHDAYSTATE));
     787
     788  return 1;
     789}
     790
     791
     792/* CHECKME: At the moment, we copy ranges anyway,regardless of
     793 * infoPtr->rangeValid; a invalid range is simply filled with zeros in
     794 * SetRange.  Is this the right behavior?
     795*/
     796
     797static LRESULT
     798MONTHCAL_GetRange (HWND hwnd, WPARAM wParam, LPARAM lParam)
     799{
     800  MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     801  SYSTEMTIME *lprgSysTimeArray=(SYSTEMTIME *) lParam;
     802
     803  /* validate parameters */
     804
     805  if ( (infoPtr==NULL) || (lprgSysTimeArray==NULL) ) return FALSE;
     806
     807  MONTHCAL_CopyTime (&infoPtr->maxDate,&lprgSysTimeArray[1]);
     808  MONTHCAL_CopyTime (&infoPtr->minDate,&lprgSysTimeArray[0]);
     809
     810  return infoPtr->rangeValid;
     811}
     812
     813static LRESULT
     814MONTHCAL_SetDayState (HWND hwnd, WPARAM wParam, LPARAM lParam)
     815
     816{
     817  MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     818  int i,iMonths=(int) wParam;
     819  MONTHDAYSTATE *dayStates=(LPMONTHDAYSTATE) lParam;
     820
     821  //TRACE ("%x %lx\n",wParam,lParam);
     822  if (iMonths!=infoPtr->monthRange) return 0;
     823
     824  for (i=0; i<iMonths; i++)
     825                infoPtr->monthdayState[i]=dayStates[i];
     826  return 1;
     827}
     828
     829static LRESULT
     830MONTHCAL_GetCurSel (HWND hwnd, WPARAM wParam, LPARAM lParam)
     831{
     832  MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     833  SYSTEMTIME *lpSel=(SYSTEMTIME *) lParam;
     834
     835  //TRACE ("%x %lx\n",wParam,lParam);
     836  if ( (infoPtr==NULL) || (lpSel==NULL) ) return FALSE;
     837  if ( GetWindowLongA( hwnd, GWL_STYLE) & MCS_MULTISELECT) return FALSE;
     838
     839  MONTHCAL_CopyTime (&infoPtr->minSel,lpSel);
     840  return TRUE;
     841}
     842
     843
     844/* FIXME: if the specified date is not visible, make it visible */
     845/* FIXME: redraw? */
     846
     847static LRESULT
     848MONTHCAL_SetCurSel (HWND hwnd, WPARAM wParam, LPARAM lParam)
     849{
     850  MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     851  SYSTEMTIME *lpSel=(SYSTEMTIME *) lParam;
     852
     853  //TRACE ("%x %lx\n",wParam,lParam);
     854  if ( (infoPtr==NULL) || (lpSel==NULL) ) return FALSE;
     855  if ( GetWindowLongA( hwnd, GWL_STYLE) & MCS_MULTISELECT) return FALSE;
     856
     857  //TRACE ("%d %d\n",lpSel->wMonth,lpSel->wDay);
     858
     859  MONTHCAL_CopyTime (lpSel,&infoPtr->minSel);
     860  MONTHCAL_CopyTime (lpSel,&infoPtr->maxSel);
     861
     862  return TRUE;
     863}
     864
     865static LRESULT
     866MONTHCAL_GetMaxSelCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
     867{
     868  MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     869
     870  //TRACE ("%x %lx\n",wParam,lParam);
     871  return infoPtr->maxSelCount;
     872}
     873
     874static LRESULT
     875MONTHCAL_SetMaxSelCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
     876{
     877  MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     878
     879  //TRACE ("%x %lx\n",wParam,lParam);
     880  if ( GetWindowLongA( hwnd, GWL_STYLE) & MCS_MULTISELECT)  {
     881                infoPtr->maxSelCount=wParam;
     882  }
     883
     884  return TRUE;
     885}
     886
     887
     888static LRESULT
     889MONTHCAL_GetSelRange (HWND hwnd, WPARAM wParam, LPARAM lParam)
     890{
     891  MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     892  SYSTEMTIME *lprgSysTimeArray=(SYSTEMTIME *) lParam;
     893
     894  //TRACE ("%x %lx\n",wParam,lParam);
     895
     896  /* validate parameters */
     897
     898  if ( (infoPtr==NULL) || (lprgSysTimeArray==NULL) ) return FALSE;
     899
     900  if ( GetWindowLongA( hwnd, GWL_STYLE) & MCS_MULTISELECT)  {
     901                MONTHCAL_CopyTime (&infoPtr->maxSel,&lprgSysTimeArray[1]);
     902        MONTHCAL_CopyTime (&infoPtr->minSel,&lprgSysTimeArray[0]);
     903                //TRACE ("[min,max]=[%d %d]\n",infoPtr->minSel.wDay,infoPtr->maxSel.wDay);
     904        return TRUE;
     905  }
     906
     907  return FALSE;
     908}
     909
     910static LRESULT
     911MONTHCAL_SetSelRange (HWND hwnd, WPARAM wParam, LPARAM lParam)
     912{
     913  MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     914  SYSTEMTIME *lprgSysTimeArray=(SYSTEMTIME *) lParam;
     915
     916  //TRACE ("%x %lx\n",wParam,lParam);
     917
     918  /* validate parameters */
     919
     920  if ( (infoPtr==NULL) || (lprgSysTimeArray==NULL) ) return FALSE;
     921
     922  if ( GetWindowLongA( hwnd, GWL_STYLE) & MCS_MULTISELECT)  {
     923                MONTHCAL_CopyTime (&lprgSysTimeArray[1],&infoPtr->maxSel);
     924        MONTHCAL_CopyTime (&lprgSysTimeArray[0],&infoPtr->minSel);
     925                //TRACE ("[min,max]=[%d %d]\n",infoPtr->minSel.wDay,infoPtr->maxSel.wDay);
     926        return TRUE;
     927  }
     928
     929  return FALSE;
     930}
     931
     932
     933
     934
     935static LRESULT
     936MONTHCAL_GetToday (HWND hwnd, WPARAM wParam, LPARAM lParam)
     937{
     938  MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     939  SYSTEMTIME *lpToday=(SYSTEMTIME *) lParam;
     940
     941  //TRACE ("%x %lx\n",wParam,lParam);
     942
     943  /* validate parameters */
     944
     945  if ( (infoPtr==NULL) || (lpToday==NULL) ) return FALSE;
     946  MONTHCAL_CopyTime (&infoPtr->todaysDate,lpToday);
     947  return TRUE;
     948}
     949
     950
     951static LRESULT
     952MONTHCAL_SetToday (HWND hwnd, WPARAM wParam, LPARAM lParam)
     953{
     954  MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     955  SYSTEMTIME *lpToday=(SYSTEMTIME *) lParam;
     956
     957  //TRACE ("%x %lx\n",wParam,lParam);
     958
     959  /* validate parameters */
     960
     961  if ( (infoPtr==NULL) || (lpToday==NULL) ) return FALSE;
     962  MONTHCAL_CopyTime (lpToday, &infoPtr->todaysDate);
     963  return TRUE;
     964}
     965
     966
     967
     968
     969static LRESULT
     970MONTHCAL_HitTest (HWND hwnd, LPARAM lParam)
     971{
     972 MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
     973 PMCHITTESTINFO lpht=(PMCHITTESTINFO) lParam;
     974 UINT x,y;
     975 DWORD retval;
     976
     977 x=lpht->pt.x;
     978 y=lpht->pt.y;
     979 retval=MCHT_NOWHERE;
     980
     981
     982        /* are we in the header? */
     983
     984 if (PtInRect (&infoPtr->title, lpht->pt)) {
     985
     986                if (PtInRect (&infoPtr->titlebtnprev, lpht->pt)) {
     987                        retval=MCHT_TITLEBTNPREV;
     988                        goto done;
     989                }
     990                if (PtInRect (&infoPtr->titlebtnnext, lpht->pt)) {
     991                        retval=MCHT_TITLEBTNNEXT;
     992                        goto done;
     993                }
     994                if (PtInRect (&infoPtr->titlemonth, lpht->pt)) {
     995                        retval=MCHT_TITLEMONTH;
     996                        goto done;
     997                }
     998                if (PtInRect (&infoPtr->titleyear, lpht->pt)) {
     999                        retval=MCHT_TITLEYEAR;
     1000                        goto done;
     1001                }
     1002                retval=MCHT_TITLE;
     1003                goto done;
     1004        }
     1005
     1006 if (PtInRect (&infoPtr->days, lpht->pt)) {
     1007                retval=MCHT_CALENDARDAY;  /* FIXME: find out which day we're on */
     1008                goto done;
     1009        }
     1010 if (PtInRect (&infoPtr->weeknums, lpht->pt)) {
     1011                retval=MCHT_CALENDARWEEKNUM;/* FIXME: find out which day we're on */
     1012                goto done;
     1013        }
     1014 if (PtInRect (&infoPtr->prevmonth, lpht->pt)) {
     1015                retval=MCHT_CALENDARDATEPREV;
     1016                goto done;
     1017        }
     1018 if (PtInRect (&infoPtr->nextmonth, lpht->pt) ||
     1019    ((x>infoPtr->nextmonth.left) && (x<infoPtr->nextmonth.right) &&
     1020     (y>infoPtr->nextmonth.bottom) && (y<infoPtr->today.top ))) {
     1021                retval=MCHT_CALENDARDATENEXT;
     1022                goto done;
     1023        }
     1024
     1025
     1026 if (PtInRect (&infoPtr->today, lpht->pt)) {
     1027                retval=MCHT_TODAYLINK;
     1028                goto done;
     1029        }
     1030
     1031/* MCHT_CALENDARDATE determination: since the next & previous month have
     1032 * been handled already (MCHT_CALENDARDATEPREV/NEXT), we only have to check
     1033 * whether we're in the calendar area. infoPtr->prevMonth.left handles the
     1034 * MCS_WEEKNUMBERS style nicely.
     1035 */
     1036
     1037
     1038 //TRACE ("%d %d [%d %d %d %d] [%d %d %d %d]\n",x,y,
     1039 //       infoPtr->prevmonth.left, infoPtr->prevmonth.right,
     1040 //       infoPtr->prevmonth.top, infoPtr->prevmonth.bottom,
     1041 //       infoPtr->nextmonth.left, infoPtr->nextmonth.right,
     1042 //       infoPtr->nextmonth.top, infoPtr->nextmonth.bottom);
     1043
     1044 if ((x>infoPtr->prevmonth.left) && (x<infoPtr->nextmonth.right) &&
     1045         (y>infoPtr->prevmonth.top) && (y<infoPtr->nextmonth.bottom))  {
     1046                lpht->st.wYear=infoPtr->currentYear;
     1047                lpht->st.wMonth=infoPtr->currentMonth;
     1048
     1049                lpht->st.wDay=MONTHCAL_CalcDayFromPos (infoPtr,x,y);
     1050
     1051                //TRACE ("day hit: %d\n",lpht->st.wDay);
     1052                retval=MCHT_CALENDARDATE;
     1053                goto done;
     1054
     1055        }
     1056
     1057        /* Hit nothing special? What's left must be background :-) */
     1058
     1059  retval=MCHT_CALENDARBK;
     1060 done:
     1061  lpht->uHit=retval;
     1062  return retval;
     1063}
     1064
     1065
     1066
     1067static void MONTHCAL_GoToNextMonth (HWND hwnd,  MONTHCAL_INFO *infoPtr)
     1068{
     1069    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
     1070
     1071        //TRACE ("\n");
     1072
     1073        infoPtr->currentMonth++;
     1074        if (infoPtr->currentMonth>12) {
     1075                infoPtr->currentYear++;
     1076                infoPtr->currentMonth=1;
     1077        }
     1078
     1079        if (dwStyle & MCS_DAYSTATE) {
     1080                NMDAYSTATE nmds;
     1081                int i;
     1082
     1083        nmds.nmhdr.hwndFrom = hwnd;
     1084                nmds.nmhdr.idFrom   = GetWindowLongA( hwnd, GWL_ID);
     1085                nmds.nmhdr.code     = MCN_GETDAYSTATE;
     1086                nmds.cDayState          = infoPtr->monthRange;
     1087                nmds.prgDayState        = COMCTL32_Alloc
     1088                                 (infoPtr->monthRange*sizeof(MONTHDAYSTATE));
     1089
     1090                SendMessageA (GetParent (hwnd), WM_NOTIFY,
     1091                                  (WPARAM)nmds.nmhdr.idFrom, (LPARAM)&nmds);
     1092                for (i=0; i<infoPtr->monthRange; i++)
     1093                infoPtr->monthdayState[i]=nmds.prgDayState[i];
     1094        }
     1095
     1096}
     1097
     1098
     1099static void MONTHCAL_GoToPrevMonth (HWND hwnd,  MONTHCAL_INFO *infoPtr)
     1100{
     1101    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
     1102
     1103        //TRACE ("\n");
     1104
     1105        infoPtr->currentMonth--;
     1106        if (infoPtr->currentMonth<1) {
     1107                infoPtr->currentYear--;
     1108                infoPtr->currentMonth=12;
     1109        }
     1110
     1111        if (dwStyle & MCS_DAYSTATE) {
     1112                NMDAYSTATE nmds;
     1113                int i;
     1114
     1115        nmds.nmhdr.hwndFrom = hwnd;
     1116                nmds.nmhdr.idFrom   = GetWindowLongA( hwnd, GWL_ID);
     1117                nmds.nmhdr.code     = MCN_GETDAYSTATE;
     1118                nmds.cDayState          = infoPtr->monthRange;
     1119                nmds.prgDayState        = COMCTL32_Alloc
     1120                                 (infoPtr->monthRange*sizeof(MONTHDAYSTATE));
     1121
     1122                SendMessageA (GetParent (hwnd), WM_NOTIFY,
     1123                                 (WPARAM)nmds.nmhdr.idFrom, (LPARAM)&nmds);
     1124                for (i=0; i<infoPtr->monthRange; i++)
     1125                infoPtr->monthdayState[i]=nmds.prgDayState[i];
     1126        }
     1127}
     1128
     1129
     1130static LRESULT
     1131MONTHCAL_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
     1132
     1133{
     1134    MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr (hwnd);
     1135        MCHITTESTINFO ht;
     1136        HDC hdc;
     1137        DWORD hit;
     1138        HMENU hMenu;
     1139        HWND retval;
     1140
     1141
     1142        //TRACE ("%x %lx\n",wParam,lParam);
     1143
     1144    ht.pt.x = (INT)LOWORD(lParam);
     1145    ht.pt.y = (INT)HIWORD(lParam);
     1146    hit=MONTHCAL_HitTest (hwnd, (LPARAM) &ht);
     1147
     1148    hdc=GetDC (hwnd);
     1149
     1150        if (hit & MCHT_NEXT){
     1151                MONTHCAL_GoToNextMonth (hwnd, infoPtr);
     1152                infoPtr->status=MC_NEXTPRESSED;
     1153                SetTimer (hwnd, MC_NEXTMONTHTIMER, MC_NEXTMONTHDELAY,0);
     1154        }
     1155        if (hit & MCHT_PREV) {
     1156                MONTHCAL_GoToPrevMonth (hwnd, infoPtr);
     1157                infoPtr->status=MC_PREVPRESSED;
     1158                SetTimer (hwnd, MC_PREVMONTHTIMER, MC_NEXTMONTHDELAY,0);
     1159        }
     1160
     1161        if (hit == MCHT_TITLEMONTH) {
     1162/*
     1163                HRSRC hrsrc = FindResourceA( COMCTL32_hModule, MAKEINTRESOURCEA(IDD_MCMONTHMENU), RT_MENUA );
     1164        if (!hrsrc) {
     1165                        TRACE ("returning zero\n");
     1166                        return 0;
     1167                }
     1168                TRACE ("resource is:%x\n",hrsrc);
     1169        hMenu=LoadMenuIndirectA( (LPCVOID)LoadResource( COMCTL32_hModule, hrsrc ));
     1170
     1171                TRACE ("menu is:%x\n",hMenu);
     1172*/
     1173
     1174                hMenu=CreateMenu ();
     1175        AppendMenuA (hMenu,MF_STRING,IDM_JAN,"January");
     1176        AppendMenuA (hMenu,MF_STRING,IDM_FEB,"February");
     1177        AppendMenuA (hMenu,MF_STRING,IDM_MAR,"March");
     1178
     1179                retval=CreateWindowA (POPUPMENU_CLASS_ATOM, NULL,
     1180                        WS_CHILD | WS_VISIBLE,
     1181                        0,0,100,220,
     1182                        hwnd, hMenu, GetWindowLongA (hwnd, GWL_HINSTANCE), NULL);
     1183                //TRACE ("hwnd returned:%x\n",retval);
     1184
     1185        }
     1186        if (hit == MCHT_TITLEYEAR) {
     1187                        //FIXME ("create updown for yearselection\n");
     1188        }
     1189        if (hit == MCHT_TODAYLINK) {
     1190                        //FIXME ("set currentday\n");
     1191        }
     1192        if (hit == MCHT_CALENDARDATE) {
     1193                        SYSTEMTIME selArray[2];
     1194                        NMSELCHANGE nmsc;
     1195
     1196                        //TRACE ("\n");
     1197                    nmsc.nmhdr.hwndFrom = hwnd;
     1198                nmsc.nmhdr.idFrom   = GetWindowLongA( hwnd, GWL_ID);
     1199                nmsc.nmhdr.code     = MCN_SELCHANGE;
     1200                        MONTHCAL_CopyTime (&nmsc.stSelStart, &infoPtr->minSel);
     1201                        MONTHCAL_CopyTime (&nmsc.stSelEnd, &infoPtr->maxSel);
     1202
     1203                SendMessageA (GetParent (hwnd), WM_NOTIFY,
     1204                                   (WPARAM)nmsc.nmhdr.idFrom, (LPARAM)&nmsc);
     1205
     1206                        MONTHCAL_CopyTime (&ht.st, &selArray[0]);
     1207                        MONTHCAL_CopyTime (&ht.st, &selArray[1]);
     1208                        MONTHCAL_SetSelRange (hwnd,0,(LPARAM) &selArray);
     1209
     1210                        infoPtr->firstSelDay=ht.st.wDay;
     1211                        infoPtr->curSelDay=ht.st.wDay;
     1212                        infoPtr->status=MC_SEL_LBUTDOWN;
     1213        }
     1214
     1215        MONTHCAL_Refresh (hwnd,hdc);
     1216        ReleaseDC (hwnd,hdc);
     1217        return 0;
     1218}
     1219
     1220static LRESULT
     1221MONTHCAL_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
     1222
     1223{
     1224    MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr (hwnd);
     1225        NMSELCHANGE nmsc;
     1226    NMHDR nmhdr;
     1227        HDC hdc;
     1228
     1229        //TRACE ("\n");
     1230
     1231        if (infoPtr->status & MC_NEXTPRESSED)
     1232                        KillTimer (hwnd, MC_NEXTMONTHTIMER);
     1233        if (infoPtr->status & MC_PREVPRESSED)
     1234                        KillTimer (hwnd, MC_PREVMONTHTIMER);
     1235        infoPtr->status=MC_SEL_LBUTUP;
     1236        infoPtr->curSelDay=0;
     1237
     1238    nmhdr.hwndFrom = hwnd;
     1239    nmhdr.idFrom   = GetWindowLongA( hwnd, GWL_ID);
     1240    nmhdr.code     = NM_RELEASEDCAPTURE;
     1241        //TRACE ("Sent notification from %x to %x\n", hwnd, GetParent (hwnd));
     1242
     1243    SendMessageA (GetParent (hwnd), WM_NOTIFY,
     1244                                   (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
     1245
     1246    nmsc.nmhdr.hwndFrom = hwnd;
     1247    nmsc.nmhdr.idFrom   = GetWindowLongA( hwnd, GWL_ID);
     1248    nmsc.nmhdr.code     = MCN_SELECT;
     1249        MONTHCAL_CopyTime (&nmsc.stSelStart, &infoPtr->minSel);
     1250        MONTHCAL_CopyTime (&nmsc.stSelEnd, &infoPtr->maxSel);
     1251
     1252    SendMessageA (GetParent (hwnd), WM_NOTIFY,
     1253                                   (WPARAM)nmsc.nmhdr.idFrom, (LPARAM)&nmsc);
     1254
     1255    hdc=GetDC (hwnd);
     1256    MONTHCAL_Refresh (hwnd,hdc);
     1257    ReleaseDC (hwnd,hdc);
     1258
     1259        return 0;
     1260}
     1261
     1262static LRESULT
     1263MONTHCAL_Timer (HWND hwnd, WPARAM wParam, LPARAM lParam)
     1264
     1265{
     1266    MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr (hwnd);
     1267    HDC hdc;
     1268
     1269    //TRACE(" %d\n",wParam);
     1270    if (!infoPtr) return FALSE;
     1271
     1272    hdc=GetDC (hwnd);
     1273    switch (wParam) {
     1274        case MC_NEXTMONTHTIMER:
     1275                MONTHCAL_GoToNextMonth (hwnd, infoPtr);
     1276                break;
     1277        case MC_PREVMONTHTIMER:
     1278                MONTHCAL_GoToPrevMonth (hwnd, infoPtr);
     1279                break;
     1280    //default:
     1281        //ERR("got unknown timer\n");
     1282        }
     1283
     1284    MONTHCAL_Refresh (hwnd,hdc);
     1285    ReleaseDC (hwnd,hdc);
     1286    return 0;
     1287}
     1288
     1289
     1290
     1291static LRESULT
     1292MONTHCAL_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
     1293{
     1294    MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr (hwnd);
     1295        MCHITTESTINFO ht;
     1296        HDC hdc;
     1297        int selday,hit;
     1298        RECT r;
     1299
     1300        if (!(infoPtr->status & MC_SEL_LBUTDOWN)) return 0;
     1301
     1302        ht.pt.x=LOWORD(lParam);
     1303        ht.pt.y=HIWORD(lParam);
     1304
     1305        hit=MONTHCAL_HitTest (hwnd, (LPARAM) &ht);
     1306
     1307        /* not on the calendar date numbers? bail out */
     1308        //TRACE ("hit:%x\n",hit);
     1309        if ((hit & MCHT_CALENDARDATE) !=MCHT_CALENDARDATE) return 0;
     1310
     1311        selday=ht.st.wDay;
     1312        infoPtr->curSelDay=selday;
     1313        MONTHCAL_CalcPosFromDay (infoPtr,selday,ht.st.wMonth,&r);
     1314
     1315        if ( GetWindowLongA( hwnd, GWL_STYLE) & MCS_MULTISELECT)  {
     1316                SYSTEMTIME selArray[2];
     1317                int i;
     1318
     1319        MONTHCAL_GetSelRange (hwnd,0,(LPARAM) &selArray);
     1320                i=0;
     1321                if (infoPtr->firstSelDay==selArray[0].wDay) i=1;
     1322                //TRACE ("oldRange:%d %d %d %d\n",infoPtr->firstSelDay,selArray[0].wDay,selArray[1].wDay,i);
     1323                if (infoPtr->firstSelDay==selArray[1].wDay) {
     1324                                /* 1st time we get here: selArray[0]=selArray[1])  */
     1325                                /* if we're still at the first selected date, return */
     1326                        if (infoPtr->firstSelDay==selday) goto done;
     1327
     1328                        if (selday<infoPtr->firstSelDay) i=0;
     1329                }
     1330
     1331                if (abs(infoPtr->firstSelDay - selday) >= infoPtr->maxSelCount) {
     1332                        if (selday>infoPtr->firstSelDay)
     1333                                selday=infoPtr->firstSelDay+infoPtr->maxSelCount;
     1334                        else
     1335                                selday=infoPtr->firstSelDay-infoPtr->maxSelCount;
     1336                }
     1337
     1338                if (selArray[i].wDay!=selday) {
     1339
     1340                //TRACE ("newRange:%d %d %d %d\n",infoPtr->firstSelDay,selArray[0].wDay,selArray[1].wDay,i);
     1341
     1342                        selArray[i].wDay=selday;
     1343
     1344
     1345                        if (selArray[0].wDay>selArray[1].wDay) {
     1346                                DWORD tempday;
     1347                                tempday=selArray[1].wDay;
     1348                                selArray[1].wDay=selArray[0].wDay;
     1349                                selArray[0].wDay=tempday;
     1350                        }
     1351
     1352                MONTHCAL_SetSelRange (hwnd,0,(LPARAM) &selArray);
     1353                }
     1354        }
     1355
     1356done:
     1357
     1358        hdc=GetDC (hwnd);
     1359        MONTHCAL_Refresh (hwnd, hdc);
     1360        ReleaseDC (hwnd, hdc);
     1361
     1362        return 0;
     1363}
     1364
     1365static LRESULT
     1366MONTHCAL_Paint (HWND hwnd, WPARAM wParam)
     1367{
     1368    HDC hdc;
     1369    PAINTSTRUCT ps;
     1370
     1371    hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
     1372    MONTHCAL_Refresh (hwnd, hdc);
     1373    if(!wParam)
     1374    EndPaint (hwnd, &ps);
     1375    return 0;
     1376}
     1377
     1378static LRESULT
     1379MONTHCAL_KillFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
     1380{
     1381    HDC hdc;
     1382
     1383    //TRACE ("\n");
     1384
     1385    hdc = GetDC (hwnd);
     1386    MONTHCAL_Refresh (hwnd, hdc);
     1387    ReleaseDC (hwnd, hdc);
     1388    InvalidateRect (hwnd, NULL, TRUE);
     1389
     1390    return 0;
     1391}
     1392
     1393
     1394static LRESULT
     1395MONTHCAL_SetFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
     1396{
     1397    HDC hdc;
     1398
     1399    //TRACE ("\n");
     1400
     1401    hdc = GetDC (hwnd);
     1402    MONTHCAL_Refresh (hwnd, hdc);
     1403    ReleaseDC (hwnd, hdc);
     1404
     1405    return 0;
     1406}
     1407
     1408
     1409/* FIXME: check whether dateMin/dateMax need to be adjusted. */
    291410
    301411
     
    331414{
    341415    MONTHCAL_INFO *infoPtr;
     1416        LOGFONTA        logFont;
    351417
    361418    /* allocate memory for info structure */
     
    381420    SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
    391421
     1422        if (infoPtr == NULL) {
     1423        //ERR ( "could not allocate info memory!\n");
     1424        return 0;
     1425    }
     1426    if ((MONTHCAL_INFO*) GetWindowLongA( hwnd, 0) != infoPtr) {
     1427        //ERR ( "pointer assignment error!\n");
     1428        return 0;
     1429    }
     1430
     1431
     1432    infoPtr->hFont=GetStockObject(DEFAULT_GUI_FONT);
     1433                GetObjectA (infoPtr->hFont, sizeof (LOGFONTA), &logFont);
     1434        logFont.lfWeight=FW_BOLD;
     1435        infoPtr->hBoldFont = CreateFontIndirectA (&logFont);
    401436
    411437    /* initialize info structure */
    42 
    43 
     1438   /* FIXME: calculate systemtime ->> localtime (substract timezoneinfo) */
     1439
     1440        GetSystemTime (&infoPtr->todaysDate);
     1441        infoPtr->firstDay  = 0;
     1442        infoPtr->currentMonth = infoPtr->todaysDate.wMonth;
     1443        infoPtr->currentYear= infoPtr->todaysDate.wYear;
     1444        MONTHCAL_CopyTime (&infoPtr->todaysDate,&infoPtr->minDate);
     1445        MONTHCAL_CopyTime (&infoPtr->todaysDate,&infoPtr->maxDate);
     1446        infoPtr->maxSelCount=6;
     1447        infoPtr->monthRange=3;
     1448        infoPtr->monthdayState=COMCTL32_Alloc
     1449                           (infoPtr->monthRange*sizeof(MONTHDAYSTATE));
     1450        infoPtr->titlebk     = GetSysColor (COLOR_GRAYTEXT);
     1451        infoPtr->titletxt    = GetSysColor (COLOR_WINDOW);
     1452        infoPtr->monthbk     = GetSysColor (COLOR_WINDOW);
     1453        infoPtr->trailingtxt = GetSysColor (COLOR_GRAYTEXT);
     1454        infoPtr->bk                  = GetSysColor (COLOR_WINDOW);
     1455        infoPtr->txt         = GetSysColor (COLOR_WINDOWTEXT);
    441456
    451457    return 0;
     
    521464    MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr (hwnd);
    531465
    54 
    55 
    56 
    57 
    58 
    59     /* free ipaddress info data */
     1466    /* free month calendar info data */
    601467    COMCTL32_Free (infoPtr);
    611468
     
    651472
    661473
    67 
    68 LRESULT WINAPI
     1474static LRESULT WINAPI
    691475MONTHCAL_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    701476{
     1477
    711478    switch (uMsg)
    721479    {
    731480
    74 
    75         case WM_CREATE:
    76             return MONTHCAL_Create (hwnd, wParam, lParam);
    77 
    78         case WM_DESTROY:
    79             return MONTHCAL_Destroy (hwnd, wParam, lParam);
    80 
    81         default:
    82 //          if (uMsg >= WM_USER)
    83 //              ERR (monthcal, "unknown msg %04x wp=%08x lp=%08lx\n",
    84 //                   uMsg, wParam, lParam);
    85             return DefWindowProcA (hwnd, uMsg, wParam, lParam);
     1481        case MCM_GETCURSEL:
     1482        return MONTHCAL_GetCurSel (hwnd, wParam, lParam);
     1483
     1484        case MCM_SETCURSEL:
     1485        return MONTHCAL_SetCurSel (hwnd, wParam, lParam);
     1486
     1487        case MCM_GETMAXSELCOUNT:
     1488        return MONTHCAL_GetMaxSelCount (hwnd, wParam, lParam);
     1489
     1490        case MCM_SETMAXSELCOUNT:
     1491        return MONTHCAL_SetMaxSelCount (hwnd, wParam, lParam);
     1492
     1493        case MCM_GETSELRANGE:
     1494        return MONTHCAL_GetSelRange (hwnd, wParam, lParam);
     1495
     1496        case MCM_SETSELRANGE:
     1497        return MONTHCAL_SetSelRange (hwnd, wParam, lParam);
     1498
     1499        case MCM_GETMONTHRANGE:
     1500        return MONTHCAL_GetMonthRange (hwnd, wParam, lParam);
     1501
     1502        case MCM_SETDAYSTATE:
     1503        return MONTHCAL_SetDayState (hwnd, wParam, lParam);
     1504
     1505        case MCM_GETMINREQRECT:
     1506        return MONTHCAL_GetMinReqRect (hwnd, wParam, lParam);
     1507
     1508        case MCM_GETCOLOR:
     1509             return MONTHCAL_GetColor (hwnd, wParam, lParam);
     1510
     1511        case MCM_SETCOLOR:
     1512             return MONTHCAL_SetColor (hwnd, wParam, lParam);
     1513
     1514        case MCM_GETTODAY:
     1515             return MONTHCAL_GetToday (hwnd, wParam, lParam);
     1516
     1517        case MCM_SETTODAY:
     1518             return MONTHCAL_SetToday (hwnd, wParam, lParam);
     1519
     1520        case MCM_HITTEST:
     1521            return MONTHCAL_HitTest (hwnd,lParam);
     1522
     1523        case MCM_GETFIRSTDAYOFWEEK:
     1524        return MONTHCAL_GetFirstDayOfWeek (hwnd, wParam, lParam);
     1525
     1526        case MCM_SETFIRSTDAYOFWEEK:
     1527        return MONTHCAL_SetFirstDayOfWeek (hwnd, wParam, lParam);
     1528
     1529        case MCM_GETRANGE:
     1530             return MONTHCAL_GetRange (hwnd, wParam, lParam);
     1531
     1532        case MCM_SETRANGE:
     1533             return MONTHCAL_SetRange (hwnd, wParam, lParam);
     1534
     1535        case MCM_GETMONTHDELTA:
     1536             return MONTHCAL_GetMonthDelta (hwnd, wParam, lParam);
     1537
     1538        case MCM_SETMONTHDELTA:
     1539             return MONTHCAL_SetMonthDelta (hwnd, wParam, lParam);
     1540
     1541        case MCM_GETMAXTODAYWIDTH:
     1542             return MONTHCAL_GetMaxTodayWidth (hwnd);
     1543
     1544        case WM_GETDLGCODE:
     1545        return DLGC_WANTARROWS | DLGC_WANTCHARS;
     1546
     1547    case WM_KILLFOCUS:
     1548        return MONTHCAL_KillFocus (hwnd, wParam, lParam);
     1549
     1550    case WM_LBUTTONDOWN:
     1551        return MONTHCAL_LButtonDown (hwnd, wParam, lParam);
     1552
     1553    case WM_MOUSEMOVE:
     1554        return MONTHCAL_MouseMove (hwnd, wParam, lParam);
     1555
     1556    case WM_LBUTTONUP:
     1557        return MONTHCAL_LButtonUp (hwnd, wParam, lParam);
     1558
     1559    case WM_PAINT:
     1560        return MONTHCAL_Paint (hwnd, wParam);
     1561
     1562    case WM_SETFOCUS:
     1563        return MONTHCAL_SetFocus (hwnd, wParam, lParam);
     1564
     1565        case WM_CREATE:
     1566            return MONTHCAL_Create (hwnd, wParam, lParam);
     1567
     1568        case WM_TIMER:
     1569            return MONTHCAL_Timer (hwnd, wParam, lParam);
     1570
     1571        case WM_DESTROY:
     1572            return MONTHCAL_Destroy (hwnd, wParam, lParam);
     1573
     1574        default:
     1575            //if (uMsg >= WM_USER)
     1576            //    ERR ( "unknown msg %04x wp=%08x lp=%08lx\n",
     1577            //         uMsg, wParam, lParam);
     1578            return DefWindowProcA (hwnd, uMsg, wParam, lParam);
    861579    }
    871580    return 0;
     
    891582
    901583
    91 VOID
    92 MONTHCAL_Register (VOID)
     1584void
     1585MONTHCAL_Register (void)
    931586{
    941587    WNDCLASSA wndClass;
     
    1041597    wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    1051598    wndClass.lpszClassName = MONTHCAL_CLASSA;
    106  
     1599
    1071600    RegisterClassA (&wndClass);
    1081601}
    1091602
    1101603
    111 VOID
    112 MONTHCAL_Unregister (VOID)
     1604void
     1605MONTHCAL_Unregister (void)
    1131606{
    1141607    if (GlobalFindAtomA (MONTHCAL_CLASSA))
    115         UnregisterClassA (MONTHCAL_CLASSA, (HINSTANCE)NULL);
    116 }
    117 
     1608        UnregisterClassA (MONTHCAL_CLASSA, (HINSTANCE)NULL);
     1609}
     1610
Note: See TracChangeset for help on using the changeset viewer.